diff options
Diffstat (limited to 'unix/tclUnixThrd.c')
-rw-r--r-- | unix/tclUnixThrd.c | 263 |
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 */ /* |