Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

312 lines
9.5 KiB

  1. /***
  2. *thread.c - Begin and end a thread
  3. *
  4. * Copyright (c) 1989-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * This source contains the _beginthread() and _endthread()
  8. * routines which are used to start and terminate a thread.
  9. *
  10. *Revision History:
  11. * 05-09-90 JCR Translated from ASM to C
  12. * 07-25-90 SBM Removed '32' from API names
  13. * 10-08-90 GJF New-style function declarators.
  14. * 10-09-90 GJF Thread ids are of type unsigned long.
  15. * 10-19-90 GJF Added code to set _stkhqq properly in stub().
  16. * 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
  17. * 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
  18. * 06-03-91 GJF Win32 version [_WIN32_].
  19. * 07-18-91 GJF Fixed many silly errors [_WIN32_].
  20. * 08-19-91 GJF Allow for newly created thread terminating before
  21. * _beginthread returns
  22. * 09-30-91 GJF Add per-thread initialization and termination calls
  23. * for floating point.
  24. * 01-18-92 GJF Revised try - except statement.
  25. * 02-25-92 GJF Initialize _holdrand field to 1.
  26. * 09-30-92 SRW Add WINAPI keyword to _threadstart routine
  27. * 10-30-92 GJF Error ret for CreateThread is 0 (NULL), not -1.
  28. * 02-13-93 GJF Revised to use TLS API. Also, purged Cruiser support.
  29. * 03-26-93 GJF Fixed horribly embarrassing bug: ptd->pxcptacttab
  30. * must be initialized to _XcptActTab!
  31. * 04-01-93 CFW Change try-except to __try-__except
  32. * 04-06-93 SKS Replace _CRTAPI* with __cdecl
  33. * 04-27-93 GJF Removed support for _RT_STACK, _RT_INTDIV,
  34. * _RT_INVALDISP and _RT_NONCONT.
  35. * 10-26-93 GJF Replaced PF with _PVFV (defined in internal.h).
  36. * 12-13-93 SKS Free up per-thread data using a call to _freeptd()
  37. * 01-06-94 GJF Free up _tiddata struct upon failure in _beginthread.
  38. * Also, set errno on failure.
  39. * 01-10-95 CFW Debug CRT allocs.
  40. * 04-18-95 SKS Add 5 MIPS per-thread variables.
  41. * 05-02-95 SKS Call _initptd for initialization of per-thread data.
  42. * 02-03-98 GJF Changes for Win64: use uintptr_t type for anything with
  43. * a HANDLE value.
  44. * 02-02-00 GB Modified threadstart() to prevent leaking of ptd
  45. * allocated during call to getptd while ATTACHing THREAD
  46. * in dlls.
  47. * 08-04-00 PML Set EINVAL error if thread start address null in
  48. * _beginthread (VS7#118688).
  49. * 10-16-01 GB Added fiber support
  50. * 12-11-01 BWT _getptd doesn't return NULL. Change to _getptd_noexit
  51. * and don't terminate the process if it can't be allocated
  52. * in endthreadex - just exit the thread.
  53. * 12-11-01 BWT Also, in threadstart - don't exit the process if FlsSetValue
  54. * fails - exit the thread instead - this isn't a fatal condition.
  55. *
  56. *******************************************************************************/
  57. #ifdef _MT
  58. #include <cruntime.h>
  59. #include <oscalls.h>
  60. #include <internal.h>
  61. #include <mtdll.h>
  62. #include <msdos.h>
  63. #include <malloc.h>
  64. #include <process.h>
  65. #include <stddef.h>
  66. #include <rterr.h>
  67. #include <dbgint.h>
  68. #include <errno.h>
  69. /*
  70. * Startup code for new thread.
  71. */
  72. static unsigned long WINAPI _threadstart(void *);
  73. /*
  74. * declare pointers to per-thread FP initialization and termination routines
  75. */
  76. _PVFV _FPmtinit;
  77. _PVFV _FPmtterm;
  78. /***
  79. *_beginthread() - Create a child thread
  80. *
  81. *Purpose:
  82. * Create a child thread.
  83. *
  84. *Entry:
  85. * initialcode = pointer to thread's startup code address
  86. * stacksize = size of stack
  87. * argument = argument to be passed to new thread
  88. *
  89. *Exit:
  90. * success = handle for new thread if successful
  91. *
  92. * failure = (unsigned long) -1L in case of error, errno and _doserrno
  93. * are set
  94. *
  95. *Exceptions:
  96. *
  97. *******************************************************************************/
  98. uintptr_t __cdecl _beginthread (
  99. void (__cdecl * initialcode) (void *),
  100. unsigned stacksize,
  101. void * argument
  102. )
  103. {
  104. _ptiddata ptd; /* pointer to per-thread data */
  105. uintptr_t thdl; /* thread handle */
  106. unsigned long errcode = 0L; /* Return from GetLastError() */
  107. if ( initialcode == NULL ) {
  108. errno = EINVAL;
  109. return( (uintptr_t)(-1) );
  110. }
  111. /*
  112. * Allocate and initialize a per-thread data structure for the to-
  113. * be-created thread.
  114. */
  115. if ( (ptd = _calloc_crt(1, sizeof(struct _tiddata))) == NULL )
  116. goto error_return;
  117. /*
  118. * Initialize the per-thread data
  119. */
  120. _initptd(ptd);
  121. ptd->_initaddr = (void *) initialcode;
  122. ptd->_initarg = argument;
  123. /*
  124. * Create the new thread. Bring it up in a suspended state so that
  125. * the _thandle and _tid fields are filled in before execution
  126. * starts.
  127. */
  128. if ( (ptd->_thandle = thdl = (uintptr_t)
  129. CreateThread( NULL,
  130. stacksize,
  131. _threadstart,
  132. (LPVOID)ptd,
  133. CREATE_SUSPENDED,
  134. (LPDWORD)&(ptd->_tid) ))
  135. == (uintptr_t)0 )
  136. {
  137. errcode = GetLastError();
  138. goto error_return;
  139. }
  140. /*
  141. * Start the new thread executing
  142. */
  143. if ( ResumeThread( (HANDLE)thdl ) == (DWORD)(-1) ) {
  144. errcode = GetLastError();
  145. goto error_return;
  146. }
  147. /*
  148. * Good return
  149. */
  150. return(thdl);
  151. /*
  152. * Error return
  153. */
  154. error_return:
  155. /*
  156. * Either ptd is NULL, or it points to the no-longer-necessary block
  157. * calloc-ed for the _tiddata struct which should now be freed up.
  158. */
  159. _free_crt(ptd);
  160. /*
  161. * Map the error, if necessary.
  162. */
  163. if ( errcode != 0L )
  164. _dosmaperr(errcode);
  165. return( (uintptr_t)(-1) );
  166. }
  167. /***
  168. *_threadstart() - New thread begins here
  169. *
  170. *Purpose:
  171. * The new thread begins execution here. This routine, in turn,
  172. * passes control to the user's code.
  173. *
  174. *Entry:
  175. * void *ptd = pointer to _tiddata structure for this thread
  176. *
  177. *Exit:
  178. * Never returns - terminates thread!
  179. *
  180. *Exceptions:
  181. *
  182. *******************************************************************************/
  183. static unsigned long WINAPI _threadstart (
  184. void * ptd
  185. )
  186. {
  187. _ptiddata _ptd; /* pointer to per-thread data */
  188. /*
  189. * Check if ptd is initialised during THREAD_ATTACH call to dll mains
  190. */
  191. if ( (_ptd = FLS_GETVALUE(__tlsindex)) == NULL)
  192. {
  193. /*
  194. * Stash the pointer to the per-thread data stucture in TLS
  195. */
  196. if ( !FLS_SETVALUE(__tlsindex, ptd) )
  197. ExitThread(GetLastError());
  198. }
  199. else
  200. {
  201. _ptd->_initaddr = ((_ptiddata) ptd)->_initaddr;
  202. _ptd->_initarg = ((_ptiddata) ptd)->_initarg;
  203. _ptd->_thandle = ((_ptiddata) ptd)->_thandle;
  204. _free_crt(ptd);
  205. ptd = _ptd;
  206. }
  207. /*
  208. * Call fp initialization, if necessary
  209. */
  210. if ( _FPmtinit != NULL )
  211. (*_FPmtinit)();
  212. /*
  213. * Guard call to user code with a _try - _except statement to
  214. * implement runtime errors and signal support
  215. */
  216. __try {
  217. ( (void(__cdecl *)(void *))(((_ptiddata)ptd)->_initaddr) )
  218. ( ((_ptiddata)ptd)->_initarg );
  219. _endthread();
  220. }
  221. __except ( _XcptFilter(GetExceptionCode(), GetExceptionInformation()) )
  222. {
  223. /*
  224. * Should never reach here
  225. */
  226. _exit( GetExceptionCode() );
  227. } /* end of _try - _except */
  228. /*
  229. * Never executed!
  230. */
  231. return(0L);
  232. }
  233. /***
  234. *_endthread() - Terminate the calling thread
  235. *
  236. *Purpose:
  237. *
  238. *Entry:
  239. * void
  240. *
  241. *Exit:
  242. * Never returns!
  243. *
  244. *Exceptions:
  245. *
  246. *******************************************************************************/
  247. void __cdecl _endthread (
  248. void
  249. )
  250. {
  251. _ptiddata ptd; /* pointer to thread's _tiddata struct */
  252. /*
  253. * Call fp termination, if necessary
  254. */
  255. if ( _FPmtterm != NULL )
  256. (*_FPmtterm)();
  257. ptd = _getptd_noexit();
  258. if (ptd) {
  259. /*
  260. * Close the thread handle (if there was one)
  261. */
  262. if ( ptd->_thandle != (uintptr_t)(-1) )
  263. (void) CloseHandle( (HANDLE)(ptd->_thandle) );
  264. /*
  265. * Free up the _tiddata structure & its subordinate buffers
  266. * _freeptd() will also clear the value for this thread
  267. * of the FLS variable __tlsindex.
  268. */
  269. _freeptd(ptd);
  270. }
  271. /*
  272. * Terminate the thread
  273. */
  274. ExitThread(0);
  275. }
  276. #endif /* _MT */