summaryrefslogtreecommitdiffstats
path: root/unix/tclUnixThrd.c
diff options
context:
space:
mode:
Diffstat (limited to 'unix/tclUnixThrd.c')
-rw-r--r--unix/tclUnixThrd.c263
1 files changed, 136 insertions, 127 deletions
diff --git a/unix/tclUnixThrd.c b/unix/tclUnixThrd.c
index 3d068e5..d34bc88 100644
--- a/unix/tclUnixThrd.c
+++ b/unix/tclUnixThrd.c
@@ -1,23 +1,20 @@
-/*
+/*
* tclUnixThrd.c --
*
* This file implements the UNIX-specific thread support.
*
* Copyright (c) 1991-1994 The Regents of the University of California.
* Copyright (c) 1994-1997 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.
- *
- * SCCS: @(#) tclUnixThrd.c 1.18 98/02/19 14:24:12
*/
#include "tclInt.h"
#ifdef TCL_THREADS
-#include "pthread.h"
-
typedef struct ThreadSpecificData {
char nabuf[16];
} ThreadSpecificData;
@@ -55,7 +52,6 @@ static pthread_mutex_t *allocLockPtr = &allocLock;
#define MASTER_UNLOCK pthread_mutex_unlock(&masterLock)
#endif /* TCL_THREADS */
-
/*
*----------------------------------------------------------------------
@@ -75,13 +71,13 @@ static pthread_mutex_t *allocLockPtr = &allocLock;
*/
int
-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. */
+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. */
{
#ifdef TCL_THREADS
pthread_attr_t attr;
@@ -109,18 +105,19 @@ TclpThreadCreate(idPtr, proc, clientData, stackSize, flags)
*/
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);
}
-#endif
+#endif /* TCL_THREAD_STACK_MIN */
}
-#endif
+#endif /* HAVE_PTHREAD_ATTR_SETSTACKSIZE */
+
if (! (flags & TCL_THREAD_JOINABLE)) {
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
}
-
if (pthread_create(&theThread, &attr,
(void * (*)(void *))proc, (void *)clientData) &&
pthread_create(&theThread, NULL,
@@ -154,16 +151,20 @@ TclpThreadCreate(idPtr, proc, clientData, stackSize, flags)
*/
int
-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. */
+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. */
{
#ifdef TCL_THREADS
int result;
+ unsigned long retcode, *retcodePtr = &retcode;
- result = pthread_join ((pthread_t) threadId, (VOID**) state);
+ result = pthread_join((pthread_t) threadId, (void**) retcodePtr);
+ if (state) {
+ *state = (int) retcode;
+ }
return (result == 0) ? TCL_OK : TCL_ERROR;
#else
return TCL_ERROR;
@@ -188,59 +189,10 @@ Tcl_JoinThread(threadId, state)
*/
void
-TclpThreadExit(status)
- int status;
+TclpThreadExit(
+ int status)
{
- pthread_exit((VOID *)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.
- *
- *----------------------------------------------------------------------
- */
-
-int
-TclpThreadGetStackSize()
-{
-#if defined(HAVE_PTHREAD_SETSTACKSIZE) && defined(TclpPthreadGetAttrs)
- pthread_attr_t threadAttr; /* This will hold the thread attributes for
- * the current thread. */
- size_t stackSize;
-
- if (pthread_attr_init(&threadAttr) != 0) {
- return -1;
- }
- if (TclpPthreadGetAttrs(pthread_self(), &threadAttr) != 0) {
- pthread_attr_destroy(&threadAttr);
- return -1;
- }
- if (pthread_attr_getstacksize(&threadAttr, &stackSize) != 0) {
- pthread_attr_destroy(&threadAttr);
- return -1;
- }
- pthread_attr_destroy(&threadAttr);
- return (int) stackSize;
-#else
- /*
- * Cannot determine the real stack size of this thread. The caller might
- * want to try looking at the process accounting limits instead.
- */
-
- return 0;
-#endif
+ pthread_exit(INT2PTR(status));
}
#endif /* TCL_THREADS */
@@ -261,7 +213,7 @@ TclpThreadGetStackSize()
*/
Tcl_ThreadId
-Tcl_GetCurrentThread()
+Tcl_GetCurrentThread(void)
{
#ifdef TCL_THREADS
return (Tcl_ThreadId) pthread_self();
@@ -269,7 +221,6 @@ Tcl_GetCurrentThread()
return (Tcl_ThreadId) 0;
#endif
}
-
/*
*----------------------------------------------------------------------
@@ -291,7 +242,7 @@ Tcl_GetCurrentThread()
*/
void
-TclpInitLock()
+TclpInitLock(void)
{
#ifdef TCL_THREADS
pthread_mutex_lock(&initLock);
@@ -317,7 +268,7 @@ TclpInitLock()
*/
void
-TclFinalizeLock ()
+TclFinalizeLock(void)
{
#ifdef TCL_THREADS
/*
@@ -348,7 +299,7 @@ TclFinalizeLock ()
*/
void
-TclpInitUnlock()
+TclpInitUnlock(void)
{
#ifdef TCL_THREADS
pthread_mutex_unlock(&initLock);
@@ -377,7 +328,7 @@ TclpInitUnlock()
*/
void
-TclpMasterLock()
+TclpMasterLock(void)
{
#ifdef TCL_THREADS
pthread_mutex_lock(&masterLock);
@@ -403,7 +354,7 @@ TclpMasterLock()
*/
void
-TclpMasterUnlock()
+TclpMasterUnlock(void)
{
#ifdef TCL_THREADS
pthread_mutex_unlock(&masterLock);
@@ -431,10 +382,11 @@ TclpMasterUnlock()
*/
Tcl_Mutex *
-Tcl_GetAllocMutex()
+Tcl_GetAllocMutex(void)
{
#ifdef TCL_THREADS
- return (Tcl_Mutex *)&allocLockPtr;
+ pthread_mutex_t **allocLockPtrPtr = &allocLockPtr;
+ return (Tcl_Mutex *) allocLockPtrPtr;
#else
return NULL;
#endif
@@ -464,18 +416,19 @@ Tcl_GetAllocMutex()
*/
void
-Tcl_MutexLock(mutexPtr)
- Tcl_Mutex *mutexPtr; /* Really (pthread_mutex_t **) */
+Tcl_MutexLock(
+ 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));
+
+ pmutexPtr = ckalloc(sizeof(pthread_mutex_t));
pthread_mutex_init(pmutexPtr, NULL);
*mutexPtr = (Tcl_Mutex)pmutexPtr;
TclRememberMutex(mutexPtr);
@@ -485,7 +438,6 @@ Tcl_MutexLock(mutexPtr)
pmutexPtr = *((pthread_mutex_t **)mutexPtr);
pthread_mutex_lock(pmutexPtr);
}
-
/*
*----------------------------------------------------------------------
@@ -505,13 +457,13 @@ Tcl_MutexLock(mutexPtr)
*/
void
-Tcl_MutexUnlock(mutexPtr)
- Tcl_Mutex *mutexPtr; /* Really (pthread_mutex_t **) */
+Tcl_MutexUnlock(
+ Tcl_Mutex *mutexPtr) /* Really (pthread_mutex_t **) */
{
- pthread_mutex_t *pmutexPtr = *(pthread_mutex_t **)mutexPtr;
+ pthread_mutex_t *pmutexPtr = *(pthread_mutex_t **) mutexPtr;
+
pthread_mutex_unlock(pmutexPtr);
}
-
/*
*----------------------------------------------------------------------
@@ -533,13 +485,14 @@ Tcl_MutexUnlock(mutexPtr)
*/
void
-TclpFinalizeMutex(mutexPtr)
- Tcl_Mutex *mutexPtr;
+TclpFinalizeMutex(
+ Tcl_Mutex *mutexPtr)
{
- pthread_mutex_t *pmutexPtr = *(pthread_mutex_t **)mutexPtr;
+ pthread_mutex_t *pmutexPtr = *(pthread_mutex_t **) mutexPtr;
+
if (pmutexPtr != NULL) {
pthread_mutex_destroy(pmutexPtr);
- ckfree((char *)pmutexPtr);
+ ckfree(pmutexPtr);
*mutexPtr = NULL;
}
}
@@ -567,10 +520,10 @@ TclpFinalizeMutex(mutexPtr)
*/
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 */
{
pthread_cond_t *pcondPtr;
pthread_mutex_t *pmutexPtr;
@@ -579,15 +532,15 @@ Tcl_ConditionWait(condPtr, mutexPtr, timePtr)
if (*condPtr == NULL) {
MASTER_LOCK;
- /*
+ /*
* 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 = ckalloc(sizeof(pthread_cond_t));
pthread_cond_init(pcondPtr, NULL);
- *condPtr = (Tcl_Condition)pcondPtr;
+ *condPtr = (Tcl_Condition) pcondPtr;
TclRememberCondition(condPtr);
}
MASTER_UNLOCK;
@@ -632,8 +585,8 @@ Tcl_ConditionWait(condPtr, mutexPtr, timePtr)
*/
void
-Tcl_ConditionNotify(condPtr)
- Tcl_Condition *condPtr;
+Tcl_ConditionNotify(
+ Tcl_Condition *condPtr)
{
pthread_cond_t *pcondPtr = *((pthread_cond_t **)condPtr);
if (pcondPtr != NULL) {
@@ -644,7 +597,6 @@ Tcl_ConditionNotify(condPtr)
*/
}
}
-
/*
*----------------------------------------------------------------------
@@ -666,13 +618,14 @@ Tcl_ConditionNotify(condPtr)
*/
void
-TclpFinalizeCondition(condPtr)
- Tcl_Condition *condPtr;
+TclpFinalizeCondition(
+ Tcl_Condition *condPtr)
{
pthread_cond_t *pcondPtr = *(pthread_cond_t **)condPtr;
+
if (pcondPtr != NULL) {
pthread_cond_destroy(pcondPtr);
- ckfree((char *)pcondPtr);
+ ckfree(pcondPtr);
*condPtr = NULL;
}
}
@@ -681,7 +634,7 @@ TclpFinalizeCondition(condPtr)
/*
*----------------------------------------------------------------------
*
- * TclpReaddir, TclpLocaltime, TclpGmtime, TclpInetNtoa --
+ * TclpReaddir, TclpInetNtoa --
*
* These procedures replace core C versions to be used in a threaded
* environment.
@@ -700,23 +653,22 @@ TclpFinalizeCondition(condPtr)
*/
Tcl_DirEntry *
-TclpReaddir(DIR * dir)
+TclpReaddir(
+ DIR * dir)
{
return TclOSreaddir(dir);
}
+#undef TclpInetNtoa
char *
-TclpInetNtoa(struct in_addr addr)
+TclpInetNtoa(
+ struct in_addr addr)
{
#ifdef TCL_THREADS
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
- union {
- unsigned long l;
- unsigned char b[4];
- } u;
-
- u.l = (unsigned long) addr.s_addr;
- sprintf(tsdPtr->nabuf, "%u.%u.%u.%u", u.b[0], u.b[1], u.b[2], u.b[3]);
+ unsigned char *b = (unsigned char*) &addr.s_addr;
+
+ sprintf(tsdPtr->nabuf, "%u.%u.%u.%u", b[0], b[1], b[2], b[3]);
return tsdPtr->nabuf;
#else
return inet_ntoa(addr);
@@ -730,7 +682,7 @@ TclpInetNtoa(struct in_addr addr)
#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;
@@ -741,19 +693,21 @@ 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");
}
- lockPtr->tlock = (Tcl_Mutex) &lockPtr->plock;
+ plockPtr = &lockPtr->plock;
+ lockPtr->tlock = (Tcl_Mutex) plockPtr;
pthread_mutex_init(&lockPtr->plock, NULL);
return &lockPtr->tlock;
}
void
-TclpFreeAllocMutex(mutex)
- Tcl_Mutex *mutex; /* The alloc mutex to free. */
+TclpFreeAllocMutex(
+ Tcl_Mutex *mutex) /* The alloc mutex to free. */
{
allocMutex* lockPtr = (allocMutex*) mutex;
if (!lockPtr) {
@@ -763,8 +717,9 @@ TclpFreeAllocMutex(mutex)
free(lockPtr);
}
-void TclpFreeAllocCache(ptr)
- void *ptr;
+void
+TclpFreeAllocCache(
+ void *ptr)
{
if (ptr != NULL) {
/*
@@ -772,6 +727,7 @@ void TclpFreeAllocCache(ptr)
*/
TclFreeAllocCache(ptr);
+ pthread_setspecific(key, NULL);
} else if (initialized) {
/*
@@ -799,11 +755,64 @@ TclpGetAllocCache(void)
}
void
-TclpSetAllocCache(void *arg)
+TclpSetAllocCache(
+ void *arg)
{
pthread_setspecific(key, arg);
}
#endif /* USE_THREAD_ALLOC */
+
+void *
+TclpThreadCreateKey(void)
+{
+ pthread_key_t *ptkeyPtr;
+
+ ptkeyPtr = TclpSysAlloc(sizeof *ptkeyPtr, 0);
+ if (NULL == ptkeyPtr) {
+ Tcl_Panic("unable to allocate thread key!");
+ }
+
+ if (pthread_key_create(ptkeyPtr, NULL)) {
+ Tcl_Panic("unable to create pthread key!");
+ }
+
+ return ptkeyPtr;
+}
+
+void
+TclpThreadDeleteKey(
+ void *keyPtr)
+{
+ pthread_key_t *ptkeyPtr = keyPtr;
+
+ if (pthread_key_delete(*ptkeyPtr)) {
+ Tcl_Panic("unable to delete key!");
+ }
+
+ TclpSysFree(keyPtr);
+}
+
+void
+TclpThreadSetMasterTSD(
+ void *tsdKeyPtr,
+ void *ptr)
+{
+ pthread_key_t *ptkeyPtr = tsdKeyPtr;
+
+ if (pthread_setspecific(*ptkeyPtr, ptr)) {
+ Tcl_Panic("unable to set master TSD value");
+ }
+}
+
+void *
+TclpThreadGetMasterTSD(
+ void *tsdKeyPtr)
+{
+ pthread_key_t *ptkeyPtr = tsdKeyPtr;
+
+ return pthread_getspecific(*ptkeyPtr);
+}
+
#endif /* TCL_THREADS */
/*