diff options
Diffstat (limited to 'unix/tclUnixThrd.c')
-rw-r--r-- | unix/tclUnixThrd.c | 182 |
1 files changed, 106 insertions, 76 deletions
diff --git a/unix/tclUnixThrd.c b/unix/tclUnixThrd.c index 0e8070d..a7a294d 100644 --- a/unix/tclUnixThrd.c +++ b/unix/tclUnixThrd.c @@ -5,7 +5,6 @@ * * 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. @@ -52,6 +51,7 @@ static pthread_mutex_t *allocLockPtr = &allocLock; #define MASTER_UNLOCK pthread_mutex_unlock(&masterLock) #endif /* TCL_THREADS */ + /* *---------------------------------------------------------------------- @@ -73,7 +73,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 @@ -105,19 +105,18 @@ 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 /* TCL_THREAD_STACK_MIN */ +#endif } -#endif /* HAVE_PTHREAD_ATTR_SETSTACKSIZE */ - +#endif 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, @@ -196,6 +195,99 @@ 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 */ + /* *---------------------------------------------------------------------- * @@ -420,8 +512,6 @@ Tcl_MutexLock( { pthread_mutex_t *pmutexPtr; -retry: - if (*mutexPtr == NULL) { MASTER_LOCK; if (*mutexPtr == NULL) { @@ -429,18 +519,14 @@ retry: * Double inside master lock check to avoid a race condition. */ - pmutexPtr = ckalloc(sizeof(pthread_mutex_t)); + pmutexPtr = (pthread_mutex_t *)ckalloc(sizeof(pthread_mutex_t)); pthread_mutex_init(pmutexPtr, NULL); *mutexPtr = (Tcl_Mutex)pmutexPtr; TclRememberMutex(mutexPtr); } MASTER_UNLOCK; } - pmutexPtr = *((pthread_mutex_t **)mutexPtr); - if (pmutexPtr == NULL) { - goto retry; - } pthread_mutex_lock(pmutexPtr); } @@ -465,8 +551,7 @@ 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); } @@ -493,11 +578,10 @@ 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(pmutexPtr); + ckfree((char *) pmutexPtr); *mutexPtr = NULL; } } @@ -528,7 +612,7 @@ void Tcl_ConditionWait( Tcl_Condition *condPtr, /* Really (pthread_cond_t **) */ Tcl_Mutex *mutexPtr, /* Really (pthread_mutex_t **) */ - const Tcl_Time *timePtr) /* Timeout on waiting period */ + Tcl_Time *timePtr) /* Timeout on waiting period */ { pthread_cond_t *pcondPtr; pthread_mutex_t *pmutexPtr; @@ -543,9 +627,9 @@ Tcl_ConditionWait( */ if (*condPtr == NULL) { - pcondPtr = ckalloc(sizeof(pthread_cond_t)); + pcondPtr = (pthread_cond_t *) ckalloc(sizeof(pthread_cond_t)); pthread_cond_init(pcondPtr, NULL); - *condPtr = (Tcl_Condition) pcondPtr; + *condPtr = (Tcl_Condition)pcondPtr; TclRememberCondition(condPtr); } MASTER_UNLOCK; @@ -627,10 +711,9 @@ TclpFinalizeCondition( Tcl_Condition *condPtr) { pthread_cond_t *pcondPtr = *(pthread_cond_t **)condPtr; - if (pcondPtr != NULL) { pthread_cond_destroy(pcondPtr); - ckfree(pcondPtr); + ckfree((char *) pcondPtr); *condPtr = NULL; } } @@ -664,7 +747,6 @@ TclpReaddir( return TclOSreaddir(dir); } -#undef TclpInetNtoa char * TclpInetNtoa( struct in_addr addr) @@ -766,58 +848,6 @@ 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 */ /* |