5 * This translation unit implements routines which are private to
6 * the implementation and may be used throughout it.
8 * --------------------------------------------------------------------------
10 * Pthreads-win32 - POSIX Threads Library for Win32
11 * Copyright(C) 1998 John E. Bossom
12 * Copyright(C) 1999,2005 Pthreads-win32 contributors
14 * Contact Email: rpj@callisto.canberra.edu.au
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
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.
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.
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
39 #include "implement.h"
42 #if defined(__CLEANUP_C)
46 #if defined(__CLEANUP_SEH)
49 ExceptionFilter (EXCEPTION_POINTERS
* ep
, DWORD
* ei
)
51 switch (ep
->ExceptionRecord
->ExceptionCode
)
53 case EXCEPTION_PTW32_SERVICES
:
56 DWORD numParams
= ep
->ExceptionRecord
->NumberParameters
;
58 numParams
= (numParams
> 3) ? 3 : numParams
;
60 for (param
= 0; param
< numParams
; param
++)
62 ei
[param
] = ep
->ExceptionRecord
->ExceptionInformation
[param
];
65 return EXCEPTION_EXECUTE_HANDLER
;
71 * A system unexpected exception has occurred running the user's
72 * routine. We need to cleanup before letting the exception
73 * out of thread scope.
75 pthread_t self
= pthread_self ();
77 ptw32_callUserDestroyRoutines (self
);
79 return EXCEPTION_CONTINUE_SEARCH
;
85 #elif defined(__CLEANUP_CXX)
89 #elif defined(__WATCOMC__)
91 # include <exceptio.h>
92 typedef terminate_handler
95 # if defined(__GNUC__) && __GNUC__ < 3
100 std::terminate_handler
;
106 typedef terminate_handler
110 static terminate_function
116 set_terminate (ptw32_oldTerminate
);
117 (void) pthread_win32_thread_detach_np ();
123 #if ! (defined(__MINGW64__) || defined(__MINGW32__)) || (defined (__MSVCRT__) && ! defined (__DMC__))
129 ptw32_threadStart (void *vthreadParms
)
131 ThreadParms
* threadParms
= (ThreadParms
*) vthreadParms
;
134 void * (PTW32_CDECL
*start
) (void *);
137 #if defined(__CLEANUP_SEH)
142 #if defined(__CLEANUP_C)
146 ptw32_mcs_local_node_t stateLock
;
147 void * status
= (void *) 0;
149 self
= threadParms
->tid
;
150 sp
= (ptw32_thread_t
*) self
.p
;
151 start
= threadParms
->start
;
152 arg
= threadParms
->arg
;
156 #if (defined(__MINGW64__) || defined(__MINGW32__)) && ! defined (__MSVCRT__)
158 * beginthread does not return the thread id and is running
159 * before it returns us the thread handle, and so we do it here.
161 sp
->thread
= GetCurrentThreadId ();
163 * Here we're using stateLock as a general-purpose lock
164 * to make the new thread wait until the creating thread
165 * has the new handle.
167 ptw32_mcs_lock_acquire (&sp
->stateLock
, &stateLock
);
168 pthread_setspecific (ptw32_selfThreadKey
, sp
);
170 pthread_setspecific (ptw32_selfThreadKey
, sp
);
171 ptw32_mcs_lock_acquire (&sp
->stateLock
, &stateLock
);
174 sp
->state
= PThreadStateRunning
;
175 ptw32_mcs_lock_release (&stateLock
);
177 #if defined(__CLEANUP_SEH)
182 * Run the caller's routine;
184 status
= sp
->exitStatus
= (*start
) (arg
);
185 sp
->state
= PThreadStateExiting
;
188 if (--pthread_count
<= 0)
193 __except (ExceptionFilter (GetExceptionInformation (), ei
))
197 case PTW32_EPS_CANCEL
:
198 status
= sp
->exitStatus
= PTHREAD_CANCELED
;
200 if (--pthread_count
<= 0)
205 status
= sp
->exitStatus
;
208 status
= sp
->exitStatus
= PTHREAD_CANCELED
;
213 #else /* __CLEANUP_SEH */
215 #if defined(__CLEANUP_C)
217 setjmp_rc
= setjmp (sp
->start_mark
);
223 * Run the caller's routine;
225 status
= sp
->exitStatus
= (*start
) (arg
);
226 sp
->state
= PThreadStateExiting
;
232 case PTW32_EPS_CANCEL
:
233 status
= sp
->exitStatus
= PTHREAD_CANCELED
;
236 status
= sp
->exitStatus
;
239 status
= sp
->exitStatus
= PTHREAD_CANCELED
;
244 #else /* __CLEANUP_C */
246 #if defined(__CLEANUP_CXX)
248 ptw32_oldTerminate
= set_terminate (&ptw32_terminate
);
253 * Run the caller's routine in a nested try block so that we
254 * can run the user's terminate function, which may call
255 * pthread_exit() or be canceled.
259 status
= sp
->exitStatus
= (*start
) (arg
);
260 sp
->state
= PThreadStateExiting
;
262 catch (ptw32_exception
&)
265 * Pass these through to the outer block.
272 * We want to run the user's terminate function if supplied.
273 * That function may call pthread_exit() or be canceled, which will
274 * be handled by the outer try block.
276 * ptw32_terminate() will be called if there is no user
280 term_func
= set_terminate (0);
281 set_terminate (term_func
);
290 catch (ptw32_exception_cancel
&)
293 * Thread was canceled.
295 status
= sp
->exitStatus
= PTHREAD_CANCELED
;
297 catch (ptw32_exception_exit
&)
300 * Thread was exited via pthread_exit().
302 status
= sp
->exitStatus
;
307 * A system unexpected exception has occurred running the user's
308 * terminate routine. We get control back within this block
309 * and exit with a substitute status. If the thread was not
310 * cancelled then this indicates the unhandled exception.
312 status
= sp
->exitStatus
= PTHREAD_CANCELED
;
315 (void) set_terminate (ptw32_oldTerminate
);
319 #error ERROR [__FILE__, line __LINE__]: Cleanup type undefined.
321 #endif /* __CLEANUP_CXX */
322 #endif /* __CLEANUP_C */
323 #endif /* __CLEANUP_SEH */
325 #if defined(PTW32_STATIC_LIB)
327 * We need to cleanup the pthread now if we have
328 * been statically linked, in which case the cleanup
329 * in dllMain won't get done. Joinable threads will
330 * only be partially cleaned up and must be fully cleaned
331 * up by pthread_join() or pthread_detach().
333 * Note: if this library has been statically linked,
334 * implicitly created pthreads (those created
335 * for Win32 threads which have called pthreads routines)
336 * must be cleaned up explicitly by the application
337 * (by calling pthread_win32_thread_detach_np()).
338 * For the dll, dllMain will do the cleanup automatically.
340 (void) pthread_win32_thread_detach_np ();
343 #if ! (defined(__MINGW64__) || defined(__MINGW32__)) || defined (__MSVCRT__) || defined (__DMC__)
344 _endthreadex ((unsigned)(size_t) status
);
353 #if ! (defined(__MINGW64__) || defined(__MINGW32__)) || defined (__MSVCRT__) || defined (__DMC__)
354 return (unsigned)(size_t) status
;
357 } /* ptw32_threadStart */