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