Update copyright to LGPL on all files
[dyninst.git] / dyninstAPI / tests / src / test15.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 <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <pthread.h>
35 #include <signal.h>
36 #include <sys/types.h>
37 #include <assert.h>
38 #include <unistd.h>
39 #include <limits.h>
40
41 #ifdef __cplusplus
42 int mutateeCplusplus = 1;
43 #else
44 int mutateeCplusplus = 0;
45 #endif
46
47 #ifndef COMPILER
48 #define COMPILER ""
49 #endif
50 const char *Builder_id=COMPILER; /* defined on compile line */
51
52 #define NTHRD 5
53 pthread_t thrds[NTHRD];
54 int thr_ids[NTHRD] = {0, 1, 2, 3, 4};
55 int ok_to_exit[NTHRD] = {0, 0, 0, 0, 0};
56
57 /* oneTimeCodes will set these to the tid for the desired thread */
58 volatile pthread_t sync_test = 0;
59 volatile pthread_t async_test = 0;
60 int sync_failure = 0;
61 int async_failure = 0;
62
63 volatile unsigned thr_exits;
64
65 void check_sync()
66 {
67    pthread_t tid = pthread_self();
68    int id = -1, i;
69    for(i = 0; i < NTHRD; i++) {
70       if(thrds[i] == tid) {
71          id = i;
72          break;
73       }
74    }
75
76    if(tid == sync_test) {
77       printf("Thread %d [tid %lu] - oneTimeCode completed successfully\n", 
78              id, tid);
79       ok_to_exit[id] = 1;
80       return;
81    }
82    else if(sync_test != 0)
83       fprintf(stderr, "%s[%d]: ERROR: Thread %d [tid %lu] - mistakenly ran oneTimeCode for thread with tid %lu\n", __FILE__, __LINE__, id, tid, sync_test);
84    else
85       fprintf(stderr, "%s[%d]: ERROR: Thread %d [tid %lu] - sync_test is 0\n", __FILE__, __LINE__, id, tid);
86    sync_failure++;
87 }
88
89 void check_async()
90 {
91    pthread_t tid = pthread_self();
92    int id = -1, i;
93    for(i = 0; i < NTHRD; i++) {
94       if(thrds[i] == tid) {
95          id = i;
96          break;
97       }
98    }
99
100    if(tid == async_test) {
101       printf("Thread %d [tid %lu] - oneTimeCodeAsync completed successfully\n",
102              id, tid);
103       return;
104    }
105    else if(async_test != 0)
106       fprintf(stderr, 
107               "%s[%d]: ERROR: Thread %d [tid %lu] - mistakenly ran oneTimeCodeAsync for thread with tid %lu\n", 
108               __FILE__, __LINE__, id, tid, async_test);
109    else
110       fprintf(stderr, 
111               "%s[%d]: ERROR: Thread %d [tid %lu] - async_test is 0\n", 
112               __FILE__, __LINE__, id, tid);
113    async_failure++;
114 }
115
116 #define MAX_TIMEOUTS 5
117 void thr_loop(int id, pthread_t tid)
118 {
119    unsigned long timeout = 0;
120    unsigned num_timeout = 0;
121    while( (! ok_to_exit[id]) && (num_timeout != MAX_TIMEOUTS) ) {
122       timeout++;
123       if(timeout == ULONG_MAX) {
124          timeout = 0;
125          num_timeout++;
126       }
127    }
128    if(num_timeout == MAX_TIMEOUTS)
129       fprintf(stderr, 
130               "%s[%d]: ERROR: Thread %d [tid %lu] - timed-out in thr_loop\n", 
131               __FILE__, __LINE__, id, (unsigned long)tid);
132 }
133
134 void thr_func(void *arg)
135 {
136    unsigned busy_work = 0;
137    int id = *((int*)arg);
138    pthread_t tid = pthread_self();
139    thr_loop(id, tid);
140    while(++busy_work != UINT_MAX/10);
141    thr_exits++;
142 }
143
144 void *init_func(void *arg)
145 {
146    assert(arg != NULL);
147    thr_func(arg);
148    return NULL;
149 }
150
151 int attached_fd;
152 void parse_args(int argc, char *argv[])
153 {
154    int i;
155    for (i=0; i<argc; i++)
156    {
157       if (strstr(argv[i], "-attach"))
158       {
159          if (++i == argc) break;
160          attached_fd = atoi(argv[i]);
161       }
162    }
163 }
164
165 int isAttached = 0;
166 /* Check to see if the mutator has attached to us. */
167 int checkIfAttached()
168 {
169     return isAttached;
170 }
171
172 int main(int argc, char *argv[])
173 {
174    unsigned i;
175    void *ret_val;
176    char c = 'T';
177    pthread_attr_t attr;
178
179    if(argc == 1) {
180       printf("Mutatee %s [%s]:\"%s\"\n", argv[0], 
181              mutateeCplusplus ? "C++" : "C", Builder_id);
182       return 0;
183    }
184
185    pthread_attr_init(&attr);
186    pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
187
188    thr_exits = 0;
189
190    parse_args(argc, argv);
191
192    /* create the workers */
193    for (i=1; i<NTHRD; i++)
194    {
195       pthread_create(&(thrds[i]), &attr, init_func, &(thr_ids[i]));
196    }
197    thrds[0] = pthread_self();
198
199    if (attached_fd) {
200       if (write(attached_fd, &c, sizeof(char)) != sizeof(char)) {
201          fprintf(stderr, "*ERROR*: Writing to pipe\n");
202          exit(-1);
203       }
204       close(attached_fd);
205       printf("Waiting for mutator to attach...\n");
206       while(! checkIfAttached()) ;
207       printf("Mutator attached.  Mutatee continuing.\n");
208    }
209    
210    /* give time for workers to run thr_loop */
211    while(thr_exits == 0)
212       sched_yield();
213
214    /* wait for worker exits */
215    for (i=1; i<NTHRD; i++)
216    {
217       pthread_join(thrds[i], &ret_val);
218    }
219    
220    if(sync_failure)
221       fprintf(stderr, 
222               "%s[%d]: ERROR: oneTimeCode failed for %d threads\n", 
223               __FILE__, __LINE__, sync_failure);
224    if(async_failure)
225       fprintf(stderr, 
226               "%s[%d]: ERROR: oneTimeCodeAsync failed for %d threads\n", 
227               __FILE__, __LINE__, async_failure);
228
229    /* let mutator do final work after noticing all workers exit */
230    sleep(5);
231
232    return 0;
233 }