diff options
Diffstat (limited to 'gl/windows-mutex.c')
| -rw-r--r-- | gl/windows-mutex.c | 26 |
1 files changed, 25 insertions, 1 deletions
diff --git a/gl/windows-mutex.c b/gl/windows-mutex.c index b112e13b..87b75735 100644 --- a/gl/windows-mutex.c +++ b/gl/windows-mutex.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* Plain mutexes (native Windows implementation). | 1 | /* Plain mutexes (native Windows implementation). |
| 2 | Copyright (C) 2005-2024 Free Software Foundation, Inc. | 2 | Copyright (C) 2005-2025 Free Software Foundation, Inc. |
| 3 | 3 | ||
| 4 | This file is free software: you can redistribute it and/or modify | 4 | This file is free software: you can redistribute it and/or modify |
| 5 | it under the terms of the GNU Lesser General Public License as | 5 | it under the terms of the GNU Lesser General Public License as |
| @@ -23,10 +23,12 @@ | |||
| 23 | #include "windows-mutex.h" | 23 | #include "windows-mutex.h" |
| 24 | 24 | ||
| 25 | #include <errno.h> | 25 | #include <errno.h> |
| 26 | #include <stdlib.h> | ||
| 26 | 27 | ||
| 27 | void | 28 | void |
| 28 | glwthread_mutex_init (glwthread_mutex_t *mutex) | 29 | glwthread_mutex_init (glwthread_mutex_t *mutex) |
| 29 | { | 30 | { |
| 31 | mutex->owner = 0; | ||
| 30 | InitializeCriticalSection (&mutex->lock); | 32 | InitializeCriticalSection (&mutex->lock); |
| 31 | mutex->guard.done = 1; | 33 | mutex->guard.done = 1; |
| 32 | } | 34 | } |
| @@ -49,7 +51,13 @@ glwthread_mutex_lock (glwthread_mutex_t *mutex) | |||
| 49 | Sleep (0); | 51 | Sleep (0); |
| 50 | } | 52 | } |
| 51 | } | 53 | } |
| 54 | /* If this thread already owns the mutex, POSIX pthread_mutex_lock() is | ||
| 55 | required to deadlock here. But let's not do that on purpose. */ | ||
| 52 | EnterCriticalSection (&mutex->lock); | 56 | EnterCriticalSection (&mutex->lock); |
| 57 | { | ||
| 58 | DWORD self = GetCurrentThreadId (); | ||
| 59 | mutex->owner = self; | ||
| 60 | } | ||
| 53 | return 0; | 61 | return 0; |
| 54 | } | 62 | } |
| 55 | 63 | ||
| @@ -72,6 +80,21 @@ glwthread_mutex_trylock (glwthread_mutex_t *mutex) | |||
| 72 | } | 80 | } |
| 73 | if (!TryEnterCriticalSection (&mutex->lock)) | 81 | if (!TryEnterCriticalSection (&mutex->lock)) |
| 74 | return EBUSY; | 82 | return EBUSY; |
| 83 | { | ||
| 84 | DWORD self = GetCurrentThreadId (); | ||
| 85 | /* TryEnterCriticalSection succeeded. This means that the mutex was either | ||
| 86 | previously unlocked (and thus mutex->owner == 0) or previously locked by | ||
| 87 | this thread (and thus mutex->owner == self). Since the mutex is meant to | ||
| 88 | be plain, we need to fail in the latter case. */ | ||
| 89 | if (mutex->owner == self) | ||
| 90 | { | ||
| 91 | LeaveCriticalSection (&mutex->lock); | ||
| 92 | return EBUSY; | ||
| 93 | } | ||
| 94 | if (mutex->owner != 0) | ||
| 95 | abort (); | ||
| 96 | mutex->owner = self; | ||
| 97 | } | ||
| 75 | return 0; | 98 | return 0; |
| 76 | } | 99 | } |
| 77 | 100 | ||
| @@ -80,6 +103,7 @@ glwthread_mutex_unlock (glwthread_mutex_t *mutex) | |||
| 80 | { | 103 | { |
| 81 | if (!mutex->guard.done) | 104 | if (!mutex->guard.done) |
| 82 | return EINVAL; | 105 | return EINVAL; |
| 106 | mutex->owner = 0; | ||
| 83 | LeaveCriticalSection (&mutex->lock); | 107 | LeaveCriticalSection (&mutex->lock); |
| 84 | return 0; | 108 | return 0; |
| 85 | } | 109 | } |
