windows-mutex.c 2.6 KB

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