home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / crt / src / tidtable.c < prev    next >
C/C++ Source or Header  |  1998-06-17  |  9KB  |  366 lines

  1. /***
  2. *tidtable.c - Access thread data table
  3. *
  4. *       Copyright (c) 1989-1997, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *       This module contains the following routines for multi-thread
  8. *       data support:
  9. *
  10. *       _mtinit     = Initialize the mthread data
  11. *       _getptd     = get the pointer to the per-thread data structure for
  12. *                       the current thread
  13. *       _freeptd    = free up a per-thread data structure and its
  14. *                       subordinate structures
  15. *       __threadid  = return thread ID for the current thread
  16. *       __threadhandle = return pseudo-handle for the current thread
  17. *
  18. *******************************************************************************/
  19.  
  20. #if defined (_MT)
  21.  
  22. # if defined(_NTSUBSET_)
  23.  
  24. #include <nt.h>
  25. #include <ntrtl.h>
  26. #include <nturtl.h>
  27. #include <ntstatus.h>
  28. #include <ntos.h>
  29. #include <fsrtl.h>
  30.  
  31. # endif /* _NTSUBSET_ */
  32.  
  33. #include <cruntime.h>
  34. #include <oscalls.h>
  35. #include <internal.h>
  36. #include <mtdll.h>
  37. #include <memory.h>
  38. #include <msdos.h>
  39. #include <rterr.h>
  40. #include <stdlib.h>
  41. #include <stddef.h>
  42. #include <dbgint.h>
  43.  
  44. unsigned long __tlsindex = 0xffffffff;
  45.  
  46.  
  47.  
  48. /****
  49. *_mtinit() - Init multi-thread data bases
  50. *
  51. *Purpose:
  52. *       (1) Call _mtinitlocks to create/open all lock semaphores.
  53. *       (2) Allocate a TLS index to hold pointers to per-thread data
  54. *           structure.
  55. *
  56. *       NOTES:
  57. *       (1) Only to be called ONCE at startup
  58. *       (2) Must be called BEFORE any mthread requests are made
  59. *
  60. *Entry:
  61. *       <NONE>
  62. *Exit:
  63. *       returns on success
  64. *       calls _amsg_exit on failure
  65. *
  66. *Uses:
  67. *       <any registers may be modified at init time>
  68. *
  69. *Exceptions:
  70. *
  71. *******************************************************************************/
  72.  
  73. int __cdecl _mtinit (
  74.         void
  75.         )
  76. {
  77.         _ptiddata ptd;
  78.  
  79.  
  80.         /*
  81.          * Initialize the mthread lock data base
  82.          */
  83.  
  84.         _mtinitlocks();
  85.  
  86.         /*
  87.          * Allocate a TLS index to maintain pointers to per-thread data
  88.          */
  89.         if ( (__tlsindex = TlsAlloc()) == 0xffffffff )
  90.             return FALSE;       /* fail to load DLL */
  91.  
  92.  
  93.         /*
  94.          * Create a per-thread data structure for this (i.e., the startup)
  95.          * thread.
  96.          */
  97.         if ( ((ptd = _calloc_crt(1, sizeof(struct _tiddata))) == NULL) ||
  98.              !TlsSetValue(__tlsindex, (LPVOID)ptd) )
  99.             return FALSE;       /* fail to load DLL */
  100.  
  101.         /*
  102.          * Initialize the per-thread data
  103.          */
  104.  
  105.         _initptd(ptd);
  106.  
  107.         ptd->_tid = GetCurrentThreadId();
  108.         ptd->_thandle = (unsigned long)(-1L);
  109.  
  110.  
  111.         return TRUE;
  112. }
  113.  
  114.  
  115. /****
  116. *_mtterm() - Clean-up multi-thread data bases
  117. *
  118. *Purpose:
  119. *       (1) Call _mtdeletelocks to free up all lock semaphores.
  120. *       (2) Free up the TLS index used to hold pointers to
  121. *           per-thread data structure.
  122. *
  123. *       NOTES:
  124. *       (1) Only to be called ONCE at termination
  125. *       (2) Must be called AFTER all mthread requests are made
  126. *
  127. *Entry:
  128. *       <NONE>
  129. *Exit:
  130. *       returns
  131. *
  132. *Uses:
  133. *
  134. *Exceptions:
  135. *
  136. *******************************************************************************/
  137.  
  138. void __cdecl _mtterm (
  139.         void
  140.         )
  141. {
  142.  
  143.  
  144.         /*
  145.          * Clean up the mthread lock data base
  146.          */
  147.  
  148.         _mtdeletelocks();
  149.  
  150.         /*
  151.          * Free up the TLS index
  152.          *
  153.          * (Set the variable __tlsindex back to the unused state (-1L).)
  154.          */
  155.  
  156.         if ( __tlsindex != 0xffffffff ) {
  157.             TlsFree(__tlsindex);
  158.             __tlsindex = 0xffffffff;
  159.         }
  160. }
  161.  
  162.  
  163.  
  164.  
  165. /***
  166. *void _initptd(_ptiddata ptd) - initialize a per-thread data structure
  167. *
  168. *Purpose:
  169. *       This routine handles all of the per-thread initialization
  170. *       which is common to _beginthread, _beginthreadex, _mtinit
  171. *       and _getptd.
  172. *
  173. *Entry:
  174. *       pointer to a per-thread data block
  175. *
  176. *Exit:
  177. *       the common fields in that block are initialized
  178. *
  179. *Exceptions:
  180. *
  181. *******************************************************************************/
  182.  
  183. void __cdecl _initptd (
  184.         _ptiddata ptd
  185.         )
  186. {
  187.         ptd->_pxcptacttab = (void *)_XcptActTab;
  188.         ptd->_holdrand = 1L;
  189.  
  190. #ifdef _M_MRX000
  191.         /*
  192.          * MIPS per-thread data
  193.          */
  194.         ptd->_MipsPtdDelta =
  195.         ptd->_MipsPtdEpsilon = -1L ;
  196. #endif  /* _M_MRX000 */
  197. }
  198.  
  199.  
  200.  
  201. /***
  202. *_ptiddata _getptd(void) - get per-thread data structure for the current thread
  203. *
  204. *Purpose:
  205. *
  206. *Entry:
  207. *       unsigned long tid
  208. *
  209. *Exit:
  210. *       success = pointer to _tiddata structure for the thread
  211. *       failure = fatal runtime exit
  212. *
  213. *Exceptions:
  214. *
  215. *******************************************************************************/
  216.  
  217. _ptiddata __cdecl _getptd (
  218.         void
  219.         )
  220. {
  221.         _ptiddata ptd;
  222.         DWORD   TL_LastError;
  223.  
  224.  
  225.         TL_LastError = GetLastError();
  226.         if ( (ptd = TlsGetValue(__tlsindex)) == NULL ) {
  227.             /*
  228.              * no per-thread data structure for this thread. try to create
  229.              * one.
  230.              */
  231.             if ( ((ptd = _calloc_crt(1, sizeof(struct _tiddata))) != NULL) &&
  232.                 TlsSetValue(__tlsindex, (LPVOID)ptd) ) {
  233.  
  234.                 /*
  235.                  * Initialize of per-thread data
  236.                  */
  237.  
  238.                 _initptd(ptd);
  239.  
  240.                 ptd->_tid = GetCurrentThreadId();
  241.                 ptd->_thandle = (unsigned long)(-1L);
  242.             }
  243.             else
  244.                 _amsg_exit(_RT_THREAD); /* write message and die */
  245.             }
  246.  
  247.         SetLastError(TL_LastError);
  248.  
  249.  
  250.         return(ptd);
  251. }
  252.  
  253.  
  254. /***
  255. *void _freeptd(_ptiddata) - free up a per-thread data structure
  256. *
  257. *Purpose:
  258. *       Called from _endthread and from a DLL thread detach handler,
  259. *       this routine frees up the per-thread buffer associated with a
  260. *       thread that is going away.  The tiddata structure itself is
  261. *       freed, but not until its subordinate buffers are freed.
  262. *
  263. *Entry:
  264. *       pointer to a per-thread data block (malloc-ed memory)
  265. *       If NULL, the pointer for the current thread is fetched.
  266. *
  267. *Exit:
  268. *
  269. *Exceptions:
  270. *
  271. *******************************************************************************/
  272.  
  273. void __cdecl _freeptd (
  274.         _ptiddata ptd
  275.         )
  276. {
  277.  
  278.  
  279.         /*
  280.          * Do nothing unless per-thread data has been allocated for this module!
  281.          */
  282.  
  283.         if ( __tlsindex != 0xFFFFFFFF ) {
  284.             /*
  285.              * if parameter "ptd" is NULL, get the per-thread data pointer
  286.              * Must NOT call _getptd because it will allocate one if none exists!
  287.              */
  288.  
  289.             if ( ! ptd )
  290.                 ptd = TlsGetValue(__tlsindex );
  291.  
  292.             /*
  293.              * Free up the _tiddata structure & its malloc-ed buffers.
  294.              */
  295.  
  296.             if ( ptd ) {
  297.                 if(ptd->_errmsg)
  298.                     _free_crt((void *)ptd->_errmsg);
  299.  
  300.                 if(ptd->_namebuf0)
  301.                     _free_crt((void *)ptd->_namebuf0);
  302.  
  303.                 if(ptd->_namebuf1)
  304.                     _free_crt((void *)ptd->_namebuf1);
  305.  
  306.                 if(ptd->_asctimebuf)
  307.                     _free_crt((void *)ptd->_asctimebuf);
  308.  
  309.                 if(ptd->_gmtimebuf)
  310.                     _free_crt((void *)ptd->_gmtimebuf);
  311.  
  312.                 if(ptd->_cvtbuf)
  313.                     _free_crt((void *)ptd->_cvtbuf);
  314.  
  315.                                 if (ptd->_pxcptacttab != _XcptActTab)
  316.                                         _free_crt((void *)ptd->_pxcptacttab);
  317.  
  318.                 _free_crt((void *)ptd);
  319.             }
  320.  
  321.             /*
  322.              * Zero out the one pointer to the per-thread data block
  323.              */
  324.  
  325.             TlsSetValue(__tlsindex, (LPVOID)0);
  326.         }
  327.  
  328.  
  329. }
  330.  
  331.  
  332.  
  333. /***
  334. *__threadid()     - Returns current thread ID
  335. *__threadhandle() - Returns "pseudo-handle" for current thread
  336. *
  337. *Purpose:
  338. *       The two function are simply do-nothing wrappers for the corresponding
  339. *       Win32 APIs (GetCurrentThreadId and GetCurrentThread, respectively).
  340. *
  341. *Entry:
  342. *       void
  343. *
  344. *Exit:
  345. *       thread ID value
  346. *
  347. *Exceptions:
  348. *
  349. *******************************************************************************/
  350.  
  351. _CRTIMP unsigned long __cdecl __threadid (
  352.         void
  353.         )
  354. {
  355.         return( GetCurrentThreadId() );
  356. }
  357.  
  358. _CRTIMP unsigned long __cdecl __threadhandle(
  359.         void
  360.         )
  361. {
  362.         return( (unsigned long)GetCurrentThread() );
  363. }
  364.  
  365. #endif  /* defined (_MT) */
  366.