atomic.h 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. /* Internal macros for atomic operations for GNU C Library.
  2. Copyright (C) 2002-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 _ATOMIC_H
  16. #define _ATOMIC_H 1
  17. /* This header defines two types of macros:
  18. - atomic arithmetic and logic operation on memory. They all
  19. have the prefix "atomic_".
  20. - support functions like barriers. They also have the prefix
  21. "atomic_".
  22. As <atomic.h> macros are usually heavily nested and often use local
  23. variables to make sure side-effects are evaluated properly, use for
  24. macro local variables a per-macro unique prefix. This file uses
  25. __atgN_ prefix where N is different in each macro. */
  26. #include <stdlib.h>
  27. #include <atomic-machine.h>
  28. # define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \
  29. ({ \
  30. __typeof (*(mem)) __atg3_old = (oldval); \
  31. atomic_compare_exchange_acquire (mem, (void*)&__atg3_old, newval); \
  32. __atg3_old; \
  33. })
  34. # define atomic_compare_and_exchange_val_rel(mem, newval, oldval) \
  35. ({ \
  36. __typeof (*(mem)) __atg3_old = (oldval); \
  37. atomic_compare_exchange_release (mem, (void*)&__atg3_old, newval); \
  38. __atg3_old; \
  39. })
  40. # define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
  41. ({ \
  42. __typeof (*(mem)) __atg3_old = (oldval); \
  43. !atomic_compare_exchange_acquire (mem, (void*)&__atg3_old, newval); \
  44. })
  45. #ifndef atomic_max
  46. # define atomic_max(mem, value) \
  47. do { \
  48. __typeof (*(mem)) __atg8_oldval; \
  49. __typeof (mem) __atg8_memp = (mem); \
  50. __typeof (*(mem)) __atg8_value = (value); \
  51. do { \
  52. __atg8_oldval = *__atg8_memp; \
  53. if (__atg8_oldval >= __atg8_value) \
  54. break; \
  55. } while (__builtin_expect \
  56. (atomic_compare_and_exchange_bool_acq (__atg8_memp, __atg8_value,\
  57. __atg8_oldval), 0)); \
  58. } while (0)
  59. #endif
  60. /* Decrement *MEM if it is > 0, and return the old value. */
  61. #ifndef atomic_decrement_if_positive
  62. # define atomic_decrement_if_positive(mem) \
  63. ({ __typeof (*(mem)) __atg11_oldval; \
  64. __typeof (mem) __atg11_memp = (mem); \
  65. \
  66. do \
  67. { \
  68. __atg11_oldval = *__atg11_memp; \
  69. if (__glibc_unlikely (__atg11_oldval <= 0)) \
  70. break; \
  71. } \
  72. while (__builtin_expect \
  73. (atomic_compare_and_exchange_bool_acq (__atg11_memp, \
  74. __atg11_oldval - 1, \
  75. __atg11_oldval), 0)); \
  76. __atg11_oldval; })
  77. #endif
  78. #ifndef atomic_full_barrier
  79. # define atomic_full_barrier() __atomic_thread_fence (__ATOMIC_SEQ_CST)
  80. #endif
  81. #ifndef atomic_read_barrier
  82. # define atomic_read_barrier() __atomic_thread_fence (__ATOMIC_ACQUIRE);
  83. #endif
  84. #ifndef atomic_write_barrier
  85. # define atomic_write_barrier() __atomic_thread_fence (__ATOMIC_RELEASE)
  86. #endif
  87. /* The following functions are a subset of the atomic operations provided by
  88. C11. Usually, a function named atomic_OP_MO(args) is equivalent to C11's
  89. atomic_OP_explicit(args, memory_order_MO); exceptions noted below. */
  90. /* Check atomic operations are lock free. Since this doesn't work correctly
  91. on all targets (eg. if uint64_t is 4-byte aligned), use__HAVE_64B_ATOMICS
  92. for 64-bit types. */
  93. #define __atomic_check_size(mem) \
  94. _Static_assert (__atomic_always_lock_free (sizeof (*(mem)), 0) && \
  95. !(sizeof (*(mem)) == 8 && HAVE_64B_ATOMICS == 0), \
  96. "atomic not lock free!")
  97. #define atomic_thread_fence_acquire() __atomic_thread_fence (__ATOMIC_ACQUIRE)
  98. #define atomic_thread_fence_release() __atomic_thread_fence (__ATOMIC_RELEASE)
  99. #define atomic_thread_fence_seq_cst() __atomic_thread_fence (__ATOMIC_SEQ_CST)
  100. # define atomic_load_relaxed(mem) \
  101. ({ __atomic_check_size((mem)); \
  102. __atomic_load_n ((mem), __ATOMIC_RELAXED); })
  103. # define atomic_load_acquire(mem) \
  104. ({ __atomic_check_size((mem)); \
  105. __atomic_load_n ((mem), __ATOMIC_ACQUIRE); })
  106. # define atomic_store_relaxed(mem, val) \
  107. do { \
  108. __atomic_check_size((mem)); \
  109. __atomic_store_n ((mem), (val), __ATOMIC_RELAXED); \
  110. } while (0)
  111. # define atomic_store_release(mem, val) \
  112. do { \
  113. __atomic_check_size((mem)); \
  114. __atomic_store_n ((mem), (val), __ATOMIC_RELEASE); \
  115. } while (0)
  116. /* On failure, this CAS has memory_order_relaxed semantics. */
  117. # define atomic_compare_exchange_weak_relaxed(mem, expected, desired) \
  118. ({ __atomic_check_size((mem)); \
  119. __atomic_compare_exchange_n ((mem), (expected), (desired), 1, \
  120. __ATOMIC_RELAXED, __ATOMIC_RELAXED); })
  121. # define atomic_compare_exchange_weak_acquire(mem, expected, desired) \
  122. ({ __atomic_check_size((mem)); \
  123. __atomic_compare_exchange_n ((mem), (expected), (desired), 1, \
  124. __ATOMIC_ACQUIRE, __ATOMIC_RELAXED); })
  125. # define atomic_compare_exchange_weak_release(mem, expected, desired) \
  126. ({ __atomic_check_size((mem)); \
  127. __atomic_compare_exchange_n ((mem), (expected), (desired), 1, \
  128. __ATOMIC_RELEASE, __ATOMIC_RELAXED); })
  129. # define atomic_compare_exchange_relaxed(mem, expected, desired) \
  130. ({ __atomic_check_size((mem)); \
  131. __atomic_compare_exchange_n ((mem), (expected), (desired), 0, \
  132. __ATOMIC_RELAXED, __ATOMIC_RELAXED); })
  133. # define atomic_compare_exchange_acquire(mem, expected, desired) \
  134. ({ __atomic_check_size((mem)); \
  135. __atomic_compare_exchange_n ((mem), (expected), (desired), 0, \
  136. __ATOMIC_ACQUIRE, __ATOMIC_RELAXED); })
  137. # define atomic_compare_exchange_release(mem, expected, desired) \
  138. ({ __atomic_check_size((mem)); \
  139. __atomic_compare_exchange_n ((mem), (expected), (desired), 0, \
  140. __ATOMIC_RELEASE, __ATOMIC_RELAXED); })
  141. # define atomic_exchange_relaxed(mem, desired) \
  142. ({ __atomic_check_size((mem)); \
  143. __atomic_exchange_n ((mem), (desired), __ATOMIC_RELAXED); })
  144. # define atomic_exchange_acquire(mem, desired) \
  145. ({ __atomic_check_size((mem)); \
  146. __atomic_exchange_n ((mem), (desired), __ATOMIC_ACQUIRE); })
  147. # define atomic_exchange_release(mem, desired) \
  148. ({ __atomic_check_size((mem)); \
  149. __atomic_exchange_n ((mem), (desired), __ATOMIC_RELEASE); })
  150. # define atomic_fetch_add_relaxed(mem, operand) \
  151. ({ __atomic_check_size((mem)); \
  152. __atomic_fetch_add ((mem), (operand), __ATOMIC_RELAXED); })
  153. # define atomic_fetch_add_acquire(mem, operand) \
  154. ({ __atomic_check_size((mem)); \
  155. __atomic_fetch_add ((mem), (operand), __ATOMIC_ACQUIRE); })
  156. # define atomic_fetch_add_release(mem, operand) \
  157. ({ __atomic_check_size((mem)); \
  158. __atomic_fetch_add ((mem), (operand), __ATOMIC_RELEASE); })
  159. # define atomic_fetch_add_acq_rel(mem, operand) \
  160. ({ __atomic_check_size((mem)); \
  161. __atomic_fetch_add ((mem), (operand), __ATOMIC_ACQ_REL); })
  162. # define atomic_fetch_and_relaxed(mem, operand) \
  163. ({ __atomic_check_size((mem)); \
  164. __atomic_fetch_and ((mem), (operand), __ATOMIC_RELAXED); })
  165. # define atomic_fetch_and_acquire(mem, operand) \
  166. ({ __atomic_check_size((mem)); \
  167. __atomic_fetch_and ((mem), (operand), __ATOMIC_ACQUIRE); })
  168. # define atomic_fetch_and_release(mem, operand) \
  169. ({ __atomic_check_size((mem)); \
  170. __atomic_fetch_and ((mem), (operand), __ATOMIC_RELEASE); })
  171. # define atomic_fetch_or_relaxed(mem, operand) \
  172. ({ __atomic_check_size((mem)); \
  173. __atomic_fetch_or ((mem), (operand), __ATOMIC_RELAXED); })
  174. # define atomic_fetch_or_acquire(mem, operand) \
  175. ({ __atomic_check_size((mem)); \
  176. __atomic_fetch_or ((mem), (operand), __ATOMIC_ACQUIRE); })
  177. # define atomic_fetch_or_release(mem, operand) \
  178. ({ __atomic_check_size((mem)); \
  179. __atomic_fetch_or ((mem), (operand), __ATOMIC_RELEASE); })
  180. # define atomic_fetch_xor_release(mem, operand) \
  181. ({ __atomic_check_size((mem)); \
  182. __atomic_fetch_xor ((mem), (operand), __ATOMIC_RELEASE); })
  183. /* This operation does not affect synchronization semantics but can be used
  184. in the body of a spin loop to potentially improve its efficiency. */
  185. #ifndef atomic_spin_nop
  186. # define atomic_spin_nop() do { /* nothing */ } while (0)
  187. #endif
  188. #endif /* atomic.h */