summaryrefslogtreecommitdiffstats
path: root/win/tclWinThrd.c
diff options
context:
space:
mode:
Diffstat (limited to 'win/tclWinThrd.c')
-rw-r--r--win/tclWinThrd.c158
1 files changed, 105 insertions, 53 deletions
diff --git a/win/tclWinThrd.c b/win/tclWinThrd.c
index 7828e65..b9cde72 100644
--- a/win/tclWinThrd.c
+++ b/win/tclWinThrd.c
@@ -5,6 +5,7 @@
*
* Copyright (c) 1998 by Sun Microsystems, Inc.
* Copyright (c) 1999 by Scriptics Corporation
+ * Copyright (c) 2008 by George Peter Staplin
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -28,10 +29,7 @@ _CRTIMP unsigned int __cdecl _controlfp (unsigned int unNew, unsigned int unMask
*/
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
@@ -109,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 */
@@ -121,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;
@@ -135,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
@@ -183,7 +180,7 @@ TclWinThreadStart(
lpOrigStartAddress = winThreadPtr->lpStartAddress;
lpOrigParameter = winThreadPtr->lpParameter;
- ckfree((char *)winThreadPtr);
+ ckfree(winThreadPtr);
return lpOrigStartAddress(lpOrigParameter);
}
@@ -207,7 +204,7 @@ TclWinThreadStart(
int
TclpThreadCreate(
Tcl_ThreadId *idPtr, /* Return, the ID of the thread. */
- Tcl_ThreadCreateProc proc, /* Main() function of the thread. */
+ Tcl_ThreadCreateProc *proc, /* Main() function of the thread. */
ClientData clientData, /* The one argument to Main(). */
int stackSize, /* Size of stack for the new thread. */
int flags) /* Flags controlling behaviour of the new
@@ -331,7 +328,7 @@ TclpThreadExit(
Tcl_ThreadId
Tcl_GetCurrentThread(void)
{
- return (Tcl_ThreadId) INT2PTR(GetCurrentThreadId());
+ return (Tcl_ThreadId)(size_t)GetCurrentThreadId();
}
/*
@@ -356,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
@@ -364,7 +361,7 @@ TclpInitLock(void)
* that create interpreters in parallel.
*/
- init = 1;
+ initialized = 1;
InitializeCriticalSection(&joinLock);
InitializeCriticalSection(&initLock);
InitializeCriticalSection(&masterLock);
@@ -418,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
@@ -426,7 +423,7 @@ TclpMasterLock(void)
* that create interpreters in parallel.
*/
- init = 1;
+ initialized = 1;
InitializeCriticalSection(&joinLock);
InitializeCriticalSection(&initLock);
InitializeCriticalSection(&masterLock);
@@ -493,7 +490,7 @@ Tcl_GetAllocMutex(void)
/*
*----------------------------------------------------------------------
*
- * TclpFinalizeLock
+ * TclFinalizeLock
*
* This procedure is used to destroy all private resources used in this
* file.
@@ -511,7 +508,7 @@ Tcl_GetAllocMutex(void)
void
TclFinalizeLock(void)
{
- MASTER_LOCK;
+ TclpMasterLock();
DeleteCriticalSection(&joinLock);
/*
@@ -519,7 +516,7 @@ TclFinalizeLock(void)
*/
DeleteCriticalSection(&masterLock);
- init = 0;
+ initialized = 0;
#ifdef TCL_THREADS
if (allocOnce) {
@@ -566,19 +563,19 @@ Tcl_MutexLock(
CRITICAL_SECTION *csPtr;
if (*mutexPtr == NULL) {
- MASTER_LOCK;
+ TclpMasterLock();
/*
* Double inside master lock check to avoid a race.
*/
if (*mutexPtr == NULL) {
- csPtr = (CRITICAL_SECTION *) ckalloc(sizeof(CRITICAL_SECTION));
+ csPtr = ckalloc(sizeof(CRITICAL_SECTION));
InitializeCriticalSection(csPtr);
*mutexPtr = (Tcl_Mutex)csPtr;
TclRememberMutex(mutexPtr);
}
- MASTER_UNLOCK;
+ TclpMasterUnlock();
}
csPtr = *((CRITICAL_SECTION **)mutexPtr);
EnterCriticalSection(csPtr);
@@ -634,7 +631,7 @@ TclpFinalizeMutex(
if (csPtr != NULL) {
DeleteCriticalSection(csPtr);
- ckfree((char *) csPtr);
+ ckfree(csPtr);
*mutexPtr = NULL;
}
}
@@ -665,7 +662,7 @@ void
Tcl_ConditionWait(
Tcl_Condition *condPtr, /* Really (WinCondition **) */
Tcl_Mutex *mutexPtr, /* Really (CRITICAL_SECTION **) */
- Tcl_Time *timePtr) /* Timeout on waiting period */
+ const Tcl_Time *timePtr) /* Timeout on waiting period */
{
WinCondition *winCondPtr; /* Per-condition queue head */
CRITICAL_SECTION *csPtr; /* Caller's Mutex, after casting */
@@ -680,7 +677,7 @@ Tcl_ConditionWait(
*/
if (tsdPtr->flags == WIN_THREAD_UNINIT) {
- MASTER_LOCK;
+ TclpMasterLock();
/*
* Create the per-thread event and queue pointers.
@@ -694,7 +691,7 @@ Tcl_ConditionWait(
tsdPtr->flags = WIN_THREAD_RUNNING;
doExit = 1;
}
- MASTER_UNLOCK;
+ TclpMasterUnlock();
if (doExit) {
/*
@@ -704,27 +701,26 @@ Tcl_ConditionWait(
* and initializing that may drop back into the Master Lock.
*/
- Tcl_CreateThreadExitHandler(FinalizeConditionEvent,
- (ClientData) tsdPtr);
+ Tcl_CreateThreadExitHandler(FinalizeConditionEvent, tsdPtr);
}
}
if (*condPtr == NULL) {
- MASTER_LOCK;
+ TclpMasterLock();
/*
* Initialize the per-condition queue pointers and Mutex.
*/
if (*condPtr == NULL) {
- winCondPtr = (WinCondition *) ckalloc(sizeof(WinCondition));
+ winCondPtr = ckalloc(sizeof(WinCondition));
InitializeCriticalSection(&winCondPtr->condLock);
winCondPtr->firstPtr = NULL;
winCondPtr->lastPtr = NULL;
*condPtr = (Tcl_Condition) winCondPtr;
TclRememberCondition(condPtr);
}
- MASTER_UNLOCK;
+ TclpMasterUnlock();
}
csPtr = *((CRITICAL_SECTION **)mutexPtr);
winCondPtr = *((WinCondition **)condPtr);
@@ -766,7 +762,8 @@ Tcl_ConditionWait(
while (!timeout && (tsdPtr->flags & WIN_THREAD_BLOCKED)) {
ResetEvent(tsdPtr->condEvent);
LeaveCriticalSection(&winCondPtr->condLock);
- if (WaitForSingleObject(tsdPtr->condEvent, wtime) == WAIT_TIMEOUT) {
+ if (WaitForSingleObjectEx(tsdPtr->condEvent, wtime,
+ TRUE) == WAIT_TIMEOUT) {
timeout = 1;
}
EnterCriticalSection(&winCondPtr->condLock);
@@ -927,7 +924,7 @@ TclpFinalizeCondition(
if (winCondPtr != NULL) {
DeleteCriticalSection(&winCondPtr->condLock);
- ckfree((char *) winCondPtr);
+ ckfree(winCondPtr);
*condPtr = NULL;
}
}
@@ -943,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");
}
@@ -967,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");
@@ -1011,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);
@@ -1020,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()
@@ -1030,11 +1029,64 @@ TclpFreeAllocCache(
if (!success) {
Tcl_Panic("TlsFree failed from TclpFreeAllocCache");
}
- once = 0; /* reset for next time. */
}
-
}
#endif /* USE_THREAD_ALLOC */
+
+
+void *
+TclpThreadCreateKey(void)
+{
+ DWORD *key;
+
+ key = TclpSysAlloc(sizeof *key, 0);
+ if (key == NULL) {
+ Tcl_Panic("unable to allocate thread key!");
+ }
+
+ *key = TlsAlloc();
+
+ if (*key == TLS_OUT_OF_INDEXES) {
+ Tcl_Panic("unable to allocate thread-local storage");
+ }
+
+ return key;
+}
+
+void
+TclpThreadDeleteKey(
+ void *keyPtr)
+{
+ DWORD *key = keyPtr;
+
+ if (!TlsFree(*key)) {
+ Tcl_Panic("unable to delete key");
+ }
+
+ TclpSysFree(keyPtr);
+}
+
+void
+TclpThreadSetMasterTSD(
+ void *tsdKeyPtr,
+ void *ptr)
+{
+ DWORD *key = tsdKeyPtr;
+
+ if (!TlsSetValue(*key, ptr)) {
+ Tcl_Panic("unable to set master TSD value");
+ }
+}
+
+void *
+TclpThreadGetMasterTSD(
+ void *tsdKeyPtr)
+{
+ DWORD *key = tsdKeyPtr;
+
+ return TlsGetValue(*key);
+}
+
#endif /* TCL_THREADS */
/*