summaryrefslogtreecommitdiffstats
path: root/generic/tclThread.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tclThread.c')
-rw-r--r--generic/tclThread.c354
1 files changed, 211 insertions, 143 deletions
diff --git a/generic/tclThread.c b/generic/tclThread.c
index 8384107..c2f769d 100644
--- a/generic/tclThread.c
+++ b/generic/tclThread.c
@@ -1,21 +1,22 @@
-/*
+/*
* tclThread.c --
*
- * This file implements Platform independent thread operations. Most of
- * the real work is done in the platform dependent files.
+ * 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.
*
- * See the file "license.terms" for information on usage and redistribution of
- * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
/*
- * There are three classes of synchronization objects: mutexes, thread data
- * keys, and condition variables. The following are used to record the memory
- * used for these objects so they can be finalized.
+ * There are three classes of synchronization objects:
+ * mutexes, thread data keys, and condition variables.
+ * The following are used to record the memory used for these
+ * objects so they can be finalized.
*
* These statics are guarded by the mutex in the caller of
* TclRememberThreadData, e.g., TclpThreadDataKeyInit
@@ -32,19 +33,19 @@ static SyncObjRecord mutexRecord = {0, 0, NULL};
static SyncObjRecord condRecord = {0, 0, NULL};
/*
- * Prototypes of functions used only in this file.
+ * 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(char *objPtr, SyncObjRecord *recPtr);
-static void RememberSyncObject(char *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.
+ * specified. Here we undo that so the procedures are defined in the
+ * stubs table.
*/
-
#ifndef TCL_THREADS
#undef Tcl_MutexLock
#undef Tcl_MutexUnlock
@@ -53,51 +54,61 @@ static void RememberSyncObject(char *objPtr,
#undef Tcl_ConditionWait
#undef Tcl_ConditionFinalize
#endif
+
/*
*----------------------------------------------------------------------
*
* Tcl_GetThreadData --
*
- * This function allocates and initializes a chunk of thread local
- * storage.
+ * This procedure allocates and initializes a chunk of thread
+ * local storage.
*
* Results:
* A thread-specific pointer to the data structure.
*
* Side effects:
- * Will allocate memory the first time this thread calls for this chunk
- * of storage.
+ * Will allocate memory the first time this thread calls for
+ * this chunk of storage.
*
*----------------------------------------------------------------------
*/
-void *
-Tcl_GetThreadData(
- Tcl_ThreadDataKey *keyPtr, /* Identifier for the data chunk */
- int size) /* Size of storage block */
+VOID *
+Tcl_GetThreadData(keyPtr, size)
+ Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk */
+ int size; /* Size of storage block */
{
- void *result;
+ VOID *result;
#ifdef TCL_THREADS
+
+ /*
+ * See if this is the first thread to init this key.
+ */
+
+ if (*keyPtr == NULL) {
+ TclpThreadDataKeyInit(keyPtr);
+ }
+
/*
* Initialize the key for this thread.
*/
- result = TclpThreadDataKeyGet(keyPtr);
+ result = TclpThreadDataKeyGet(keyPtr);
if (result == NULL) {
- result = ckalloc((size_t) size);
- memset(result, 0, (size_t) size);
+ result = (VOID *)ckalloc((size_t)size);
+ memset(result, 0, (size_t)size);
TclpThreadDataKeySet(keyPtr, result);
}
-#else /* TCL_THREADS */
+#else
if (*keyPtr == NULL) {
- result = ckalloc((size_t) size);
- memset(result, 0, (size_t) size);
+ result = (VOID *)ckalloc((size_t)size);
+ memset((char *)result, 0, (size_t)size);
*keyPtr = (Tcl_ThreadDataKey)result;
- RememberSyncObject((char *) keyPtr, &keyRecord);
+ TclRememberDataKey(keyPtr);
}
- result = * (void **) keyPtr;
-#endif /* TCL_THREADS */
+ result = *(VOID **)keyPtr;
+#endif
return result;
}
@@ -106,11 +117,11 @@ Tcl_GetThreadData(
*
* TclThreadDataKeyGet --
*
- * This function returns a pointer to a block of thread local storage.
+ * This procedure returns a pointer to a block of thread local storage.
*
* Results:
- * A thread-specific pointer to the data structure, or NULL if the memory
- * has not been assigned to this key for this thread.
+ * A thread-specific pointer to the data structure, or NULL
+ * if the memory has not been assigned to this key for this thread.
*
* Side effects:
* None.
@@ -118,27 +129,61 @@ Tcl_GetThreadData(
*----------------------------------------------------------------------
*/
-void *
-TclThreadDataKeyGet(
- Tcl_ThreadDataKey *keyPtr) /* Identifier for the data chunk, really
- * (pthread_key_t **) */
+VOID *
+TclThreadDataKeyGet(keyPtr)
+ Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk,
+ * really (pthread_key_t **) */
{
#ifdef TCL_THREADS
- return TclpThreadDataKeyGet(keyPtr);
-#else /* TCL_THREADS */
- char *result = *(char **) keyPtr;
- return result;
+ return (VOID *)TclpThreadDataKeyGet(keyPtr);
+#else
+ char *result = *(char **)keyPtr;
+ return (VOID *)result;
+#endif /* TCL_THREADS */
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclThreadDataKeySet --
+ *
+ * This procedure sets a thread local storage pointer.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The assigned value will be returned by TclpThreadDataKeyGet.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclThreadDataKeySet(keyPtr, data)
+ Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk,
+ * really (pthread_key_t **) */
+ VOID *data; /* Thread local storage */
+{
+#ifdef TCL_THREADS
+ if (*keyPtr == NULL) {
+ TclpThreadDataKeyInit(keyPtr);
+ }
+ TclpThreadDataKeySet(keyPtr, data);
+#else
+ *keyPtr = (Tcl_ThreadDataKey)data;
#endif /* TCL_THREADS */
}
+
/*
*----------------------------------------------------------------------
*
* RememberSyncObject
*
- * Keep a list of (mutexes/condition variable/data key) used during
- * finalization.
+ * Keep a list of (mutexes/condition variable/data key)
+ * used during finalization.
*
* Assume master lock is held.
*
@@ -152,23 +197,22 @@ TclThreadDataKeyGet(
*/
static void
-RememberSyncObject(
- char *objPtr, /* Pointer to sync object */
- SyncObjRecord *recPtr) /* Record of sync objects */
+RememberSyncObject(objPtr, recPtr)
+ char *objPtr; /* Pointer to sync object */
+ SyncObjRecord *recPtr; /* Record of sync objects */
{
char **newList;
int i, j;
-
/*
- * Reuse any free slot in the 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;
- }
+ }
}
/*
@@ -178,14 +222,14 @@ RememberSyncObject(
if (recPtr->num >= recPtr->max) {
recPtr->max += 8;
- newList = (char **) ckalloc(recPtr->max * sizeof(char *));
- for (i=0,j=0 ; i<recPtr->num ; i++) {
- if (recPtr->list[i] != NULL) {
+ newList = (char **)ckalloc(recPtr->max * sizeof(char *));
+ 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((char *)recPtr->list);
}
recPtr->list = newList;
recPtr->num = j;
@@ -200,7 +244,7 @@ RememberSyncObject(
*
* ForgetSyncObject
*
- * Remove a single object from the list.
+ * Remove a single object from the list.
* Assume master lock is held.
*
* Results:
@@ -213,9 +257,9 @@ RememberSyncObject(
*/
static void
-ForgetSyncObject(
- char *objPtr, /* Pointer to sync object */
- SyncObjRecord *recPtr) /* Record of sync objects */
+ForgetSyncObject(objPtr, recPtr)
+ char *objPtr; /* Pointer to sync object */
+ SyncObjRecord *recPtr; /* Record of sync objects */
{
int i;
@@ -232,7 +276,7 @@ ForgetSyncObject(
*
* TclRememberMutex
*
- * Keep a list of mutexes used during finalization.
+ * Keep a list of mutexes used during finalization.
* Assume master lock is held.
*
* Results:
@@ -245,8 +289,8 @@ ForgetSyncObject(
*/
void
-TclRememberMutex(
- Tcl_Mutex *mutexPtr)
+TclRememberMutex(mutexPtr)
+ Tcl_Mutex *mutexPtr;
{
RememberSyncObject((char *)mutexPtr, &mutexRecord);
}
@@ -254,10 +298,10 @@ TclRememberMutex(
/*
*----------------------------------------------------------------------
*
- * Tcl_MutexFinalize --
+ * Tcl_MutexFinalize
*
- * Finalize a single mutex and remove it from the list of remembered
- * objects.
+ * Finalize a single mutex and remove it from the
+ * list of remembered objects.
*
* Results:
* None.
@@ -269,23 +313,47 @@ TclRememberMutex(
*/
void
-Tcl_MutexFinalize(
- Tcl_Mutex *mutexPtr)
+Tcl_MutexFinalize(mutexPtr)
+ Tcl_Mutex *mutexPtr;
{
#ifdef TCL_THREADS
TclpFinalizeMutex(mutexPtr);
#endif
TclpMasterLock();
- ForgetSyncObject((char *) mutexPtr, &mutexRecord);
+ ForgetSyncObject((char *)mutexPtr, &mutexRecord);
TclpMasterUnlock();
}
/*
*----------------------------------------------------------------------
*
+ * TclRememberDataKey
+ *
+ * Keep a list of thread data keys used during finalization.
+ * Assume master lock is held.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Add to the key list.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclRememberDataKey(keyPtr)
+ Tcl_ThreadDataKey *keyPtr;
+{
+ RememberSyncObject((char *)keyPtr, &keyRecord);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* TclRememberCondition
*
- * Keep a list of condition variables used during finalization.
+ * Keep a list of condition variables used during finalization.
* Assume master lock is held.
*
* Results:
@@ -298,19 +366,19 @@ Tcl_MutexFinalize(
*/
void
-TclRememberCondition(
- Tcl_Condition *condPtr)
+TclRememberCondition(condPtr)
+ Tcl_Condition *condPtr;
{
- RememberSyncObject((char *) condPtr, &condRecord);
+ RememberSyncObject((char *)condPtr, &condRecord);
}
/*
*----------------------------------------------------------------------
*
- * Tcl_ConditionFinalize --
+ * Tcl_ConditionFinalize
*
- * Finalize a single condition variable and remove it from the list of
- * remembered objects.
+ * Finalize a single condition variable and remove it from the
+ * list of remembered objects.
*
* Results:
* None.
@@ -322,14 +390,14 @@ TclRememberCondition(
*/
void
-Tcl_ConditionFinalize(
- Tcl_Condition *condPtr)
+Tcl_ConditionFinalize(condPtr)
+ Tcl_Condition *condPtr;
{
#ifdef TCL_THREADS
TclpFinalizeCondition(condPtr);
#endif
TclpMasterLock();
- ForgetSyncObject((char *) condPtr, &condRecord);
+ ForgetSyncObject((char *)condPtr, &condRecord);
TclpMasterUnlock();
}
@@ -338,8 +406,8 @@ Tcl_ConditionFinalize(
*
* TclFinalizeThreadData --
*
- * This function cleans up the thread-local storage. This is called once
- * for each thread.
+ * This procedure cleans up the thread-local storage. This is
+ * called once for each thread.
*
* Results:
* None.
@@ -351,9 +419,24 @@ Tcl_ConditionFinalize(
*/
void
-TclFinalizeThreadData(void)
+TclFinalizeThreadData()
{
- TclpFinalizeThreadDataThread();
+ int i;
+ Tcl_ThreadDataKey *keyPtr;
+
+ TclpMasterLock();
+ for (i=0 ; i<keyRecord.num ; i++) {
+ keyPtr = (Tcl_ThreadDataKey *) keyRecord.list[i];
+#ifdef TCL_THREADS
+ TclpFinalizeThreadData(keyPtr);
+#else
+ if (*keyPtr != NULL) {
+ ckfree((char *)*keyPtr);
+ *keyPtr = NULL;
+ }
+#endif
+ }
+ TclpMasterUnlock();
}
/*
@@ -361,8 +444,8 @@ TclFinalizeThreadData(void)
*
* TclFinalizeSynchronization --
*
- * This function cleans up all synchronization objects: mutexes,
- * condition variables, and thread-local storage.
+ * This procedure cleans up all synchronization objects:
+ * mutexes, condition variables, and thread-local storage.
*
* Results:
* None.
@@ -374,41 +457,25 @@ TclFinalizeThreadData(void)
*/
void
-TclFinalizeSynchronization(void)
+TclFinalizeSynchronization()
{
- int i;
- void *blockPtr;
- Tcl_ThreadDataKey *keyPtr;
#ifdef TCL_THREADS
+ Tcl_ThreadDataKey *keyPtr;
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];
+ TclpFinalizeThreadDataKey(keyPtr);
+ }
if (keyRecord.list != NULL) {
- for (i=0 ; i<keyRecord.num ; i++) {
- keyPtr = (Tcl_ThreadDataKey *) keyRecord.list[i];
- blockPtr = (void *) *keyPtr;
- ckfree(blockPtr);
- }
- ckfree((char *) keyRecord.list);
+ ckfree((char *)keyRecord.list);
keyRecord.list = NULL;
}
keyRecord.max = 0;
keyRecord.num = 0;
-
-#ifdef TCL_THREADS
- /*
- * Call thread storage master cleanup.
- */
-
- TclFinalizeThreadStorage();
for (i=0 ; i<mutexRecord.num ; i++) {
mutexPtr = (Tcl_Mutex *)mutexRecord.list[i];
@@ -417,37 +484,45 @@ TclFinalizeSynchronization(void)
}
}
if (mutexRecord.list != NULL) {
- ckfree((char *) mutexRecord.list);
+ ckfree((char *)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((char *)condRecord.list);
condRecord.list = NULL;
}
condRecord.max = 0;
condRecord.num = 0;
TclpMasterUnlock();
-#endif /* TCL_THREADS */
+#else
+ if (keyRecord.list != NULL) {
+ ckfree((char *)keyRecord.list);
+ keyRecord.list = NULL;
+ }
+ keyRecord.max = 0;
+ keyRecord.num = 0;
+#endif
}
+
/*
*----------------------------------------------------------------------
*
* Tcl_ExitThread --
*
- * This function is called to terminate the current thread. This should
- * be used by extensions that create threads with additional interpreters
- * in them.
+ * This procedure is called to terminate the current thread.
+ * This should be used by extensions that create threads with
+ * additional interpreters in them.
*
* Results:
* None.
@@ -459,8 +534,8 @@ TclFinalizeSynchronization(void)
*/
void
-Tcl_ExitThread(
- int status)
+Tcl_ExitThread(status)
+ int status;
{
Tcl_FinalizeThread();
#ifdef TCL_THREADS
@@ -475,9 +550,10 @@ Tcl_ExitThread(
*
* Tcl_ConditionWait, et al. --
*
- * These noop functions are provided so the stub table does not have to
- * be conditionalized for threads. The real implementations of these
- * functions live in the platform specific files.
+ * These noop procedures are provided so the stub table does
+ * not have to be conditionalized for threads. The real
+ * implementations of these functions live in the platform
+ * specific files.
*
* Results:
* None.
@@ -490,39 +566,31 @@ Tcl_ExitThread(
#undef Tcl_ConditionWait
void
-Tcl_ConditionWait(
- Tcl_Condition *condPtr, /* Really (pthread_cond_t **) */
- Tcl_Mutex *mutexPtr, /* Really (pthread_mutex_t **) */
- Tcl_Time *timePtr) /* Timeout on waiting period */
+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 */
{
}
#undef Tcl_ConditionNotify
void
-Tcl_ConditionNotify(
- Tcl_Condition *condPtr)
+Tcl_ConditionNotify(condPtr)
+ Tcl_Condition *condPtr;
{
}
#undef Tcl_MutexLock
void
-Tcl_MutexLock(
- Tcl_Mutex *mutexPtr)
+Tcl_MutexLock(mutexPtr)
+ Tcl_Mutex *mutexPtr;
{
}
#undef Tcl_MutexUnlock
void
-Tcl_MutexUnlock(
- Tcl_Mutex *mutexPtr)
+Tcl_MutexUnlock(mutexPtr)
+ Tcl_Mutex *mutexPtr;
{
}
-#endif /* !TCL_THREADS */
-
-/*
- * Local Variables:
- * mode: c
- * c-basic-offset: 4
- * fill-column: 78
- * End:
- */
+#endif