Index: generic/tclInt.h ================================================================== --- generic/tclInt.h +++ generic/tclInt.h @@ -3057,13 +3057,10 @@ MODULE_SCOPE void TclpInitPlatform(void); MODULE_SCOPE void TclpInitUnlock(void); MODULE_SCOPE Tcl_Obj * TclpObjListVolumes(void); MODULE_SCOPE void TclpMasterLock(void); MODULE_SCOPE void TclpMasterUnlock(void); -MODULE_SCOPE void TclpMutexLock(void); -MODULE_SCOPE void TclpMutexUnlock(void); -MODULE_SCOPE void TclMutexUnlockAndFinalize(Tcl_Mutex *mutex); MODULE_SCOPE int TclpMatchFiles(Tcl_Interp *interp, char *separators, Tcl_DString *dirPtr, char *pattern, char *tail); MODULE_SCOPE int TclpObjNormalizePath(Tcl_Interp *interp, Tcl_Obj *pathPtr, int nextCheckpoint); MODULE_SCOPE void TclpNativeJoinPath(Tcl_Obj *prefix, const char *joining); Index: generic/tclThread.c ================================================================== --- generic/tclThread.c +++ generic/tclThread.c @@ -276,49 +276,10 @@ #ifdef TCL_THREADS TclpFinalizeMutex(mutexPtr); #endif TclpMasterLock(); ForgetSyncObject(mutexPtr, &mutexRecord); - TclpMasterUnlock(); -} - -/* - *---------------------------------------------------------------------- - * - * TclMutexUnlockAndFinalize -- - * - * This procedure is invoked to unlock and then finalize a mutex. - * The mutex must have been locked by Tcl_MutexLock. It is also - * removed from the list of remembered objects. The mutex can no - * longer be used after calling this procedure. - * - * Results: - * None. - * - * Side effects: - * Remove the mutex from the list. - * - *---------------------------------------------------------------------- - */ - -void -TclMutexUnlockAndFinalize( - Tcl_Mutex *mutexPtr) -{ -#ifdef TCL_THREADS - Tcl_Mutex mutex; -#endif - TclpMasterLock(); - TclpMutexLock(); -#ifdef TCL_THREADS - mutex = *mutexPtr; - *mutexPtr = NULL; /* Force it to be created again. */ - Tcl_MutexUnlock(&mutex); - TclpFinalizeMutex(&mutex); -#endif - ForgetSyncObject(mutexPtr, &mutexRecord); - TclpMutexUnlock(); TclpMasterUnlock(); } /* *---------------------------------------------------------------------- Index: unix/tclUnixNotfy.c ================================================================== --- unix/tclUnixNotfy.c +++ unix/tclUnixNotfy.c @@ -1,5 +1,7 @@ +#define AT_FORK_INIT_VALUE 0 +#define RESET_ATFORK_MUTEX 1 /* * tclUnixNotify.c -- * * This file contains the implementation of the select()-based * Unix-specific notifier, which is the lowest-level part of the Tcl @@ -95,14 +97,15 @@ void *event; /* Any other thread alerts a notifier * that an event is ready to be processed * by sending this event. */ void *hwnd; /* Messaging window. */ #else /* !__CYGWIN__ */ - Tcl_Condition waitCV; /* Any other thread alerts a notifier that an + pthread_cond_t waitCV; /* Any other thread alerts a notifier that an * event is ready to be processed by signaling * this condition variable. */ #endif /* __CYGWIN__ */ + int waitCVinitialized; /* Variable to flag initialization of the structure */ int eventReady; /* True if an event is ready to be processed. * Used as condition flag together with waitCV * above. */ #endif /* TCL_THREADS */ } ThreadSpecificData; @@ -117,19 +120,10 @@ * You must hold the notifierMutex lock before accessing this variable. */ static int notifierCount = 0; -/* - * The following static stores the process ID of the initialized notifier - * thread. If it changes, we have passed a fork and we should start a new - * notifier thread. - * - * You must hold the notifierMutex lock before accessing this variable. - */ -static pid_t processIDInitialized = 0; - /* * The following variable points to the head of a doubly-linked list of * ThreadSpecificData structures for all threads that are currently waiting on * an event. * @@ -156,19 +150,27 @@ /* * The notifierMutex locks access to all of the global notifier state. */ -TCL_DECLARE_MUTEX(notifierMutex) +pthread_mutex_t notifierInitMutex = PTHREAD_MUTEX_INITIALIZER; +pthread_mutex_t notifierMutex = PTHREAD_MUTEX_INITIALIZER; +/* + * The following static indicates if the notifier thread is running. + * + * You must hold the notifierInitMutex before accessing this variable. + */ + +static int notifierThreadRunning = 0; /* * The notifier thread signals the notifierCV when it has finished * initializing the triggerPipe and right before the notifier thread * terminates. */ -static Tcl_Condition notifierCV; +static pthread_cond_t notifierCV = PTHREAD_COND_INITIALIZER; /* * The pollState bits * POLL_WANT is set by each thread before it waits on its condition * variable. It is checked by the notifier before it does select. @@ -192,12 +194,12 @@ * Static routines defined in this file. */ #ifdef TCL_THREADS static void NotifierThreadProc(ClientData clientData); -#if defined(HAVE_PTHREAD_ATFORK) && !defined(__APPLE__) && !defined(__hpux) -static int atForkInit = 0; +#if defined(HAVE_PTHREAD_ATFORK) +static int atForkInit = AT_FORK_INIT_VALUE; static void AtForkPrepare(void); static void AtForkParent(void); static void AtForkChild(void); #endif /* HAVE_PTHREAD_ATFORK */ #endif /* TCL_THREADS */ @@ -249,17 +251,62 @@ extern void *__stdcall RegisterClassW(const WNDCLASS *); extern unsigned char __stdcall ResetEvent(void *); extern unsigned char __stdcall TranslateMessage(const MSG *); /* - * Threaded-cygwin specific functions in this file: + * Threaded-cygwin specific constants and functions in this file: */ +static const WCHAR NotfyClassName[] = L"TclNotifier"; static DWORD __stdcall NotifierProc(void *hwnd, unsigned int message, void *wParam, void *lParam); #endif /* TCL_THREADS && __CYGWIN__ */ +#if TCL_THREADS +/* + *---------------------------------------------------------------------- + * + * StartNotifierThread -- + * + * Start a notfier thread and wait for the notifier pipe to be created. + * + * Results: + * None. + * + * Side effects: + * Running Thread. + * + *---------------------------------------------------------------------- + */ +static void +StartNotifierThread(const char *proc) +{ + if (!notifierThreadRunning) { + pthread_mutex_lock(¬ifierInitMutex); + if (!notifierThreadRunning) { + if (TclpThreadCreate(¬ifierThread, NotifierThreadProc, NULL, + TCL_THREAD_STACK_DEFAULT, TCL_THREAD_JOINABLE) != TCL_OK) { + Tcl_Panic("%s: unable to start notifier thread", proc); + } + + pthread_mutex_lock(¬ifierMutex); + /* + * Wait for the notifier pipe to be created. + */ + + while (triggerPipe < 0) { + pthread_cond_wait(¬ifierCV, ¬ifierMutex); + } + pthread_mutex_unlock(¬ifierMutex); + + notifierThreadRunning = 1; + } + pthread_mutex_unlock(¬ifierInitMutex); + } +} +#endif /* TCL_THREADS */ + /* *---------------------------------------------------------------------- * * Tcl_InitNotifier -- * @@ -284,17 +331,43 @@ #ifdef TCL_THREADS tsdPtr->eventReady = 0; /* - * Start the Notifier thread if necessary. + * Initialize thread specific condition variable for this thread. */ + if (tsdPtr->waitCVinitialized == 0) { +#ifdef __CYGWIN__ + WNDCLASS class; - Tcl_MutexLock(¬ifierMutex); -#if defined(HAVE_PTHREAD_ATFORK) && !defined(__APPLE__) && !defined(__hpux) + class.style = 0; + class.cbClsExtra = 0; + class.cbWndExtra = 0; + class.hInstance = TclWinGetTclInstance(); + class.hbrBackground = NULL; + class.lpszMenuName = NULL; + class.lpszClassName = NotfyClassName; + class.lpfnWndProc = NotifierProc; + class.hIcon = NULL; + class.hCursor = NULL; + + RegisterClassW(&class); + tsdPtr->hwnd = CreateWindowExW(NULL, class.lpszClassName, + class.lpszClassName, 0, 0, 0, 0, 0, NULL, NULL, + TclWinGetTclInstance(), NULL); + tsdPtr->event = CreateEventW(NULL, 1 /* manual */, + 0 /* !signaled */, NULL); +#else + pthread_cond_init(&tsdPtr->waitCV, NULL); +#endif /* __CYGWIN__ */ + tsdPtr->waitCVinitialized = 1; + } + + pthread_mutex_lock(¬ifierInitMutex); +#if defined(HAVE_PTHREAD_ATFORK) /* - * Install pthread_atfork handlers to reinitialize the notifier in the + * Install pthread_atfork handlers to clean up the notifier in the * child of a fork. */ if (!atForkInit) { int result = pthread_atfork(AtForkPrepare, AtForkParent, AtForkChild); @@ -303,40 +376,15 @@ Tcl_Panic("Tcl_InitNotifier: pthread_atfork failed"); } atForkInit = 1; } #endif /* HAVE_PTHREAD_ATFORK */ - /* - * Check if my process id changed, e.g. I was forked - * In this case, restart the notifier thread and close the - * pipe to the original notifier thread - */ - if (notifierCount > 0 && processIDInitialized != getpid()) { - Tcl_ConditionFinalize(¬ifierCV); - notifierCount = 0; - processIDInitialized = 0; - close(triggerPipe); - triggerPipe = -1; - } - if (notifierCount == 0) { - if (TclpThreadCreate(¬ifierThread, NotifierThreadProc, NULL, - TCL_THREAD_STACK_DEFAULT, TCL_THREAD_JOINABLE) != TCL_OK) { - Tcl_Panic("Tcl_InitNotifier: unable to start notifier thread"); - } - processIDInitialized = getpid(); - } + notifierCount++; - /* - * Wait for the notifier pipe to be created. - */ - - while (triggerPipe < 0) { - Tcl_ConditionWait(¬ifierCV, ¬ifierMutex, NULL); - } - - Tcl_MutexUnlock(¬ifierMutex); + pthread_mutex_unlock(¬ifierInitMutex); + #endif /* TCL_THREADS */ return tsdPtr; } } @@ -367,64 +415,54 @@ return; } else { #ifdef TCL_THREADS ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - Tcl_MutexLock(¬ifierMutex); + pthread_mutex_lock(¬ifierInitMutex); notifierCount--; /* * If this is the last thread to use the notifier, close the notifier * pipe and wait for the background thread to terminate. */ if (notifierCount == 0) { - int result; - - if (triggerPipe < 0) { - Tcl_Panic("Tcl_FinalizeNotifier: %s", - "notifier pipe not initialized"); - } - - /* - * Send "q" message to the notifier thread so that it will - * terminate. The notifier will return from its call to select() - * and notice that a "q" message has arrived, it will then close - * its side of the pipe and terminate its thread. Note the we can - * not just close the pipe and check for EOF in the notifier thread - * because if a background child process was created with exec, - * select() would not register the EOF on the pipe until the child - * processes had terminated. [Bug: 4139] [Bug: 1222872] - */ - - if (write(triggerPipe, "q", 1) != 1) { - Tcl_Panic("Tcl_FinalizeNotifier: %s", - "unable to write q to triggerPipe"); - } - close(triggerPipe); - while(triggerPipe >= 0) { - Tcl_ConditionWait(¬ifierCV, ¬ifierMutex, NULL); - } - - result = Tcl_JoinThread(notifierThread, NULL); - if (result) { - Tcl_Panic("Tcl_FinalizeNotifier: %s", - "unable to join notifier thread"); + + if (triggerPipe != -1) { + if (write(triggerPipe, "q", 1) != 1) { + Tcl_Panic("Tcl_FinalizeNotifier: %s", + "unable to write q to triggerPipe"); + } + close(triggerPipe); + while(triggerPipe != -1) { + pthread_cond_wait(¬ifierCV, ¬ifierMutex); + } + if (notifierThreadRunning) { + int result = pthread_join((pthread_t) notifierThread, NULL); + + if (result) { + Tcl_Panic("Tcl_FinalizeNotifier: unable to join notifier " + "thread"); + } + notifierThreadRunning = 0; + } } } /* * Clean up any synchronization objects in the thread local storage. */ #ifdef __CYGWIN__ + DestroyWindow(tsdPtr->hwnd); CloseHandle(tsdPtr->event); #else /* __CYGWIN__ */ - Tcl_ConditionFinalize(&(tsdPtr->waitCV)); + pthread_cond_destroy(&tsdPtr->waitCV); #endif /* __CYGWIN__ */ + tsdPtr->waitCVinitialized = 0; - Tcl_MutexUnlock(¬ifierMutex); + pthread_mutex_unlock(¬ifierInitMutex); #endif /* TCL_THREADS */ } } /* @@ -455,18 +493,19 @@ return; } else { #ifdef TCL_THREADS ThreadSpecificData *tsdPtr = clientData; - Tcl_MutexLock(¬ifierMutex); + pthread_mutex_lock(¬ifierMutex); tsdPtr->eventReady = 1; + # ifdef __CYGWIN__ PostMessageW(tsdPtr->hwnd, 1024, 0, 0); # else - Tcl_ConditionNotify(&tsdPtr->waitCV); + pthread_cond_broadcast(&tsdPtr->waitCV); # endif /* __CYGWIN__ */ - Tcl_MutexUnlock(¬ifierMutex); + pthread_mutex_unlock(¬ifierMutex); #endif /* TCL_THREADS */ } } /* @@ -525,12 +564,14 @@ * TCL_SERVICE_NONE. */ { if (tclNotifierHooks.serviceModeHookProc) { tclNotifierHooks.serviceModeHookProc(mode); return; - } else { - /* Does nothing in this implementation. */ + } else if (mode == TCL_SERVICE_ALL) { +#if TCL_THREADS + StartNotifierThread("Tcl_ServiceModeHook"); +#endif } } /* *---------------------------------------------------------------------- @@ -739,10 +780,11 @@ * directly in the event, so that the handler can be deleted while the * event is queued without leaving a dangling pointer. */ tsdPtr = TCL_TSD_INIT(&dataKey); + for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL; filePtr = filePtr->nextPtr) { if (filePtr->fd != fileEvPtr->fd) { continue; } @@ -876,39 +918,17 @@ #endif /* !TCL_THREADS */ } #ifdef TCL_THREADS /* - * Place this thread on the list of interested threads, signal the - * notifier thread, and wait for a response or a timeout. + * Start notifier thread and place this thread on the list of + * interested threads, signal the notifier thread, and wait for a + * response or a timeout. */ - -#ifdef __CYGWIN__ - if (!tsdPtr->hwnd) { - WNDCLASS class; - - class.style = 0; - class.cbClsExtra = 0; - class.cbWndExtra = 0; - class.hInstance = TclWinGetTclInstance(); - class.hbrBackground = NULL; - class.lpszMenuName = NULL; - class.lpszClassName = L"TclNotifier"; - class.lpfnWndProc = NotifierProc; - class.hIcon = NULL; - class.hCursor = NULL; - - RegisterClassW(&class); - tsdPtr->hwnd = CreateWindowExW(NULL, class.lpszClassName, - class.lpszClassName, 0, 0, 0, 0, 0, NULL, NULL, - TclWinGetTclInstance(), NULL); - tsdPtr->event = CreateEventW(NULL, 1 /* manual */, - 0 /* !signaled */, NULL); - } -#endif /* __CYGWIN */ - - Tcl_MutexLock(¬ifierMutex); + StartNotifierThread("Tcl_WaitForEvent"); + + pthread_mutex_lock(¬ifierMutex); if (timePtr != NULL && timePtr->sec == 0 && (timePtr->usec == 0 #if defined(__APPLE__) && defined(__LP64__) /* * On 64-bit Darwin, pthread_cond_timedwait() appears to have @@ -969,16 +989,27 @@ if (timePtr) { timeout = timePtr->sec * 1000 + timePtr->usec / 1000; } else { timeout = 0xFFFFFFFF; } - Tcl_MutexUnlock(¬ifierMutex); + pthread_mutex_unlock(¬ifierMutex); MsgWaitForMultipleObjects(1, &tsdPtr->event, 0, timeout, 1279); - Tcl_MutexLock(¬ifierMutex); + pthread_mutex_lock(¬ifierMutex); } #else - Tcl_ConditionWait(&tsdPtr->waitCV, ¬ifierMutex, timePtr); + if (timePtr != NULL) { + Tcl_Time now; + struct timespec ptime; + + Tcl_GetTime(&now); + ptime.tv_sec = timePtr->sec + now.sec + (timePtr->usec + now.usec) / 1000000; + ptime.tv_nsec = 1000 * ((timePtr->usec + now.usec) % 1000000); + + pthread_cond_timedwait(&tsdPtr->waitCV, ¬ifierMutex, &ptime); + } else { + pthread_cond_wait(&tsdPtr->waitCV, ¬ifierMutex); + } #endif /* __CYGWIN__ */ } tsdPtr->eventReady = 0; #ifdef __CYGWIN__ @@ -1077,11 +1108,11 @@ Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL); } filePtr->readyMask = mask; } #ifdef TCL_THREADS - Tcl_MutexUnlock(¬ifierMutex); + pthread_mutex_unlock(¬ifierMutex); #endif /* TCL_THREADS */ return 0; } } @@ -1149,19 +1180,19 @@ /* * Install the write end of the pipe into the global variable. */ - Tcl_MutexLock(¬ifierMutex); + pthread_mutex_lock(¬ifierMutex); triggerPipe = fds[1]; /* * Signal any threads that are waiting. */ - Tcl_ConditionNotify(¬ifierCV); - Tcl_MutexUnlock(¬ifierMutex); + pthread_cond_broadcast(¬ifierCV); + pthread_mutex_unlock(¬ifierMutex); /* * Look for file events and report them to interested threads. */ @@ -1173,11 +1204,11 @@ /* * Compute the logical OR of the select masks from all the waiting * notifiers. */ - Tcl_MutexLock(¬ifierMutex); + pthread_mutex_lock(¬ifierMutex); timePtr = NULL; for (tsdPtr = waitingListPtr; tsdPtr; tsdPtr = tsdPtr->nextPtr) { for (i = tsdPtr->numFdBits-1; i >= 0; --i) { if (FD_ISSET(i, &tsdPtr->checkMasks.readable)) { FD_SET(i, &readableMask); @@ -1200,11 +1231,11 @@ tsdPtr->pollState |= POLL_DONE; timePtr = &poll; } } - Tcl_MutexUnlock(¬ifierMutex); + pthread_mutex_unlock(¬ifierMutex); /* * Set up the select mask to include the receive pipe. */ @@ -1224,11 +1255,11 @@ /* * Alert any threads that are waiting on a ready file descriptor. */ - Tcl_MutexLock(¬ifierMutex); + pthread_mutex_lock(¬ifierMutex); for (tsdPtr = waitingListPtr; tsdPtr; tsdPtr = tsdPtr->nextPtr) { found = 0; for (i = tsdPtr->numFdBits-1; i >= 0; --i) { if (FD_ISSET(i, &tsdPtr->checkMasks.readable) @@ -1271,15 +1302,15 @@ tsdPtr->pollState = 0; } #ifdef __CYGWIN__ PostMessageW(tsdPtr->hwnd, 1024, 0, 0); #else /* __CYGWIN__ */ - Tcl_ConditionNotify(&tsdPtr->waitCV); + pthread_cond_broadcast(&tsdPtr->waitCV); #endif /* __CYGWIN__ */ } } - Tcl_MutexUnlock(¬ifierMutex); + pthread_mutex_unlock(¬ifierMutex); /* * Consume the next byte from the notifier pipe if the pipe was * readable. Note that there may be multiple bytes pending, but to * avoid a race condition we only read one at a time. @@ -1304,19 +1335,19 @@ * Clean up the read end of the pipe and signal any threads waiting on * termination of the notifier thread. */ close(receivePipe); - Tcl_MutexLock(¬ifierMutex); + pthread_mutex_lock(¬ifierMutex); triggerPipe = -1; - Tcl_ConditionNotify(¬ifierCV); - Tcl_MutexUnlock(¬ifierMutex); + pthread_cond_broadcast(¬ifierCV); + pthread_mutex_unlock(¬ifierMutex); TclpThreadExit(0); } -#if defined(HAVE_PTHREAD_ATFORK) && !defined(__APPLE__) && !defined(__hpux) +#if defined(HAVE_PTHREAD_ATFORK) /* *---------------------------------------------------------------------- * * AtForkPrepare -- * @@ -1332,13 +1363,13 @@ */ static void AtForkPrepare(void) { - Tcl_MutexLock(¬ifierMutex); - TclpMasterLock(); - TclpMutexLock(); +#if RESET_ATFORK_MUTEX == 0 + pthread_mutex_lock(¬ifierInitMutex); +#endif } /* *---------------------------------------------------------------------- * @@ -1356,13 +1387,13 @@ */ static void AtForkParent(void) { - TclpMutexUnlock(); - TclpMasterUnlock(); - Tcl_MutexUnlock(¬ifierMutex); +#if RESET_ATFORK_MUTEX == 0 + pthread_mutex_unlock(¬ifierInitMutex); +#endif } /* *---------------------------------------------------------------------- * @@ -1380,13 +1411,71 @@ */ static void AtForkChild(void) { - TclpMutexUnlock(); - TclpMasterUnlock(); - TclMutexUnlockAndFinalize(¬ifierMutex); + if (notifierThreadRunning == 1) { + pthread_cond_destroy(¬ifierCV); + } +#if RESET_ATFORK_MUTEX == 0 + pthread_mutex_unlock(¬ifierInitMutex); +#else + pthread_mutex_init(¬ifierInitMutex, NULL); + pthread_mutex_init(¬ifierMutex, NULL); +#endif + pthread_cond_init(¬ifierCV, NULL); + + /* + * notifierThreadRunning == 1: thread is running, (there might be data in notifier lists) + * atForkInit == 0: InitNotifier was never called + * notifierCount != 0: unbalanced InitNotifier() / FinalizeNotifier calls + * waitingListPtr != 0: there are threads currently waiting for events. + */ + + if (atForkInit == 1) { + + notifierCount = 0; + if (notifierThreadRunning == 1) { + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + notifierThreadRunning = 0; + + close(triggerPipe); + triggerPipe = -1; + /* + * The waitingListPtr might contain event info from multiple + * threads, which are invalid here, so setting it to NULL is not + * unreasonable. + */ + waitingListPtr = NULL; + + /* + * The tsdPtr from before the fork is copied as well. But since + * we are paranoic, we don't trust its condvar and reset it. + */ +#ifdef __CYGWIN__ + DestroyWindow(tsdPtr->hwnd); + tsdPtr->hwnd = CreateWindowExW(NULL, NotfyClassName, + NotfyClassName, 0, 0, 0, 0, 0, NULL, NULL, + TclWinGetTclInstance(), NULL); + ResetEvent(tsdPtr->event); +#else + pthread_cond_destroy(&tsdPtr->waitCV); + pthread_cond_init(&tsdPtr->waitCV, NULL); +#endif + /* + * In case, we had multiple threads running before the fork, + * make sure, we don't try to reach out to their thread local data. + */ + tsdPtr->nextPtr = tsdPtr->prevPtr = NULL; + + /* + * The list of registered event handlers at fork time is in + * tsdPtr->firstFileHandlerPtr; + */ + } + } + Tcl_InitNotifier(); } #endif /* HAVE_PTHREAD_ATFORK */ #endif /* TCL_THREADS */ Index: unix/tclUnixThrd.c ================================================================== --- unix/tclUnixThrd.c +++ unix/tclUnixThrd.c @@ -383,62 +383,10 @@ /* *---------------------------------------------------------------------- * - * TclpMutexLock - * - * This procedure is used to grab a lock that serializes locking - * another mutex. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -void -TclpMutexLock(void) -{ -#ifdef TCL_THREADS - pthread_mutex_lock(&mutexLock); -#endif -} - - -/* - *---------------------------------------------------------------------- - * - * TclpMutexUnlock - * - * This procedure is used to release a lock that serializes locking - * another mutex. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -void -TclpMutexUnlock(void) -{ -#ifdef TCL_THREADS - pthread_mutex_unlock(&mutexLock); -#endif -} - - -/* - *---------------------------------------------------------------------- - * * Tcl_GetAllocMutex * * This procedure returns a pointer to a statically initialized mutex for * use by the memory allocator. The alloctor must use this lock, because * all other locks are allocated... @@ -508,21 +456,21 @@ TclRememberMutex(mutexPtr); } MASTER_UNLOCK; } while (1) { - TclpMutexLock(); + pthread_mutex_lock(&mutexLock); pmutexPtr = *((pthread_mutex_t **)mutexPtr); if (pmutexPtr == NULL) { - TclpMutexUnlock(); + pthread_mutex_unlock(&mutexLock); goto retry; } if (pthread_mutex_trylock(pmutexPtr) == 0) { - TclpMutexUnlock(); + pthread_mutex_unlock(&mutexLock); return; } - TclpMutexUnlock(); + 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 Index: win/tclWinThrd.c ================================================================== --- win/tclWinThrd.c +++ win/tclWinThrd.c @@ -480,56 +480,10 @@ } /* *---------------------------------------------------------------------- * - * TclpMutexLock - * - * This procedure is used to grab a lock that serializes locking - * another mutex. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -void -TclpMutexLock(void) -{ - EnterCriticalSection(&mutexLock); -} - -/* - *---------------------------------------------------------------------- - * - * TclpMutexUnlock - * - * This procedure is used to release a lock that serializes locking - * another mutex. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -void -TclpMutexUnlock(void) -{ - LeaveCriticalSection(&mutexLock); -} - -/* - *---------------------------------------------------------------------- - * * Tcl_GetAllocMutex * * This procedure returns a pointer to a statically initialized mutex for * use by the memory allocator. The alloctor must use this lock, because * all other locks are allocated... @@ -650,21 +604,21 @@ TclRememberMutex(mutexPtr); } MASTER_UNLOCK; } while (1) { - TclpMutexLock(); + EnterCriticalSection(&mutexLock); csPtr = *((CRITICAL_SECTION **)mutexPtr); if (csPtr == NULL) { - TclpMutexUnlock(); + LeaveCriticalSection(&mutexLock); goto retry; } if (TryEnterCriticalSection(csPtr)) { - TclpMutexUnlock(); + LeaveCriticalSection(&mutexLock); return; } - TclpMutexUnlock(); + LeaveCriticalSection(&mutexLock); Tcl_Sleep(TCL_MUTEX_LOCK_SLEEP_TIME); } } /*