summaryrefslogtreecommitdiffstats
path: root/generic/tclThread.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tclThread.c')
-rw-r--r--generic/tclThread.c125
1 files changed, 72 insertions, 53 deletions
diff --git a/generic/tclThread.c b/generic/tclThread.c
index c5def48..8c972a8 100644
--- a/generic/tclThread.c
+++ b/generic/tclThread.c
@@ -5,11 +5,10 @@
* the real work is done in the platform dependent files.
*
* Copyright (c) 1998 by Sun Microsystems, Inc.
+ * 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.
- *
- * RCS: @(#) $Id: tclThread.c,v 1.14 2005/11/02 11:55:47 dkf Exp $
*/
#include "tclInt.h"
@@ -26,7 +25,7 @@
typedef struct {
int num; /* Number of objects remembered */
int max; /* Max size of the array */
- char **list; /* List of pointers */
+ void **list; /* List of pointers */
} SyncObjRecord;
static SyncObjRecord keyRecord = {0, 0, NULL};
@@ -37,8 +36,8 @@ static SyncObjRecord condRecord = {0, 0, NULL};
* Prototypes of functions used only in this file.
*/
-static void ForgetSyncObject(char *objPtr, SyncObjRecord *recPtr);
-static void RememberSyncObject(char *objPtr,
+static void ForgetSyncObject(void *objPtr, SyncObjRecord *recPtr);
+static void RememberSyncObject(void *objPtr,
SyncObjRecord *recPtr);
/*
@@ -84,21 +83,23 @@ Tcl_GetThreadData(
/*
* Initialize the key for this thread.
*/
- result = TclpThreadDataKeyGet(keyPtr);
+
+ result = TclThreadStorageKeyGet(keyPtr);
if (result == NULL) {
- result = (void *) ckalloc((size_t) size);
+ result = ckalloc(size);
memset(result, 0, (size_t) size);
- TclpThreadDataKeySet(keyPtr, result);
+ TclThreadStorageKeySet(keyPtr, result);
}
#else /* TCL_THREADS */
if (*keyPtr == NULL) {
- result = (void *) ckalloc((size_t) size);
- memset((char *) result, 0, (size_t) size);
- *keyPtr = (Tcl_ThreadDataKey)result;
- RememberSyncObject((char *) keyPtr, &keyRecord);
+ result = ckalloc(size);
+ memset(result, 0, (size_t)size);
+ *keyPtr = result;
+ RememberSyncObject(keyPtr, &keyRecord);
+ } else {
+ result = *keyPtr;
}
- result = * (void **) keyPtr;
#endif /* TCL_THREADS */
return result;
}
@@ -122,17 +123,15 @@ Tcl_GetThreadData(
void *
TclThreadDataKeyGet(
- Tcl_ThreadDataKey *keyPtr) /* Identifier for the data chunk, really
- * (pthread_key_t **) */
+ Tcl_ThreadDataKey *keyPtr) /* Identifier for the data chunk. */
+
{
#ifdef TCL_THREADS
- return (void *) TclpThreadDataKeyGet(keyPtr);
+ return TclThreadStorageKeyGet(keyPtr);
#else /* TCL_THREADS */
- char *result = *(char **) keyPtr;
- return (void *) result;
+ return *keyPtr;
#endif /* TCL_THREADS */
}
-
/*
*----------------------------------------------------------------------
@@ -142,6 +141,8 @@ TclThreadDataKeyGet(
* Keep a list of (mutexes/condition variable/data key) used during
* finalization.
*
+ * Assume master lock is held.
+ *
* Results:
* None.
*
@@ -153,32 +154,44 @@ TclThreadDataKeyGet(
static void
RememberSyncObject(
- char *objPtr, /* Pointer to sync object */
+ void *objPtr, /* Pointer to sync object */
SyncObjRecord *recPtr) /* Record of sync objects */
{
- char **newList;
+ void **newList;
int i, j;
+
/*
- * Save the pointer to the allocated object so it can be finalized. Grow
- * the list of pointers if necessary, copying only non-NULL pointers to
- * the new list.
+ * Reuse any free slot in the list.
+ */
+
+ for (i=0 ; i < recPtr->num ; ++i) {
+ if (recPtr->list[i] == NULL) {
+ recPtr->list[i] = objPtr;
+ return;
+ }
+ }
+
+ /*
+ * Grow the list of pointers if necessary, copying only non-NULL
+ * pointers to the new list.
*/
if (recPtr->num >= recPtr->max) {
recPtr->max += 8;
- newList = (char **) ckalloc(recPtr->max * sizeof(char *));
+ newList = ckalloc(recPtr->max * sizeof(void *));
for (i=0,j=0 ; i<recPtr->num ; i++) {
if (recPtr->list[i] != NULL) {
newList[j++] = recPtr->list[i];
}
}
if (recPtr->list != NULL) {
- ckfree((char *) recPtr->list);
+ ckfree(recPtr->list);
}
recPtr->list = newList;
recPtr->num = j;
}
+
recPtr->list[recPtr->num] = objPtr;
recPtr->num++;
}
@@ -189,6 +202,7 @@ RememberSyncObject(
* ForgetSyncObject
*
* Remove a single object from the list.
+ * Assume master lock is held.
*
* Results:
* None.
@@ -201,7 +215,7 @@ RememberSyncObject(
static void
ForgetSyncObject(
- char *objPtr, /* Pointer to sync object */
+ void *objPtr, /* Pointer to sync object */
SyncObjRecord *recPtr) /* Record of sync objects */
{
int i;
@@ -220,6 +234,7 @@ ForgetSyncObject(
* TclRememberMutex
*
* Keep a list of mutexes used during finalization.
+ * Assume master lock is held.
*
* Results:
* None.
@@ -234,7 +249,7 @@ void
TclRememberMutex(
Tcl_Mutex *mutexPtr)
{
- RememberSyncObject((char *)mutexPtr, &mutexRecord);
+ RememberSyncObject(mutexPtr, &mutexRecord);
}
/*
@@ -261,7 +276,9 @@ Tcl_MutexFinalize(
#ifdef TCL_THREADS
TclpFinalizeMutex(mutexPtr);
#endif
- ForgetSyncObject((char *) mutexPtr, &mutexRecord);
+ TclpMasterLock();
+ ForgetSyncObject(mutexPtr, &mutexRecord);
+ TclpMasterUnlock();
}
/*
@@ -270,6 +287,7 @@ Tcl_MutexFinalize(
* TclRememberCondition
*
* Keep a list of condition variables used during finalization.
+ * Assume master lock is held.
*
* Results:
* None.
@@ -284,7 +302,7 @@ void
TclRememberCondition(
Tcl_Condition *condPtr)
{
- RememberSyncObject((char *) condPtr, &condRecord);
+ RememberSyncObject(condPtr, &condRecord);
}
/*
@@ -311,7 +329,9 @@ Tcl_ConditionFinalize(
#ifdef TCL_THREADS
TclpFinalizeCondition(condPtr);
#endif
- ForgetSyncObject((char *) condPtr, &condRecord);
+ TclpMasterLock();
+ ForgetSyncObject(condPtr, &condRecord);
+ TclpMasterUnlock();
}
/*
@@ -319,8 +339,9 @@ Tcl_ConditionFinalize(
*
* TclFinalizeThreadData --
*
- * This function cleans up the thread-local storage. This is called once
- * for each thread.
+ * This function cleans up the thread-local storage. Secondary, it cleans
+ * thread alloc cache.
+ * This is called once for each thread before thread exits.
*
* Results:
* None.
@@ -334,7 +355,10 @@ Tcl_ConditionFinalize(
void
TclFinalizeThreadData(void)
{
- TclpFinalizeThreadDataThread();
+ TclFinalizeThreadDataThread();
+#if defined(TCL_THREADS) && defined(USE_THREAD_ALLOC)
+ TclFinalizeThreadAllocThread();
+#endif
}
/*
@@ -357,32 +381,34 @@ TclFinalizeThreadData(void)
void
TclFinalizeSynchronization(void)
{
-#ifdef TCL_THREADS
- void* blockPtr;
+ int i;
+ void *blockPtr;
Tcl_ThreadDataKey *keyPtr;
+#ifdef TCL_THREADS
Tcl_Mutex *mutexPtr;
Tcl_Condition *condPtr;
- int i;
TclpMasterLock();
+#endif
/*
* If we're running unthreaded, the TSD blocks are simply stored inside
* their thread data keys. Free them here.
*/
- for (i=0 ; i<keyRecord.num ; i++) {
- keyPtr = (Tcl_ThreadDataKey *) keyRecord.list[i];
- blockPtr = (void *) *keyPtr;
- ckfree(blockPtr);
- }
if (keyRecord.list != NULL) {
- ckfree((char *) keyRecord.list);
+ for (i=0 ; i<keyRecord.num ; i++) {
+ keyPtr = (Tcl_ThreadDataKey *) keyRecord.list[i];
+ blockPtr = *keyPtr;
+ ckfree(blockPtr);
+ }
+ ckfree(keyRecord.list);
keyRecord.list = NULL;
}
keyRecord.max = 0;
keyRecord.num = 0;
+#ifdef TCL_THREADS
/*
* Call thread storage master cleanup.
*/
@@ -396,7 +422,7 @@ TclFinalizeSynchronization(void)
}
}
if (mutexRecord.list != NULL) {
- ckfree((char *) mutexRecord.list);
+ ckfree(mutexRecord.list);
mutexRecord.list = NULL;
}
mutexRecord.max = 0;
@@ -409,20 +435,13 @@ TclFinalizeSynchronization(void)
}
}
if (condRecord.list != NULL) {
- ckfree((char *) condRecord.list);
+ ckfree(condRecord.list);
condRecord.list = NULL;
}
condRecord.max = 0;
condRecord.num = 0;
TclpMasterUnlock();
-#else /* TCL_THREADS */
- if (keyRecord.list != NULL) {
- ckfree((char *) keyRecord.list);
- keyRecord.list = NULL;
- }
- keyRecord.max = 0;
- keyRecord.num = 0;
#endif /* TCL_THREADS */
}
@@ -479,7 +498,7 @@ void
Tcl_ConditionWait(
Tcl_Condition *condPtr, /* Really (pthread_cond_t **) */
Tcl_Mutex *mutexPtr, /* Really (pthread_mutex_t **) */
- Tcl_Time *timePtr) /* Timeout on waiting period */
+ const Tcl_Time *timePtr) /* Timeout on waiting period */
{
}