1 /* Plain mutexes (native Windows implementation).
2 Copyright (C) 2005-2024 Free Software Foundation, Inc.
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
6 published by the Free Software Foundation; either version 2.1 of the
7 License, or (at your option) any later version.
9 This file 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.
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/>. */
17 /* Written by Bruno Haible <bruno@clisp.org>, 2005.
18 Based on GCC's gthr-win32.h. */
23 #include "windows-mutex.h"
29 glwthread_mutex_init (glwthread_mutex_t
*mutex
)
32 InitializeCriticalSection (&mutex
->lock
);
33 mutex
->guard
.done
= 1;
37 glwthread_mutex_lock (glwthread_mutex_t
*mutex
)
39 if (!mutex
->guard
.done
)
41 if (InterlockedIncrement (&mutex
->guard
.started
) == 0)
42 /* This thread is the first one to need this mutex. Initialize it. */
43 glwthread_mutex_init (mutex
);
46 /* Don't let mutex->guard.started grow and wrap around. */
47 InterlockedDecrement (&mutex
->guard
.started
);
48 /* Yield the CPU while waiting for another thread to finish
49 initializing this mutex. */
50 while (!mutex
->guard
.done
)
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. */
56 EnterCriticalSection (&mutex
->lock
);
58 DWORD self
= GetCurrentThreadId ();
65 glwthread_mutex_trylock (glwthread_mutex_t
*mutex
)
67 if (!mutex
->guard
.done
)
69 if (InterlockedIncrement (&mutex
->guard
.started
) == 0)
70 /* This thread is the first one to need this mutex. Initialize it. */
71 glwthread_mutex_init (mutex
);
74 /* Don't let mutex->guard.started grow and wrap around. */
75 InterlockedDecrement (&mutex
->guard
.started
);
76 /* Let another thread finish initializing this mutex, and let it also
81 if (!TryEnterCriticalSection (&mutex
->lock
))
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
)
91 LeaveCriticalSection (&mutex
->lock
);
94 if (mutex
->owner
!= 0)
102 glwthread_mutex_unlock (glwthread_mutex_t
*mutex
)
104 if (!mutex
->guard
.done
)
107 LeaveCriticalSection (&mutex
->lock
);
112 glwthread_mutex_destroy (glwthread_mutex_t
*mutex
)
114 if (!mutex
->guard
.done
)
116 DeleteCriticalSection (&mutex
->lock
);
117 mutex
->guard
.done
= 0;