diff options
Diffstat (limited to 'unix/tclUnixThrd.c')
-rw-r--r-- | unix/tclUnixThrd.c | 178 |
1 files changed, 71 insertions, 107 deletions
diff --git a/unix/tclUnixThrd.c b/unix/tclUnixThrd.c index bc80e00..0469d7a 100644 --- a/unix/tclUnixThrd.c +++ b/unix/tclUnixThrd.c @@ -5,6 +5,7 @@ * * 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. @@ -14,7 +15,7 @@ #ifdef TCL_THREADS -#include "pthread.h" +#include <pthread.h> typedef struct ThreadSpecificData { char nabuf[16]; @@ -53,7 +54,6 @@ static pthread_mutex_t *allocLockPtr = &allocLock; #define MASTER_UNLOCK pthread_mutex_unlock(&masterLock) #endif /* TCL_THREADS */ - /* *---------------------------------------------------------------------- @@ -75,7 +75,7 @@ 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 */ + 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 @@ -107,18 +107,19 @@ TclpThreadCreate( */ 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, @@ -197,99 +198,6 @@ TclpThreadExit( } #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) -{ - 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; -} -#endif /* TCL_THREADS */ - /* *---------------------------------------------------------------------- * @@ -514,6 +422,7 @@ Tcl_MutexLock( Tcl_Mutex *mutexPtr) /* Really (pthread_mutex_t **) */ { pthread_mutex_t *pmutexPtr; + if (*mutexPtr == NULL) { MASTER_LOCK; if (*mutexPtr == NULL) { @@ -521,7 +430,7 @@ Tcl_MutexLock( * 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); @@ -553,7 +462,8 @@ void 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); } @@ -580,10 +490,11 @@ void 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; } } @@ -614,7 +525,7 @@ void Tcl_ConditionWait( Tcl_Condition *condPtr, /* Really (pthread_cond_t **) */ Tcl_Mutex *mutexPtr, /* Really (pthread_mutex_t **) */ - Tcl_Time *timePtr) /* Timeout on waiting period */ + const Tcl_Time *timePtr) /* Timeout on waiting period */ { pthread_cond_t *pcondPtr; pthread_mutex_t *pmutexPtr; @@ -629,9 +540,9 @@ Tcl_ConditionWait( */ 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; @@ -713,9 +624,10 @@ 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; } } @@ -849,6 +761,58 @@ TclpSetAllocCache( 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 */ /* |