atomic.h 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. /* Internal macros for atomic operations for GNU C Library.
  2. Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  4. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
  5. The GNU C Library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Lesser General Public
  7. License as published by the Free Software Foundation; either
  8. version 2.1 of the License, or (at your option) any later version.
  9. The GNU C Library 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 GNU
  12. Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public
  14. License along with the GNU C Library; if not, write to the Free
  15. Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  16. 02111-1307 USA. */
  17. #ifndef _ATOMIC_H
  18. #define _ATOMIC_H 1
  19. #include <stdlib.h>
  20. #include <bits/atomic.h>
  21. /* Wrapper macros to call pre_NN_post (mem, ...) where NN is the
  22. bit width of *MEM. The calling macro puts parens around MEM
  23. and following args. */
  24. #define __atomic_val_bysize(pre, post, mem, ...) \
  25. ({ \
  26. __typeof (*mem) __result; \
  27. if (sizeof (*mem) == 1) \
  28. __result = pre##_8_##post (mem, __VA_ARGS__); \
  29. else if (sizeof (*mem) == 2) \
  30. __result = pre##_16_##post (mem, __VA_ARGS__); \
  31. else if (sizeof (*mem) == 4) \
  32. __result = pre##_32_##post (mem, __VA_ARGS__); \
  33. else if (sizeof (*mem) == 8) \
  34. __result = pre##_64_##post (mem, __VA_ARGS__); \
  35. else \
  36. abort (); \
  37. __result; \
  38. })
  39. #define __atomic_bool_bysize(pre, post, mem, ...) \
  40. ({ \
  41. int __result; \
  42. if (sizeof (*mem) == 1) \
  43. __result = pre##_8_##post (mem, __VA_ARGS__); \
  44. else if (sizeof (*mem) == 2) \
  45. __result = pre##_16_##post (mem, __VA_ARGS__); \
  46. else if (sizeof (*mem) == 4) \
  47. __result = pre##_32_##post (mem, __VA_ARGS__); \
  48. else if (sizeof (*mem) == 8) \
  49. __result = pre##_64_##post (mem, __VA_ARGS__); \
  50. else \
  51. abort (); \
  52. __result; \
  53. })
  54. /* Atomically store NEWVAL in *MEM if *MEM is equal to OLDVAL.
  55. Return the old *MEM value. */
  56. #if !defined atomic_compare_and_exchange_val_acq \
  57. && defined __arch_compare_and_exchange_val_32_acq
  58. # define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \
  59. __atomic_val_bysize (__arch_compare_and_exchange_val,acq, \
  60. mem, newval, oldval)
  61. #endif
  62. #ifndef atomic_compare_and_exchange_val_rel
  63. # define atomic_compare_and_exchange_val_rel(mem, newval, oldval) \
  64. atomic_compare_and_exchange_val_acq (mem, newval, oldval)
  65. #endif
  66. /* Atomically store NEWVAL in *MEM if *MEM is equal to OLDVAL.
  67. Return zero if *MEM was changed or non-zero if no exchange happened. */
  68. #ifndef atomic_compare_and_exchange_bool_acq
  69. # ifdef __arch_compare_and_exchange_bool_32_acq
  70. # define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
  71. __atomic_bool_bysize (__arch_compare_and_exchange_bool,acq, \
  72. mem, newval, oldval)
  73. # else
  74. # define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
  75. ({ /* Cannot use __oldval here, because macros later in this file might \
  76. call this macro with __oldval argument. */ \
  77. __typeof (oldval) __old = (oldval); \
  78. atomic_compare_and_exchange_val_acq (mem, newval, __old) != __old; \
  79. })
  80. # endif
  81. #endif
  82. #ifndef atomic_compare_and_exchange_bool_rel
  83. # define atomic_compare_and_exchange_bool_rel(mem, newval, oldval) \
  84. atomic_compare_and_exchange_bool_acq (mem, newval, oldval)
  85. #endif
  86. /* Store NEWVALUE in *MEM and return the old value. */
  87. #ifndef atomic_exchange_acq
  88. # define atomic_exchange_acq(mem, newvalue) \
  89. ({ __typeof (*(mem)) __oldval; \
  90. __typeof (mem) __memp = (mem); \
  91. __typeof (*(mem)) __value = (newvalue); \
  92. \
  93. do \
  94. __oldval = (*__memp); \
  95. while (__builtin_expect (atomic_compare_and_exchange_bool_acq (__memp, \
  96. __value, \
  97. __oldval),\
  98. 0)); \
  99. \
  100. __oldval; })
  101. #endif
  102. #ifndef atomic_exchange_rel
  103. # define atomic_exchange_rel(mem, newvalue) atomic_exchange_acq (mem, newvalue)
  104. #endif
  105. /* Add VALUE to *MEM and return the old value of *MEM. */
  106. #ifndef atomic_exchange_and_add
  107. # define atomic_exchange_and_add(mem, value) \
  108. ({ __typeof (*(mem)) __oldval; \
  109. __typeof (mem) __memp = (mem); \
  110. __typeof (*(mem)) __value = (value); \
  111. \
  112. do \
  113. __oldval = (*__memp); \
  114. while (__builtin_expect (atomic_compare_and_exchange_bool_acq (__memp, \
  115. __oldval \
  116. + __value,\
  117. __oldval),\
  118. 0)); \
  119. \
  120. __oldval; })
  121. #endif
  122. #ifndef atomic_add
  123. # define atomic_add(mem, value) (void) atomic_exchange_and_add ((mem), (value))
  124. #endif
  125. #ifndef atomic_increment
  126. # define atomic_increment(mem) atomic_add ((mem), 1)
  127. #endif
  128. #ifndef atomic_increment_val
  129. # define atomic_increment_val(mem) (atomic_exchange_and_add ((mem), 1) + 1)
  130. #endif
  131. /* Add one to *MEM and return true iff it's now zero. */
  132. #ifndef atomic_increment_and_test
  133. # define atomic_increment_and_test(mem) \
  134. (atomic_exchange_and_add ((mem), 1) + 1 == 0)
  135. #endif
  136. #ifndef atomic_decrement
  137. # define atomic_decrement(mem) atomic_add ((mem), -1)
  138. #endif
  139. #ifndef atomic_decrement_val
  140. # define atomic_decrement_val(mem) (atomic_exchange_and_add ((mem), -1) - 1)
  141. #endif
  142. /* Subtract 1 from *MEM and return true iff it's now zero. */
  143. #ifndef atomic_decrement_and_test
  144. # define atomic_decrement_and_test(mem) \
  145. (atomic_exchange_and_add ((mem), -1) == 1)
  146. #endif
  147. /* Decrement *MEM if it is > 0, and return the old value. */
  148. #ifndef atomic_decrement_if_positive
  149. # define atomic_decrement_if_positive(mem) \
  150. ({ __typeof (*(mem)) __oldval; \
  151. __typeof (mem) __memp = (mem); \
  152. \
  153. do \
  154. { \
  155. __oldval = *__memp; \
  156. if (__builtin_expect (__oldval <= 0, 0)) \
  157. break; \
  158. } \
  159. while (__builtin_expect (atomic_compare_and_exchange_bool_acq (__memp, \
  160. __oldval \
  161. - 1, \
  162. __oldval),\
  163. 0));\
  164. __oldval; })
  165. #endif
  166. #ifndef atomic_add_negative
  167. # define atomic_add_negative(mem, value) \
  168. ({ __typeof (value) __aan_value = (value); \
  169. atomic_exchange_and_add (mem, __aan_value) < -__aan_value; })
  170. #endif
  171. #ifndef atomic_add_zero
  172. # define atomic_add_zero(mem, value) \
  173. ({ __typeof (value) __aaz_value = (value); \
  174. atomic_exchange_and_add (mem, __aaz_value) == -__aaz_value; })
  175. #endif
  176. #ifndef atomic_bit_set
  177. # define atomic_bit_set(mem, bit) \
  178. (void) atomic_bit_test_set(mem, bit)
  179. #endif
  180. #ifndef atomic_bit_test_set
  181. # define atomic_bit_test_set(mem, bit) \
  182. ({ __typeof (*(mem)) __oldval; \
  183. __typeof (mem) __memp = (mem); \
  184. __typeof (*(mem)) __mask = ((__typeof (*(mem))) 1 << (bit)); \
  185. \
  186. do \
  187. __oldval = (*__memp); \
  188. while (__builtin_expect (atomic_compare_and_exchange_bool_acq (__memp, \
  189. __oldval \
  190. | __mask, \
  191. __oldval),\
  192. 0)); \
  193. \
  194. __oldval & __mask; })
  195. #endif
  196. #ifndef atomic_full_barrier
  197. # define atomic_full_barrier() __asm ("" ::: "memory")
  198. #endif
  199. #ifndef atomic_read_barrier
  200. # define atomic_read_barrier() atomic_full_barrier ()
  201. #endif
  202. #ifndef atomic_write_barrier
  203. # define atomic_write_barrier() atomic_full_barrier ()
  204. #endif
  205. #ifndef atomic_delay
  206. # define atomic_delay() do { /* nothing */ } while (0)
  207. #endif
  208. #endif /* atomic.h */