summaryrefslogtreecommitdiffstats
path: root/generic/tclThread.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tclThread.c')
-rw-r--r--generic/tclThread.c210
1 files changed, 113 insertions, 97 deletions
diff --git a/generic/tclThread.c b/generic/tclThread.c
index 17dd0ad..8c972a8 100644
--- a/generic/tclThread.c
+++ b/generic/tclThread.c
@@ -1,15 +1,14 @@
-/*
+/*
* tclThread.c --
*
* This file implements Platform independent thread operations. Most of
* 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.13 2005/08/11 22:06:47 kennykb 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};
@@ -36,13 +35,12 @@ static SyncObjRecord condRecord = {0, 0, NULL};
/*
* Prototypes of functions used only in this file.
*/
-
-static void RememberSyncObject _ANSI_ARGS_((char *objPtr,
- SyncObjRecord *recPtr));
-static void ForgetSyncObject _ANSI_ARGS_((char *objPtr,
- SyncObjRecord *recPtr));
-/*
+static void ForgetSyncObject(void *objPtr, SyncObjRecord *recPtr);
+static void RememberSyncObject(void *objPtr,
+ SyncObjRecord *recPtr);
+
+/*
* Several functions are #defined to nothing in tcl.h if TCL_THREADS is not
* specified. Here we undo that so the functions are defined in the stubs
* table.
@@ -56,7 +54,6 @@ static void ForgetSyncObject _ANSI_ARGS_((char *objPtr,
#undef Tcl_ConditionWait
#undef Tcl_ConditionFinalize
#endif
-
/*
*----------------------------------------------------------------------
@@ -76,31 +73,33 @@ static void ForgetSyncObject _ANSI_ARGS_((char *objPtr,
*----------------------------------------------------------------------
*/
-VOID *
-Tcl_GetThreadData(keyPtr, size)
- Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk */
- int size; /* Size of storage block */
+void *
+Tcl_GetThreadData(
+ Tcl_ThreadDataKey *keyPtr, /* Identifier for the data chunk */
+ int size) /* Size of storage block */
{
- VOID *result;
+ void *result;
#ifdef TCL_THREADS
/*
* Initialize the key for this thread.
*/
- result = TclpThreadDataKeyGet(keyPtr);
+
+ result = TclThreadStorageKeyGet(keyPtr);
if (result == NULL) {
- result = (VOID *)ckalloc((size_t)size);
- memset(result, 0, (size_t)size);
- TclpThreadDataKeySet(keyPtr, result);
+ result = ckalloc(size);
+ memset(result, 0, (size_t) size);
+ 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,19 +121,17 @@ Tcl_GetThreadData(keyPtr, size)
*----------------------------------------------------------------------
*/
-VOID *
-TclThreadDataKeyGet(keyPtr)
- Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk, really
- * (pthread_key_t **) */
+void *
+TclThreadDataKeyGet(
+ 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 */
}
-
/*
*----------------------------------------------------------------------
@@ -144,6 +141,8 @@ TclThreadDataKeyGet(keyPtr)
* Keep a list of (mutexes/condition variable/data key) used during
* finalization.
*
+ * Assume master lock is held.
+ *
* Results:
* None.
*
@@ -154,33 +153,45 @@ TclThreadDataKeyGet(keyPtr)
*/
static void
-RememberSyncObject(objPtr, recPtr)
- char *objPtr; /* Pointer to sync object */
- SyncObjRecord *recPtr; /* Record of sync objects */
+RememberSyncObject(
+ 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++;
}
@@ -191,6 +202,7 @@ RememberSyncObject(objPtr, recPtr)
* ForgetSyncObject
*
* Remove a single object from the list.
+ * Assume master lock is held.
*
* Results:
* None.
@@ -202,9 +214,9 @@ RememberSyncObject(objPtr, recPtr)
*/
static void
-ForgetSyncObject(objPtr, recPtr)
- char *objPtr; /* Pointer to sync object */
- SyncObjRecord *recPtr; /* Record of sync objects */
+ForgetSyncObject(
+ void *objPtr, /* Pointer to sync object */
+ SyncObjRecord *recPtr) /* Record of sync objects */
{
int i;
@@ -222,6 +234,7 @@ ForgetSyncObject(objPtr, recPtr)
* TclRememberMutex
*
* Keep a list of mutexes used during finalization.
+ * Assume master lock is held.
*
* Results:
* None.
@@ -233,10 +246,10 @@ ForgetSyncObject(objPtr, recPtr)
*/
void
-TclRememberMutex(mutexPtr)
- Tcl_Mutex *mutexPtr;
+TclRememberMutex(
+ Tcl_Mutex *mutexPtr)
{
- RememberSyncObject((char *)mutexPtr, &mutexRecord);
+ RememberSyncObject(mutexPtr, &mutexRecord);
}
/*
@@ -257,13 +270,15 @@ TclRememberMutex(mutexPtr)
*/
void
-Tcl_MutexFinalize(mutexPtr)
- Tcl_Mutex *mutexPtr;
+Tcl_MutexFinalize(
+ Tcl_Mutex *mutexPtr)
{
#ifdef TCL_THREADS
TclpFinalizeMutex(mutexPtr);
#endif
- ForgetSyncObject((char *)mutexPtr, &mutexRecord);
+ TclpMasterLock();
+ ForgetSyncObject(mutexPtr, &mutexRecord);
+ TclpMasterUnlock();
}
/*
@@ -272,6 +287,7 @@ Tcl_MutexFinalize(mutexPtr)
* TclRememberCondition
*
* Keep a list of condition variables used during finalization.
+ * Assume master lock is held.
*
* Results:
* None.
@@ -283,10 +299,10 @@ Tcl_MutexFinalize(mutexPtr)
*/
void
-TclRememberCondition(condPtr)
- Tcl_Condition *condPtr;
+TclRememberCondition(
+ Tcl_Condition *condPtr)
{
- RememberSyncObject((char *)condPtr, &condRecord);
+ RememberSyncObject(condPtr, &condRecord);
}
/*
@@ -307,13 +323,15 @@ TclRememberCondition(condPtr)
*/
void
-Tcl_ConditionFinalize(condPtr)
- Tcl_Condition *condPtr;
+Tcl_ConditionFinalize(
+ Tcl_Condition *condPtr)
{
#ifdef TCL_THREADS
TclpFinalizeCondition(condPtr);
#endif
- ForgetSyncObject((char *)condPtr, &condRecord);
+ TclpMasterLock();
+ ForgetSyncObject(condPtr, &condRecord);
+ TclpMasterUnlock();
}
/*
@@ -321,8 +339,9 @@ Tcl_ConditionFinalize(condPtr)
*
* 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,9 +353,12 @@ Tcl_ConditionFinalize(condPtr)
*/
void
-TclFinalizeThreadData()
+TclFinalizeThreadData(void)
{
- TclpFinalizeThreadDataThread();
+ TclFinalizeThreadDataThread();
+#if defined(TCL_THREADS) && defined(USE_THREAD_ALLOC)
+ TclFinalizeThreadAllocThread();
+#endif
}
/*
@@ -357,34 +379,36 @@ TclFinalizeThreadData()
*/
void
-TclFinalizeSynchronization()
+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.
+ /*
+ * 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.
*/
@@ -398,36 +422,28 @@ TclFinalizeSynchronization()
}
}
if (mutexRecord.list != NULL) {
- ckfree((char *)mutexRecord.list);
+ ckfree(mutexRecord.list);
mutexRecord.list = NULL;
}
mutexRecord.max = 0;
mutexRecord.num = 0;
for (i=0 ; i<condRecord.num ; i++) {
- condPtr = (Tcl_Condition *)condRecord.list[i];
+ condPtr = (Tcl_Condition *) condRecord.list[i];
if (condPtr != NULL) {
TclpFinalizeCondition(condPtr);
}
}
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 */
}
-
/*
*----------------------------------------------------------------------
@@ -448,8 +464,8 @@ TclFinalizeSynchronization()
*/
void
-Tcl_ExitThread(status)
- int status;
+Tcl_ExitThread(
+ int status)
{
Tcl_FinalizeThread();
#ifdef TCL_THREADS
@@ -479,31 +495,31 @@ Tcl_ExitThread(status)
#undef Tcl_ConditionWait
void
-Tcl_ConditionWait(condPtr, mutexPtr, timePtr)
- Tcl_Condition *condPtr; /* Really (pthread_cond_t **) */
- Tcl_Mutex *mutexPtr; /* Really (pthread_mutex_t **) */
- Tcl_Time *timePtr; /* Timeout on waiting period */
+Tcl_ConditionWait(
+ Tcl_Condition *condPtr, /* Really (pthread_cond_t **) */
+ Tcl_Mutex *mutexPtr, /* Really (pthread_mutex_t **) */
+ const Tcl_Time *timePtr) /* Timeout on waiting period */
{
}
#undef Tcl_ConditionNotify
void
-Tcl_ConditionNotify(condPtr)
- Tcl_Condition *condPtr;
+Tcl_ConditionNotify(
+ Tcl_Condition *condPtr)
{
}
#undef Tcl_MutexLock
void
-Tcl_MutexLock(mutexPtr)
- Tcl_Mutex *mutexPtr;
+Tcl_MutexLock(
+ Tcl_Mutex *mutexPtr)
{
}
#undef Tcl_MutexUnlock
void
-Tcl_MutexUnlock(mutexPtr)
- Tcl_Mutex *mutexPtr;
+Tcl_MutexUnlock(
+ Tcl_Mutex *mutexPtr)
{
}
#endif /* !TCL_THREADS */