• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "test.h"
2 #include <sys/timeb.h>
3 
4 /*
5  * Create NUMTHREADS threads in addition to the Main thread.
6  */
7 enum {
8   NUMTHREADS = 9
9 };
10 
11 typedef struct bag_t_ bag_t;
12 struct bag_t_ {
13   int threadnum;
14   int started;
15   int finished;
16   /* Add more per-thread state variables here */
17 };
18 
19 static bag_t threadbag[NUMTHREADS + 1];
20 
21 typedef struct cvthing_t_ cvthing_t;
22 
23 struct cvthing_t_ {
24   pthread_cond_t notbusy;
25   pthread_mutex_t lock;
26   int shared;
27 };
28 
29 static cvthing_t cvthing = {
30   PTHREAD_COND_INITIALIZER,
31   PTHREAD_MUTEX_INITIALIZER,
32   0
33 };
34 
35 static pthread_mutex_t start_flag = PTHREAD_MUTEX_INITIALIZER;
36 
37 static struct timespec abstime = { 0, 0 };
38 
39 static int awoken;
40 
41 static void *
mythread(void * arg)42 mythread(void * arg)
43 {
44   bag_t * bag = (bag_t *) arg;
45 
46   assert(bag == &threadbag[bag->threadnum]);
47   assert(bag->started == 0);
48   bag->started = 1;
49 
50   /* Wait for the start gun */
51   assert(pthread_mutex_lock(&start_flag) == 0);
52   assert(pthread_mutex_unlock(&start_flag) == 0);
53 
54   assert(pthread_mutex_lock(&cvthing.lock) == 0);
55 
56   /*
57    * pthread_cond_timedwait is a cancelation point and we're
58    * going to cancel some threads deliberately.
59    */
60 #ifdef _MSC_VER
61 #pragma inline_depth(0)
62 #endif
63   pthread_cleanup_push(pthread_mutex_unlock, (void *) &cvthing.lock);
64 
65   while (! (cvthing.shared > 0))
66     assert(pthread_cond_timedwait(&cvthing.notbusy, &cvthing.lock, &abstime) == 0);
67 
68   pthread_cleanup_pop(0);
69 #ifdef _MSC_VER
70 #pragma inline_depth()
71 #endif
72 
73   assert(cvthing.shared > 0);
74 
75   awoken++;
76   bag->finished = 1;
77 
78   assert(pthread_mutex_unlock(&cvthing.lock) == 0);
79 
80   return (void *) 0;
81 }
82 
83 int
main()84 main()
85 {
86   int failed = 0;
87   int i;
88   int first, last;
89   int canceledThreads = 0;
90   pthread_t t[NUMTHREADS + 1];
91 
92   struct _timeb currSysTime;
93   const DWORD NANOSEC_PER_MILLISEC = 1000000;
94 
95   assert((t[0] = pthread_self()) != 0);
96   assert(pthread_gethandle (t[0]) != NULL);
97 
98   assert(cvthing.notbusy == PTHREAD_COND_INITIALIZER);
99 
100   assert(cvthing.lock == PTHREAD_MUTEX_INITIALIZER);
101 
102   _ftime(&currSysTime);
103 
104   abstime.tv_sec = currSysTime.time;
105   abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm;
106 
107   abstime.tv_sec += 5;
108 
109   assert((t[0] = pthread_self()) != 0);
110   assert(pthread_gethandle (t[0]) != NULL);
111 
112   awoken = 0;
113 
114   for (first = 1, last = NUMTHREADS / 2;
115        first < NUMTHREADS;
116        first = last + 1, last = NUMTHREADS)
117     {
118       int ct;
119 
120       assert(pthread_mutex_lock(&start_flag) == 0);
121 
122       for (i = first; i <= last; i++)
123 	{
124 	  threadbag[i].started = threadbag[i].finished = 0;
125 	  threadbag[i].threadnum = i;
126 	  assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0);
127 	}
128 
129       /*
130        * Code to control or munipulate child threads should probably go here.
131        */
132       cvthing.shared = 0;
133 
134       assert(pthread_mutex_unlock(&start_flag) == 0);
135 
136       /*
137        * Give threads time to start.
138        */
139       Sleep(1000);
140 
141       ct = (first + last) / 2;
142       assert(pthread_cancel(t[ct]) == 0);
143       canceledThreads++;
144       assert(pthread_join(t[ct], NULL) == 0);
145 
146       assert(pthread_mutex_lock(&cvthing.lock) == 0);
147       cvthing.shared++;
148       assert(pthread_mutex_unlock(&cvthing.lock) == 0);
149 
150       assert(pthread_cond_broadcast(&cvthing.notbusy) == 0);
151 
152       /*
153        * Standard check that all threads started - and wait for them to finish.
154        */
155       for (i = first; i <= last; i++)
156 	{
157 	  failed = !threadbag[i].started;
158 
159           if (failed)
160 	    {
161 	      fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started);
162 	    }
163 	  else
164 	    {
165 	      assert(pthread_join(t[i], NULL) == 0 || threadbag[i].finished == 0);
166 //	      fprintf(stderr, "Thread %d: finished %d\n", i, threadbag[i].finished);
167 	    }
168 	}
169     }
170 
171   /*
172    * Cleanup the CV.
173    */
174 
175   assert(pthread_mutex_destroy(&cvthing.lock) == 0);
176 
177   assert(cvthing.lock == NULL);
178 
179   assert_e(pthread_cond_destroy(&cvthing.notbusy), ==, 0);
180 
181   assert(cvthing.notbusy == NULL);
182 
183   assert(!failed);
184 
185   /*
186    * Check any results here.
187    */
188 
189   assert(awoken == NUMTHREADS - canceledThreads);
190 
191   /*
192    * Success.
193    */
194   return 0;
195 }
196