lowlevellock.h 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. /* Low-level lock implementation. Mach gsync-based version.
  2. Copyright (C) 1994-2026 Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. The GNU C Library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with the GNU C Library; if not, see
  14. <https://www.gnu.org/licenses/>. */
  15. #ifndef _MACH_LOWLEVELLOCK_H
  16. #define _MACH_LOWLEVELLOCK_H 1
  17. #include <mach.h>
  18. #include <mach/gnumach.h>
  19. #include <atomic.h>
  20. /* Gsync flags. */
  21. #ifndef GSYNC_SHARED
  22. # define GSYNC_SHARED 0x01
  23. # define GSYNC_QUAD 0x02
  24. # define GSYNC_TIMED 0x04
  25. # define GSYNC_BROADCAST 0x08
  26. # define GSYNC_MUTATE 0x10
  27. #endif
  28. /* Static initializer for low-level locks. */
  29. #define LLL_LOCK_INITIALIZER 0
  30. #define LLL_PRIVATE 0
  31. #define LLL_SHARED GSYNC_SHARED
  32. /* Interruptible version of __gsync_wait. */
  33. extern kern_return_t __gsync_wait_intr
  34. (
  35. mach_port_t task,
  36. vm_offset_t addr,
  37. unsigned val1,
  38. unsigned val2,
  39. natural_t msec,
  40. int flags
  41. );
  42. /* Wait on address PTR, without blocking if its contents
  43. * are different from VAL. */
  44. #define __lll_wait(ptr, val, flags) \
  45. __gsync_wait (__mach_task_self (), \
  46. (vm_offset_t)(ptr), (val), 0, 0, (flags))
  47. #define lll_wait(var, val, flags) \
  48. __lll_wait (&(var), val, flags)
  49. /* Interruptible version. */
  50. #define __lll_wait_intr(ptr, val, flags) \
  51. __gsync_wait_intr (__mach_task_self (), \
  52. (vm_offset_t)(ptr), (val), 0, 0, (flags))
  53. #define lll_wait_intr(var, val, flags) \
  54. __lll_wait_intr ((&var), val, flags)
  55. /* Wake one or more threads waiting on address PTR. */
  56. #define __lll_wake(ptr, flags) \
  57. __gsync_wake (__mach_task_self (), (vm_offset_t)(ptr), 0, (flags))
  58. #define lll_wake(var, flags) \
  59. __lll_wake (&(var), flags)
  60. /* Acquire the lock at PTR. */
  61. #define __lll_lock(ptr, flags) \
  62. ({ \
  63. int *__iptr = (int *)(ptr); \
  64. int __flags = (flags); \
  65. if (*__iptr != 0 \
  66. || atomic_compare_and_exchange_bool_acq (__iptr, 1, 0) != 0) \
  67. while (1) \
  68. { \
  69. if (atomic_exchange_acquire (__iptr, 2) == 0) \
  70. break; \
  71. __lll_wait (__iptr, 2, __flags); \
  72. } \
  73. (void)0; \
  74. })
  75. #define lll_lock(var, flags) \
  76. __lll_lock (&(var), flags)
  77. /* Try to acquire the lock at PTR, without blocking.
  78. Evaluates to zero on success. */
  79. #define __lll_trylock(ptr) \
  80. ({ \
  81. int *__iptr = (int *)(ptr); \
  82. *__iptr == 0 \
  83. && atomic_compare_and_exchange_bool_acq (__iptr, 1, 0) == 0 ? 0 : -1; \
  84. })
  85. #define lll_trylock(var) \
  86. __lll_trylock (&(var))
  87. /* Release the lock at PTR. */
  88. #define __lll_unlock(ptr, flags) \
  89. ({ \
  90. int *__iptr = (int *)(ptr); \
  91. if (atomic_exchange_release (__iptr, 0) == 2) \
  92. __lll_wake (__iptr, (flags)); \
  93. (void)0; \
  94. })
  95. #define lll_unlock(var, flags) \
  96. __lll_unlock (&(var), flags)
  97. #endif