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

  1. /***
  2. *mlock.c - Multi-thread locking routines
  3. *
  4. *       Copyright (c) 1987-1997, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *
  8. *******************************************************************************/
  9.  
  10. #ifdef _MT
  11.  
  12. #include <cruntime.h>
  13. #include <oscalls.h>
  14. #include <internal.h>
  15. #include <mtdll.h>
  16. #include <rterr.h>
  17. #include <stddef.h>
  18. #include <malloc.h>
  19. #include <limits.h>
  20. #include <stdio.h>
  21. #include <dbgint.h>
  22.  
  23.  
  24. /*
  25.  * Local routines
  26.  */
  27. void __cdecl _lockerr_exit(char *);
  28.  
  29.  
  30. /*
  31.  * Global Data
  32.  */
  33.  
  34. /*
  35.  * Statically allocated critical section structures for _LOCKTAB_LOCK,
  36.  * _EXIT_LOCK1, _HEAP_LOCK and _SIGNAL_LOCK.
  37.  */
  38. static CRITICAL_SECTION ltlcritsect;
  39. static CRITICAL_SECTION xlcritsect;
  40. static CRITICAL_SECTION hlcritsect;
  41. static CRITICAL_SECTION sigcritsect;
  42.  
  43. /*
  44.  * Lock Table
  45.  * This table contains a pointer to the critical section management structure
  46.  * for each lock.
  47.  */
  48. PCRITICAL_SECTION _locktable[_TOTAL_LOCKS] = {
  49.         NULL,           /* 0  == no lock defined   *** OBSOLETE *** */
  50.         &sigcritsect,   /* 1  == _SIGNAL_LOCK      */
  51.         NULL,           /* 2  == _IOB_SCAN_LOCK    */
  52.         NULL,           /* 3  == _TMPNAM_LOCK      */
  53.         NULL,           /* 4  == _INPUT_LOCK       */
  54.         NULL,           /* 5  == _OUTPUT_LOCK      */
  55.         NULL,           /* 6  == _CSCANF_LOCK      */
  56.         NULL,           /* 7  == _CPRINTF_LOCK     */
  57.         NULL,           /* 8  == _CONIO_LOCK       */
  58.         &hlcritsect,    /* 9  == _HEAP_LOCK    */
  59.         NULL,           /* 10 == _BHEAP_LOCK       *** OBSOLETE *** */
  60.         NULL,           /* 11 == _TIME_LOCK    */
  61.         NULL,           /* 12 == _ENV_LOCK     */
  62.         &xlcritsect,    /* 13 == _EXIT_LOCK1       */
  63.         NULL,           /* 14 == _EXIT_LOCK2       *** OBSOLETE *** */
  64.         NULL,           /* 15 == _THREADDATA_LOCK  *** OBSOLETE *** */
  65.         NULL,           /* 16 == _POPEN_LOCK       */
  66.         <lcritsect,   /* 17 == _LOCKTAB_LOCK     */
  67.         NULL,           /* 18 == _OSFHND_LOCK      */
  68.         NULL,           /* 19 == _SETLOCALE_LOCK   */
  69.         NULL,           /* 20 == _LC_COLLATE_LOCK  *** OBSOLETE *** */
  70.         NULL,           /* 21 == _LC_CTYPE_LOCK    *** OBSOLETE *** */
  71.         NULL,           /* 22 == _LC_MONETARY_LOCK *** OBSOLETE *** */
  72.         NULL,           /* 23 == _LC_NUMERIC_LOCK  *** OBSOLETE *** */
  73.         NULL,           /* 24 == _LC_TIME_LOCK     *** OBSOLETE *** */
  74.         NULL,           /* 25 == _STREAM_LOCKS     */
  75.         NULL            /* ... */
  76.         };
  77.  
  78.  
  79. #define _FATAL  _amsg_exit(_RT_LOCK)
  80.  
  81. #ifdef _M_IX86
  82. #pragma optimize("y",off)
  83. #endif  /* _M_IX86 */
  84.  
  85. /***
  86. *_mtinitlocks() - Initialize multi-thread lock scheme
  87. *
  88. *Purpose:
  89. *       Perform whatever initialization is required for the multi-thread
  90. *       locking (synchronization) scheme. This routine should be called
  91. *       exactly once, during startup, and this must be before any requests
  92. *       are made to assert locks.
  93. *
  94. *       NOTES: In Win32, the multi-thread locks are created individually,
  95. *       each upon its first use. That is when any particular lock is asserted
  96. *       for the first time, the underlying critical section is then allocated,
  97. *       initialized and (finally) entered. This allocation and initialization
  98. *       is protected under _LOCKTAB_LOCK. It is _mtinitlocks' job to set up
  99. *       _LOCKTAB_LOCK. _EXIT_LOCK1 is also set up by _mtinitlock
  100. *
  101. *Entry:
  102. *       <none>
  103. *
  104. *Exit:
  105. *       returns on success
  106. *       calls _amsg_exit on failure
  107. *
  108. *Exceptions:
  109. *
  110. *******************************************************************************/
  111.  
  112. void __cdecl _mtinitlocks (
  113.         void
  114.         )
  115. {
  116.  
  117.  
  118.         /*
  119.          * All we need to do is initialize _LOCKTAB_LOCK and _EXIT_LOCK1.
  120.          */
  121.         InitializeCriticalSection( _locktable[_LOCKTAB_LOCK] );
  122.         InitializeCriticalSection( _locktable[_EXIT_LOCK1] );
  123.         InitializeCriticalSection( _locktable[_HEAP_LOCK] );
  124.         InitializeCriticalSection( _locktable[_SIGNAL_LOCK] );
  125.  
  126. }
  127.  
  128.  
  129. /***
  130. *_mtdeletelocks() - Delete all initialized locks
  131. *
  132. *Purpose:
  133. *       Walks _locktable[] and _lockmap, and deletes every 'lock' (i.e.,
  134. *       critical section) which has been initialized.
  135. *
  136. *       This function is intended for use in DLLs containing the C runtime
  137. *       (i.e., crtdll.dll and user DLLs built using libcmt.lib and the
  138. *       special startup objects). It is to be called from within the DLL's
  139. *       entrypoint function when that function is called with
  140. *       DLL_PROCESS_DETACH.
  141. *
  142. *Entry:
  143. *       <none>
  144. *
  145. *Exit:
  146. *
  147. *Exceptions:
  148. *       behavior undefined/unknown if a lock is being held when this routine
  149. *       is called.
  150. *
  151. *******************************************************************************/
  152.  
  153. void __cdecl _mtdeletelocks(
  154.         void
  155.         )
  156. {
  157.  
  158.         int locknum;
  159.  
  160.         for ( locknum = 0 ; locknum < _TOTAL_LOCKS ; locknum++ ) {
  161.  
  162.             /*
  163.              * If the 'lock' has been created, delete it
  164.              */
  165.             /*
  166.              * Delete the lock if it had been created
  167.              */
  168.             if ( _locktable[locknum] != NULL ) {
  169.                 if ( (locknum != _LOCKTAB_LOCK) && (locknum !=
  170.                   _EXIT_LOCK1) && (locknum != _HEAP_LOCK) &&
  171.                  (locknum != _SIGNAL_LOCK) )
  172.                 {
  173.                 /*
  174.                  * Free the memory for the CritSect after deleting
  175.                  * it.  It is okay to call free() if the heap lock
  176.                  * is kept valid until after all calls to the heap.
  177.                  */
  178.                 DeleteCriticalSection(_locktable[locknum]);
  179.                 _free_crt(_locktable[locknum]);
  180.                 }
  181.             }
  182.  
  183.         }
  184.  
  185.         /*
  186.          * Finally, clean up the special locks
  187.          */
  188.         DeleteCriticalSection( _locktable[_HEAP_LOCK] );
  189.         DeleteCriticalSection( _locktable[_EXIT_LOCK1] );
  190.         DeleteCriticalSection( _locktable[_LOCKTAB_LOCK] );
  191.         DeleteCriticalSection( _locktable[_SIGNAL_LOCK] );
  192.  
  193. }
  194.  
  195.  
  196. /***
  197. * _lock - Acquire a multi-thread lock
  198. *
  199. *Purpose:
  200. *       Note that it is legal for a thread to aquire _EXIT_LOCK1
  201. *       multiple times.
  202. *
  203. *Entry:
  204. *       locknum = number of the lock to aquire
  205. *
  206. *Exit:
  207. *
  208. *Exceptions:
  209. *
  210. *******************************************************************************/
  211.  
  212. void __cdecl _lock (
  213.         int locknum
  214.         )
  215. {
  216.  
  217.         PCRITICAL_SECTION pcs;
  218.  
  219.  
  220.         /*
  221.          * Create/open the lock, if necessary
  222.          */
  223.         if ( _locktable[locknum] == NULL ) {
  224.  
  225.             if ( (pcs = _malloc_crt(sizeof(CRITICAL_SECTION))) == NULL )
  226.                 _amsg_exit(_RT_LOCK);
  227.  
  228.             _mlock(_LOCKTAB_LOCK);  /*** WARNING: Recursive lock call ***/
  229.  
  230.             if ( _locktable[locknum] == NULL ) {
  231.                 InitializeCriticalSection(pcs);
  232.                 _locktable[locknum] = pcs;
  233.             }
  234.             else {
  235.                 _free_crt(pcs);
  236.             }
  237.  
  238.             _munlock(_LOCKTAB_LOCK);
  239.         }
  240.  
  241.         /*
  242.          * Enter the critical section.
  243.          */
  244.  
  245.         EnterCriticalSection( _locktable[locknum] );
  246.  
  247. }
  248.  
  249.  
  250. /***
  251. * _unlock - Release multi-thread lock
  252. *
  253. *Purpose:
  254. *       Note that it is legal for a thread to aquire _EXIT_LOCK1
  255. *       multiple times.
  256. *
  257. *Entry:
  258. *       locknum = number of the lock to release
  259. *
  260. *Exit:
  261. *
  262. *Exceptions:
  263. *
  264. *******************************************************************************/
  265.  
  266. void __cdecl _unlock (
  267.         int locknum
  268.         )
  269. {
  270.  
  271.         /*
  272.          * leave the critical section.
  273.          */
  274.         LeaveCriticalSection( _locktable[locknum] );
  275.  
  276. }
  277.  
  278.  
  279. #ifdef _M_IX86
  280. #pragma optimize("y",on)
  281. #endif  /* _M_IX86 */
  282.  
  283. /***
  284. *_lockerr_exit() - Write error message and die
  285. *
  286. *Purpose:
  287. *       Attempt to write out the unexpected lock error message, then terminate
  288. *       the program by a direct API call.  This function is used in place of
  289. *       amsg_exit(_RT_LOCK) when it is judged unsafe to allow further lock
  290. *       or unlock calls.
  291. *
  292. *Entry:
  293. *
  294. *Exit:
  295. *
  296. *Exceptions:
  297. *
  298. *******************************************************************************/
  299.  
  300. void __cdecl _lockerr_exit (
  301.         char *msg
  302.         )
  303. {
  304.         FatalAppExit(0, msg);       /* Die with message box */
  305.         ExitProcess(255);           /* Just die */
  306. }
  307.  
  308.  
  309. #endif  /* _MT */
  310.