summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhobbs <hobbs>2004-07-21 01:45:44 (GMT)
committerhobbs <hobbs>2004-07-21 01:45:44 (GMT)
commit4dcfe1cc24fd10bd3e184990a3b7f7c3042d6e03 (patch)
treea73f70550f592464825b855b97bcf3574735f983
parentb7baa5cf544d8865daa4745ad9616caabfedd664 (diff)
downloadtcl-4dcfe1cc24fd10bd3e184990a3b7f7c3042d6e03.zip
tcl-4dcfe1cc24fd10bd3e184990a3b7f7c3042d6e03.tar.gz
tcl-4dcfe1cc24fd10bd3e184990a3b7f7c3042d6e03.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--ChangeLog8
-rw-r--r--generic/tclEvent.c6
-rw-r--r--generic/tclInt.h4
-rwxr-xr-xgeneric/tclThreadAlloc.c62
-rw-r--r--unix/tclUnixThrd.c46
-rw-r--r--win/tclWinThrd.c35
6 files changed, 137 insertions, 24 deletions
diff --git a/ChangeLog b/ChangeLog
index d817ee0..587876d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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-21 Kevin Kenny <kennykb@acm.org>
* generic/tclBasic.c (DeleteInterpProc):
diff --git a/generic/tclEvent.c b/generic/tclEvent.c
index b169196..187a6e3 100644
--- a/generic/tclEvent.c
+++ b/generic/tclEvent.c
@@ -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: tclEvent.c,v 1.43 2004/07/15 20:04:38 vasiljevic Exp $
+ * RCS: @(#) $Id: tclEvent.c,v 1.44 2004/07/21 01:45:44 hobbs Exp $
*/
#include "tclInt.h"
@@ -973,7 +973,9 @@ Tcl_Finalize()
/*
* There shouldn't be any malloc'ed memory after this.
*/
-
+#if defined(TCL_THREADS) && defined(USE_THREAD_ALLOC)
+ TclFinalizeThreadAlloc();
+#endif
TclFinalizeMemorySubsystem();
inFinalize = 0;
}
diff --git a/generic/tclInt.h b/generic/tclInt.h
index f3db00e..0c5d431 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.169 2004/07/21 00:42:38 kennykb Exp $
+ * RCS: @(#) $Id: tclInt.h,v 1.170 2004/07/21 01:45:44 hobbs Exp $
*/
#ifndef _TCLINT
@@ -2363,6 +2363,8 @@ EXTERN void TclThreadFreeObj _ANSI_ARGS_((Tcl_Obj *));
EXTERN Tcl_Mutex *TclpNewAllocMutex _ANSI_ARGS_((void));
EXTERN void *TclpGetAllocCache _ANSI_ARGS_((void));
EXTERN void TclpSetAllocCache _ANSI_ARGS_((void *));
+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 8f2b336..553bd4f 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.13 2004/06/21 08:54:34 dkf Exp $
+ * RCS: @(#) $Id: tclThreadAlloc.c,v 1.14 2004/07/21 01:45:44 hobbs Exp $
*/
#include "tclInt.h"
@@ -631,7 +631,7 @@ Tcl_GetMemoryInfo(dsPtr)
if (cachePtr == sharedPtr) {
Tcl_DStringAppendElement(dsPtr, "shared");
} else {
- sprintf(buf, "thread%d", (int) cachePtr->owner);
+ sprintf(buf, "thread%p", cachePtr->owner);
Tcl_DStringAppendElement(dsPtr, buf);
}
for (n = 0; n < NBUCKETS; ++n) {
@@ -957,4 +957,62 @@ GetBlocks(cachePtr, 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(bucketInfo[i].lockPtr);
+ bucketInfo[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 edcb0f3..aad394f 100644
--- a/unix/tclUnixThrd.c
+++ b/unix/tclUnixThrd.c
@@ -934,19 +934,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) {
Tcl_Panic("could not allocate lock");
}
@@ -955,20 +956,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 c968a53..e2f399f 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.32 2004/07/19 19:19:07 vasiljevic Exp $
+ * RCS: @(#) $Id: tclWinThrd.c,v 1.33 2004/07/21 01:45:45 hobbs Exp $
*/
#include "tclWinInt.h"
@@ -1040,17 +1040,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) {
Tcl_Panic("could not allocate lock");
}
@@ -1059,10 +1062,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) {
@@ -1113,6 +1125,15 @@ TclWinFreeAllocCache(void)
Tcl_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 */