1 #include "test.h"
2 #ifndef _UWIN
3 #include <process.h>
4 #endif
5
6 /*
7 * Create NUMTHREADS threads in addition to the Main thread.
8 */
9 enum {
10 NUMTHREADS = 4
11 };
12
13 typedef struct bag_t_ bag_t;
14 struct bag_t_ {
15 int threadnum;
16 int started;
17 /* Add more per-thread state variables here */
18 int count;
19 pthread_t self;
20 };
21
22 static bag_t threadbag[NUMTHREADS + 1];
23
24 pthread_cond_t CV = PTHREAD_COND_INITIALIZER;
25 pthread_mutex_t CVLock = PTHREAD_MUTEX_INITIALIZER;
26
27 unsigned int __stdcall
Win32thread(void * arg)28 Win32thread(void * arg)
29 {
30 bag_t * bag = (bag_t *) arg;
31
32 assert(bag == &threadbag[bag->threadnum]);
33 assert(bag->started == 0);
34 bag->started = 1;
35
36 assert((bag->self = pthread_self()) != 0);
37 assert(pthread_gethandle (bag->self) != NULL);
38
39 assert(pthread_kill(bag->self, 0) == 0);
40
41 assert(pthread_mutex_lock(&CVLock) == 0);
42 pthread_cleanup_push(pthread_mutex_unlock, &CVLock);
43 pthread_cond_wait(&CV, &CVLock);
44 pthread_cleanup_pop(1);
45
46 return 0;
47 }
48
49 int
main()50 main()
51 {
52 int failed = 0;
53 int i;
54 HANDLE h[NUMTHREADS + 1];
55 unsigned thrAddr; /* Dummy variable to pass a valid location to _beginthreadex (Win98). */
56
57 for (i = 1; i <= NUMTHREADS; i++)
58 {
59 threadbag[i].started = 0;
60 threadbag[i].threadnum = i;
61 h[i] = (HANDLE) _beginthreadex(NULL, 0, Win32thread, (void *) &threadbag[i], 0, &thrAddr);
62 }
63
64 /*
65 * Code to control or munipulate child threads should probably go here.
66 */
67 Sleep(500);
68
69 /*
70 * Cancel all threads.
71 */
72 for (i = 1; i <= NUMTHREADS; i++)
73 {
74 assert(pthread_kill(threadbag[i].self, 0) == 0);
75 assert(pthread_cancel(threadbag[i].self) == 0);
76 }
77
78 /*
79 * Give threads time to run.
80 */
81 Sleep(NUMTHREADS * 100);
82
83 /*
84 * Standard check that all threads started.
85 */
86 for (i = 1; i <= NUMTHREADS; i++)
87 {
88 if (!threadbag[i].started)
89 {
90 failed |= !threadbag[i].started;
91 fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started);
92 }
93 }
94
95 assert(!failed);
96
97 /*
98 * Check any results here. Set "failed" and only print output on failure.
99 */
100 failed = 0;
101 for (i = 1; i <= NUMTHREADS; i++)
102 {
103 int fail = 0;
104 int result = 0;
105
106 assert(GetExitCodeThread(h[i], (LPDWORD) &result) == TRUE);
107
108 //assert(threadbag[i].self->h != NULL);
109 assert(pthread_kill(threadbag[i].self, 0) == ESRCH);
110
111 fail = (result != (int) (size_t) PTHREAD_CANCELED);
112
113 if (fail)
114 {
115 fprintf(stderr, "Thread %d: started %d: count %d\n",
116 i,
117 threadbag[i].started,
118 threadbag[i].count);
119 }
120 failed = (failed || fail);
121 }
122
123 assert(!failed);
124
125 /*
126 * Success.
127 */
128 return 0;
129 }
130
131