1 /*
2 * File: cancel6d.c
3 *
4 *
5 * Pthreads-win32 - POSIX Threads Library for Win32
6 * Copyright (C) 1998 Ben Elliston and Ross Johnson
7 * Copyright (C) 1999,2000,2001 Ross Johnson
8 *
9 * Contact Email: rpj@ise.canberra.edu.au
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 * --------------------------------------------------------------------------
26 *
27 * Test Synopsis: Test double cancelation - deferred.
28 * Second attempt should succeed (unless the canceled thread has started
29 * cancelation already - not tested here).
30 *
31 * Test Method (Validation or Falsification):
32 * -
33 *
34 * Requirements Tested:
35 * -
36 *
37 * Features Tested:
38 * -
39 *
40 * Cases Tested:
41 * -
42 *
43 * Description:
44 * -
45 *
46 * Environment:
47 * -
48 *
49 * Input:
50 * - None.
51 *
52 * Output:
53 * - File name, Line number, and failed expression on failure.
54 * - No output on success.
55 *
56 * Assumptions:
57 * - have working pthread_create, pthread_self, pthread_mutex_lock/unlock
58 * pthread_testcancel, pthread_cancel, pthread_join
59 *
60 * Pass Criteria:
61 * - Process returns zero exit status.
62 *
63 * Fail Criteria:
64 * - Process returns non-zero exit status.
65 */
66
67 #include "test.h"
68
69 /*
70 * Create NUMTHREADS threads in addition to the Main thread.
71 */
72 enum {
73 NUMTHREADS = 4
74 };
75
76 typedef struct bag_t_ bag_t;
77 struct bag_t_ {
78 int threadnum;
79 int started;
80 /* Add more per-thread state variables here */
81 int count;
82 };
83
84 static bag_t threadbag[NUMTHREADS + 1];
85
86 void *
mythread(void * arg)87 mythread(void * arg)
88 {
89 int result = ((int)(size_t)PTHREAD_CANCELED + 1);
90 bag_t * bag = (bag_t *) arg;
91
92 assert(bag == &threadbag[bag->threadnum]);
93 assert(bag->started == 0);
94 bag->started = 1;
95
96 /* Set to known state and type */
97
98 assert(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) == 0);
99
100 assert(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) == 0);
101
102 /*
103 * We wait up to 10 seconds, waking every 0.1 seconds,
104 * for a cancelation to be applied to us.
105 */
106 for (bag->count = 0; bag->count < 100; bag->count++)
107 {
108 Sleep(100);
109 pthread_testcancel();
110 }
111
112 return (void *) (size_t) result;
113 }
114
115 int
main()116 main()
117 {
118 int failed = 0;
119 int i;
120 pthread_t t[NUMTHREADS + 1];
121
122 assert((t[0] = pthread_self()) != 0);
123 assert(pthread_gethandle (t[0]) != NULL);
124
125 for (i = 1; i <= NUMTHREADS; i++)
126 {
127 threadbag[i].started = 0;
128 threadbag[i].threadnum = i;
129 assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0);
130 }
131
132 /*
133 * Code to control or munipulate child threads should probably go here.
134 */
135 Sleep(500);
136
137 for (i = 1; i <= NUMTHREADS; i++)
138 {
139 assert(pthread_cancel(t[i]) == 0);
140 assert(pthread_cancel(t[i]) == 0);
141 }
142
143 /*
144 * Give threads time to run.
145 */
146 Sleep(NUMTHREADS * 100);
147
148 /*
149 * Standard check that all threads started.
150 */
151 for (i = 1; i <= NUMTHREADS; i++)
152 {
153 if (!threadbag[i].started)
154 {
155 failed |= !threadbag[i].started;
156 fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started);
157 }
158 }
159
160 assert(!failed);
161
162 /*
163 * Check any results here. Set "failed" and only print output on failure.
164 */
165 failed = 0;
166 for (i = 1; i <= NUMTHREADS; i++)
167 {
168 int fail = 0;
169 intptr_t result = 0;
170
171 assert(pthread_join(t[i], (void **) &result) == 0);
172
173 fail = (result != (intptr_t) PTHREAD_CANCELED);
174
175 if (fail)
176 {
177 fprintf(stderr, "Thread %d: started %d: count %d\n",
178 i,
179 threadbag[i].started,
180 threadbag[i].count);
181 }
182 failed = (failed || fail);
183 }
184
185 assert(!failed);
186
187 /*
188 * Success.
189 */
190 return 0;
191 }
192