-- cgit v0.12 From b91a2765aef7499e3bf0ca35d47c6dc068c35ed6 Mon Sep 17 00:00:00 2001 From: fbonnet Date: Fri, 25 May 2018 19:43:23 +0000 Subject: TIP #509: Implement reentrant mutexes on all platforms --- unix/configure | 78 ++++++++++++++++++++++++++- unix/tcl.m4 | 3 ++ unix/tclUnixThrd.c | 156 +++++++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 213 insertions(+), 24 deletions(-) diff --git a/unix/configure b/unix/configure index 36bc4b9..11c04c3 100755 --- a/unix/configure +++ b/unix/configure @@ -730,6 +730,7 @@ infodir docdir oldincludedir includedir +runstatedir localstatedir sharedstatedir sysconfdir @@ -817,6 +818,7 @@ datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' +runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' @@ -1069,6 +1071,15 @@ do | -silent | --silent | --silen | --sile | --sil) silent=yes ;; + -runstatedir | --runstatedir | --runstatedi | --runstated \ + | --runstate | --runstat | --runsta | --runst | --runs \ + | --run | --ru | --r) + ac_prev=runstatedir ;; + -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ + | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ + | --run=* | --ru=* | --r=*) + runstatedir=$ac_optarg ;; + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ @@ -1206,7 +1217,7 @@ fi for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir + libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. @@ -1359,6 +1370,7 @@ Fine tuning of the installation directories: --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] @@ -1856,6 +1868,52 @@ $as_echo "$ac_res" >&6; } } # ac_fn_c_check_func +# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES +# --------------------------------------------- +# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR +# accordingly. +ac_fn_c_check_decl () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + as_decl_name=`echo $2|sed 's/ *(.*//'` + as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 +$as_echo_n "checking whether $as_decl_name is declared... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +#ifndef $as_decl_name +#ifdef __cplusplus + (void) $as_decl_use; +#else + (void) $as_decl_name; +#endif +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_decl + # ac_fn_c_check_type LINENO TYPE VAR INCLUDES # ------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache @@ -4224,6 +4282,24 @@ $as_echo "yes" >&6; } $as_echo "no" >&6; } fi + ac_fn_c_check_decl "$LINENO" "PTHREAD_MUTEX_RECURSIVE" "ac_cv_have_decl_PTHREAD_MUTEX_RECURSIVE" "#include +" +if test "x$ac_cv_have_decl_PTHREAD_MUTEX_RECURSIVE" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_PTHREAD_MUTEX_RECURSIVE $ac_have_decl +_ACEOF +if test $ac_have_decl = 1; then : + tcl_ok=yes +else + tcl_ok=no +fi + + diff --git a/unix/tcl.m4 b/unix/tcl.m4 index 4acbed0..6d650ea 100644 --- a/unix/tcl.m4 +++ b/unix/tcl.m4 @@ -696,6 +696,9 @@ AC_DEFUN([SC_ENABLE_THREADS], [ AC_MSG_RESULT([no]) fi + # TIP #509. + AC_CHECK_DECLS([PTHREAD_MUTEX_RECURSIVE],tcl_ok=yes,tcl_ok=no, [[#include ]]) + AC_SUBST(TCL_THREADS) ]) diff --git a/unix/tclUnixThrd.c b/unix/tclUnixThrd.c index 120d5d5..3d3f81d 100644 --- a/unix/tclUnixThrd.c +++ b/unix/tclUnixThrd.c @@ -15,6 +15,109 @@ #ifdef TCL_THREADS +/* + * TIP #509. + */ + +#if defined(HAVE_DECL_PTHREAD_MUTEX_RECURSIVE) \ + && HAVE_DECL_PTHREAD_MUTEX_RECURSIVE +/* + * Pthread has native reentrant (AKA recursive) mutexes. Use them for Tcl_Mutex. + */ + +typedef pthread_mutex_t PMutex; + +static void +PMutexInit( + PMutex *pmutexPtr +) +{ + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(pmutexPtr, &attr); +} + +#define PMutexDestroy pthread_mutex_destroy +#define PMutexLock pthread_mutex_lock +#define PMutexUnlock pthread_mutex_unlock +#define PCondWait pthread_cond_wait +#define PCondTimedWait pthread_cond_timedwait + +#else /* HAVE_PTHREAD_MUTEX_RECURSIVE */ + +/* + * No native support for reentrant mutexes. Emulate them with regular mutexes + * and thread-local counters. + */ + +typedef struct PMutex { + pthread_mutex_t mutex; + pthread_key_t counter; +} PMutex; + +static void +PMutexInit( + PMutex *pmutexPtr +) +{ + pthread_mutex_init(&pmutexPtr->mutex, NULL); + pthread_key_create(&pmutexPtr->counter, NULL); +} + +static void +PMutexDestroy( + PMutex *pmutexPtr +) +{ + pthread_mutex_destroy(&pmutexPtr->mutex); + pthread_key_delete(pmutexPtr->counter); +} + +static void +PMutexLock( + PMutex *pmutexPtr +) +{ + intptr_t count = (intptr_t)pthread_getspecific(pmutexPtr->counter); + pthread_setspecific(pmutexPtr->counter, (const void *)(count+1)); + if (count == 0) { + pthread_mutex_lock(&pmutexPtr->mutex); + } +} + +static void +PMutexUnlock( + PMutex *pmutexPtr +) +{ + intptr_t count = (intptr_t)pthread_getspecific(pmutexPtr->counter); + pthread_setspecific(pmutexPtr->counter, (const void *)(count-1)); + if (count == 1) { + pthread_mutex_unlock(&pmutexPtr->mutex); + } +} + +static void +PCondWait( + pthread_cond_t *pcondPtr, + PMutex *pmutexPtr +) +{ + pthread_cond_wait(pcondPtr, &pmutexPtr->mutex); +} + +static void +PCondTimedWait( + pthread_cond_t *pcondPtr, + PMutex *pmutexPtr, + struct timespec *ptime +) +{ + pthread_cond_timedwait(pcondPtr, &pmutexPtr->mutex, ptime); +} +#endif /* HAVE_PTHREAD_MUTEX_RECURSIVE */ + #ifndef TCL_NO_DEPRECATED typedef struct { char nabuf[16]; @@ -43,8 +146,14 @@ static pthread_mutex_t initLock = PTHREAD_MUTEX_INITIALIZER; * obvious reasons, cannot use any dyamically allocated storage. */ -static pthread_mutex_t allocLock = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t *allocLockPtr = &allocLock; +static PMutex allocLock; +static pthread_once_t allocLockInitOnce = PTHREAD_ONCE_INIT; +static void +allocLockInit() +{ + PMutexInit(&allocLock); +} +static PMutex *allocLockPtr = &allocLock; #endif /* TCL_THREADS */ @@ -379,7 +488,8 @@ Tcl_Mutex * Tcl_GetAllocMutex(void) { #ifdef TCL_THREADS - pthread_mutex_t **allocLockPtrPtr = &allocLockPtr; + PMutex **allocLockPtrPtr = &allocLockPtr; + pthread_once(&allocLockInitOnce, allocLockInit); return (Tcl_Mutex *) allocLockPtrPtr; #else return NULL; @@ -411,9 +521,9 @@ Tcl_GetAllocMutex(void) void Tcl_MutexLock( - Tcl_Mutex *mutexPtr) /* Really (pthread_mutex_t **) */ + Tcl_Mutex *mutexPtr) /* Really (PMutex **) */ { - pthread_mutex_t *pmutexPtr; + PMutex *pmutexPtr; if (*mutexPtr == NULL) { pthread_mutex_lock(&masterLock); @@ -422,15 +532,15 @@ Tcl_MutexLock( * Double inside master lock check to avoid a race condition. */ - pmutexPtr = ckalloc(sizeof(pthread_mutex_t)); - pthread_mutex_init(pmutexPtr, NULL); + pmutexPtr = ckalloc(sizeof(PMutex)); + PMutexInit(pmutexPtr); *mutexPtr = (Tcl_Mutex)pmutexPtr; TclRememberMutex(mutexPtr); } pthread_mutex_unlock(&masterLock); } - pmutexPtr = *((pthread_mutex_t **)mutexPtr); - pthread_mutex_lock(pmutexPtr); + pmutexPtr = *((PMutex **)mutexPtr); + PMutexLock(pmutexPtr); } /* @@ -452,11 +562,11 @@ Tcl_MutexLock( void Tcl_MutexUnlock( - Tcl_Mutex *mutexPtr) /* Really (pthread_mutex_t **) */ + Tcl_Mutex *mutexPtr) /* Really (PMutex **) */ { - pthread_mutex_t *pmutexPtr = *(pthread_mutex_t **) mutexPtr; + PMutex *pmutexPtr = *(PMutex **) mutexPtr; - pthread_mutex_unlock(pmutexPtr); + PMutexUnlock(pmutexPtr); } /* @@ -482,10 +592,10 @@ void TclpFinalizeMutex( Tcl_Mutex *mutexPtr) { - pthread_mutex_t *pmutexPtr = *(pthread_mutex_t **) mutexPtr; + PMutex *pmutexPtr = *(PMutex **) mutexPtr; if (pmutexPtr != NULL) { - pthread_mutex_destroy(pmutexPtr); + PMutexDestroy(pmutexPtr); ckfree(pmutexPtr); *mutexPtr = NULL; } @@ -516,11 +626,11 @@ TclpFinalizeMutex( void Tcl_ConditionWait( Tcl_Condition *condPtr, /* Really (pthread_cond_t **) */ - Tcl_Mutex *mutexPtr, /* Really (pthread_mutex_t **) */ + Tcl_Mutex *mutexPtr, /* Really (PMutex **) */ const Tcl_Time *timePtr) /* Timeout on waiting period */ { pthread_cond_t *pcondPtr; - pthread_mutex_t *pmutexPtr; + PMutex *pmutexPtr; struct timespec ptime; if (*condPtr == NULL) { @@ -539,10 +649,10 @@ Tcl_ConditionWait( } pthread_mutex_unlock(&masterLock); } - pmutexPtr = *((pthread_mutex_t **)mutexPtr); + pmutexPtr = *((PMutex **)mutexPtr); pcondPtr = *((pthread_cond_t **)condPtr); if (timePtr == NULL) { - pthread_cond_wait(pcondPtr, pmutexPtr); + PCondWait(pcondPtr, pmutexPtr); } else { Tcl_Time now; @@ -555,7 +665,7 @@ Tcl_ConditionWait( ptime.tv_sec = timePtr->sec + now.sec + (timePtr->usec + now.usec) / 1000000; ptime.tv_nsec = 1000 * ((timePtr->usec + now.usec) % 1000000); - pthread_cond_timedwait(pcondPtr, pmutexPtr, &ptime); + PCondTimedWait(pcondPtr, pmutexPtr, &ptime); } } @@ -681,14 +791,14 @@ static pthread_key_t key; typedef struct { Tcl_Mutex tlock; - pthread_mutex_t plock; + PMutex plock; } allocMutex; Tcl_Mutex * TclpNewAllocMutex(void) { allocMutex *lockPtr; - register pthread_mutex_t *plockPtr; + register PMutex *plockPtr; lockPtr = malloc(sizeof(allocMutex)); if (lockPtr == NULL) { @@ -696,7 +806,7 @@ TclpNewAllocMutex(void) } plockPtr = &lockPtr->plock; lockPtr->tlock = (Tcl_Mutex) plockPtr; - pthread_mutex_init(&lockPtr->plock, NULL); + PMutexInit(&lockPtr->plock); return &lockPtr->tlock; } @@ -708,7 +818,7 @@ TclpFreeAllocMutex( if (!lockPtr) { return; } - pthread_mutex_destroy(&lockPtr->plock); + PMutexDestroy(&lockPtr->plock); free(lockPtr); } -- cgit v0.12 From 7fe9e1b90c4464f3f288cecc3fa1d65bb6904cd1 Mon Sep 17 00:00:00 2001 From: fbonnet Date: Sat, 9 Jun 2018 17:20:15 +0000 Subject: Removed thread-specific mutex lock counter and replaced by shared counter + thread ID for systems without PTHREAD_MUTEX_RECURSIVE --- unix/tclUnixThrd.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/unix/tclUnixThrd.c b/unix/tclUnixThrd.c index 3d3f81d..226552f 100644 --- a/unix/tclUnixThrd.c +++ b/unix/tclUnixThrd.c @@ -53,7 +53,8 @@ PMutexInit( typedef struct PMutex { pthread_mutex_t mutex; - pthread_key_t counter; + pthread_t thread; + int counter; } PMutex; static void @@ -62,7 +63,8 @@ PMutexInit( ) { pthread_mutex_init(&pmutexPtr->mutex, NULL); - pthread_key_create(&pmutexPtr->counter, NULL); + pmutexPtr->thread = 0; + pmutexPtr->counter = 0; } static void @@ -71,7 +73,6 @@ PMutexDestroy( ) { pthread_mutex_destroy(&pmutexPtr->mutex); - pthread_key_delete(pmutexPtr->counter); } static void @@ -79,11 +80,12 @@ PMutexLock( PMutex *pmutexPtr ) { - intptr_t count = (intptr_t)pthread_getspecific(pmutexPtr->counter); - pthread_setspecific(pmutexPtr->counter, (const void *)(count+1)); - if (count == 0) { - pthread_mutex_lock(&pmutexPtr->mutex); + if (pmutexPtr->thread != pthread_self() || pmutexPtr->counter == 0) { + pthread_mutex_lock(&pmutexPtr->mutex); + pmutexPtr->thread = pthread_self(); + pmutexPtr->counter = 0; } + pmutexPtr->counter++; } static void @@ -91,10 +93,10 @@ PMutexUnlock( PMutex *pmutexPtr ) { - intptr_t count = (intptr_t)pthread_getspecific(pmutexPtr->counter); - pthread_setspecific(pmutexPtr->counter, (const void *)(count-1)); - if (count == 1) { - pthread_mutex_unlock(&pmutexPtr->mutex); + pmutexPtr->counter--; + if (pmutexPtr->counter == 0) { + pmutexPtr->thread = 0; + pthread_mutex_unlock(&pmutexPtr->mutex); } } -- cgit v0.12 From eede8c60a140b1ebb3eb6a795ecc703e89f466f4 Mon Sep 17 00:00:00 2001 From: dkf Date: Fri, 28 Sep 2018 09:49:57 +0000 Subject: Clean up code style and add key phrases to documentation. --- doc/Thread.3 | 10 +++- unix/tclUnixThrd.c | 147 ++++++++++++++++++++++++++++++++++------------------- 2 files changed, 103 insertions(+), 54 deletions(-) diff --git a/doc/Thread.3 b/doc/Thread.3 index 5966a71..59bf488 100644 --- a/doc/Thread.3 +++ b/doc/Thread.3 @@ -45,7 +45,9 @@ int .AP Tcl_Condition *condPtr in A condition variable, which must be associated with a mutex lock. .AP Tcl_Mutex *mutexPtr in -A mutex lock. +.VS TIP509 +A recursive mutex lock. +.VE TIP509 .AP "const Tcl_Time" *timePtr in A time limit on the condition wait. NULL to wait forever. Note that a polling value of 0 seconds does not make much sense. @@ -135,7 +137,11 @@ Tcl provides \fBTcl_ThreadQueueEvent\fR and \fBTcl_ThreadAlert\fR for handling event queuing in multithreaded applications. See the \fBNotifier\fR manual page for more information on these procedures. .PP -A mutex is a lock that is used to serialize all threads through a piece +A mutex is a +.VS TIP509 +recursive +.VE TIP509 +lock that is used to serialize all threads through a piece of code by calling \fBTcl_MutexLock\fR and \fBTcl_MutexUnlock\fR. If one thread holds a mutex, any other thread calling \fBTcl_MutexLock\fR will block until \fBTcl_MutexUnlock\fR is called. diff --git a/unix/tclUnixThrd.c b/unix/tclUnixThrd.c index 925f8b8..60340b0 100644 --- a/unix/tclUnixThrd.c +++ b/unix/tclUnixThrd.c @@ -14,37 +14,83 @@ #include "tclInt.h" #if TCL_THREADS - + /* - * TIP #509. + * TIP #509. Ensures that Tcl's mutexes are reentrant. + * + *---------------------------------------------------------------------- + * + * PMutexInit -- + * + * Sets up the memory pointed to by its argument so that it contains the + * implementation of a recursive lock. Caller supplies the space. + * + *---------------------------------------------------------------------- + * + * PMutexDestroy -- + * + * Tears down the implementation of a recursive lock (but does not + * deallocate the space holding the lock). + * + *---------------------------------------------------------------------- + * + * PMutexLock -- + * + * Locks a recursive lock. (Similar to pthread_mutex_lock) + * + *---------------------------------------------------------------------- + * + * PMutexUnlock -- + * + * Unlocks a recursive lock. (Similar to pthread_mutex_unlock) + * + *---------------------------------------------------------------------- + * + * PCondWait -- + * + * Waits on a condition variable linked a recursive lock. (Similar to + * pthread_cond_wait) + * + *---------------------------------------------------------------------- + * + * PCondTimedWait -- + * + * Waits for a limited amount of time on a condition variable linked to a + * recursive lock. (Similar to pthread_cond_timedwait) + * + *---------------------------------------------------------------------- */ -#if defined(HAVE_DECL_PTHREAD_MUTEX_RECURSIVE) \ - && HAVE_DECL_PTHREAD_MUTEX_RECURSIVE +#ifndef HAVE_DECL_PTHREAD_MUTEX_RECURSIVE +#define HAVE_DECL_PTHREAD_MUTEX_RECURSIVE 0 +#endif + +#if HAVE_DECL_PTHREAD_MUTEX_RECURSIVE /* - * Pthread has native reentrant (AKA recursive) mutexes. Use them for Tcl_Mutex. + * Pthread has native reentrant (AKA recursive) mutexes. Use them for + * Tcl_Mutex. */ typedef pthread_mutex_t PMutex; static void PMutexInit( - PMutex *pmutexPtr -) + PMutex *pmutexPtr) { pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init(pmutexPtr, &attr); } -#define PMutexDestroy pthread_mutex_destroy -#define PMutexLock pthread_mutex_lock -#define PMutexUnlock pthread_mutex_unlock -#define PCondWait pthread_cond_wait -#define PCondTimedWait pthread_cond_timedwait +#define PMutexDestroy pthread_mutex_destroy +#define PMutexLock pthread_mutex_lock +#define PMutexUnlock pthread_mutex_unlock +#define PCondWait pthread_cond_wait +#define PCondTimedWait pthread_cond_timedwait -#else /* HAVE_PTHREAD_MUTEX_RECURSIVE */ +#else /* !HAVE_PTHREAD_MUTEX_RECURSIVE */ /* * No native support for reentrant mutexes. Emulate them with regular mutexes @@ -59,8 +105,7 @@ typedef struct PMutex { static void PMutexInit( - PMutex *pmutexPtr -) + PMutex *pmutexPtr) { pthread_mutex_init(&pmutexPtr->mutex, NULL); pmutexPtr->thread = 0; @@ -69,42 +114,38 @@ PMutexInit( static void PMutexDestroy( - PMutex *pmutexPtr -) + PMutex *pmutexPtr) { - pthread_mutex_destroy(&pmutexPtr->mutex); + pthread_mutex_destroy(&pmutexPtr->mutex); } static void PMutexLock( - PMutex *pmutexPtr -) + PMutex *pmutexPtr) { if (pmutexPtr->thread != pthread_self() || pmutexPtr->counter == 0) { - pthread_mutex_lock(&pmutexPtr->mutex); - pmutexPtr->thread = pthread_self(); - pmutexPtr->counter = 0; + pthread_mutex_lock(&pmutexPtr->mutex); + pmutexPtr->thread = pthread_self(); + pmutexPtr->counter = 0; } pmutexPtr->counter++; } static void PMutexUnlock( - PMutex *pmutexPtr -) + PMutex *pmutexPtr) { pmutexPtr->counter--; if (pmutexPtr->counter == 0) { - pmutexPtr->thread = 0; - pthread_mutex_unlock(&pmutexPtr->mutex); + pmutexPtr->thread = 0; + pthread_mutex_unlock(&pmutexPtr->mutex); } } static void PCondWait( pthread_cond_t *pcondPtr, - PMutex *pmutexPtr -) + PMutex *pmutexPtr) { pthread_cond_wait(pcondPtr, &pmutexPtr->mutex); } @@ -113,20 +154,19 @@ static void PCondTimedWait( pthread_cond_t *pcondPtr, PMutex *pmutexPtr, - struct timespec *ptime -) + struct timespec *ptime) { pthread_cond_timedwait(pcondPtr, &pmutexPtr->mutex, ptime); } #endif /* HAVE_PTHREAD_MUTEX_RECURSIVE */ - + #ifndef TCL_NO_DEPRECATED typedef struct { char nabuf[16]; } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; -#endif +#endif /* TCL_NO_DEPRECATED */ /* * masterLock is used to serialize creation of mutexes, condition variables, @@ -150,8 +190,9 @@ static pthread_mutex_t initLock = PTHREAD_MUTEX_INITIALIZER; static PMutex allocLock; static pthread_once_t allocLockInitOnce = PTHREAD_ONCE_INIT; + static void -allocLockInit() +allocLockInit(void) { PMutexInit(&allocLock); } @@ -220,17 +261,17 @@ TclpThreadCreate( } #endif /* HAVE_PTHREAD_ATTR_SETSTACKSIZE */ - if (! (flags & TCL_THREAD_JOINABLE)) { - pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); + if (!(flags & TCL_THREAD_JOINABLE)) { + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); } if (pthread_create(&theThread, &attr, - (void * (*)(void *))proc, (void *)clientData) && + (void * (*)(void *)) proc, (void *) clientData) && pthread_create(&theThread, NULL, - (void * (*)(void *))proc, (void *)clientData)) { + (void * (*)(void *)) proc, (void *) clientData)) { result = TCL_ERROR; } else { - *idPtr = (Tcl_ThreadId)theThread; + *idPtr = (Tcl_ThreadId) theThread; result = TCL_OK; } pthread_attr_destroy(&attr); @@ -442,7 +483,6 @@ TclpMasterLock(void) pthread_mutex_lock(&masterLock); #endif } - /* *---------------------------------------------------------------------- @@ -493,6 +533,7 @@ Tcl_GetAllocMutex(void) { #if TCL_THREADS PMutex **allocLockPtrPtr = &allocLockPtr; + pthread_once(&allocLockInitOnce, allocLockInit); return (Tcl_Mutex *) allocLockPtrPtr; #else @@ -538,12 +579,12 @@ Tcl_MutexLock( pmutexPtr = ckalloc(sizeof(PMutex)); PMutexInit(pmutexPtr); - *mutexPtr = (Tcl_Mutex)pmutexPtr; + *mutexPtr = (Tcl_Mutex) pmutexPtr; TclRememberMutex(mutexPtr); } pthread_mutex_unlock(&masterLock); } - pmutexPtr = *((PMutex **)mutexPtr); + pmutexPtr = *((PMutex **) mutexPtr); PMutexLock(pmutexPtr); } @@ -653,8 +694,8 @@ Tcl_ConditionWait( } pthread_mutex_unlock(&masterLock); } - pmutexPtr = *((PMutex **)mutexPtr); - pcondPtr = *((pthread_cond_t **)condPtr); + pmutexPtr = *((PMutex **) mutexPtr); + pcondPtr = *((pthread_cond_t **) condPtr); if (timePtr == NULL) { PCondWait(pcondPtr, pmutexPtr); } else { @@ -696,12 +737,13 @@ void Tcl_ConditionNotify( Tcl_Condition *condPtr) { - pthread_cond_t *pcondPtr = *((pthread_cond_t **)condPtr); + pthread_cond_t *pcondPtr = *((pthread_cond_t **) condPtr); + if (pcondPtr != NULL) { pthread_cond_broadcast(pcondPtr); } else { /* - * Noone has used the condition variable, so there are no waiters. + * No-one has used the condition variable, so there are no waiters. */ } } @@ -729,7 +771,7 @@ void TclpFinalizeCondition( Tcl_Condition *condPtr) { - pthread_cond_t *pcondPtr = *(pthread_cond_t **)condPtr; + pthread_cond_t *pcondPtr = *(pthread_cond_t **) condPtr; if (pcondPtr != NULL) { pthread_cond_destroy(pcondPtr); @@ -796,15 +838,15 @@ static pthread_key_t key; typedef struct { Tcl_Mutex tlock; PMutex plock; -} allocMutex; +} AllocMutex; Tcl_Mutex * TclpNewAllocMutex(void) { - allocMutex *lockPtr; + AllocMutex *lockPtr; register PMutex *plockPtr; - lockPtr = malloc(sizeof(allocMutex)); + lockPtr = malloc(sizeof(AllocMutex)); if (lockPtr == NULL) { Tcl_Panic("could not allocate lock"); } @@ -818,7 +860,8 @@ void TclpFreeAllocMutex( Tcl_Mutex *mutex) /* The alloc mutex to free. */ { - allocMutex* lockPtr = (allocMutex*) mutex; + AllocMutex *lockPtr = (AllocMutex *) mutex; + if (!lockPtr) { return; } @@ -874,7 +917,7 @@ TclpThreadCreateKey(void) { pthread_key_t *ptkeyPtr; - ptkeyPtr = TclpSysAlloc(sizeof *ptkeyPtr, 0); + ptkeyPtr = TclpSysAlloc(sizeof(pthread_key_t), 0); if (NULL == ptkeyPtr) { Tcl_Panic("unable to allocate thread key!"); } -- cgit v0.12