Tcl Source Code

Changes On Branch tip-509
Login
Bounty program for improvements to Tcl and certain Tcl packages.

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Changes In Branch tip-509 Excluding Merge-Ins

This is equivalent to a diff from bfedd422d9 to c35c3a7455

2018-09-28
09:50
Implement TIP 509: reentrant mutexes on all platforms check-in: 27777c925a user: dkf tags: core-8-branch
09:49
Clean up code style and add key phrases to documentation. Closed-Leaf check-in: c35c3a7455 user: dkf tags: tip-509
09:18
merge core-8-branch check-in: b3d9254efa user: dkf tags: tip-509
07:24
Fix minor typo check-in: bfedd422d9 user: dkf tags: core-8-branch
2018-09-27
11:08
Implementation of TIP 426: Determining the "Type" of Commands check-in: 4dbf61778e user: dkf tags: core-8-branch

Changes to doc/Thread.3.

    41     41   int
    42     42   \fBTcl_JoinThread\fR(\fIid, result\fR)
    43     43   .SH ARGUMENTS
    44     44   .AS Tcl_CreateThreadProc proc out
    45     45   .AP Tcl_Condition *condPtr in
    46     46   A condition variable, which must be associated with a mutex lock.
    47     47   .AP Tcl_Mutex *mutexPtr in
    48         -A mutex lock.
           48  +.VS TIP509
           49  +A recursive mutex lock.
           50  +.VE TIP509
    49     51   .AP "const Tcl_Time" *timePtr in
    50     52   A time limit on the condition wait.  NULL to wait forever.
    51     53   Note that a polling value of 0 seconds does not make much sense.
    52     54   .AP Tcl_ThreadDataKey *keyPtr in
    53     55   This identifies a block of thread local storage.  The key should be
    54     56   static and process-wide, yet each thread will end up associating
    55     57   a different block of storage with this key.
................................................................................
   131    133   allocated and initialized to all zeros the first time each thread asks for it.
   132    134   The storage is automatically deallocated by \fBTcl_FinalizeThread\fR.
   133    135   .SS "SYNCHRONIZATION AND COMMUNICATION"
   134    136   Tcl provides \fBTcl_ThreadQueueEvent\fR and \fBTcl_ThreadAlert\fR
   135    137   for handling event queuing in multithreaded applications.  See
   136    138   the \fBNotifier\fR manual page for more information on these procedures.
   137    139   .PP
   138         -A mutex is a lock that is used to serialize all threads through a piece
          140  +A mutex is a
          141  +.VS TIP509
          142  +recursive
          143  +.VE TIP509
          144  +lock that is used to serialize all threads through a piece
   139    145   of code by calling \fBTcl_MutexLock\fR and \fBTcl_MutexUnlock\fR.
   140    146   If one thread holds a mutex, any other thread calling \fBTcl_MutexLock\fR will
   141    147   block until \fBTcl_MutexUnlock\fR is called.
   142    148   A mutex can be destroyed after its use by calling \fBTcl_MutexFinalize\fR.
   143    149   The result of locking a mutex twice from the same thread is undefined.
   144    150   On some platforms it will result in a deadlock.
   145    151   The \fBTcl_MutexLock\fR, \fBTcl_MutexUnlock\fR and \fBTcl_MutexFinalize\fR

Changes to unix/configure.

  1862   1862   fi
  1863   1863   eval ac_res=\$$3
  1864   1864   	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
  1865   1865   $as_echo "$ac_res" >&6; }
  1866   1866     eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
  1867   1867   
  1868   1868   } # ac_fn_c_check_func
         1869  +
         1870  +# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES
         1871  +# ---------------------------------------------
         1872  +# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR
         1873  +# accordingly.
         1874  +ac_fn_c_check_decl ()
         1875  +{
         1876  +  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
         1877  +  as_decl_name=`echo $2|sed 's/ *(.*//'`
         1878  +  as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
         1879  +  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
         1880  +$as_echo_n "checking whether $as_decl_name is declared... " >&6; }
         1881  +if eval \${$3+:} false; then :
         1882  +  $as_echo_n "(cached) " >&6
         1883  +else
         1884  +  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
         1885  +/* end confdefs.h.  */
         1886  +$4
         1887  +int
         1888  +main ()
         1889  +{
         1890  +#ifndef $as_decl_name
         1891  +#ifdef __cplusplus
         1892  +  (void) $as_decl_use;
         1893  +#else
         1894  +  (void) $as_decl_name;
         1895  +#endif
         1896  +#endif
         1897  +
         1898  +  ;
         1899  +  return 0;
         1900  +}
         1901  +_ACEOF
         1902  +if ac_fn_c_try_compile "$LINENO"; then :
         1903  +  eval "$3=yes"
         1904  +else
         1905  +  eval "$3=no"
         1906  +fi
         1907  +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
         1908  +fi
         1909  +eval ac_res=\$$3
         1910  +	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
         1911  +$as_echo "$ac_res" >&6; }
         1912  +  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
         1913  +
         1914  +} # ac_fn_c_check_decl
  1869   1915   
  1870   1916   # ac_fn_c_check_type LINENO TYPE VAR INCLUDES
  1871   1917   # -------------------------------------------
  1872   1918   # Tests whether TYPE exists after having included INCLUDES, setting cache
  1873   1919   # variable VAR accordingly.
  1874   1920   ac_fn_c_check_type ()
  1875   1921   {
................................................................................
  4406   4452   #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
  4407   4453   _ACEOF
  4408   4454   
  4409   4455   fi
  4410   4456   done
  4411   4457   
  4412   4458       LIBS=$ac_saved_libs
         4459  +
         4460  +    # TIP #509
         4461  +    ac_fn_c_check_decl "$LINENO" "PTHREAD_MUTEX_RECURSIVE" "ac_cv_have_decl_PTHREAD_MUTEX_RECURSIVE" "#include <pthread.h>
         4462  +"
         4463  +if test "x$ac_cv_have_decl_PTHREAD_MUTEX_RECURSIVE" = xyes; then :
         4464  +  ac_have_decl=1
         4465  +else
         4466  +  ac_have_decl=0
         4467  +fi
         4468  +
         4469  +cat >>confdefs.h <<_ACEOF
         4470  +#define HAVE_DECL_PTHREAD_MUTEX_RECURSIVE $ac_have_decl
         4471  +_ACEOF
         4472  +if test $ac_have_decl = 1; then :
         4473  +  tcl_ok=yes
         4474  +else
         4475  +  tcl_ok=no
         4476  +fi
         4477  +
  4413   4478   
  4414   4479   
  4415   4480   # Add the threads support libraries
  4416   4481   LIBS="$LIBS$THREADS_LIBS"
  4417   4482   
  4418   4483   
  4419   4484       { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to build libraries" >&5

Changes to unix/tcl.m4.

  2352   2352       # Does the pthread-implementation provide
  2353   2353       # 'pthread_attr_setstacksize' ?
  2354   2354   
  2355   2355       ac_saved_libs=$LIBS
  2356   2356       LIBS="$LIBS $THREADS_LIBS"
  2357   2357       AC_CHECK_FUNCS(pthread_attr_setstacksize pthread_atfork)
  2358   2358       LIBS=$ac_saved_libs
         2359  +
         2360  +    # TIP #509
         2361  +    AC_CHECK_DECLS([PTHREAD_MUTEX_RECURSIVE],tcl_ok=yes,tcl_ok=no, [[#include <pthread.h>]])
  2359   2362   ])
  2360   2363   
  2361   2364   #--------------------------------------------------------------------
  2362   2365   # SC_TCL_EARLY_FLAGS
  2363   2366   #
  2364   2367   #	Check for what flags are needed to be passed so the correct OS
  2365   2368   #	features are available.

Changes to unix/tclUnixThrd.c.

    10     10    * See the file "license.terms" for information on usage and redistribution of
    11     11    * this file, and for a DISCLAIMER OF ALL WARRANTIES.
    12     12    */
    13     13   
    14     14   #include "tclInt.h"
    15     15   
    16     16   #if TCL_THREADS
           17  +
           18  +/*
           19  + * TIP #509. Ensures that Tcl's mutexes are reentrant.
           20  + *
           21  + *----------------------------------------------------------------------
           22  + *
           23  + * PMutexInit --
           24  + *
           25  + *	Sets up the memory pointed to by its argument so that it contains the
           26  + *	implementation of a recursive lock. Caller supplies the space.
           27  + *
           28  + *----------------------------------------------------------------------
           29  + *
           30  + * PMutexDestroy --
           31  + *
           32  + *	Tears down the implementation of a recursive lock (but does not
           33  + *	deallocate the space holding the lock).
           34  + *
           35  + *----------------------------------------------------------------------
           36  + *
           37  + * PMutexLock --
           38  + *
           39  + *	Locks a recursive lock. (Similar to pthread_mutex_lock)
           40  + *
           41  + *----------------------------------------------------------------------
           42  + *
           43  + * PMutexUnlock --
           44  + *
           45  + *	Unlocks a recursive lock. (Similar to pthread_mutex_unlock)
           46  + *
           47  + *----------------------------------------------------------------------
           48  + *
           49  + * PCondWait --
           50  + *
           51  + *	Waits on a condition variable linked a recursive lock. (Similar to
           52  + *	pthread_cond_wait)
           53  + *
           54  + *----------------------------------------------------------------------
           55  + *
           56  + * PCondTimedWait --
           57  + *
           58  + *	Waits for a limited amount of time on a condition variable linked to a
           59  + *	recursive lock. (Similar to pthread_cond_timedwait)
           60  + *
           61  + *----------------------------------------------------------------------
           62  + */
    17     63   
           64  +#ifndef HAVE_DECL_PTHREAD_MUTEX_RECURSIVE
           65  +#define HAVE_DECL_PTHREAD_MUTEX_RECURSIVE 0
           66  +#endif
           67  +
           68  +#if HAVE_DECL_PTHREAD_MUTEX_RECURSIVE
           69  +/*
           70  + * Pthread has native reentrant (AKA recursive) mutexes. Use them for
           71  + * Tcl_Mutex.
           72  + */
           73  +
           74  +typedef pthread_mutex_t PMutex;
           75  +
           76  +static void
           77  +PMutexInit(
           78  +    PMutex *pmutexPtr)
           79  +{
           80  +    pthread_mutexattr_t attr;
           81  +
           82  +    pthread_mutexattr_init(&attr);
           83  +    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
           84  +    pthread_mutex_init(pmutexPtr, &attr);
           85  +}
           86  +
           87  +#define PMutexDestroy	pthread_mutex_destroy
           88  +#define PMutexLock	pthread_mutex_lock
           89  +#define PMutexUnlock	pthread_mutex_unlock
           90  +#define PCondWait	pthread_cond_wait
           91  +#define PCondTimedWait	pthread_cond_timedwait
           92  +
           93  +#else /* !HAVE_PTHREAD_MUTEX_RECURSIVE */
           94  +
           95  +/*
           96  + * No native support for reentrant mutexes. Emulate them with regular mutexes
           97  + * and thread-local counters.
           98  + */
           99  +
          100  +typedef struct PMutex {
          101  +    pthread_mutex_t mutex;
          102  +    pthread_t thread;
          103  +    int counter;
          104  +} PMutex;
          105  +
          106  +static void
          107  +PMutexInit(
          108  +    PMutex *pmutexPtr)
          109  +{
          110  +    pthread_mutex_init(&pmutexPtr->mutex, NULL);
          111  +    pmutexPtr->thread = 0;
          112  +    pmutexPtr->counter = 0;
          113  +}
          114  +
          115  +static void
          116  +PMutexDestroy(
          117  +    PMutex *pmutexPtr)
          118  +{
          119  +    pthread_mutex_destroy(&pmutexPtr->mutex);
          120  +}
          121  +
          122  +static void
          123  +PMutexLock(
          124  +    PMutex *pmutexPtr)
          125  +{
          126  +    if (pmutexPtr->thread != pthread_self() || pmutexPtr->counter == 0) {
          127  +	pthread_mutex_lock(&pmutexPtr->mutex);
          128  +	pmutexPtr->thread = pthread_self();
          129  +	pmutexPtr->counter = 0;
          130  +    }
          131  +    pmutexPtr->counter++;
          132  +}
          133  +
          134  +static void
          135  +PMutexUnlock(
          136  +    PMutex *pmutexPtr)
          137  +{
          138  +    pmutexPtr->counter--;
          139  +    if (pmutexPtr->counter == 0) {
          140  +	pmutexPtr->thread = 0;
          141  +	pthread_mutex_unlock(&pmutexPtr->mutex);
          142  +    }
          143  +}
          144  +
          145  +static void
          146  +PCondWait(
          147  +    pthread_cond_t *pcondPtr,
          148  +    PMutex *pmutexPtr)
          149  +{
          150  +    pthread_cond_wait(pcondPtr, &pmutexPtr->mutex);
          151  +}
          152  +
          153  +static void
          154  +PCondTimedWait(
          155  +    pthread_cond_t *pcondPtr,
          156  +    PMutex *pmutexPtr,
          157  +    struct timespec *ptime)
          158  +{
          159  +    pthread_cond_timedwait(pcondPtr, &pmutexPtr->mutex, ptime);
          160  +}
          161  +#endif /* HAVE_PTHREAD_MUTEX_RECURSIVE */
          162  +
    18    163   #ifndef TCL_NO_DEPRECATED
    19    164   typedef struct {
    20    165       char nabuf[16];
    21    166   } ThreadSpecificData;
    22    167   
    23    168   static Tcl_ThreadDataKey dataKey;
    24         -#endif
          169  +#endif /* TCL_NO_DEPRECATED */
    25    170   
    26    171   /*
    27    172    * masterLock is used to serialize creation of mutexes, condition variables,
    28    173    * and thread local storage. This is the only place that can count on the
    29    174    * ability to statically initialize the mutex.
    30    175    */
    31    176   
................................................................................
    39    184   static pthread_mutex_t initLock = PTHREAD_MUTEX_INITIALIZER;
    40    185   
    41    186   /*
    42    187    * allocLock is used by Tcl's version of malloc for synchronization. For
    43    188    * obvious reasons, cannot use any dyamically allocated storage.
    44    189    */
    45    190   
    46         -static pthread_mutex_t allocLock = PTHREAD_MUTEX_INITIALIZER;
    47         -static pthread_mutex_t *allocLockPtr = &allocLock;
          191  +static PMutex allocLock;
          192  +static pthread_once_t allocLockInitOnce = PTHREAD_ONCE_INIT;
          193  +
          194  +static void
          195  +allocLockInit(void)
          196  +{
          197  +    PMutexInit(&allocLock);
          198  +}
          199  +static PMutex *allocLockPtr = &allocLock;
    48    200   
    49    201   #endif /* TCL_THREADS */
    50    202   
    51    203   /*
    52    204    *----------------------------------------------------------------------
    53    205    *
    54    206    * TclpThreadCreate --
................................................................................
   105    257   	if (!result && (size < TCL_THREAD_STACK_MIN)) {
   106    258   	    pthread_attr_setstacksize(&attr, (size_t) TCL_THREAD_STACK_MIN);
   107    259   	}
   108    260   #endif /* TCL_THREAD_STACK_MIN */
   109    261       }
   110    262   #endif /* HAVE_PTHREAD_ATTR_SETSTACKSIZE */
   111    263   
   112         -    if (! (flags & TCL_THREAD_JOINABLE)) {
   113         -	pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
          264  +    if (!(flags & TCL_THREAD_JOINABLE)) {
          265  +	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
   114    266       }
   115    267   
   116    268       if (pthread_create(&theThread, &attr,
   117         -	    (void * (*)(void *))proc, (void *)clientData) &&
          269  +	    (void * (*)(void *)) proc, (void *) clientData) &&
   118    270   	    pthread_create(&theThread, NULL,
   119         -		    (void * (*)(void *))proc, (void *)clientData)) {
          271  +		    (void * (*)(void *)) proc, (void *) clientData)) {
   120    272   	result = TCL_ERROR;
   121    273       } else {
   122         -	*idPtr = (Tcl_ThreadId)theThread;
          274  +	*idPtr = (Tcl_ThreadId) theThread;
   123    275   	result = TCL_OK;
   124    276       }
   125    277       pthread_attr_destroy(&attr);
   126    278       return result;
   127    279   #else
   128    280       return TCL_ERROR;
   129    281   #endif /* TCL_THREADS */
................................................................................
   327    479   void
   328    480   TclpMasterLock(void)
   329    481   {
   330    482   #if TCL_THREADS
   331    483       pthread_mutex_lock(&masterLock);
   332    484   #endif
   333    485   }
   334         -
   335    486   
   336    487   /*
   337    488    *----------------------------------------------------------------------
   338    489    *
   339    490    * TclpMasterUnlock
   340    491    *
   341    492    *	This procedure is used to release a lock that serializes creation and
................................................................................
   377    528    *----------------------------------------------------------------------
   378    529    */
   379    530   
   380    531   Tcl_Mutex *
   381    532   Tcl_GetAllocMutex(void)
   382    533   {
   383    534   #if TCL_THREADS
   384         -    pthread_mutex_t **allocLockPtrPtr = &allocLockPtr;
          535  +    PMutex **allocLockPtrPtr = &allocLockPtr;
          536  +
          537  +    pthread_once(&allocLockInitOnce, allocLockInit);
   385    538       return (Tcl_Mutex *) allocLockPtrPtr;
   386    539   #else
   387    540       return NULL;
   388    541   #endif
   389    542   }
   390    543   
   391    544   #if TCL_THREADS
................................................................................
   409    562    *	first time this Tcl_Mutex is used.
   410    563    *
   411    564    *----------------------------------------------------------------------
   412    565    */
   413    566   
   414    567   void
   415    568   Tcl_MutexLock(
   416         -    Tcl_Mutex *mutexPtr)	/* Really (pthread_mutex_t **) */
          569  +    Tcl_Mutex *mutexPtr)	/* Really (PMutex **) */
   417    570   {
   418         -    pthread_mutex_t *pmutexPtr;
          571  +    PMutex *pmutexPtr;
   419    572   
   420    573       if (*mutexPtr == NULL) {
   421    574   	pthread_mutex_lock(&masterLock);
   422    575   	if (*mutexPtr == NULL) {
   423    576   	    /*
   424    577   	     * Double inside master lock check to avoid a race condition.
   425    578   	     */
   426    579   
   427         -	    pmutexPtr = ckalloc(sizeof(pthread_mutex_t));
   428         -	    pthread_mutex_init(pmutexPtr, NULL);
   429         -	    *mutexPtr = (Tcl_Mutex)pmutexPtr;
          580  +	    pmutexPtr = ckalloc(sizeof(PMutex));
          581  +	    PMutexInit(pmutexPtr);
          582  +	    *mutexPtr = (Tcl_Mutex) pmutexPtr;
   430    583   	    TclRememberMutex(mutexPtr);
   431    584   	}
   432    585   	pthread_mutex_unlock(&masterLock);
   433    586       }
   434         -    pmutexPtr = *((pthread_mutex_t **)mutexPtr);
   435         -    pthread_mutex_lock(pmutexPtr);
          587  +    pmutexPtr = *((PMutex **) mutexPtr);
          588  +    PMutexLock(pmutexPtr);
   436    589   }
   437    590   
   438    591   /*
   439    592    *----------------------------------------------------------------------
   440    593    *
   441    594    * Tcl_MutexUnlock --
   442    595    *
................................................................................
   450    603    *	The mutex is released when this returns.
   451    604    *
   452    605    *----------------------------------------------------------------------
   453    606    */
   454    607   
   455    608   void
   456    609   Tcl_MutexUnlock(
   457         -    Tcl_Mutex *mutexPtr)	/* Really (pthread_mutex_t **) */
          610  +    Tcl_Mutex *mutexPtr)	/* Really (PMutex **) */
   458    611   {
   459         -    pthread_mutex_t *pmutexPtr = *(pthread_mutex_t **) mutexPtr;
          612  +    PMutex *pmutexPtr = *(PMutex **) mutexPtr;
   460    613   
   461         -    pthread_mutex_unlock(pmutexPtr);
          614  +    PMutexUnlock(pmutexPtr);
   462    615   }
   463    616   
   464    617   /*
   465    618    *----------------------------------------------------------------------
   466    619    *
   467    620    * TclpFinalizeMutex --
   468    621    *
................................................................................
   480    633    *----------------------------------------------------------------------
   481    634    */
   482    635   
   483    636   void
   484    637   TclpFinalizeMutex(
   485    638       Tcl_Mutex *mutexPtr)
   486    639   {
   487         -    pthread_mutex_t *pmutexPtr = *(pthread_mutex_t **) mutexPtr;
          640  +    PMutex *pmutexPtr = *(PMutex **) mutexPtr;
   488    641   
   489    642       if (pmutexPtr != NULL) {
   490         -	pthread_mutex_destroy(pmutexPtr);
          643  +	PMutexDestroy(pmutexPtr);
   491    644   	ckfree(pmutexPtr);
   492    645   	*mutexPtr = NULL;
   493    646       }
   494    647   }
   495    648   
   496    649   /*
   497    650    *----------------------------------------------------------------------
................................................................................
   514    667    *
   515    668    *----------------------------------------------------------------------
   516    669    */
   517    670   
   518    671   void
   519    672   Tcl_ConditionWait(
   520    673       Tcl_Condition *condPtr,	/* Really (pthread_cond_t **) */
   521         -    Tcl_Mutex *mutexPtr,	/* Really (pthread_mutex_t **) */
          674  +    Tcl_Mutex *mutexPtr,	/* Really (PMutex **) */
   522    675       const Tcl_Time *timePtr) /* Timeout on waiting period */
   523    676   {
   524    677       pthread_cond_t *pcondPtr;
   525         -    pthread_mutex_t *pmutexPtr;
          678  +    PMutex *pmutexPtr;
   526    679       struct timespec ptime;
   527    680   
   528    681       if (*condPtr == NULL) {
   529    682   	pthread_mutex_lock(&masterLock);
   530    683   
   531    684   	/*
   532    685   	 * Double check inside mutex to avoid race, then initialize condition
................................................................................
   537    690   	    pcondPtr = ckalloc(sizeof(pthread_cond_t));
   538    691   	    pthread_cond_init(pcondPtr, NULL);
   539    692   	    *condPtr = (Tcl_Condition) pcondPtr;
   540    693   	    TclRememberCondition(condPtr);
   541    694   	}
   542    695   	pthread_mutex_unlock(&masterLock);
   543    696       }
   544         -    pmutexPtr = *((pthread_mutex_t **)mutexPtr);
   545         -    pcondPtr = *((pthread_cond_t **)condPtr);
          697  +    pmutexPtr = *((PMutex **) mutexPtr);
          698  +    pcondPtr = *((pthread_cond_t **) condPtr);
   546    699       if (timePtr == NULL) {
   547         -	pthread_cond_wait(pcondPtr, pmutexPtr);
          700  +	PCondWait(pcondPtr, pmutexPtr);
   548    701       } else {
   549    702   	Tcl_Time now;
   550    703   
   551    704   	/*
   552    705   	 * Make sure to take into account the microsecond component of the
   553    706   	 * current time, including possible overflow situations. [Bug #411603]
   554    707   	 */
   555    708   
   556    709   	Tcl_GetTime(&now);
   557    710   	ptime.tv_sec = timePtr->sec + now.sec +
   558    711   	    (timePtr->usec + now.usec) / 1000000;
   559    712   	ptime.tv_nsec = 1000 * ((timePtr->usec + now.usec) % 1000000);
   560         -	pthread_cond_timedwait(pcondPtr, pmutexPtr, &ptime);
          713  +	PCondTimedWait(pcondPtr, pmutexPtr, &ptime);
   561    714       }
   562    715   }
   563    716   
   564    717   /*
   565    718    *----------------------------------------------------------------------
   566    719    *
   567    720    * Tcl_ConditionNotify --
................................................................................
   580    733    *----------------------------------------------------------------------
   581    734    */
   582    735   
   583    736   void
   584    737   Tcl_ConditionNotify(
   585    738       Tcl_Condition *condPtr)
   586    739   {
   587         -    pthread_cond_t *pcondPtr = *((pthread_cond_t **)condPtr);
          740  +    pthread_cond_t *pcondPtr = *((pthread_cond_t **) condPtr);
          741  +
   588    742       if (pcondPtr != NULL) {
   589    743   	pthread_cond_broadcast(pcondPtr);
   590    744       } else {
   591    745   	/*
   592         -	 * Noone has used the condition variable, so there are no waiters.
          746  +	 * No-one has used the condition variable, so there are no waiters.
   593    747   	 */
   594    748       }
   595    749   }
   596    750   
   597    751   /*
   598    752    *----------------------------------------------------------------------
   599    753    *
................................................................................
   613    767    *----------------------------------------------------------------------
   614    768    */
   615    769   
   616    770   void
   617    771   TclpFinalizeCondition(
   618    772       Tcl_Condition *condPtr)
   619    773   {
   620         -    pthread_cond_t *pcondPtr = *(pthread_cond_t **)condPtr;
          774  +    pthread_cond_t *pcondPtr = *(pthread_cond_t **) condPtr;
   621    775   
   622    776       if (pcondPtr != NULL) {
   623    777   	pthread_cond_destroy(pcondPtr);
   624    778   	ckfree(pcondPtr);
   625    779   	*condPtr = NULL;
   626    780       }
   627    781   }
................................................................................
   679    833    */
   680    834   
   681    835   #ifdef USE_THREAD_ALLOC
   682    836   static pthread_key_t key;
   683    837   
   684    838   typedef struct {
   685    839       Tcl_Mutex tlock;
   686         -    pthread_mutex_t plock;
   687         -} allocMutex;
          840  +    PMutex plock;
          841  +} AllocMutex;
   688    842   
   689    843   Tcl_Mutex *
   690    844   TclpNewAllocMutex(void)
   691    845   {
   692         -    allocMutex *lockPtr;
   693         -    register pthread_mutex_t *plockPtr;
          846  +    AllocMutex *lockPtr;
          847  +    register PMutex *plockPtr;
   694    848   
   695         -    lockPtr = malloc(sizeof(allocMutex));
          849  +    lockPtr = malloc(sizeof(AllocMutex));
   696    850       if (lockPtr == NULL) {
   697    851   	Tcl_Panic("could not allocate lock");
   698    852       }
   699    853       plockPtr = &lockPtr->plock;
   700    854       lockPtr->tlock = (Tcl_Mutex) plockPtr;
   701         -    pthread_mutex_init(&lockPtr->plock, NULL);
          855  +    PMutexInit(&lockPtr->plock);
   702    856       return &lockPtr->tlock;
   703    857   }
   704    858   
   705    859   void
   706    860   TclpFreeAllocMutex(
   707    861       Tcl_Mutex *mutex)		/* The alloc mutex to free. */
   708    862   {
   709         -    allocMutex* lockPtr = (allocMutex*) mutex;
          863  +    AllocMutex *lockPtr = (AllocMutex *) mutex;
          864  +
   710    865       if (!lockPtr) {
   711    866   	return;
   712    867       }
   713         -    pthread_mutex_destroy(&lockPtr->plock);
          868  +    PMutexDestroy(&lockPtr->plock);
   714    869       free(lockPtr);
   715    870   }
   716    871   
   717    872   void
   718    873   TclpInitAllocCache(void)
   719    874   {
   720    875       pthread_key_create(&key, NULL);
................................................................................
   758    913   #endif /* USE_THREAD_ALLOC */
   759    914   
   760    915   void *
   761    916   TclpThreadCreateKey(void)
   762    917   {
   763    918       pthread_key_t *ptkeyPtr;
   764    919   
   765         -    ptkeyPtr = TclpSysAlloc(sizeof *ptkeyPtr, 0);
          920  +    ptkeyPtr = TclpSysAlloc(sizeof(pthread_key_t), 0);
   766    921       if (NULL == ptkeyPtr) {
   767    922   	Tcl_Panic("unable to allocate thread key!");
   768    923       }
   769    924   
   770    925       if (pthread_key_create(ptkeyPtr, NULL)) {
   771    926   	Tcl_Panic("unable to create pthread key!");
   772    927       }