• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * File: cleanup3.c
3  *
4  *
5  * --------------------------------------------------------------------------
6  *
7  *      Pthreads-win32 - POSIX Threads Library for Win32
8  *      Copyright(C) 1998 John E. Bossom
9  *      Copyright(C) 1999,2005 Pthreads-win32 contributors
10  *
11  *      Contact Email: rpj@callisto.canberra.edu.au
12  *
13  *      The current list of contributors is contained
14  *      in the file CONTRIBUTORS included with the source
15  *      code distribution. The list can also be seen at the
16  *      following World Wide Web location:
17  *      http://sources.redhat.com/pthreads-win32/contributors.html
18  *
19  *      This library is free software; you can redistribute it and/or
20  *      modify it under the terms of the GNU Lesser General Public
21  *      License as published by the Free Software Foundation; either
22  *      version 2 of the License, or (at your option) any later version.
23  *
24  *      This library is distributed in the hope that it will be useful,
25  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
26  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
27  *      Lesser General Public License for more details.
28  *
29  *      You should have received a copy of the GNU Lesser General Public
30  *      License along with this library in the file COPYING.LIB;
31  *      if not, write to the Free Software Foundation, Inc.,
32  *      59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
33  *
34  * --------------------------------------------------------------------------
35  *
36  * Test Synopsis: Test cleanup handler does not execute (when thread is
37  * not canceled).
38  *
39  * Test Method (Validation or Falsification):
40  * -
41  *
42  * Requirements Tested:
43  * -
44  *
45  * Features Tested:
46  * -
47  *
48  * Cases Tested:
49  * -
50  *
51  * Description:
52  * -
53  *
54  * Environment:
55  * -
56  *
57  * Input:
58  * - None.
59  *
60  * Output:
61  * - File name, Line number, and failed expression on failure.
62  * - No output on success.
63  *
64  * Assumptions:
65  * - have working pthread_create, pthread_self, pthread_mutex_lock/unlock
66  *   pthread_testcancel, pthread_cancel, pthread_join
67  *
68  * Pass Criteria:
69  * - Process returns zero exit status.
70  *
71  * Fail Criteria:
72  * - Process returns non-zero exit status.
73  */
74 
75 #if defined(_MSC_VER) || defined(__cplusplus)
76 
77 #include "test.h"
78 
79 /*
80  * Create NUMTHREADS threads in addition to the Main thread.
81  */
82 enum {
83   NUMTHREADS = 10
84 };
85 
86 typedef struct bag_t_ bag_t;
87 struct bag_t_ {
88   int threadnum;
89   int started;
90   /* Add more per-thread state variables here */
91   int count;
92 };
93 
94 static bag_t threadbag[NUMTHREADS + 1];
95 
96 typedef struct {
97   int i;
98   CRITICAL_SECTION cs;
99 } sharedInt_t;
100 
101 static sharedInt_t pop_count = {0, {0}};
102 
103 static void
increment_pop_count(void * arg)104 increment_pop_count(void * arg)
105 {
106   sharedInt_t * sI = (sharedInt_t *) arg;
107 
108   EnterCriticalSection(&sI->cs);
109   sI->i++;
110   LeaveCriticalSection(&sI->cs);
111 }
112 
113 void *
mythread(void * arg)114 mythread(void * arg)
115 {
116   intptr_t result = 0;
117   bag_t * bag = (bag_t *) arg;
118 
119   assert(bag == &threadbag[bag->threadnum]);
120   assert(bag->started == 0);
121   bag->started = 1;
122 
123 #ifdef _MSC_VER
124 #pragma inline_depth(0)
125 #endif
126   pthread_cleanup_push(increment_pop_count, (void *) &pop_count);
127 
128   sched_yield();
129 
130   EnterCriticalSection(&pop_count.cs);
131   pop_count.i--;
132   LeaveCriticalSection(&pop_count.cs);
133 
134   pthread_cleanup_pop(0);
135 #ifdef _MSC_VER
136 #pragma inline_depth()
137 #endif
138 
139   return (void *) result;
140 }
141 
142 int
main()143 main()
144 {
145   int failed = 0;
146   int i;
147   pthread_t t[NUMTHREADS + 1];
148 
149   InitializeCriticalSection(&pop_count.cs);
150 
151   assert((t[0] = pthread_self()).p != NULL);
152 
153   for (i = 1; i <= NUMTHREADS; i++)
154     {
155       threadbag[i].started = 0;
156       threadbag[i].threadnum = i;
157       assert(pthread_create(&t[i], NULL, mythread, (void *) &threadbag[i]) == 0);
158     }
159 
160   /*
161    * Code to control or munipulate child threads should probably go here.
162    */
163   Sleep(1000);
164 
165   /*
166    * Standard check that all threads started.
167    */
168   for (i = 1; i <= NUMTHREADS; i++)
169     {
170       if (!threadbag[i].started)
171 	{
172 	  failed |= !threadbag[i].started;
173 	  fprintf(stderr, "Thread %d: started %d\n", i, threadbag[i].started);
174 	}
175     }
176 
177   assert(!failed);
178 
179   /*
180    * Check any results here. Set "failed" and only print output on failure.
181    */
182   failed = 0;
183   for (i = 1; i <= NUMTHREADS; i++)
184     {
185       int fail = 0;
186       intptr_t result = 0;
187 
188       assert(pthread_join(t[i], (void **) &result) == 0);
189 
190       fail = (result != 0);
191 
192       if (fail)
193 	{
194 	  fprintf(stderr, "Thread %d: started %d: result: %d\n",
195 		  i,
196 		  threadbag[i].started,
197 		  (int)result);
198 	}
199       failed = (failed || fail);
200     }
201 
202   assert(!failed);
203 
204   assert(pop_count.i == -(NUMTHREADS));
205 
206   DeleteCriticalSection(&pop_count.cs);
207 
208   /*
209    * Success.
210    */
211   return 0;
212 }
213 
214 #else /* defined(_MSC_VER) || defined(__cplusplus) */
215 
216 int
main()217 main()
218 {
219   return 0;
220 }
221 
222 #endif /* defined(_MSC_VER) || defined(__cplusplus) */
223