diff -r adbdb3e74461 Python/thread_nt.h --- a/Python/thread_nt.h Sun Mar 20 17:36:26 2011 +0100 +++ b/Python/thread_nt.h Sun Mar 20 22:28:09 2011 +0100 @@ -10,18 +10,22 @@ #endif typedef struct NRMUTEX { - LONG owned ; - DWORD thread_id ; - HANDLE hevent ; + CRITICAL_SECTION csection; + HANDLE hevent; + /* Is someone waiting to take it? */ + LONG waiting; + /* Is it owned? */ + LONG owned; } NRMUTEX, *PNRMUTEX ; BOOL InitializeNonRecursiveMutex(PNRMUTEX mutex) { - mutex->owned = -1 ; /* No threads have entered NonRecursiveMutex */ - mutex->thread_id = 0 ; + mutex->owned = 0; /* No threads have entered NonRecursiveMutex */ + mutex->waiting = 0; mutex->hevent = CreateEvent(NULL, FALSE, FALSE, NULL) ; + InitializeCriticalSection(&mutex->csection); return mutex->hevent != NULL ; /* TRUE if the mutex is created */ } @@ -30,6 +34,7 @@ DeleteNonRecursiveMutex(PNRMUTEX mutex) { /* No in-use check */ CloseHandle(mutex->hevent) ; + DeleteCriticalSection(&mutex->csection); mutex->hevent = NULL ; /* Just in case */ } @@ -37,32 +42,51 @@ DWORD EnterNonRecursiveMutex(PNRMUTEX mutex, DWORD milliseconds) { /* Assume that the thread waits successfully */ - DWORD ret ; + DWORD ret = WAIT_TIMEOUT; - /* InterlockedIncrement(&mutex->owned) == 0 means that no thread currently owns the mutex */ - if (milliseconds == 0) - { - if (InterlockedCompareExchange(&mutex->owned, 0, -1) != -1) - return WAIT_TIMEOUT ; - ret = WAIT_OBJECT_0 ; + EnterCriticalSection(&mutex->csection); + if (mutex->waiting++ == 0) { + /* Fast path when one waiter and uncontended lock */ + /* Have to manually reset the event so that no spurious wakeup + occurs */ + ResetEvent(mutex->hevent); + if (!mutex->owned) { + mutex->owned = 1; + mutex->waiting = 0; + LeaveCriticalSection(&mutex->csection); + return WAIT_OBJECT_0; + } } - else - ret = InterlockedIncrement(&mutex->owned) ? - /* Some thread owns the mutex, let's wait... */ - WaitForSingleObject(mutex->hevent, milliseconds) : WAIT_OBJECT_0 ; + /* Several threads are waiting, let's all fall back on + WaitForSingleObject(). */ + if (milliseconds != 0) { + LeaveCriticalSection(&mutex->csection); + ret = WaitForSingleObject(mutex->hevent, milliseconds); + EnterCriticalSection(&mutex->csection); + if (ret == WAIT_OBJECT_0) { + assert(!mutex->owned); + mutex->owned = 1; + } + } + --mutex->waiting; + LeaveCriticalSection(&mutex->csection); - mutex->thread_id = GetCurrentThreadId() ; /* We own it */ return ret ; } BOOL LeaveNonRecursiveMutex(PNRMUTEX mutex) { + BOOL ret = FALSE; /* We don't own the mutex */ - mutex->thread_id = 0 ; - return - InterlockedDecrement(&mutex->owned) < 0 || - SetEvent(mutex->hevent) ; /* Other threads are waiting, wake one on them up */ + EnterCriticalSection(&mutex->csection); + if (mutex->owned) { + mutex->owned = 0; + /* If some threads are waiting, wake up exactly one of them */ + ret = SetEvent(mutex->hevent); + } + LeaveCriticalSection(&mutex->csection); + return ret; } PNRMUTEX