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