diff options
Diffstat (limited to 'lib/windows-mutex.c')
-rw-r--r-- | lib/windows-mutex.c | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/lib/windows-mutex.c b/lib/windows-mutex.c index b112e13b..2ac73a07 100644 --- a/lib/windows-mutex.c +++ b/lib/windows-mutex.c @@ -23,10 +23,12 @@ #include "windows-mutex.h" #include <errno.h> +#include <stdlib.h> void glwthread_mutex_init (glwthread_mutex_t *mutex) { + mutex->owner = 0; InitializeCriticalSection (&mutex->lock); mutex->guard.done = 1; } @@ -49,7 +51,13 @@ glwthread_mutex_lock (glwthread_mutex_t *mutex) Sleep (0); } } + /* If this thread already owns the mutex, POSIX pthread_mutex_lock() is + required to deadlock here. But let's not do that on purpose. */ EnterCriticalSection (&mutex->lock); + { + DWORD self = GetCurrentThreadId (); + mutex->owner = self; + } return 0; } @@ -72,6 +80,21 @@ glwthread_mutex_trylock (glwthread_mutex_t *mutex) } if (!TryEnterCriticalSection (&mutex->lock)) return EBUSY; + { + DWORD self = GetCurrentThreadId (); + /* TryEnterCriticalSection succeeded. This means that the mutex was either + previously unlocked (and thus mutex->owner == 0) or previously locked by + this thread (and thus mutex->owner == self). Since the mutex is meant to + be plain, we need to fail in the latter case. */ + if (mutex->owner == self) + { + LeaveCriticalSection (&mutex->lock); + return EBUSY; + } + if (mutex->owner != 0) + abort (); + mutex->owner = self; + } return 0; } @@ -80,6 +103,7 @@ glwthread_mutex_unlock (glwthread_mutex_t *mutex) { if (!mutex->guard.done) return EINVAL; + mutex->owner = 0; LeaveCriticalSection (&mutex->lock); return 0; } |