summaryrefslogtreecommitdiffstats
path: root/unix/tclUnixThrd.c
diff options
context:
space:
mode:
Diffstat (limited to 'unix/tclUnixThrd.c')
-rw-r--r--unix/tclUnixThrd.c101
1 files changed, 23 insertions, 78 deletions
diff --git a/unix/tclUnixThrd.c b/unix/tclUnixThrd.c
index ae81c5f..f475aed 100644
--- a/unix/tclUnixThrd.c
+++ b/unix/tclUnixThrd.c
@@ -15,26 +15,13 @@
#ifdef TCL_THREADS
-typedef struct ThreadSpecificData {
+typedef struct {
char nabuf[16];
} ThreadSpecificData;
static Tcl_ThreadDataKey dataKey;
/*
- * This is the number of milliseconds to wait between internal retries in
- * the Tcl_MutexLock function. This value must be greater than zero and
- * should be a suitable value for the given platform.
- *
- * TODO: This may need to be dynamically determined, based on the relative
- * performance of the running process.
- */
-
-#ifndef TCL_MUTEX_LOCK_SLEEP_TIME
-# define TCL_MUTEX_LOCK_SLEEP_TIME (25)
-#endif
-
-/*
* masterLock is used to serialize creation of mutexes, condition variables,
* and thread local storage. This is the only place that can count on the
* ability to statically initialize the mutex.
@@ -57,20 +44,6 @@ static pthread_mutex_t initLock = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t allocLock = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t *allocLockPtr = &allocLock;
-/*
- * The mutexLock serializes Tcl_MutexLock. This is necessary to prevent
- * races when finalizing a mutex that some other thread may want to lock.
- */
-
-static pthread_mutex_t mutexLock = PTHREAD_MUTEX_INITIALIZER;
-
-/*
- * These are for the critical sections inside this file.
- */
-
-#define MASTER_LOCK pthread_mutex_lock(&masterLock)
-#define MASTER_UNLOCK pthread_mutex_unlock(&masterLock)
-
#endif /* TCL_THREADS */
/*
@@ -272,7 +245,7 @@ TclpInitLock(void)
/*
*----------------------------------------------------------------------
*
- * TclpFinalizeLock
+ * TclFinalizeLock
*
* This procedure is used to destroy all private resources used in this
* file.
@@ -380,7 +353,6 @@ TclpMasterUnlock(void)
pthread_mutex_unlock(&masterLock);
#endif
}
-
/*
*----------------------------------------------------------------------
@@ -441,10 +413,8 @@ Tcl_MutexLock(
{
pthread_mutex_t *pmutexPtr;
-retry:
-
if (*mutexPtr == NULL) {
- MASTER_LOCK;
+ pthread_mutex_lock(&masterLock);
if (*mutexPtr == NULL) {
/*
* Double inside master lock check to avoid a race condition.
@@ -455,34 +425,10 @@ retry:
*mutexPtr = (Tcl_Mutex)pmutexPtr;
TclRememberMutex(mutexPtr);
}
- MASTER_UNLOCK;
- }
- while (1) {
- pthread_mutex_lock(&mutexLock);
- pmutexPtr = *((pthread_mutex_t **)mutexPtr);
- if (pmutexPtr == NULL) {
- pthread_mutex_unlock(&mutexLock);
- goto retry;
- }
- if (pthread_mutex_trylock(pmutexPtr) == 0) {
- pthread_mutex_unlock(&mutexLock);
- return;
- }
- pthread_mutex_unlock(&mutexLock);
- /*
- * BUGBUG: All core and Thread package tests pass when usleep()
- * is used; however, the Thread package tests hang at
- * various places when Tcl_Sleep() is used, typically
- * while running test "thread-17.8", "thread-17.9", or
- * "thread-17.11a". Really, what we want here is just
- * to yield to other threads for a while.
- */
-#ifdef HAVE_USLEEP
- usleep(TCL_MUTEX_LOCK_SLEEP_TIME * 1000);
-#else
- Tcl_Sleep(TCL_MUTEX_LOCK_SLEEP_TIME);
-#endif
+ pthread_mutex_unlock(&masterLock);
}
+ pmutexPtr = *((pthread_mutex_t **)mutexPtr);
+ pthread_mutex_lock(pmutexPtr);
}
/*
@@ -576,7 +522,7 @@ Tcl_ConditionWait(
struct timespec ptime;
if (*condPtr == NULL) {
- MASTER_LOCK;
+ pthread_mutex_lock(&masterLock);
/*
* Double check inside mutex to avoid race, then initialize condition
@@ -589,7 +535,7 @@ Tcl_ConditionWait(
*condPtr = (Tcl_Condition) pcondPtr;
TclRememberCondition(condPtr);
}
- MASTER_UNLOCK;
+ pthread_mutex_unlock(&masterLock);
}
pmutexPtr = *((pthread_mutex_t **)mutexPtr);
pcondPtr = *((pthread_cond_t **)condPtr);
@@ -698,6 +644,7 @@ TclpFinalizeCondition(
*----------------------------------------------------------------------
*/
+#ifndef TCL_NO_DEPRECATED
Tcl_DirEntry *
TclpReaddir(
DIR * dir)
@@ -720,6 +667,7 @@ TclpInetNtoa(
return inet_ntoa(addr);
#endif
}
+#endif /* TCL_NO_DEPRECATED */
#ifdef TCL_THREADS
/*
@@ -727,10 +675,9 @@ TclpInetNtoa(
*/
#ifdef USE_THREAD_ALLOC
-static volatile int initialized = 0;
static pthread_key_t key;
-typedef struct allocMutex {
+typedef struct {
Tcl_Mutex tlock;
pthread_mutex_t plock;
} allocMutex;
@@ -738,10 +685,10 @@ typedef struct allocMutex {
Tcl_Mutex *
TclpNewAllocMutex(void)
{
- struct allocMutex *lockPtr;
+ allocMutex *lockPtr;
register pthread_mutex_t *plockPtr;
- lockPtr = malloc(sizeof(struct allocMutex));
+ lockPtr = malloc(sizeof(allocMutex));
if (lockPtr == NULL) {
Tcl_Panic("could not allocate lock");
}
@@ -764,39 +711,37 @@ TclpFreeAllocMutex(
}
void
+TclpInitAllocCache(void)
+{
+ pthread_key_create(&key, NULL);
+}
+
+void
TclpFreeAllocCache(
void *ptr)
{
if (ptr != NULL) {
/*
- * Called by the pthread lib when a thread exits
+ * Called by TclFinalizeThreadAllocThread() during the thread
+ * finalization initiated from Tcl_FinalizeThread()
*/
TclFreeAllocCache(ptr);
pthread_setspecific(key, NULL);
- } else if (initialized) {
+ } else {
/*
- * Called by us in TclFinalizeThreadAlloc() during the library
+ * Called by TclFinalizeThreadAlloc() during the process
* finalization initiated from Tcl_Finalize()
*/
pthread_key_delete(key);
- initialized = 0;
}
}
void *
TclpGetAllocCache(void)
{
- if (!initialized) {
- pthread_mutex_lock(allocLockPtr);
- if (!initialized) {
- pthread_key_create(&key, TclpFreeAllocCache);
- initialized = 1;
- }
- pthread_mutex_unlock(allocLockPtr);
- }
return pthread_getspecific(key);
}