(root)/
m4-1.4.19/
lib/
windows-mutex.c
       1  /* Plain mutexes (native Windows implementation).
       2     Copyright (C) 2005-2021 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 General Public License as published by
       6     the Free Software Foundation; either version 3, or (at your option)
       7     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 General Public License for more details.
      13  
      14     You should have received a copy of the GNU 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
      28  glwthread_mutex_init (glwthread_mutex_t *mutex)
      29  {
      30    InitializeCriticalSection (&mutex->lock);
      31    mutex->guard.done = 1;
      32  }
      33  
      34  int
      35  glwthread_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
      57  glwthread_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
      79  glwthread_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
      88  glwthread_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  }