• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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