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