ptw32_threadStart.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  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: [email protected]
  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. #include "pthread.h"
  38. #include "implement.h"
  39. #include <stdio.h>
  40. #if defined(__CLEANUP_C)
  41. # include <setjmp.h>
  42. #endif
  43. #if defined(__CLEANUP_SEH)
  44. static DWORD
  45. ExceptionFilter (EXCEPTION_POINTERS * ep, DWORD * ei)
  46. {
  47. switch (ep->ExceptionRecord->ExceptionCode)
  48. {
  49. case EXCEPTION_PTW32_SERVICES:
  50. {
  51. DWORD param;
  52. DWORD numParams = ep->ExceptionRecord->NumberParameters;
  53. numParams = (numParams > 3) ? 3 : numParams;
  54. for (param = 0; param < numParams; param++)
  55. {
  56. ei[param] = ep->ExceptionRecord->ExceptionInformation[param];
  57. }
  58. return EXCEPTION_EXECUTE_HANDLER;
  59. break;
  60. }
  61. default:
  62. {
  63. /*
  64. * A system unexpected exception has occurred running the user's
  65. * routine. We need to cleanup before letting the exception
  66. * out of thread scope.
  67. */
  68. pthread_t self = pthread_self ();
  69. ptw32_callUserDestroyRoutines (self);
  70. return EXCEPTION_CONTINUE_SEARCH;
  71. break;
  72. }
  73. }
  74. }
  75. #elif defined(__CLEANUP_CXX)
  76. #if defined(_MSC_VER)
  77. # include <eh.h>
  78. #elif defined(__WATCOMC__)
  79. # include <eh.h>
  80. # include <exceptio.h>
  81. typedef terminate_handler
  82. terminate_function;
  83. #else
  84. # if defined(__GNUC__) && __GNUC__ < 3
  85. # include <new.h>
  86. # else
  87. # include <new>
  88. using
  89. std::terminate_handler;
  90. using
  91. std::terminate;
  92. using
  93. std::set_terminate;
  94. # endif
  95. typedef terminate_handler
  96. terminate_function;
  97. #endif
  98. static terminate_function
  99. ptw32_oldTerminate;
  100. void
  101. ptw32_terminate ()
  102. {
  103. set_terminate (ptw32_oldTerminate);
  104. (void) pthread_win32_thread_detach_np ();
  105. terminate ();
  106. }
  107. #endif
  108. #if ! (defined(__MINGW64__) || defined(__MINGW32__)) || (defined (__MSVCRT__) && ! defined (__DMC__))
  109. unsigned
  110. __stdcall
  111. #else
  112. void
  113. #endif
  114. ptw32_threadStart (void *vthreadParms)
  115. {
  116. ThreadParms * threadParms = (ThreadParms *) vthreadParms;
  117. pthread_t self;
  118. ptw32_thread_t * sp;
  119. void * (PTW32_CDECL *start) (void *);
  120. void * arg;
  121. #if defined(__CLEANUP_SEH)
  122. DWORD
  123. ei[] = { 0, 0, 0 };
  124. #endif
  125. #if defined(__CLEANUP_C)
  126. int setjmp_rc;
  127. #endif
  128. ptw32_mcs_local_node_t stateLock;
  129. void * status = (void *) 0;
  130. self = threadParms->tid;
  131. sp = (ptw32_thread_t *) self.p;
  132. start = threadParms->start;
  133. arg = threadParms->arg;
  134. free (threadParms);
  135. #if (defined(__MINGW64__) || defined(__MINGW32__)) && ! defined (__MSVCRT__)
  136. /*
  137. * beginthread does not return the thread id and is running
  138. * before it returns us the thread handle, and so we do it here.
  139. */
  140. sp->thread = GetCurrentThreadId ();
  141. /*
  142. * Here we're using stateLock as a general-purpose lock
  143. * to make the new thread wait until the creating thread
  144. * has the new handle.
  145. */
  146. ptw32_mcs_lock_acquire (&sp->stateLock, &stateLock);
  147. pthread_setspecific (ptw32_selfThreadKey, sp);
  148. #else
  149. pthread_setspecific (ptw32_selfThreadKey, sp);
  150. ptw32_mcs_lock_acquire (&sp->stateLock, &stateLock);
  151. #endif
  152. sp->state = PThreadStateRunning;
  153. ptw32_mcs_lock_release (&stateLock);
  154. #if defined(__CLEANUP_SEH)
  155. __try
  156. {
  157. /*
  158. * Run the caller's routine;
  159. */
  160. status = sp->exitStatus = (*start) (arg);
  161. sp->state = PThreadStateExiting;
  162. #if defined(_UWIN)
  163. if (--pthread_count <= 0)
  164. exit (0);
  165. #endif
  166. }
  167. __except (ExceptionFilter (GetExceptionInformation (), ei))
  168. {
  169. switch (ei[0])
  170. {
  171. case PTW32_EPS_CANCEL:
  172. status = sp->exitStatus = PTHREAD_CANCELED;
  173. #if defined(_UWIN)
  174. if (--pthread_count <= 0)
  175. exit (0);
  176. #endif
  177. break;
  178. case PTW32_EPS_EXIT:
  179. status = sp->exitStatus;
  180. break;
  181. default:
  182. status = sp->exitStatus = PTHREAD_CANCELED;
  183. break;
  184. }
  185. }
  186. #else /* __CLEANUP_SEH */
  187. #if defined(__CLEANUP_C)
  188. setjmp_rc = setjmp (sp->start_mark);
  189. if (0 == setjmp_rc)
  190. {
  191. /*
  192. * Run the caller's routine;
  193. */
  194. status = sp->exitStatus = (*start) (arg);
  195. sp->state = PThreadStateExiting;
  196. }
  197. else
  198. {
  199. switch (setjmp_rc)
  200. {
  201. case PTW32_EPS_CANCEL:
  202. status = sp->exitStatus = PTHREAD_CANCELED;
  203. break;
  204. case PTW32_EPS_EXIT:
  205. status = sp->exitStatus;
  206. break;
  207. default:
  208. status = sp->exitStatus = PTHREAD_CANCELED;
  209. break;
  210. }
  211. }
  212. #else /* __CLEANUP_C */
  213. #if defined(__CLEANUP_CXX)
  214. ptw32_oldTerminate = set_terminate (&ptw32_terminate);
  215. try
  216. {
  217. /*
  218. * Run the caller's routine in a nested try block so that we
  219. * can run the user's terminate function, which may call
  220. * pthread_exit() or be canceled.
  221. */
  222. try
  223. {
  224. status = sp->exitStatus = (*start) (arg);
  225. sp->state = PThreadStateExiting;
  226. }
  227. catch (ptw32_exception &)
  228. {
  229. /*
  230. * Pass these through to the outer block.
  231. */
  232. throw;
  233. }
  234. catch (...)
  235. {
  236. /*
  237. * We want to run the user's terminate function if supplied.
  238. * That function may call pthread_exit() or be canceled, which will
  239. * be handled by the outer try block.
  240. *
  241. * ptw32_terminate() will be called if there is no user
  242. * supplied function.
  243. */
  244. terminate_function
  245. term_func = set_terminate (0);
  246. set_terminate (term_func);
  247. if (term_func != 0)
  248. {
  249. term_func ();
  250. }
  251. throw;
  252. }
  253. }
  254. catch (ptw32_exception_cancel &)
  255. {
  256. /*
  257. * Thread was canceled.
  258. */
  259. status = sp->exitStatus = PTHREAD_CANCELED;
  260. }
  261. catch (ptw32_exception_exit &)
  262. {
  263. /*
  264. * Thread was exited via pthread_exit().
  265. */
  266. status = sp->exitStatus;
  267. }
  268. catch (...)
  269. {
  270. /*
  271. * A system unexpected exception has occurred running the user's
  272. * terminate routine. We get control back within this block
  273. * and exit with a substitute status. If the thread was not
  274. * cancelled then this indicates the unhandled exception.
  275. */
  276. status = sp->exitStatus = PTHREAD_CANCELED;
  277. }
  278. (void) set_terminate (ptw32_oldTerminate);
  279. #else
  280. #error ERROR [__FILE__, line __LINE__]: Cleanup type undefined.
  281. #endif /* __CLEANUP_CXX */
  282. #endif /* __CLEANUP_C */
  283. #endif /* __CLEANUP_SEH */
  284. #if defined(PTW32_STATIC_LIB)
  285. /*
  286. * We need to cleanup the pthread now if we have
  287. * been statically linked, in which case the cleanup
  288. * in dllMain won't get done. Joinable threads will
  289. * only be partially cleaned up and must be fully cleaned
  290. * up by pthread_join() or pthread_detach().
  291. *
  292. * Note: if this library has been statically linked,
  293. * implicitly created pthreads (those created
  294. * for Win32 threads which have called pthreads routines)
  295. * must be cleaned up explicitly by the application
  296. * (by calling pthread_win32_thread_detach_np()).
  297. * For the dll, dllMain will do the cleanup automatically.
  298. */
  299. (void) pthread_win32_thread_detach_np ();
  300. #endif
  301. #if ! (defined(__MINGW64__) || defined(__MINGW32__)) || defined (__MSVCRT__) || defined (__DMC__)
  302. _endthreadex ((unsigned)(size_t) status);
  303. #else
  304. _endthread ();
  305. #endif
  306. /*
  307. * Never reached.
  308. */
  309. #if ! (defined(__MINGW64__) || defined(__MINGW32__)) || defined (__MSVCRT__) || defined (__DMC__)
  310. return (unsigned)(size_t) status;
  311. #endif
  312. } /* ptw32_threadStart */