diff options
Diffstat (limited to 'private/crt32/startup/mlock.c')
-rw-r--r-- | private/crt32/startup/mlock.c | 382 |
1 files changed, 382 insertions, 0 deletions
diff --git a/private/crt32/startup/mlock.c b/private/crt32/startup/mlock.c new file mode 100644 index 000000000..8c8cf33ea --- /dev/null +++ b/private/crt32/startup/mlock.c @@ -0,0 +1,382 @@ +#ifdef MTHREAD + +/*** +*mlock.c - Multi-thread locking routines +* +* Copyright (c) 1987-1993, Microsoft Corporation. All rights reserved. +* +*Purpose: +* +*Revision History: +* 05-07-90 JCR Module created. +* 06-04-90 GJF Changed error message interface. +* 08-08-90 GJF Removed 32 from API names. +* 08-08-90 SBM _lockmap no longer 8 times required size +* 10-08-90 GJF New-style function declarators. Removed questionable +* return statements from void functions (weren't needed +* and the compiler was bitching). +* 10-09-90 GJF Thread ids are unsigned longs. +* 06-06-91 GJF Adapted for Win32 [_WIN32_]. +* 09-29-91 GJF Fixed infinite recursion problem with DEBUG version +* of _lock [_WIN32_]. +* 03-06-92 GJF Removed _[un]lock_fh() and _[un]lock_stream for Win32 +* targets. +* 05-28-92 GJF Added _mtdeletelocks() for Win32 for DLLs with contain +* the C runtime (e.g., crtdll.dll). +* 10-06-92 SRW Make _locktable an array of PCRITICAL_SECTION pointers +* instead of structures. Allocate each critical section +* as it is needed. +* 02-25-93 GJF Substantially revised. Restored static critical section +* structures for some locks. Replaced bit-array scheme +* of keeping track of locks. Removed Cruiser support and +* replaced obsolete DEBUG code. +* 03-03-93 GJF Made CRITICAL_SECTION structure for _HEAP_LOCK static. +* 03-08-93 SKS Fix ptr use error in DEBUG version of _mtdeletelocks +* 03-08-93 SKS Fix deletion of the special critical sections, +* especially the heap lock. +* 05-05-93 GJF Turned DEBUG code off. +* 06-03-93 SRW Disable FPO optimizations for this file so it can call +* CriticalSection routines on a checked build even though +* the C Runtimes are compiled free. +* +*******************************************************************************/ + +#include <cruntime.h> +#include <oscalls.h> +#include <internal.h> +#include <os2dll.h> +#include <rterr.h> +#include <stddef.h> +#include <malloc.h> +#include <limits.h> + + +/* + * Local routines + */ +void _CRTAPI3 _lockerr_exit(char *); + + +/* + * Global Data + */ + +/* + * Statically allocated critical section structures for _LOCKTAB_LOCK, + * _EXIT_LOCK1 and _HEAP_LOCK. + */ +static CRITICAL_SECTION ltlcritsect; +static CRITICAL_SECTION xlcritsect; +static CRITICAL_SECTION hlcritsect; + +/* + * Lock Table + * This table contains a pointer to the critical section management structure + * for each lock. + */ +PCRITICAL_SECTION _locktable[_TOTAL_LOCKS] = { + NULL, /* 0 == no lock defined *** OBSOLETE *** */ + NULL, /* 1 == _SIGNAL_LOCK */ + NULL, /* 2 == _IOB_SCAN_LOCK */ + NULL, /* 3 == _TMPNAM_LOCK */ + NULL, /* 4 == _INPUT_LOCK */ + NULL, /* 5 == _OUTPUT_LOCK */ + NULL, /* 6 == _CSCANF_LOCK */ + NULL, /* 7 == _CPRINTF_LOCK */ + NULL, /* 8 == _CONIO_LOCK */ + &hlcritsect, /* 9 == _HEAP_LOCK */ + NULL, /* 10 == _BHEAP_LOCK *** OBSOLETE *** */ + NULL, /* 11 == _TIME_LOCK */ + NULL, /* 12 == _ENV_LOCK */ + &xlcritsect, /* 13 == _EXIT_LOCK1 */ + NULL, /* 14 == _EXIT_LOCK2 *** OBSOLETE *** */ + NULL, /* 15 == _THREADDATA_LOCK *** OBSOLETE *** */ + NULL, /* 16 == _POPEN_LOCK */ + <lcritsect, /* 17 == _LOCKTAB_LOCK */ + NULL, /* 18 == _OSFHND_LOCK */ + NULL, /* 19 == _SETLOCALE_LOCK */ + NULL, /* 20 == _LC_COLLATE_LOCK */ + NULL, /* 21 == _LC_CTYPE_LOCK */ + NULL, /* 22 == _LC_MONETARY_LOCK */ + NULL, /* 23 == _LC_NUMERIC_LOCK */ + NULL, /* 24 == _LC_TIME_LOCK */ + NULL, /* 25 == _STREAM_LOCKS */ + NULL /* ... */ + }; + + +#define _FATAL _amsg_exit(_RT_LOCK) + +#pragma optimize("y",off) + +/*** +*_mtinitlocks() - Initialize multi-thread lock scheme +* +*Purpose: +* Perform whatever initialization is required for the multi-thread +* locking (synchronization) scheme. This routine should be called +* exactly once, during startup, and this must be before any requests +* are made to assert locks. +* +* NOTES: In Win32, the multi-thread locks are created individually, +* each upon its first use. That is when any particular lock is asserted +* for the first time, the underlying critical section is then allocated, +* initialized and (finally) entered. This allocation and initialization +* is protected under _LOCKTAB_LOCK. It is _mtinitlocks' job to set up +* _LOCKTAB_LOCK. _EXIT_LOCK1 is also set up by _mtinitlock +* +*Entry: +* <none> +* +*Exit: +* returns on success +* calls _amsg_exit on failure +* +*Exceptions: +* +*******************************************************************************/ + +void _CRTAPI1 _mtinitlocks ( + void + ) +{ +#ifdef DEBUG + int i; + + /* + * Scan _locktable[] and make sure everything was initialized properly + */ + for ( i = 0 ; i < _TOTAL_LOCKS ; i++ ) { + if ( i == _LOCKTAB_LOCK ) { + if ( _locktable[i] != <lcritsect ) + _lockerr_exit("fatal error in _mtinitlocks #1\n"); + } + else if ( i == _EXIT_LOCK1 ) { + if ( _locktable[i] != &xlcritsect ) + _lockerr_exit("fatal error in _mtinitlocks #2\n"); + } + else if ( i == _HEAP_LOCK ) { + if ( _locktable[i] != &hlcritsect ) + _lockerr_exit("fatal error in _mtinitlocks #3\n"); + } + else if ( _locktable[i] != NULL ) + _lockerr_exit("fatal error in _mtinitlocks #3\n"); + } +#endif /* DEBUG */ + + /* + * All we need to do is initialize _LOCKTAB_LOCK and _EXIT_LOCK1. + */ + InitializeCriticalSection( _locktable[_LOCKTAB_LOCK] ); + InitializeCriticalSection( _locktable[_EXIT_LOCK1] ); + InitializeCriticalSection( _locktable[_HEAP_LOCK] ); +} + + +/*** +*_mtdeletelocks() - Delete all initialized locks +* +*Purpose: +* Walks _locktable[] and _lockmap, and deletes every 'lock' (i.e., +* critical section) which has been initialized. +* +* This function is intended for use in DLLs containing the C runtime +* (i.e., crtdll.dll and user DLLs built using libcmt.lib and the +* special startup objects). It is to be called from within the DLL's +* entrypoint function when that function is called with +* DLL_PROCESS_DETACH. +* +*Entry: +* <none> +* +*Exit: +* +*Exceptions: +* behavior undefined/unknown if a lock is being held when this routine +* is called. +* +*******************************************************************************/ + +void _CRTAPI1 _mtdeletelocks( + void + ) +{ + int locknum; + + for ( locknum = 0 ; locknum < _TOTAL_LOCKS ; locknum++ ) { + + /* + * If the 'lock' has been created, delete it + */ +#ifdef DEBUG + /* + * See if the lock has already been deleted. + */ + if ( _locktable[locknum] == (PCRITICAL_SECTION)(-1L) ) + _lockerr_exit("fatal error in _mtdeletelocks #1\n"); + + /* + * Delete the lock if it had been created. + */ + if ( _locktable[locknum] != NULL ) { + if ( (locknum != _LOCKTAB_LOCK) && (locknum != + _EXIT_LOCK1) && (locknum != _HEAP_LOCK) ) + { + PCRITICAL_SECTION pcs = _locktable[locknum]; + + /* mark as deleted */ + _locktable[locknum] = (PCRITICAL_SECTION)(-1L); + + /* double check that it wasn't already deleted */ + if ( pcs == (PCRITICAL_SECTION)(-1L) ) + _lockerr_exit("fatal error in _mtdeletelocks #2\n"); + + DeleteCriticalSection(pcs); + free(pcs); + } + } +#else /* non DEBUG */ + /* + * Delete the lock if it had been created + */ + if ( _locktable[locknum] != NULL ) { + if ( (locknum != _LOCKTAB_LOCK) && (locknum != + _EXIT_LOCK1) && (locknum != _HEAP_LOCK) ) + { + /* + * Free the memory for the CritSect after deleting + * it. It is okay to call free() if the heap lock + * is kept valid until after all calls to the heap. + */ + DeleteCriticalSection(_locktable[locknum]); + free(_locktable[locknum]); + } + } +#endif /* DEBUG */ + + } + + /* + * Finally, clean up the special locks + */ + DeleteCriticalSection( _locktable[_HEAP_LOCK] ); + DeleteCriticalSection( _locktable[_EXIT_LOCK1] ); + DeleteCriticalSection( _locktable[_LOCKTAB_LOCK] ); +} + + +/*** +* _lock - Acquire a multi-thread lock +* +*Purpose: +* Note that it is legal for a thread to aquire _EXIT_LOCK1 +* multiple times. +* +*Entry: +* locknum = number of the lock to aquire +* +*Exit: +* +*Exceptions: +* +*******************************************************************************/ + +void _CRTAPI1 _lock ( + int locknum + ) +{ + PCRITICAL_SECTION pcs; + +#ifdef DEBUG + if ( _locktable[locknum] == (PCRITICAL_SECTION)(-1L) ) + _lockerr_exit("fatal error in _lock #1\n"); +#endif /* DEBUG */ + + /* + * Create/open the lock, if necessary + */ + if ( _locktable[locknum] == NULL ) { + + if ( (pcs = malloc(sizeof(CRITICAL_SECTION))) == NULL ) + _amsg_exit(_RT_LOCK); + + _mlock(_LOCKTAB_LOCK); /*** WARNING: Recursive lock call ***/ + + if ( _locktable[locknum] == NULL ) { + InitializeCriticalSection(pcs); + _locktable[locknum] = pcs; + } + else { +#ifdef DEBUG + if ( _locktable[locknum] == (PCRITICAL_SECTION)(-1L) ) + _lockerr_exit("fatal error in _lock #2\n"); +#endif /* DEBUG */ + free(pcs); + } + + _munlock(_LOCKTAB_LOCK); + } + + /* + * Enter the critical section. + */ + + EnterCriticalSection( _locktable[locknum] ); +} + + +/*** +* _unlock - Release multi-thread lock +* +*Purpose: +* Note that it is legal for a thread to aquire _EXIT_LOCK1 +* multiple times. +* +*Entry: +* locknum = number of the lock to release +* +*Exit: +* +*Exceptions: +* +*******************************************************************************/ + +void _CRTAPI1 _unlock ( + int locknum + ) +{ + /* + * leave the critical section. + */ + LeaveCriticalSection( _locktable[locknum] ); +} + +#pragma optimize("y",) + +/*** +*_lockerr_exit() - Write error message and die +* +*Purpose: +* Attempt to write out the unexpected lock error message, then terminate +* the program by a direct API call. This function is used in place of +* amsg_exit(_RT_LOCK) when it is judged unsafe to allow further lock +* or unlock calls. +* +*Entry: +* +*Exit: +* +*Exceptions: +* +*******************************************************************************/ + +void _CRTAPI3 _lockerr_exit ( + char *msg + ) +{ + FatalAppExit(0, msg); /* Die with message box */ + ExitProcess(255); /* Just die */ +} + + +#endif /* MTHREAD */ |