/[pcsx2_0.9.7]/trunk/3rdparty/w32pthreads/ptw32_threadStart.c
ViewVC logotype

Contents of /trunk/3rdparty/w32pthreads/ptw32_threadStart.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 273 - (show annotations) (download)
Fri Nov 12 01:10:22 2010 UTC (9 years, 9 months ago) by william
File MIME type: text/plain
File size: 10174 byte(s)
Auto Commited Import of: pcsx2-0.9.7-DEBUG (upstream: v0.9.7.4013 local: v0.9.7.197-latest) in ./trunk
1 /*
2 * ptw32_threadStart.c
3 *
4 * Description:
5 * This translation unit implements routines which are private to
6 * the implementation and may be used throughout it.
7 *
8 * --------------------------------------------------------------------------
9 *
10 * Pthreads-win32 - POSIX Threads Library for Win32
11 * Copyright(C) 1998 John E. Bossom
12 * Copyright(C) 1999,2005 Pthreads-win32 contributors
13 *
14 * Contact Email: rpj@callisto.canberra.edu.au
15 *
16 * The current list of contributors is contained
17 * in the file CONTRIBUTORS included with the source
18 * code distribution. The list can also be seen at the
19 * following World Wide Web location:
20 * http://sources.redhat.com/pthreads-win32/contributors.html
21 *
22 * This library is free software; you can redistribute it and/or
23 * modify it under the terms of the GNU Lesser General Public
24 * License as published by the Free Software Foundation; either
25 * version 2 of the License, or (at your option) any later version.
26 *
27 * This library is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
30 * Lesser General Public License for more details.
31 *
32 * You should have received a copy of the GNU Lesser General Public
33 * License along with this library in the file COPYING.LIB;
34 * if not, write to the Free Software Foundation, Inc.,
35 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
36 */
37
38 #include "ptw32pch.h"
39 #include <assert.h>
40
41 // This is a "safe" cleanup handler for the cancel optimization. It ensures
42 // the testcancel_enable flag gets cleared even when threads commit grotesque
43 // exceptions.
44
45 static void
46 _cleanup_testcancel_optimization( void* specific )
47 {
48 ptw32_thread_t * sp = (ptw32_thread_t*)specific; //(ptw32_thread_t *)pthread_getspecific (ptw32_selfThreadKey);
49 if( sp == NULL ) return;
50
51 pthread_mutex_lock (&sp->cancelLock);
52 if( sp->cancelType == PTHREAD_CANCEL_DEFERRED )
53 {
54 if( sp->state == PThreadStateCancelPending || sp->state == PThreadStateCanceling )
55 {
56 int result = _InterlockedDecrement( &ptw32_testcancel_enable );
57 assert( result >= 0 );
58 sp->state = PThreadStateCanceling;
59 }
60 else if( sp->state == PThreadStateRunning )
61 {
62 // We need to prevent other threads, which may try to cancel this thread
63 // in parallel to it's cancellation here, from incrementing the cancel_enable flag.
64 // (and without clobbering the StateException, if that's already been set)
65
66 sp->state = PThreadStateLast;
67 }
68 else
69 {
70 assert(0);
71 }
72 }
73 pthread_mutex_unlock (&sp->cancelLock);
74 }
75
76 #ifdef __CLEANUP_SEH
77
78 static DWORD
79 ExceptionFilter (EXCEPTION_POINTERS * ep, DWORD * ei)
80 {
81 switch (ep->ExceptionRecord->ExceptionCode)
82 {
83 case EXCEPTION_PTW32_SERVICES:
84 {
85 DWORD param;
86 DWORD numParams = ep->ExceptionRecord->NumberParameters;
87
88 numParams = (numParams > 3) ? 3 : numParams;
89
90 for (param = 0; param < numParams; param++)
91 {
92 ei[param] = ep->ExceptionRecord->ExceptionInformation[param];
93 }
94
95 return EXCEPTION_EXECUTE_HANDLER;
96 break;
97 }
98 default:
99 {
100 /*
101 * A system unexpected exception has occurred running the user's
102 * routine. We need to cleanup before letting the exception
103 * out of thread scope.
104 */
105
106 // Air Says: No we don't. If a structured exception makes it this far, the program is
107 // screwed anyway (will cause a GPF / close program dialog to the user) and so a little lost
108 // cleanup isn't going to matter anyway. Furthermore, no other stack objects are
109 // getting unwound, so if anything in the User destroy routines are dependent on other
110 // stack objects being unwound, it'll cause a secondary premature crash which can confuse
111 // debugging efforts. There is a reason microsoft recommends *not* doing much of anything
112 // from the context of an exception filter... --air
113
114 //pthread_t self = pthread_self ();
115 //(void) pthread_mutex_destroy (&((ptw32_thread_t *)self.p)->cancelLock);
116 //ptw32_callUserDestroyRoutines (self);
117
118 return EXCEPTION_CONTINUE_SEARCH;
119 break;
120 }
121 }
122 }
123
124 #elif defined(__CLEANUP_CXX)
125
126 #if defined(_MSC_VER)
127 # include <eh.h>
128 #elif defined(__WATCOMC__)
129 # include <eh.h>
130 # include <exceptio.h>
131 typedef terminate_handler
132 terminate_function;
133 #else
134 # if defined(__GNUC__) && __GNUC__ < 3
135 # include <new.h>
136 # else
137 # include <new>
138 using
139 std::terminate_handler;
140 using
141 std::terminate;
142 using
143 std::set_terminate;
144 # endif
145 typedef terminate_handler
146 terminate_function;
147 #endif
148
149 static terminate_function
150 ptw32_oldTerminate;
151
152 void
153 ptw32_terminate ()
154 {
155 set_terminate (ptw32_oldTerminate);
156 (void) pthread_win32_thread_detach_np ();
157 terminate ();
158 }
159
160 #endif
161
162 #if ! defined (__MINGW32__) || (defined (__MSVCRT__) && ! defined (__DMC__))
163 unsigned
164 __stdcall
165 #else
166 void
167 #endif
168 ptw32_threadStart (void *vthreadParms)
169 {
170 ThreadParms * threadParms = (ThreadParms *) vthreadParms;
171 pthread_t self;
172 ptw32_thread_t * sp;
173 void *(*start) (void *);
174 void * arg;
175
176 #ifdef __CLEANUP_SEH
177 DWORD
178 ei[] = { 0, 0, 0 };
179 #endif
180
181 #ifdef __CLEANUP_C
182 int setjmp_rc;
183 #endif
184
185 void * status = (void *) 0;
186
187 self = threadParms->tid;
188 sp = (ptw32_thread_t *) self.p;
189 start = threadParms->start;
190 arg = threadParms->arg;
191
192 free (threadParms);
193
194 #if defined (__MINGW32__) && ! defined (__MSVCRT__)
195 /*
196 * beginthread does not return the thread id and is running
197 * before it returns us the thread handle, and so we do it here.
198 */
199 sp->thread = GetCurrentThreadId ();
200 /*
201 * Here we're using cancelLock as a general-purpose lock
202 * to make the new thread wait until the creating thread
203 * has the new handle.
204 */
205 if (pthread_mutex_lock (&sp->cancelLock) == 0)
206 {
207 (void) pthread_mutex_unlock (&sp->cancelLock);
208 }
209 #endif
210
211 pthread_setspecific (ptw32_selfThreadKey, sp);
212
213 sp->state = PThreadStateRunning;
214
215 #ifdef __CLEANUP_SEH
216
217 __try
218 {
219 /*
220 * Run the caller's routine;
221 */
222 pthread_cleanup_push( _cleanup_testcancel_optimization, sp );
223 status = sp->exitStatus = (*start) (arg);
224 pthread_cleanup_pop( 1 );
225
226 #ifdef _UWIN
227 if (--pthread_count <= 0)
228 exit (0);
229 #endif
230
231 }
232 __except (ExceptionFilter (GetExceptionInformation (), ei))
233 {
234 switch (ei[0])
235 {
236 case PTW32_EPS_CANCEL:
237 status = sp->exitStatus = PTHREAD_CANCELED;
238 #ifdef _UWIN
239 if (--pthread_count <= 0)
240 exit (0);
241 #endif
242 break;
243 case PTW32_EPS_EXIT:
244 status = sp->exitStatus;
245 break;
246 default:
247 status = sp->exitStatus = PTHREAD_CANCELED;
248 break;
249 }
250 }
251
252 #else /* __CLEANUP_SEH */
253
254 #ifdef __CLEANUP_C
255
256 setjmp_rc = setjmp (sp->start_mark);
257
258 if (0 == setjmp_rc)
259 {
260
261 /*
262 * Run the caller's routine;
263 */
264 status = sp->exitStatus = (*start) (arg);
265 }
266 else
267 {
268 switch (setjmp_rc)
269 {
270 case PTW32_EPS_CANCEL:
271 status = sp->exitStatus = PTHREAD_CANCELED;
272 break;
273 case PTW32_EPS_EXIT:
274 status = sp->exitStatus;
275 break;
276 default:
277 status = sp->exitStatus = PTHREAD_CANCELED;
278 break;
279 }
280 }
281
282 #else /* __CLEANUP_C */
283
284 #ifdef __CLEANUP_CXX
285
286 ptw32_oldTerminate = set_terminate (&ptw32_terminate);
287
288 try
289 {
290 /*
291 * Run the caller's routine in a nested try block so that we
292 * can run the user's terminate function, which may call
293 * pthread_exit() or be canceled.
294 */
295 try
296 {
297 status = sp->exitStatus = (*start) (arg);
298 }
299 catch (ptw32_exception &)
300 {
301 /*
302 * Pass these through to the outer block.
303 */
304 throw;
305 }
306 catch (...)
307 {
308 /*
309 * We want to run the user's terminate function if supplied.
310 * That function may call pthread_exit() or be canceled, which will
311 * be handled by the outer try block.
312 *
313 * ptw32_terminate() will be called if there is no user
314 * supplied function.
315 */
316
317 terminate_function
318 term_func = set_terminate (0);
319 set_terminate (term_func);
320
321 if (term_func != 0)
322 {
323 term_func ();
324 }
325
326 throw;
327 }
328 }
329 catch (ptw32_exception_cancel &)
330 {
331 /*
332 * Thread was canceled.
333 */
334 status = sp->exitStatus = PTHREAD_CANCELED;
335 }
336 catch (ptw32_exception_exit &)
337 {
338 /*
339 * Thread was exited via pthread_exit().
340 */
341 status = sp->exitStatus;
342 }
343 catch (...)
344 {
345 /*
346 * A system unexpected exception has occurred running the user's
347 * terminate routine. We get control back within this block - cleanup
348 * and release the exception out of thread scope.
349 */
350 status = sp->exitStatus = PTHREAD_CANCELED;
351 (void) pthread_mutex_lock (&sp->cancelLock);
352 sp->state = PThreadStateException;
353 (void) pthread_mutex_unlock (&sp->cancelLock);
354 (void) pthread_win32_thread_detach_np ();
355 (void) set_terminate (ptw32_oldTerminate);
356 throw;
357
358 /*
359 * Never reached.
360 */
361 }
362
363 (void) set_terminate (ptw32_oldTerminate);
364
365 #else
366
367 #error ERROR [__FILE__, line __LINE__]: Cleanup type undefined.
368
369 #endif /* __CLEANUP_CXX */
370 #endif /* __CLEANUP_C */
371 #endif /* __CLEANUP_SEH */
372
373 //_cleanup_testcancel_optimization();
374
375 #if defined(PTW32_STATIC_LIB)
376 /*
377 * We need to cleanup the pthread now if we have
378 * been statically linked, in which case the cleanup
379 * in dllMain won't get done. Joinable threads will
380 * only be partially cleaned up and must be fully cleaned
381 * up by pthread_join() or pthread_detach().
382 *
383 * Note: if this library has been statically linked,
384 * implicitly created pthreads (those created
385 * for Win32 threads which have called pthreads routines)
386 * must be cleaned up explicitly by the application
387 * (by calling pthread_win32_thread_detach_np()).
388 * For the dll, dllMain will do the cleanup automatically.
389 */
390 (void) pthread_win32_thread_detach_np ();
391 #endif
392
393 #if ! defined (__MINGW32__) || defined (__MSVCRT__) || defined (__DMC__)
394 _endthreadex ((unsigned) status);
395 #else
396 _endthread ();
397 #endif
398
399 /*
400 * Never reached.
401 */
402
403 #if ! defined (__MINGW32__) || defined (__MSVCRT__) || defined (__DMC__)
404 return (unsigned) status;
405 #endif
406
407 } /* ptw32_threadStart */

  ViewVC Help
Powered by ViewVC 1.1.22