1 /* Plain mutexes (native Windows implementation). 2 Copyright (C) 2005-2019 Free Software Foundation, Inc. 3 4 This program is free software: you can redistribute it and/or modify 5 it under the terms of the GNU Lesser General Public License as published by 6 the Free Software Foundation; either version 2.1 of the License, or 7 (at your option) any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU Lesser General Public License for more details. 13 14 You should have received a copy of the GNU Lesser General Public License 15 along with this program. If not, see <https://www.gnu.org/licenses/>. */ 16 17 /* Written by Bruno Haible <bruno@clisp.org>, 2005. 18 Based on GCC's gthr-win32.h. */ 19 20 #include <config.h> 21 22 /* Specification. */ 23 #include "windows-mutex.h" 24 25 #include <errno.h> 26 27 void glwthread_mutex_init(glwthread_mutex_t * mutex)28glwthread_mutex_init (glwthread_mutex_t *mutex) 29 { 30 InitializeCriticalSection (&mutex->lock); 31 mutex->guard.done = 1; 32 } 33 34 int glwthread_mutex_lock(glwthread_mutex_t * mutex)35glwthread_mutex_lock (glwthread_mutex_t *mutex) 36 { 37 if (!mutex->guard.done) 38 { 39 if (InterlockedIncrement (&mutex->guard.started) == 0) 40 /* This thread is the first one to need this mutex. Initialize it. */ 41 glwthread_mutex_init (mutex); 42 else 43 { 44 /* Don't let mutex->guard.started grow and wrap around. */ 45 InterlockedDecrement (&mutex->guard.started); 46 /* Yield the CPU while waiting for another thread to finish 47 initializing this mutex. */ 48 while (!mutex->guard.done) 49 Sleep (0); 50 } 51 } 52 EnterCriticalSection (&mutex->lock); 53 return 0; 54 } 55 56 int glwthread_mutex_trylock(glwthread_mutex_t * mutex)57glwthread_mutex_trylock (glwthread_mutex_t *mutex) 58 { 59 if (!mutex->guard.done) 60 { 61 if (InterlockedIncrement (&mutex->guard.started) == 0) 62 /* This thread is the first one to need this mutex. Initialize it. */ 63 glwthread_mutex_init (mutex); 64 else 65 { 66 /* Don't let mutex->guard.started grow and wrap around. */ 67 InterlockedDecrement (&mutex->guard.started); 68 /* Let another thread finish initializing this mutex, and let it also 69 lock this mutex. */ 70 return EBUSY; 71 } 72 } 73 if (!TryEnterCriticalSection (&mutex->lock)) 74 return EBUSY; 75 return 0; 76 } 77 78 int glwthread_mutex_unlock(glwthread_mutex_t * mutex)79glwthread_mutex_unlock (glwthread_mutex_t *mutex) 80 { 81 if (!mutex->guard.done) 82 return EINVAL; 83 LeaveCriticalSection (&mutex->lock); 84 return 0; 85 } 86 87 int glwthread_mutex_destroy(glwthread_mutex_t * mutex)88glwthread_mutex_destroy (glwthread_mutex_t *mutex) 89 { 90 if (!mutex->guard.done) 91 return EINVAL; 92 DeleteCriticalSection (&mutex->lock); 93 mutex->guard.done = 0; 94 return 0; 95 } 96