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, 143 insertions, 211 deletions
diff --git a/generic/tclThread.c b/generic/tclThread.c
index c2f769d..8384107 100644
--- a/generic/tclThread.c
+++ b/generic/tclThread.c
@@ -1,22 +1,21 @@
-/*
+/*
* 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
@@ -33,19 +32,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 procedures are defined in the
- * stubs table.
+ * specified. Here we undo that so the functions are defined in the stubs
+ * table.
*/
+
#ifndef TCL_THREADS
#undef Tcl_MutexLock
#undef Tcl_MutexUnlock
@@ -54,61 +53,51 @@ static void ForgetSyncObject _ANSI_ARGS_((char *objPtr,
#undef Tcl_ConditionWait
#undef Tcl_ConditionFinalize
#endif
-
/*
*----------------------------------------------------------------------
*
* Tcl_GetThreadData --
*
- * This procedure allocates and initializes a chunk of thread
- * local storage.
+ * This function 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(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
-
- /*
- * 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);
+
if (result == NULL) {
- result = (VOID *)ckalloc((size_t)size);
- memset(result, 0, (size_t)size);
+ result = ckalloc((size_t) size);
+ memset(result, 0, (size_t) size);
TclpThreadDataKeySet(keyPtr, result);
}
-#else
+#else /* TCL_THREADS */
if (*keyPtr == NULL) {
- result = (VOID *)ckalloc((size_t)size);
- memset((char *)result, 0, (size_t)size);
+ result = ckalloc((size_t) size);
+ memset(result, 0, (size_t) size);
*keyPtr = (Tcl_ThreadDataKey)result;
- TclRememberDataKey(keyPtr);
+ RememberSyncObject((char *) keyPtr, &keyRecord);
}
- result = *(VOID **)keyPtr;
-#endif
+ result = * (void **) keyPtr;
+#endif /* TCL_THREADS */
return result;
}
@@ -117,11 +106,11 @@ Tcl_GetThreadData(keyPtr, size)
*
* TclThreadDataKeyGet --
*
- * This procedure returns a pointer to a block of thread local storage.
+ * This function 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.
@@ -129,61 +118,27 @@ Tcl_GetThreadData(keyPtr, size)
*----------------------------------------------------------------------
*/
-VOID *
-TclThreadDataKeyGet(keyPtr)
- Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk,
- * really (pthread_key_t **) */
-{
-#ifdef TCL_THREADS
- 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 */
+void *
+TclThreadDataKeyGet(
+ Tcl_ThreadDataKey *keyPtr) /* Identifier for the data chunk, really
+ * (pthread_key_t **) */
{
#ifdef TCL_THREADS
- if (*keyPtr == NULL) {
- TclpThreadDataKeyInit(keyPtr);
- }
- TclpThreadDataKeySet(keyPtr, data);
-#else
- *keyPtr = (Tcl_ThreadDataKey)data;
+ return TclpThreadDataKeyGet(keyPtr);
+#else /* TCL_THREADS */
+ char *result = *(char **) keyPtr;
+ return result;
#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.
*
@@ -197,22 +152,23 @@ TclThreadDataKeySet(keyPtr, data)
*/
static void
-RememberSyncObject(objPtr, recPtr)
- char *objPtr; /* Pointer to sync object */
- SyncObjRecord *recPtr; /* Record of sync objects */
+RememberSyncObject(
+ 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;
- }
+ }
}
/*
@@ -222,14 +178,14 @@ RememberSyncObject(objPtr, recPtr)
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;
@@ -244,7 +200,7 @@ RememberSyncObject(objPtr, recPtr)
*
* ForgetSyncObject
*
- * Remove a single object from the list.
+ * Remove a single object from the list.
* Assume master lock is held.
*
* Results:
@@ -257,9 +213,9 @@ RememberSyncObject(objPtr, recPtr)
*/
static void
-ForgetSyncObject(objPtr, recPtr)
- char *objPtr; /* Pointer to sync object */
- SyncObjRecord *recPtr; /* Record of sync objects */
+ForgetSyncObject(
+ char *objPtr, /* Pointer to sync object */
+ SyncObjRecord *recPtr) /* Record of sync objects */
{
int i;
@@ -276,7 +232,7 @@ ForgetSyncObject(objPtr, recPtr)
*
* TclRememberMutex
*
- * Keep a list of mutexes used during finalization.
+ * Keep a list of mutexes used during finalization.
* Assume master lock is held.
*
* Results:
@@ -289,8 +245,8 @@ ForgetSyncObject(objPtr, recPtr)
*/
void
-TclRememberMutex(mutexPtr)
- Tcl_Mutex *mutexPtr;
+TclRememberMutex(
+ Tcl_Mutex *mutexPtr)
{
RememberSyncObject((char *)mutexPtr, &mutexRecord);
}
@@ -298,10 +254,10 @@ TclRememberMutex(mutexPtr)
/*
*----------------------------------------------------------------------
*
- * 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.
@@ -313,47 +269,23 @@ TclRememberMutex(mutexPtr)
*/
void
-Tcl_MutexFinalize(mutexPtr)
- Tcl_Mutex *mutexPtr;
+Tcl_MutexFinalize(
+ 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:
@@ -366,19 +298,19 @@ TclRememberDataKey(keyPtr)
*/
void
-TclRememberCondition(condPtr)
- Tcl_Condition *condPtr;
+TclRememberCondition(
+ 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.
@@ -390,14 +322,14 @@ TclRememberCondition(condPtr)
*/
void
-Tcl_ConditionFinalize(condPtr)
- Tcl_Condition *condPtr;
+Tcl_ConditionFinalize(
+ Tcl_Condition *condPtr)
{
#ifdef TCL_THREADS
TclpFinalizeCondition(condPtr);
#endif
TclpMasterLock();
- ForgetSyncObject((char *)condPtr, &condRecord);
+ ForgetSyncObject((char *) condPtr, &condRecord);
TclpMasterUnlock();
}
@@ -406,8 +338,8 @@ Tcl_ConditionFinalize(condPtr)
*
* TclFinalizeThreadData --
*
- * This procedure cleans up the thread-local storage. This is
- * called once for each thread.
+ * This function cleans up the thread-local storage. This is called once
+ * for each thread.
*
* Results:
* None.
@@ -419,24 +351,9 @@ Tcl_ConditionFinalize(condPtr)
*/
void
-TclFinalizeThreadData()
+TclFinalizeThreadData(void)
{
- 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();
+ TclpFinalizeThreadDataThread();
}
/*
@@ -444,8 +361,8 @@ TclFinalizeThreadData()
*
* TclFinalizeSynchronization --
*
- * This procedure cleans up all synchronization objects:
- * mutexes, condition variables, and thread-local storage.
+ * This function cleans up all synchronization objects: mutexes,
+ * condition variables, and thread-local storage.
*
* Results:
* None.
@@ -457,25 +374,41 @@ TclFinalizeThreadData()
*/
void
-TclFinalizeSynchronization()
+TclFinalizeSynchronization(void)
{
-#ifdef TCL_THREADS
+ int i;
+ void *blockPtr;
Tcl_ThreadDataKey *keyPtr;
+#ifdef TCL_THREADS
Tcl_Mutex *mutexPtr;
Tcl_Condition *condPtr;
- int i;
TclpMasterLock();
- for (i=0 ; i<keyRecord.num ; i++) {
- keyPtr = (Tcl_ThreadDataKey *)keyRecord.list[i];
- TclpFinalizeThreadDataKey(keyPtr);
- }
+#endif
+
+ /*
+ * If we're running unthreaded, the TSD blocks are simply stored inside
+ * their thread data keys. Free them here.
+ */
+
if (keyRecord.list != NULL) {
- ckfree((char *)keyRecord.list);
+ for (i=0 ; i<keyRecord.num ; i++) {
+ keyPtr = (Tcl_ThreadDataKey *) keyRecord.list[i];
+ blockPtr = (void *) *keyPtr;
+ ckfree(blockPtr);
+ }
+ 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];
@@ -484,45 +417,37 @@ TclFinalizeSynchronization()
}
}
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();
-#else
- if (keyRecord.list != NULL) {
- ckfree((char *)keyRecord.list);
- keyRecord.list = NULL;
- }
- keyRecord.max = 0;
- keyRecord.num = 0;
-#endif
+#endif /* TCL_THREADS */
}
-
/*
*----------------------------------------------------------------------
*
* Tcl_ExitThread --
*
- * This procedure is called to terminate the current thread.
- * This should be used by extensions that create threads with
- * additional interpreters in them.
+ * This function is called to terminate the current thread. This should
+ * be used by extensions that create threads with additional interpreters
+ * in them.
*
* Results:
* None.
@@ -534,8 +459,8 @@ TclFinalizeSynchronization()
*/
void
-Tcl_ExitThread(status)
- int status;
+Tcl_ExitThread(
+ int status)
{
Tcl_FinalizeThread();
#ifdef TCL_THREADS
@@ -550,10 +475,9 @@ Tcl_ExitThread(status)
*
* Tcl_ConditionWait, et al. --
*
- * 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.
+ * 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.
*
* Results:
* None.
@@ -566,31 +490,39 @@ 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 **) */
+ 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
+#endif /* !TCL_THREADS */
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */