|  | /* | 
|  | * Copyright (c) 2002, TransGaming Technologies Inc. | 
|  | * | 
|  | * This library is free software; you can redistribute it and/or | 
|  | * modify it under the terms of the GNU Lesser General Public | 
|  | * License as published by the Free Software Foundation; either | 
|  | * version 2.1 of the License, or (at your option) any later version. | 
|  | * | 
|  | * This library is distributed in the hope that it will be useful, | 
|  | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|  | * Lesser General Public License for more details. | 
|  | * | 
|  | * You should have received a copy of the GNU Lesser General Public | 
|  | * License along with this library; if not, write to the Free Software | 
|  | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | 
|  | */ | 
|  |  | 
|  | #include "mtdll.h" | 
|  |  | 
|  | #include "wine/debug.h" | 
|  | #include "winbase.h" | 
|  |  | 
|  | WINE_DEFAULT_DEBUG_CHANNEL(msvcrt); | 
|  |  | 
|  | typedef struct | 
|  | { | 
|  | BOOL             bInit; | 
|  | CRITICAL_SECTION crit; | 
|  | } LOCKTABLEENTRY; | 
|  |  | 
|  | static LOCKTABLEENTRY lock_table[ _TOTAL_LOCKS ]; | 
|  |  | 
|  | static inline void msvcrt_mlock_set_entry_initialized( int locknum, BOOL initialized ) | 
|  | { | 
|  | lock_table[ locknum ].bInit = initialized; | 
|  | } | 
|  |  | 
|  | static inline void msvcrt_initialize_mlock( int locknum ) | 
|  | { | 
|  | InitializeCriticalSection( &(lock_table[ locknum ].crit) ); | 
|  | msvcrt_mlock_set_entry_initialized( locknum, TRUE ); | 
|  | } | 
|  |  | 
|  | static inline void msvcrt_uninitialize_mlock( int locknum ) | 
|  | { | 
|  | DeleteCriticalSection( &(lock_table[ locknum ].crit) ); | 
|  | msvcrt_mlock_set_entry_initialized( locknum, FALSE ); | 
|  | } | 
|  |  | 
|  | /********************************************************************** | 
|  | *     msvcrt_init_mt_locks (internal) | 
|  | * | 
|  | * Initialize the table lock. All other locks will be initialized | 
|  | * upon first use. | 
|  | * | 
|  | */ | 
|  | void msvcrt_init_mt_locks(void) | 
|  | { | 
|  | int i; | 
|  |  | 
|  | TRACE( "initializing mtlocks\n" ); | 
|  |  | 
|  | /* Initialize the table */ | 
|  | for( i=0; i < _TOTAL_LOCKS; i++ ) | 
|  | { | 
|  | msvcrt_mlock_set_entry_initialized( i, FALSE ); | 
|  | } | 
|  |  | 
|  | /* Initialize our lock table lock */ | 
|  | msvcrt_initialize_mlock( _LOCKTAB_LOCK ); | 
|  | } | 
|  |  | 
|  | /********************************************************************** | 
|  | *     msvcrt_free_mt_locks (internal) | 
|  | * | 
|  | * Uninitialize all mt locks. Assume that neither _lock or _unlock will | 
|  | * be called once we're calling this routine (ie _LOCKTAB_LOCK can be deleted) | 
|  | * | 
|  | */ | 
|  | void msvcrt_free_mt_locks(void) | 
|  | { | 
|  | int i; | 
|  |  | 
|  | TRACE( ": uninitializing all mtlocks\n" ); | 
|  |  | 
|  | /* Uninitialize the table */ | 
|  | for( i=0; i < _TOTAL_LOCKS; i++ ) | 
|  | { | 
|  | if( lock_table[ i ].bInit == TRUE ) | 
|  | { | 
|  | msvcrt_uninitialize_mlock( i ); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | /********************************************************************** | 
|  | *              _lock (MSVCRT.@) | 
|  | */ | 
|  | void _lock( int locknum ) | 
|  | { | 
|  | TRACE( "(%d)\n", locknum ); | 
|  |  | 
|  | /* If the lock doesn't exist yet, create it */ | 
|  | if( lock_table[ locknum ].bInit == FALSE ) | 
|  | { | 
|  | /* Lock while we're changing the lock table */ | 
|  | _lock( _LOCKTAB_LOCK ); | 
|  |  | 
|  | /* Check again if we've got a bit of a race on lock creation */ | 
|  | if( lock_table[ locknum ].bInit == FALSE ) | 
|  | { | 
|  | TRACE( ": creating lock #%d\n", locknum ); | 
|  | msvcrt_initialize_mlock( locknum ); | 
|  | } | 
|  |  | 
|  | /* Unlock ourselves */ | 
|  | _unlock( _LOCKTAB_LOCK ); | 
|  | } | 
|  |  | 
|  | EnterCriticalSection( &(lock_table[ locknum ].crit) ); | 
|  | } | 
|  |  | 
|  | /********************************************************************** | 
|  | *              _unlock (MSVCRT.@) | 
|  | * | 
|  | * NOTE: There is no error detection to make sure the lock exists and is acquired. | 
|  | */ | 
|  | void _unlock( int locknum ) | 
|  | { | 
|  | TRACE( "(%d)\n", locknum ); | 
|  |  | 
|  | LeaveCriticalSection( &(lock_table[ locknum ].crit) ); | 
|  | } | 
|  |  |