diff options
Diffstat (limited to 'win/tclWinThrd.c')
-rw-r--r-- | win/tclWinThrd.c | 130 |
1 files changed, 45 insertions, 85 deletions
diff --git a/win/tclWinThrd.c b/win/tclWinThrd.c index ae7ce80..b9cde72 100644 --- a/win/tclWinThrd.c +++ b/win/tclWinThrd.c @@ -24,25 +24,12 @@ _CRTIMP unsigned int __cdecl _controlfp (unsigned int unNew, unsigned int unMask #endif /* - * This is the number of milliseconds to wait between internal retries in - * the Tcl_MutexLock function. This value must be greater than or equal - * to zero and should be a suitable value for the given platform. - */ - -#ifndef TCL_MUTEX_LOCK_SLEEP_TIME -# define TCL_MUTEX_LOCK_SLEEP_TIME (0) -#endif - -/* * This is the master lock used to serialize access to other serialization * data structures. */ static CRITICAL_SECTION masterLock; -static int init = 0; -#define MASTER_LOCK TclpMasterLock() -#define MASTER_UNLOCK TclpMasterUnlock() - +static int initialized = 0; /* * This is the master lock used to serialize initialization and finalization @@ -67,13 +54,6 @@ static int allocOnce = 0; #endif /* TCL_THREADS */ /* - * The mutexLock serializes Tcl_MutexLock. This is necessary to prevent - * races when finalizing a mutex that some other thread may want to lock. - */ - -static CRITICAL_SECTION mutexLock; - -/* * The joinLock serializes Create- and ExitThread. This is necessary to * prevent a race where a new joinable thread exits before the creating thread * had the time to create the necessary data structures in the emulation @@ -127,7 +107,7 @@ static Tcl_ThreadDataKey dataKey; * the queue. */ -typedef struct WinCondition { +typedef struct { CRITICAL_SECTION condLock; /* Lock to serialize queuing on the * condition. */ struct ThreadSpecificData *firstPtr; /* Queue pointers */ @@ -139,10 +119,9 @@ typedef struct WinCondition { */ #ifdef USE_THREAD_ALLOC -static int once; static DWORD tlsKey; -typedef struct allocMutex { +typedef struct { Tcl_Mutex tlock; CRITICAL_SECTION wlock; } allocMutex; @@ -153,7 +132,7 @@ typedef struct allocMutex { * to TclWinThreadStart. */ -typedef struct WinThread { +typedef struct { LPTHREAD_START_ROUTINE lpStartAddress; /* Original startup routine */ LPVOID lpParameter; /* Original startup data */ unsigned int fpControl; /* Floating point control word from the @@ -185,7 +164,6 @@ TclWinThreadStart( * from TclpThreadCreate */ { WinThread *winThreadPtr = (WinThread *) lpParameter; - unsigned int fpmask; LPTHREAD_START_ROUTINE lpOrigStartAddress; LPVOID lpOrigParameter; @@ -193,18 +171,16 @@ TclWinThreadStart( return TCL_ERROR; } - fpmask = _MCW_EM | _MCW_RC | _MCW_PC; - -#if defined(_MSC_VER) && _MSC_VER >= 1200 - fpmask |= _MCW_DN; + _controlfp(winThreadPtr->fpControl, _MCW_EM | _MCW_RC | 0x03000000 /* _MCW_DN */ +#if !defined(_WIN64) + | _MCW_PC #endif - - _controlfp(winThreadPtr->fpControl, fpmask); + ); lpOrigStartAddress = winThreadPtr->lpStartAddress; lpOrigParameter = winThreadPtr->lpParameter; - ckfree((char *)winThreadPtr); + ckfree(winThreadPtr); return lpOrigStartAddress(lpOrigParameter); } @@ -377,7 +353,7 @@ Tcl_GetCurrentThread(void) void TclpInitLock(void) { - if (!init) { + if (!initialized) { /* * There is a fundamental race here that is solved by creating the * first Tcl interpreter in a single threaded environment. Once the @@ -385,8 +361,7 @@ TclpInitLock(void) * that create interpreters in parallel. */ - init = 1; - InitializeCriticalSection(&mutexLock); + initialized = 1; InitializeCriticalSection(&joinLock); InitializeCriticalSection(&initLock); InitializeCriticalSection(&masterLock); @@ -440,7 +415,7 @@ TclpInitUnlock(void) void TclpMasterLock(void) { - if (!init) { + if (!initialized) { /* * There is a fundamental race here that is solved by creating the * first Tcl interpreter in a single threaded environment. Once the @@ -448,7 +423,7 @@ TclpMasterLock(void) * that create interpreters in parallel. */ - init = 1; + initialized = 1; InitializeCriticalSection(&joinLock); InitializeCriticalSection(&initLock); InitializeCriticalSection(&masterLock); @@ -515,7 +490,7 @@ Tcl_GetAllocMutex(void) /* *---------------------------------------------------------------------- * - * TclpFinalizeLock + * TclFinalizeLock * * This procedure is used to destroy all private resources used in this * file. @@ -533,8 +508,7 @@ Tcl_GetAllocMutex(void) void TclFinalizeLock(void) { - MASTER_LOCK; - DeleteCriticalSection(&mutexLock); + TclpMasterLock(); DeleteCriticalSection(&joinLock); /* @@ -542,7 +516,7 @@ TclFinalizeLock(void) */ DeleteCriticalSection(&masterLock); - init = 0; + initialized = 0; #ifdef TCL_THREADS if (allocOnce) { @@ -588,10 +562,8 @@ Tcl_MutexLock( { CRITICAL_SECTION *csPtr; -retry: - if (*mutexPtr == NULL) { - MASTER_LOCK; + TclpMasterLock(); /* * Double inside master lock check to avoid a race. @@ -603,22 +575,10 @@ retry: *mutexPtr = (Tcl_Mutex)csPtr; TclRememberMutex(mutexPtr); } - MASTER_UNLOCK; - } - while (1) { - EnterCriticalSection(&mutexLock); - csPtr = *((CRITICAL_SECTION **)mutexPtr); - if (csPtr == NULL) { - LeaveCriticalSection(&mutexLock); - goto retry; - } - if (TryEnterCriticalSection(csPtr)) { - LeaveCriticalSection(&mutexLock); - return; - } - LeaveCriticalSection(&mutexLock); - Tcl_Sleep(TCL_MUTEX_LOCK_SLEEP_TIME); + TclpMasterUnlock(); } + csPtr = *((CRITICAL_SECTION **)mutexPtr); + EnterCriticalSection(csPtr); } /* @@ -717,7 +677,7 @@ Tcl_ConditionWait( */ if (tsdPtr->flags == WIN_THREAD_UNINIT) { - MASTER_LOCK; + TclpMasterLock(); /* * Create the per-thread event and queue pointers. @@ -731,7 +691,7 @@ Tcl_ConditionWait( tsdPtr->flags = WIN_THREAD_RUNNING; doExit = 1; } - MASTER_UNLOCK; + TclpMasterUnlock(); if (doExit) { /* @@ -746,7 +706,7 @@ Tcl_ConditionWait( } if (*condPtr == NULL) { - MASTER_LOCK; + TclpMasterLock(); /* * Initialize the per-condition queue pointers and Mutex. @@ -760,7 +720,7 @@ Tcl_ConditionWait( *condPtr = (Tcl_Condition) winCondPtr; TclRememberCondition(condPtr); } - MASTER_UNLOCK; + TclpMasterUnlock(); } csPtr = *((CRITICAL_SECTION **)mutexPtr); winCondPtr = *((WinCondition **)condPtr); @@ -980,9 +940,9 @@ TclpFinalizeCondition( Tcl_Mutex * TclpNewAllocMutex(void) { - struct allocMutex *lockPtr; + allocMutex *lockPtr; - lockPtr = malloc(sizeof(struct allocMutex)); + lockPtr = malloc(sizeof(allocMutex)); if (lockPtr == NULL) { Tcl_Panic("could not allocate lock"); } @@ -1004,24 +964,24 @@ TclpFreeAllocMutex( free(lockPtr); } -void * -TclpGetAllocCache(void) +void +TclpInitAllocCache(void) { - void *result; - - if (!once) { - /* - * We need to make sure that TclpFreeAllocCache is called on each - * thread that calls this, but only on threads that call this. - */ + /* + * We need to make sure that TclpFreeAllocCache is called on each + * thread that calls this, but only on threads that call this. + */ - tlsKey = TlsAlloc(); - once = 1; - if (tlsKey == TLS_OUT_OF_INDEXES) { - Tcl_Panic("could not allocate thread local storage"); - } + tlsKey = TlsAlloc(); + if (tlsKey == TLS_OUT_OF_INDEXES) { + Tcl_Panic("could not allocate thread local storage"); } +} +void * +TclpGetAllocCache(void) +{ + void *result; result = TlsGetValue(tlsKey); if ((result == NULL) && (GetLastError() != NO_ERROR)) { Tcl_Panic("TlsGetValue failed from TclpGetAllocCache"); @@ -1048,8 +1008,10 @@ TclpFreeAllocCache( if (ptr != NULL) { /* - * Called by us in TclpFinalizeThreadData when a thread exits and - * destroys the tsd key which stores allocator caches. + * Called by TclFinalizeThreadAlloc() and + * TclFinalizeThreadAllocThread() during Tcl_Finalize() or + * Tcl_FinalizeThread(). This function destroys the tsd key which + * stores allocator caches in thread local storage. */ TclFreeAllocCache(ptr); @@ -1057,7 +1019,7 @@ TclpFreeAllocCache( if (!success) { Tcl_Panic("TlsSetValue failed from TclpFreeAllocCache"); } - } else if (once) { + } else { /* * Called by us in TclFinalizeThreadAlloc() during the library * finalization initiated from Tcl_Finalize() @@ -1067,9 +1029,7 @@ TclpFreeAllocCache( if (!success) { Tcl_Panic("TlsFree failed from TclpFreeAllocCache"); } - once = 0; /* reset for next time. */ } - } #endif /* USE_THREAD_ALLOC */ |