Update copyright to LGPL on all files
[dyninst.git] / testsuite / src / dyninst / test_thread_1_mutatee.c
1 /*
2  * Copyright (c) 1996-2009 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31 #include <assert.h>
32 #include <dlfcn.h>
33 #include <errno.h>
34 #include <pthread.h>
35 #include <stdlib.h>
36 #include <time.h>
37 #include <unistd.h>
38
39 #include "mutatee_util.h"
40 #include "test_thread.h"
41 #include "test12.h"
42 #include "../../dyninstAPI_RT/h/dyninstRTExport.h"
43
44 /* Externally accessed function prototypes.  These must have globally unique
45  * names.  I suggest following the pattern <testname>_<function>
46  */
47
48 /* Global variables accessed by the mutator.  These must have globally unique
49  * names.
50  */
51
52 /* Internally used function prototypes.  These should be declared with the
53  * keyword static so they don't interfere with other mutatees in the group.
54  */
55
56 /* Global variables used internally by the mutatee.  These should be declared
57  * with the keyword static so they don't interfere with other mutatees in the
58  * group.
59  */
60
61 /* Function definitions follow */
62
63 /********************************************************************/
64 /********************************************************************/
65 /***********  Subtest 1:  rtlib spinlocks */
66 /***********  use dlopen/dlsym to get access to rt lib lock */
67 /***********  then start up a bunch of threads to contend for it */
68 /***********  monitor contention for deadlock/broken lock */
69 /********************************************************************/
70 /********************************************************************/
71
72 unsigned long current_locks[TEST1_THREADS];
73 /*Thread_t  *test2threads; */
74 Thread_t test1threads[TEST1_THREADS];
75 pthread_mutex_t real_lock;
76
77 int subtest1counter = 0;
78 int subtest1err = 0;
79
80 void register_my_lock(unsigned long id, unsigned int val)
81 {
82   unsigned int i;
83   int found = 0;
84   dprintf("%s[%d]:  %sregister lock for thread %lu\n", __FILE__, __LINE__,
85            val ? "" : "un", id);
86   for (i = 0; i < TEST1_THREADS; ++i) {
87     if (pthread_equal(test1threads[i],(pthread_t)id)) {
88       found = 1;
89       current_locks[i] = (unsigned)val;
90       break;
91     }
92   }
93   if (!found)
94     logerror("%s[%d]: FIXME\n", __FILE__, __LINE__);
95 }
96
97 int done_threads = 0;
98
99 int all_threads_done()
100 {
101   return done_threads == TEST1_THREADS;
102 }
103
104 int is_only_one() {
105   unsigned int i;
106   int foundone = 0;
107   for (i = 0; i < TEST1_THREADS; ++i) {
108     if (0 != current_locks[i]) {
109       if (foundone) return 0; /*false*/
110       foundone++;
111     }
112   }
113   return 1; /*true */
114 }
115
116 void (*DYNINSTinit_thelock)(dyninst_lock_t *);
117 int (*DYNINSTlock_thelock)(dyninst_lock_t *);
118 void (*DYNINSTunlock_thelock)(dyninst_lock_t *);
119 /*dyninst_lock_t test1lock; */
120 static DECLARE_DYNINST_LOCK(test1lock);
121
122 void *thread_main1 (void *arg)
123 {
124    (*DYNINSTlock_thelock)(&test1lock);
125    register_my_lock((unsigned long)pthread_self(),1);
126    pthread_mutex_lock(&real_lock);
127    arg = NULL; /*Silence warnings*/
128
129   /*sleep_ms(1); */
130
131    if (!is_only_one()) {
132      subtest1err = 1;
133    }
134    pthread_mutex_unlock(&real_lock);
135    register_my_lock((unsigned long)pthread_self(),0);
136    subtest1counter++;
137
138    (*DYNINSTunlock_thelock)(&test1lock); 
139
140    pthread_mutex_lock(&real_lock);
141     done_threads++;
142    pthread_mutex_unlock(&real_lock);
143    return NULL;
144 }
145
146 unsigned long local_pthread_self() {
147   return (unsigned long) pthread_self();
148 }
149
150 int func1_1()
151 {
152
153   dyntid_t (**DYNINST_pthread_self)(void);
154   int lockres;
155   int bigTIMEOUT;
156   int timeout;
157   char *libname;
158   /*pthread_attr_t attr;*/
159   unsigned int i;
160   void *RTlib;
161
162   /* zero out lock registry: */
163   for (i = 0; i < TEST1_THREADS; ++i) {
164     current_locks[i] = 0;
165   }
166
167 #if !defined (os_windows_test) && !defined(os_irix)
168
169 #if defined(m32_test)
170   libname = "libdyninstAPI_RT_m32.so.1";
171 #else
172   libname = "libdyninstAPI_RT.so.1";
173 #endif
174   RTlib = dlopen(libname, RTLD_NOW);
175   if (!RTlib) {
176     logerror("%s[%d]:  could not open dyninst RT lib: %s\n", __FILE__, __LINE__, dlerror());
177     /* FIXME Don't exit()! */
178     /* exit(1); */
179     return -1;
180   }
181
182   DYNINSTinit_thelock = (void (*)(dyninst_lock_t *))dlsym(RTlib, "dyninst_init_lock");
183   DYNINSTlock_thelock = (int (*)(dyninst_lock_t *))dlsym(RTlib, "dyninst_lock");
184   DYNINSTunlock_thelock = (void (*)(dyninst_lock_t *))dlsym(RTlib, "dyninst_unlock");
185   DYNINST_pthread_self = (dyntid_t (**)(void))dlsym(RTlib, "DYNINST_pthread_self");
186   if (!DYNINSTinit_thelock) {
187     logerror("%s[%d]:  could not DYNINSTinit_thelock: %s\n", __FILE__, __LINE__, dlerror());
188     /* FIXME Don't exit()! */
189     /* exit(1); */
190     return -1;
191   }
192   if (!DYNINSTlock_thelock) {
193     logerror("%s[%d]:  could not DYNINSTlock_thelock: %s\n", __FILE__, __LINE__, dlerror());
194     /* FIXME Don't exit()! */
195     /* exit(1); */
196     return -1;
197   }
198   if (!DYNINSTunlock_thelock) {
199     logerror("%s[%d]:  could not DYNINSTunlock_thelock:%s\n", __FILE__, __LINE__, dlerror());
200     /* FIXME Don't exit()! */
201     /* exit(1); */
202     return -1;
203   }
204
205   pthread_mutex_init(&real_lock, NULL);
206
207   (*DYNINSTunlock_thelock)(&test1lock);
208 #if !defined(os_solaris_test)
209    /*  XXX this is nasty */
210    /*  The way this is supposed to work is that we get a lock, then start a bunch of
211        threads, which all try to get the same lock, pretty much as soon as they start.
212        Then, after starting all the threads, we release the lock and let the threads
213        compete for it, checking to make sure that all threads get the lock at some point
214        and that no two threads have it at the same time.  
215        The problem is that solaris is having problems with this system when the lock is 
216        obtained before the threads are spawned (pthread_create hangs) -- it is still ok
217        to just start all the threads and have the system run, its just not quite as clean.
218        This might be bad asm programming on my behalf, or it might be some idiosyncracy
219        with solaris libpthreads.  This worked, incidentally, when this stuff was all in
220        the mutator, but that might've been because the asm that was imported to implement
221        the locks was the gnu asm, not the solaris-cc asm, which is the stuff that gets
222        compiled, by default into the runtime lib*/
223 /*
224    int lockres = (*DYNINSTlock_thelock)(&test1lock); 
225 */
226 #endif
227   lockres = (*DYNINSTlock_thelock)(&test1lock);
228   createThreads(TEST1_THREADS, thread_main1, test1threads);
229
230   sleep_ms(5);
231
232   dprintf("%s[%d]:  doing initial unlock...\n", __FILE__, __LINE__);
233 #if !defined(os_solaris_test)
234   /* (*DYNINSTunlock_thelock)(&test1lock); */ 
235
236 #endif
237    (*DYNINSTunlock_thelock)(&test1lock); 
238   /*pthread_mutex_unlock(&real_lock); */
239
240 #endif
241
242   bigTIMEOUT = 5000;
243   timeout = 0;
244
245   /*   wait for all threads to exit */
246   while (timeout < bigTIMEOUT && ! all_threads_done()) {
247     timeout += 100;
248     sleep_ms(100);
249   }
250
251   dlclose(RTlib);
252   return subtest1err;
253 }
254
255 /* skeleton test doesn't do anything besides say that it passed */
256 int test_thread_1_mutatee() {
257   int status;
258
259   status = func1_1();
260   /* TODO Make sure this is correct */
261   if (status != 0) {
262     return -1; /* Error of some kind */
263   } else {
264     test_passes(testname);
265     return 0;
266   }
267 }