diff options
author | hobbs <hobbs> | 2004-07-21 01:30:56 (GMT) |
---|---|---|
committer | hobbs <hobbs> | 2004-07-21 01:30:56 (GMT) |
commit | 1421351399efa280f6108d55bc38c5bc90051dcc (patch) | |
tree | 485b0b4f6b33aad1eb86cc5ec0ddf7c71966fd7c | |
parent | 3d2e7995dd6ea56840a0c4a2c00466ae914251db (diff) | |
download | tcl-1421351399efa280f6108d55bc38c5bc90051dcc.zip tcl-1421351399efa280f6108d55bc38c5bc90051dcc.tar.gz tcl-1421351399efa280f6108d55bc38c5bc90051dcc.tar.bz2 |
* generic/tclEvent.c: Correct threaded obj allocator to
* generic/tclInt.h: fully cleanup on exit and allow for
* generic/tclThreadAlloc.c: reinitialization. [Bug #736426]
* unix/tclUnixThrd.c: (mistachkin, kenny)
* win/tclWinThrd.c:
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | generic/tclEvent.c | 6 | ||||
-rw-r--r-- | generic/tclInt.h | 5 | ||||
-rwxr-xr-x | generic/tclThreadAlloc.c | 60 | ||||
-rw-r--r-- | unix/tclUnixThrd.c | 46 | ||||
-rw-r--r-- | win/tclWinThrd.c | 35 |
6 files changed, 137 insertions, 23 deletions
@@ -1,3 +1,11 @@ +2004-07-20 Jeff Hobbs <jeffh@ActiveState.com> + + * generic/tclEvent.c: Correct threaded obj allocator to + * generic/tclInt.h: fully cleanup on exit and allow for + * generic/tclThreadAlloc.c: reinitialization. [Bug #736426] + * unix/tclUnixThrd.c: (mistachkin, kenny) + * win/tclWinThrd.c: + 2004-07-20 Daniel Steffen <das@users.sourceforge.net> * unix/tcl.m4: fixed Darwin autoconf breakage caused by diff --git a/generic/tclEvent.c b/generic/tclEvent.c index 19bb0d6..67ec728 100644 --- a/generic/tclEvent.c +++ b/generic/tclEvent.c @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclEvent.c,v 1.28.2.7 2004/07/15 09:57:10 vasiljevic Exp $ + * RCS: @(#) $Id: tclEvent.c,v 1.28.2.8 2004/07/21 01:30:57 hobbs Exp $ */ #include "tclInt.h" @@ -897,7 +897,9 @@ Tcl_Finalize() /* * There shouldn't be any malloc'ed memory after this. */ - +#if defined(TCL_THREADS) && defined(USE_THREAD_ALLOC) && !defined(TCL_MEM_DEBUG) && !defined(PURIFY) + TclFinalizeThreadAlloc(); +#endif TclFinalizeMemorySubsystem(); inFinalize = 0; } diff --git a/generic/tclInt.h b/generic/tclInt.h index 95129b6..c3c0904 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -12,7 +12,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclInt.h,v 1.118.2.6 2004/06/22 11:55:35 vasiljevic Exp $ + * RCS: @(#) $Id: tclInt.h,v 1.118.2.7 2004/07/21 01:30:57 hobbs Exp $ */ #ifndef _TCLINT @@ -2138,6 +2138,9 @@ EXTERN Tcl_Obj *TclPtrIncrVar _ANSI_ARGS_((Tcl_Interp *interp, Var *varPtr, EXTERN Tcl_Obj *TclThreadAllocObj _ANSI_ARGS_((void)); EXTERN void TclThreadFreeObj _ANSI_ARGS_((Tcl_Obj *)); +EXTERN void TclFinalizeThreadAlloc _ANSI_ARGS_((void)); +EXTERN void TclpFreeAllocMutex _ANSI_ARGS_((Tcl_Mutex* mutex)); + # define TclAllocObjStorage(objPtr) \ (objPtr) = TclThreadAllocObj() diff --git a/generic/tclThreadAlloc.c b/generic/tclThreadAlloc.c index 0023e35..1bd51e6 100755 --- a/generic/tclThreadAlloc.c +++ b/generic/tclThreadAlloc.c @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclThreadAlloc.c,v 1.4.2.2 2003/05/10 04:57:40 mistachkin Exp $ + * RCS: @(#) $Id: tclThreadAlloc.c,v 1.4.2.3 2004/07/21 01:30:57 hobbs Exp $ */ #if defined(TCL_THREADS) && defined(USE_THREAD_ALLOC) @@ -949,4 +949,62 @@ GetBlocks(Cache *cachePtr, int bucket) return 1; } +/* + *---------------------------------------------------------------------- + * + * TclFinalizeThreadAlloc -- + * + * This procedure is used to destroy all private resources used in + * this file. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TclFinalizeThreadAlloc() +{ + int i; + for (i = 0; i < NBUCKETS; ++i) { + TclpFreeAllocMutex(binfo[i].lockPtr); + binfo[i].lockPtr = NULL; + } + + TclpFreeAllocMutex(objLockPtr); + objLockPtr = NULL; + + TclpFreeAllocMutex(listLockPtr); + listLockPtr = NULL; +} + +#else + +/* + *---------------------------------------------------------------------- + * + * TclFinalizeThreadAlloc -- + * + * This procedure is used to destroy all private resources used in + * this file. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TclFinalizeThreadAlloc() +{ + Tcl_Panic("TclFinalizeThreadAlloc called when threaded memory allocator not in use."); +} + #endif /* TCL_THREADS */ diff --git a/unix/tclUnixThrd.c b/unix/tclUnixThrd.c index d300d34..edfc44a 100644 --- a/unix/tclUnixThrd.c +++ b/unix/tclUnixThrd.c @@ -886,19 +886,20 @@ TclpInetNtoa(struct in_addr addr) * Additions by AOL for specialized thread memory allocator. */ #ifdef USE_THREAD_ALLOC -static int initialized = 0; +static volatile int initialized = 0; static pthread_key_t key; -static pthread_once_t once = PTHREAD_ONCE_INIT; + +typedef struct allocMutex { + Tcl_Mutex tlock; + pthread_mutex_t plock; +} allocMutex; Tcl_Mutex * TclpNewAllocMutex(void) { - struct lock { - Tcl_Mutex tlock; - pthread_mutex_t plock; - } *lockPtr; + struct allocMutex *lockPtr; - lockPtr = malloc(sizeof(struct lock)); + lockPtr = malloc(sizeof(struct allocMutex)); if (lockPtr == NULL) { panic("could not allocate lock"); } @@ -907,20 +908,41 @@ TclpNewAllocMutex(void) return &lockPtr->tlock; } -static void -InitKey(void) +void +TclpFreeAllocMutex(mutex) + Tcl_Mutex *mutex; /* The alloc mutex to free. */ +{ + allocMutex* lockPtr = (allocMutex*) mutex; + if (!lockPtr) return; + pthread_mutex_destroy(&lockPtr->plock); + free(lockPtr); +} + +void TclpFreeAllocCache(ptr) + void *ptr; { extern void TclFreeAllocCache(void *); - pthread_key_create(&key, TclFreeAllocCache); - initialized = 1; + TclFreeAllocCache(ptr); + /* + * Perform proper cleanup of things done in TclpGetAllocCache. + */ + if (initialized) { + pthread_key_delete(key); + initialized = 0; + } } void * TclpGetAllocCache(void) { if (!initialized) { - pthread_once(&once, InitKey); + pthread_mutex_lock(allocLockPtr); + if (!initialized) { + pthread_key_create(&key, TclpFreeAllocCache); + initialized = 1; + } + pthread_mutex_unlock(allocLockPtr); } return pthread_getspecific(key); } diff --git a/win/tclWinThrd.c b/win/tclWinThrd.c index 4f0caac..c99f27b 100644 --- a/win/tclWinThrd.c +++ b/win/tclWinThrd.c @@ -9,7 +9,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclWinThrd.c,v 1.24.2.7 2004/07/19 19:23:03 vasiljevic Exp $ + * RCS: @(#) $Id: tclWinThrd.c,v 1.24.2.8 2004/07/21 01:30:58 hobbs Exp $ */ #include "tclWinInt.h" @@ -1038,17 +1038,20 @@ TclpFinalizeCondition(condPtr) * Additions by AOL for specialized thread memory allocator. */ #ifdef USE_THREAD_ALLOC +static int once; static DWORD key; +typedef struct allocMutex { + Tcl_Mutex tlock; + CRITICAL_SECTION wlock; +} allocMutex; + Tcl_Mutex * TclpNewAllocMutex(void) { - struct lock { - Tcl_Mutex tlock; - CRITICAL_SECTION wlock; - } *lockPtr; + struct allocMutex *lockPtr; - lockPtr = malloc(sizeof(struct lock)); + lockPtr = malloc(sizeof(struct allocMutex)); if (lockPtr == NULL) { panic("could not allocate lock"); } @@ -1057,10 +1060,19 @@ TclpNewAllocMutex(void) return &lockPtr->tlock; } +void +TclpFreeAllocMutex(mutex) + Tcl_Mutex *mutex; /* The alloc mutex to free. */ +{ + allocMutex* lockPtr = (allocMutex*) mutex; + if (!lockPtr) return; + DeleteCriticalSection(&lockPtr->wlock); + free(lockPtr); +} + void * TclpGetAllocCache(void) { - static int once = 0; VOID *result; if (!once) { @@ -1111,6 +1123,15 @@ TclWinFreeAllocCache(void) panic("TlsGetValue failed from TclWinFreeAllocCache!"); } } + + if (once) { + success = TlsFree(key); + if (!success) { + Tcl_Panic("TlsFree failed from TclWinFreeAllocCache!"); + } + + once = 0; /* reset for next time. */ + } } #endif /* USE_THREAD_ALLOC */ |