summaryrefslogtreecommitdiffstats
path: root/unix/tclUnixThrd.c
diff options
context:
space:
mode:
Diffstat (limited to 'unix/tclUnixThrd.c')
-rw-r--r--unix/tclUnixThrd.c582
1 files changed, 323 insertions, 259 deletions
diff --git a/unix/tclUnixThrd.c b/unix/tclUnixThrd.c
index ad36242..7b99896 100644
--- a/unix/tclUnixThrd.c
+++ b/unix/tclUnixThrd.c
@@ -1,4 +1,4 @@
-/*
+/*
* tclUnixThrd.c --
*
* This file implements the UNIX-specific thread support.
@@ -6,14 +6,17 @@
* Copyright (c) 1991-1994 The Regents of the University of California.
* Copyright (c) 1994-1997 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"
+#include "tclPort.h"
#ifdef TCL_THREADS
+#include "pthread.h"
+
typedef struct ThreadSpecificData {
char nabuf[16];
} ThreadSpecificData;
@@ -21,23 +24,24 @@ typedef struct ThreadSpecificData {
static Tcl_ThreadDataKey dataKey;
/*
- * masterLock is used to serialize creation of mutexes, condition variables,
- * and thread local storage. This is the only place that can count on the
- * ability to statically initialize the mutex.
+ * masterLock is used to serialize creation of mutexes, condition
+ * variables, and thread local storage.
+ * This is the only place that can count on the ability to statically
+ * initialize the mutex.
*/
static pthread_mutex_t masterLock = PTHREAD_MUTEX_INITIALIZER;
/*
- * initLock is used to serialize initialization and finalization of Tcl. It
- * cannot use any dyamically allocated storage.
+ * initLock is used to serialize initialization and finalization
+ * of Tcl. It cannot use any dyamically allocated storage.
*/
static pthread_mutex_t initLock = PTHREAD_MUTEX_INITIALIZER;
/*
- * allocLock is used by Tcl's version of malloc for synchronization. For
- * obvious reasons, cannot use any dyamically allocated storage.
+ * allocLock is used by Tcl's version of malloc for synchronization.
+ * For obvious reasons, cannot use any dyamically allocated storage.
*/
static pthread_mutex_t allocLock = PTHREAD_MUTEX_INITIALIZER;
@@ -61,8 +65,8 @@ static pthread_mutex_t *allocLockPtr = &allocLock;
* This procedure creates a new thread.
*
* Results:
- * TCL_OK if the thread could be created. The thread ID is returned in a
- * parameter.
+ * TCL_OK if the thread could be created. The thread ID is
+ * returned in a parameter.
*
* Side effects:
* A new thread is created.
@@ -71,13 +75,13 @@ static pthread_mutex_t *allocLockPtr = &allocLock;
*/
int
-TclpThreadCreate(
- Tcl_ThreadId *idPtr, /* Return, the ID of the thread */
- Tcl_ThreadCreateProc proc, /* Main() function of the thread */
- ClientData clientData, /* The one argument to Main() */
- int stackSize, /* Size of stack for the new thread */
- int flags) /* Flags controlling behaviour of the new
- * thread. */
+TclpThreadCreate(idPtr, proc, clientData, stackSize, flags)
+ Tcl_ThreadId *idPtr; /* Return, the ID of the thread */
+ Tcl_ThreadCreateProc proc; /* Main() function of the thread */
+ ClientData clientData; /* The one argument to Main() */
+ int stackSize; /* Size of stack for the new thread */
+ int flags; /* Flags controlling behaviour of
+ * the new thread */
{
#ifdef TCL_THREADS
pthread_attr_t attr;
@@ -89,14 +93,14 @@ TclpThreadCreate(
#ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE
if (stackSize != TCL_THREAD_STACK_DEFAULT) {
- pthread_attr_setstacksize(&attr, (size_t) stackSize);
+ pthread_attr_setstacksize(&attr, (size_t) stackSize);
#ifdef TCL_THREAD_STACK_MIN
} else {
- /*
- * Certain systems define a thread stack size that by default is too
- * small for many operations. The user has the option of defining
- * TCL_THREAD_STACK_MIN to a value large enough to work for their
- * needs. This would look like (for 128K min stack):
+ /*
+ * Certain systems define a thread stack size that by default is
+ * too small for many operations. The user has the option of
+ * defining TCL_THREAD_STACK_MIN to a value large enough to work
+ * for their needs. This would look like (for 128K min stack):
* make MEM_DEBUG_FLAGS=-DTCL_THREAD_STACK_MIN=131072L
*
* This solution is not optimal, as we should allow the user to
@@ -104,7 +108,7 @@ TclpThreadCreate(
* down, and that would still leave the main thread at the default.
*/
- size_t size;
+ size_t size;
result = pthread_attr_getstacksize(&attr, &size);
if (!result && (size < TCL_THREAD_STACK_MIN)) {
pthread_attr_setstacksize(&attr, (size_t) TCL_THREAD_STACK_MIN);
@@ -113,14 +117,14 @@ TclpThreadCreate(
}
#endif
if (! (flags & TCL_THREAD_JOINABLE)) {
- pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
+ pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
}
if (pthread_create(&theThread, &attr,
- (void * (*)(void *))proc, (void *)clientData) &&
+ (void * (*)())proc, (void *)clientData) &&
pthread_create(&theThread, NULL,
- (void * (*)(void *))proc, (void *)clientData)) {
+ (void * (*)())proc, (void *)clientData)) {
result = TCL_ERROR;
} else {
*idPtr = (Tcl_ThreadId)theThread;
@@ -144,23 +148,24 @@ TclpThreadCreate(
* TCL_OK if the wait was successful, TCL_ERROR else.
*
* Side effects:
- * The result area is set to the exit code of the thread we waited upon.
+ * The result area is set to the exit code of the thread we
+ * waited upon.
*
*----------------------------------------------------------------------
*/
int
-Tcl_JoinThread(
- Tcl_ThreadId threadId, /* Id of the thread to wait upon. */
- int *state) /* Reference to the storage the result of the
- * thread we wait upon will be written into.
- * May be NULL. */
+Tcl_JoinThread(threadId, state)
+ Tcl_ThreadId threadId; /* Id of the thread to wait upon */
+ int* state; /* Reference to the storage the result
+ * of the thread we wait upon will be
+ * written into. */
{
#ifdef TCL_THREADS
int result;
- unsigned long retcode, *retcodePtr = &retcode;
+ unsigned long retcode;
- result = pthread_join((pthread_t) threadId, (void**) retcodePtr);
+ result = pthread_join((pthread_t) threadId, (void**) &retcode);
if (state) {
*state = (int) retcode;
}
@@ -188,103 +193,10 @@ Tcl_JoinThread(
*/
void
-TclpThreadExit(
- int status)
-{
- pthread_exit(INT2PTR(status));
-}
-#endif /* TCL_THREADS */
-
-#ifdef TCL_THREADS
-/*
- *----------------------------------------------------------------------
- *
- * TclpThreadGetStackSize --
- *
- * This procedure returns the size of the current thread's stack.
- *
- * Results:
- * Stack size (in bytes?) or -1 for error or 0 for undeterminable.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-size_t
-TclpThreadGetStackSize(void)
+TclpThreadExit(status)
+ int status;
{
- size_t stackSize = 0;
-#if defined(HAVE_PTHREAD_ATTR_SETSTACKSIZE) && defined(TclpPthreadGetAttrs)
- pthread_attr_t threadAttr; /* This will hold the thread attributes for
- * the current thread. */
-#ifdef __GLIBC__
- /*
- * Fix for [Bug 1815573]
- *
- * DESCRIPTION:
- * On linux TclpPthreadGetAttrs (which is pthread_attr_get_np) may return
- * bogus values on the initial thread.
- *
- * ASSUMPTIONS:
- * There seems to be no api to determine if we are on the initial
- * thread. The simple scheme implemented here assumes:
- * 1. The first Tcl interp to be created lives in the initial thread. If
- * this assumption is not true, the fix is to call
- * TclpThreadGetStackSize from the initial thread previous to
- * creating any Tcl interpreter. In this case, especially if another
- * Tcl interpreter may be created in the initial thread, it might be
- * better to enable the second branch in the #if below
- * 2. There will be no races in creating the first Tcl interp - ie, the
- * second Tcl interp will be created only after the first call to
- * Tcl_CreateInterp returns.
- *
- * These assumptions are satisfied by tclsh. Embedders on linux may want
- * to check their validity, and possibly adapt the code on failing to meet
- * them.
- */
-
- static int initialized = 0;
-
- if (!initialized) {
- initialized = 1;
- return 0;
- } else {
-#else
- {
-#endif
- if (pthread_attr_init(&threadAttr) != 0) {
- return -1;
- }
- if (TclpPthreadGetAttrs(pthread_self(), &threadAttr) != 0) {
- pthread_attr_destroy(&threadAttr);
- return (size_t)-1;
- }
- }
-
-
- if (pthread_attr_getstacksize(&threadAttr, &stackSize) != 0) {
- pthread_attr_destroy(&threadAttr);
- return (size_t)-1;
- }
- pthread_attr_destroy(&threadAttr);
-#elif defined(HAVE_PTHREAD_GET_STACKSIZE_NP)
-#ifdef __APPLE__
- /*
- * On Darwin, the API below does not return the correct stack size for the
- * main thread (which is not a real pthread), so fallback to getrlimit().
- */
- if (!pthread_main_np())
-#endif
- stackSize = pthread_get_stacksize_np(pthread_self());
-#else
- /*
- * Cannot determine the real stack size of this thread. The caller might
- * want to try looking at the process accounting limits instead.
- */
-#endif
- return stackSize;
+ pthread_exit((VOID *)status);
}
#endif /* TCL_THREADS */
@@ -305,7 +217,7 @@ TclpThreadGetStackSize(void)
*/
Tcl_ThreadId
-Tcl_GetCurrentThread(void)
+Tcl_GetCurrentThread()
{
#ifdef TCL_THREADS
return (Tcl_ThreadId) pthread_self();
@@ -313,6 +225,7 @@ Tcl_GetCurrentThread(void)
return (Tcl_ThreadId) 0;
#endif
}
+
/*
*----------------------------------------------------------------------
@@ -320,9 +233,9 @@ Tcl_GetCurrentThread(void)
* TclpInitLock
*
* This procedure is used to grab a lock that serializes initialization
- * and finalization of Tcl. On some platforms this may also initialize
- * the mutex used to serialize creation of more mutexes and thread local
- * storage keys.
+ * and finalization of Tcl. On some platforms this may also initialize
+ * the mutex used to serialize creation of more mutexes and thread
+ * local storage keys.
*
* Results:
* None.
@@ -334,7 +247,7 @@ Tcl_GetCurrentThread(void)
*/
void
-TclpInitLock(void)
+TclpInitLock()
{
#ifdef TCL_THREADS
pthread_mutex_lock(&initLock);
@@ -346,29 +259,28 @@ TclpInitLock(void)
*
* TclpFinalizeLock
*
- * This procedure is used to destroy all private resources used in this
- * file.
+ * This procedure is used to destroy all private resources used in
+ * this file.
*
* Results:
* None.
*
* Side effects:
- * Destroys everything private. TclpInitLock must be held entering this
- * function.
+ * Destroys everything private. TclpInitLock must be held
+ * entering this function.
*
*----------------------------------------------------------------------
*/
void
-TclFinalizeLock(void)
+TclFinalizeLock ()
{
#ifdef TCL_THREADS
/*
* You do not need to destroy mutexes that were created with the
- * PTHREAD_MUTEX_INITIALIZER macro. These mutexes do not need any
- * destruction: masterLock, allocLock, and initLock.
+ * PTHREAD_MUTEX_INITIALIZER macro. These mutexes do not need
+ * any destruction: masterLock, allocLock, and initLock.
*/
-
pthread_mutex_unlock(&initLock);
#endif
}
@@ -378,8 +290,8 @@ TclFinalizeLock(void)
*
* TclpInitUnlock
*
- * This procedure is used to release a lock that serializes
- * initialization and finalization of Tcl.
+ * This procedure is used to release a lock that serializes initialization
+ * and finalization of Tcl.
*
* Results:
* None.
@@ -391,7 +303,7 @@ TclFinalizeLock(void)
*/
void
-TclpInitUnlock(void)
+TclpInitUnlock()
{
#ifdef TCL_THREADS
pthread_mutex_unlock(&initLock);
@@ -403,12 +315,13 @@ TclpInitUnlock(void)
*
* TclpMasterLock
*
- * This procedure is used to grab a lock that serializes creation and
- * finalization of serialization objects. This interface is only needed
- * in finalization; it is hidden during creation of the objects.
+ * This procedure is used to grab a lock that serializes creation
+ * and finalization of serialization objects. This interface is
+ * only needed in finalization; it is hidden during
+ * creation of the objects.
*
- * This lock must be different than the initLock because the initLock is
- * held during creation of syncronization objects.
+ * This lock must be different than the initLock because the
+ * initLock is held during creation of syncronization objects.
*
* Results:
* None.
@@ -420,7 +333,7 @@ TclpInitUnlock(void)
*/
void
-TclpMasterLock(void)
+TclpMasterLock()
{
#ifdef TCL_THREADS
pthread_mutex_lock(&masterLock);
@@ -433,8 +346,8 @@ TclpMasterLock(void)
*
* TclpMasterUnlock
*
- * This procedure is used to release a lock that serializes creation and
- * finalization of synchronization objects.
+ * This procedure is used to release a lock that serializes creation
+ * and finalization of synchronization objects.
*
* Results:
* None.
@@ -446,7 +359,7 @@ TclpMasterLock(void)
*/
void
-TclpMasterUnlock(void)
+TclpMasterUnlock()
{
#ifdef TCL_THREADS
pthread_mutex_unlock(&masterLock);
@@ -459,13 +372,13 @@ TclpMasterUnlock(void)
*
* Tcl_GetAllocMutex
*
- * This procedure returns a pointer to a statically initialized mutex for
- * use by the memory allocator. The alloctor must use this lock, because
- * all other locks are allocated...
+ * This procedure returns a pointer to a statically initialized
+ * mutex for use by the memory allocator. The alloctor must
+ * use this lock, because all other locks are allocated...
*
* Results:
- * A pointer to a mutex that is suitable for passing to Tcl_MutexLock and
- * Tcl_MutexUnlock.
+ * A pointer to a mutex that is suitable for passing to
+ * Tcl_MutexLock and Tcl_MutexUnlock.
*
* Side effects:
* None.
@@ -474,11 +387,10 @@ TclpMasterUnlock(void)
*/
Tcl_Mutex *
-Tcl_GetAllocMutex(void)
+Tcl_GetAllocMutex()
{
#ifdef TCL_THREADS
- pthread_mutex_t **allocLockPtrPtr = &allocLockPtr;
- return (Tcl_Mutex *) allocLockPtrPtr;
+ return (Tcl_Mutex *)&allocLockPtr;
#else
return NULL;
#endif
@@ -491,34 +403,34 @@ Tcl_GetAllocMutex(void)
*
* Tcl_MutexLock --
*
- * This procedure is invoked to lock a mutex. This procedure handles
- * initializing the mutex, if necessary. The caller can rely on the fact
- * that Tcl_Mutex is an opaque pointer. This routine will change that
- * pointer from NULL after first use.
+ * This procedure is invoked to lock a mutex. This procedure
+ * handles initializing the mutex, if necessary. The caller
+ * can rely on the fact that Tcl_Mutex is an opaque pointer.
+ * This routine will change that pointer from NULL after first use.
*
* Results:
* None.
*
* Side effects:
- * May block the current thread. The mutex is aquired when this returns.
- * Will allocate memory for a pthread_mutex_t and initialize this the
- * first time this Tcl_Mutex is used.
+ * May block the current thread. The mutex is aquired when
+ * this returns. Will allocate memory for a pthread_mutex_t
+ * and initialize this the first time this Tcl_Mutex is used.
*
*----------------------------------------------------------------------
*/
void
-Tcl_MutexLock(
- Tcl_Mutex *mutexPtr) /* Really (pthread_mutex_t **) */
+Tcl_MutexLock(mutexPtr)
+ Tcl_Mutex *mutexPtr; /* Really (pthread_mutex_t **) */
{
pthread_mutex_t *pmutexPtr;
if (*mutexPtr == NULL) {
MASTER_LOCK;
if (*mutexPtr == NULL) {
- /*
+ /*
* Double inside master lock check to avoid a race condition.
*/
-
+
pmutexPtr = (pthread_mutex_t *)ckalloc(sizeof(pthread_mutex_t));
pthread_mutex_init(pmutexPtr, NULL);
*mutexPtr = (Tcl_Mutex)pmutexPtr;
@@ -529,14 +441,15 @@ Tcl_MutexLock(
pmutexPtr = *((pthread_mutex_t **)mutexPtr);
pthread_mutex_lock(pmutexPtr);
}
+
/*
*----------------------------------------------------------------------
*
* Tcl_MutexUnlock --
*
- * This procedure is invoked to unlock a mutex. The mutex must have been
- * locked by Tcl_MutexLock.
+ * This procedure is invoked to unlock a mutex. The mutex must
+ * have been locked by Tcl_MutexLock.
*
* Results:
* None.
@@ -548,20 +461,21 @@ Tcl_MutexLock(
*/
void
-Tcl_MutexUnlock(
- Tcl_Mutex *mutexPtr) /* Really (pthread_mutex_t **) */
+Tcl_MutexUnlock(mutexPtr)
+ Tcl_Mutex *mutexPtr; /* Really (pthread_mutex_t **) */
{
pthread_mutex_t *pmutexPtr = *(pthread_mutex_t **)mutexPtr;
pthread_mutex_unlock(pmutexPtr);
}
+
/*
*----------------------------------------------------------------------
*
* TclpFinalizeMutex --
*
- * This procedure is invoked to clean up one mutex. This is only safe to
- * call at the end of time.
+ * This procedure is invoked to clean up one mutex. This is only
+ * safe to call at the end of time.
*
* This assumes the Master Lock is held.
*
@@ -575,25 +489,194 @@ Tcl_MutexUnlock(
*/
void
-TclpFinalizeMutex(
- Tcl_Mutex *mutexPtr)
+TclpFinalizeMutex(mutexPtr)
+ Tcl_Mutex *mutexPtr;
{
pthread_mutex_t *pmutexPtr = *(pthread_mutex_t **)mutexPtr;
if (pmutexPtr != NULL) {
- pthread_mutex_destroy(pmutexPtr);
- ckfree((char *) pmutexPtr);
+ pthread_mutex_destroy(pmutexPtr);
+ ckfree((char *)pmutexPtr);
*mutexPtr = NULL;
}
}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpThreadDataKeyInit --
+ *
+ * This procedure initializes a thread specific data block key.
+ * Each thread has table of pointers to thread specific data.
+ * all threads agree on which table entry is used by each module.
+ * this is remembered in a "data key", that is just an index into
+ * this table. To allow self initialization, the interface
+ * passes a pointer to this key and the first thread to use
+ * the key fills in the pointer to the key. The key should be
+ * a process-wide static.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Will allocate memory the first time this process calls for
+ * this key. In this case it modifies its argument
+ * to hold the pointer to information about the key.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclpThreadDataKeyInit(keyPtr)
+ Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk,
+ * really (pthread_key_t **) */
+{
+ pthread_key_t *pkeyPtr;
+
+ MASTER_LOCK;
+ if (*keyPtr == NULL) {
+ pkeyPtr = (pthread_key_t *)ckalloc(sizeof(pthread_key_t));
+ pthread_key_create(pkeyPtr, NULL);
+ *keyPtr = (Tcl_ThreadDataKey)pkeyPtr;
+ TclRememberDataKey(keyPtr);
+ }
+ MASTER_UNLOCK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpThreadDataKeyGet --
+ *
+ * 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.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+VOID *
+TclpThreadDataKeyGet(keyPtr)
+ Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk,
+ * really (pthread_key_t **) */
+{
+ pthread_key_t *pkeyPtr = *(pthread_key_t **)keyPtr;
+ if (pkeyPtr == NULL) {
+ return NULL;
+ } else {
+ return (VOID *)pthread_getspecific(*pkeyPtr);
+ }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpThreadDataKeySet --
+ *
+ * This procedure sets the pointer to a block of thread local storage.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Sets up the thread so future calls to TclpThreadDataKeyGet with
+ * this key will return the data pointer.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclpThreadDataKeySet(keyPtr, data)
+ Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk,
+ * really (pthread_key_t **) */
+ VOID *data; /* Thread local storage */
+{
+ pthread_key_t *pkeyPtr = *(pthread_key_t **)keyPtr;
+ pthread_setspecific(*pkeyPtr, data);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpFinalizeThreadData --
+ *
+ * This procedure cleans up the thread-local storage. This is
+ * called once for each thread.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Frees up all thread local storage.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclpFinalizeThreadData(keyPtr)
+ Tcl_ThreadDataKey *keyPtr;
+{
+ VOID *result;
+ pthread_key_t *pkeyPtr;
+
+ if (*keyPtr != NULL) {
+ pkeyPtr = *(pthread_key_t **)keyPtr;
+ result = (VOID *)pthread_getspecific(*pkeyPtr);
+ if (result != NULL) {
+ ckfree((char *)result);
+ pthread_setspecific(*pkeyPtr, (void *)NULL);
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpFinalizeThreadDataKey --
+ *
+ * This procedure is invoked to clean up one key. This is a
+ * process-wide storage identifier. The thread finalization code
+ * cleans up the thread local storage itself.
+ *
+ * This assumes the master lock is held.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The key is deallocated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclpFinalizeThreadDataKey(keyPtr)
+ Tcl_ThreadDataKey *keyPtr;
+{
+ pthread_key_t *pkeyPtr;
+ if (*keyPtr != NULL) {
+ pkeyPtr = *(pthread_key_t **)keyPtr;
+ pthread_key_delete(*pkeyPtr);
+ ckfree((char *)pkeyPtr);
+ *keyPtr = NULL;
+ }
+}
+
/*
*----------------------------------------------------------------------
*
* Tcl_ConditionWait --
*
- * This procedure is invoked to wait on a condition variable. The mutex
- * is automically released as part of the wait, and automatically grabbed
- * when the condition is signaled.
+ * This procedure is invoked to wait on a condition variable.
+ * The mutex is automically released as part of the wait, and
+ * automatically grabbed when the condition is signaled.
*
* The mutex must be held when this procedure is called.
*
@@ -601,18 +684,18 @@ TclpFinalizeMutex(
* None.
*
* Side effects:
- * May block the current thread. The mutex is aquired when this returns.
- * Will allocate memory for a pthread_mutex_t and initialize this the
- * first time this Tcl_Mutex is used.
+ * May block the current thread. The mutex is aquired when
+ * this returns. Will allocate memory for a pthread_mutex_t
+ * and initialize this the first time this Tcl_Mutex is used.
*
*----------------------------------------------------------------------
*/
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 */
{
pthread_cond_t *pcondPtr;
pthread_mutex_t *pmutexPtr;
@@ -621,13 +704,13 @@ Tcl_ConditionWait(
if (*condPtr == NULL) {
MASTER_LOCK;
- /*
- * Double check inside mutex to avoid race, then initialize condition
- * variable if necessary.
+ /*
+ * Double check inside mutex to avoid race,
+ * then initialize condition variable if necessary.
*/
if (*condPtr == NULL) {
- pcondPtr = (pthread_cond_t *) ckalloc(sizeof(pthread_cond_t));
+ pcondPtr = (pthread_cond_t *)ckalloc(sizeof(pthread_cond_t));
pthread_cond_init(pcondPtr, NULL);
*condPtr = (Tcl_Condition)pcondPtr;
TclRememberCondition(condPtr);
@@ -661,8 +744,8 @@ Tcl_ConditionWait(
*
* This procedure is invoked to signal a condition variable.
*
- * The mutex must be held during this call to avoid races, but this
- * interface does not enforce that.
+ * The mutex must be held during this call to avoid races,
+ * but this interface does not enforce that.
*
* Results:
* None.
@@ -674,8 +757,8 @@ Tcl_ConditionWait(
*/
void
-Tcl_ConditionNotify(
- Tcl_Condition *condPtr)
+Tcl_ConditionNotify(condPtr)
+ Tcl_Condition *condPtr;
{
pthread_cond_t *pcondPtr = *((pthread_cond_t **)condPtr);
if (pcondPtr != NULL) {
@@ -686,14 +769,15 @@ Tcl_ConditionNotify(
*/
}
}
+
/*
*----------------------------------------------------------------------
*
* TclpFinalizeCondition --
*
- * This procedure is invoked to clean up a condition variable. This is
- * only safe to call at the end of time.
+ * This procedure is invoked to clean up a condition variable.
+ * This is only safe to call at the end of time.
*
* This assumes the Master Lock is held.
*
@@ -707,13 +791,13 @@ Tcl_ConditionNotify(
*/
void
-TclpFinalizeCondition(
- Tcl_Condition *condPtr)
+TclpFinalizeCondition(condPtr)
+ Tcl_Condition *condPtr;
{
pthread_cond_t *pcondPtr = *(pthread_cond_t **)condPtr;
if (pcondPtr != NULL) {
pthread_cond_destroy(pcondPtr);
- ckfree((char *) pcondPtr);
+ ckfree((char *)pcondPtr);
*condPtr = NULL;
}
}
@@ -724,8 +808,8 @@ TclpFinalizeCondition(
*
* TclpReaddir, TclpInetNtoa --
*
- * These procedures replace core C versions to be used in a threaded
- * environment.
+ * These procedures replace core C versions to be used in a
+ * threaded environment.
*
* Results:
* See documentation of C functions.
@@ -734,22 +818,19 @@ TclpFinalizeCondition(
* See documentation of C functions.
*
* Notes:
- * TclpReaddir is no longer used by the core (see 1095909), but it
- * appears in the internal stubs table (see #589526).
- *
+ * TclpReaddir is no longer used by the core (see 1095909),
+ * but it appears in the internal stubs table (see #589526).
*----------------------------------------------------------------------
*/
Tcl_DirEntry *
-TclpReaddir(
- DIR * dir)
+TclpReaddir(DIR * dir)
{
return TclOSreaddir(dir);
}
char *
-TclpInetNtoa(
- struct in_addr addr)
+TclpInetNtoa(struct in_addr addr)
{
#ifdef TCL_THREADS
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
@@ -761,18 +842,17 @@ TclpInetNtoa(
return inet_ntoa(addr);
#endif
}
-
-#ifdef TCL_THREADS
+
+#if defined(TCL_THREADS) && defined(USE_THREAD_ALLOC) && !defined(TCL_MEM_DEBUG)
/*
* Additions by AOL for specialized thread memory allocator.
*/
-
#ifdef USE_THREAD_ALLOC
static volatile int initialized = 0;
-static pthread_key_t key;
+static pthread_key_t key;
typedef struct allocMutex {
- Tcl_Mutex tlock;
+ Tcl_Mutex tlock;
pthread_mutex_t plock;
} allocMutex;
@@ -780,49 +860,41 @@ Tcl_Mutex *
TclpNewAllocMutex(void)
{
struct allocMutex *lockPtr;
- register pthread_mutex_t *plockPtr;
lockPtr = malloc(sizeof(struct allocMutex));
if (lockPtr == NULL) {
- Tcl_Panic("could not allocate lock");
+ panic("could not allocate lock");
}
- plockPtr = &lockPtr->plock;
- lockPtr->tlock = (Tcl_Mutex) plockPtr;
+ lockPtr->tlock = (Tcl_Mutex) &lockPtr->plock;
pthread_mutex_init(&lockPtr->plock, NULL);
return &lockPtr->tlock;
}
void
-TclpFreeAllocMutex(
- Tcl_Mutex *mutex) /* The alloc mutex to free. */
+TclpFreeAllocMutex(mutex)
+ Tcl_Mutex *mutex; /* The alloc mutex to free. */
{
allocMutex* lockPtr = (allocMutex*) mutex;
- if (!lockPtr) {
- return;
- }
+ if (!lockPtr) return;
pthread_mutex_destroy(&lockPtr->plock);
free(lockPtr);
}
-void
-TclpFreeAllocCache(
- void *ptr)
+void TclpFreeAllocCache(ptr)
+ void *ptr;
{
if (ptr != NULL) {
- /*
- * Called by the pthread lib when a thread exits
- */
-
- TclFreeAllocCache(ptr);
-
+ /*
+ * Called by the pthread lib when a thread exits
+ */
+ TclFreeAllocCache(ptr);
} else if (initialized) {
- /*
- * Called by us in TclFinalizeThreadAlloc() during the library
- * finalization initiated from Tcl_Finalize()
- */
-
- pthread_key_delete(key);
- initialized = 0;
+ /*
+ * Called by us in TclFinalizeThreadAlloc() during
+ * the library finalization initiated from Tcl_Finalize()
+ */
+ pthread_key_delete(key);
+ initialized = 0;
}
}
@@ -841,18 +913,10 @@ TclpGetAllocCache(void)
}
void
-TclpSetAllocCache(
- void *arg)
+TclpSetAllocCache(void *arg)
{
pthread_setspecific(key, arg);
}
+
#endif /* USE_THREAD_ALLOC */
#endif /* TCL_THREADS */
-
-/*
- * Local Variables:
- * mode: c
- * c-basic-offset: 4
- * fill-column: 78
- * End:
- */