atomic.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537
  1. /* Internal macros for atomic operations for GNU C Library.
  2. Copyright (C) 2002-2006, 2009 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. /* This header defines three types of macros:
  20. - atomic arithmetic and logic operation on memory. They all
  21. have the prefix "atomic_".
  22. - conditionally atomic operations of the same kinds. These
  23. always behave identical but can be faster when atomicity
  24. is not really needed since only one thread has access to
  25. the memory location. In that case the code is slower in
  26. the multi-thread case. The interfaces have the prefix
  27. "catomic_".
  28. - support functions like barriers. They also have the preifx
  29. "atomic_".
  30. Architectures must provide a few lowlevel macros (the compare
  31. and exchange definitions). All others are optional. They
  32. should only be provided if the architecture has specific
  33. support for the operation.
  34. As <atomic.h> macros are usually heavily nested and often use local
  35. variables to make sure side-effects are evaluated properly, use for
  36. macro local variables a per-macro unique prefix. This file uses
  37. __atgN_ prefix where N is different in each macro. */
  38. #include <stdlib.h>
  39. #include <bits/atomic.h>
  40. /* Wrapper macros to call pre_NN_post (mem, ...) where NN is the
  41. bit width of *MEM. The calling macro puts parens around MEM
  42. and following args. */
  43. #define __atomic_val_bysize(pre, post, mem, ...) \
  44. ({ \
  45. __typeof (*mem) __atg1_result; \
  46. if (sizeof (*mem) == 1) \
  47. __atg1_result = pre##_8_##post (mem, __VA_ARGS__); \
  48. else if (sizeof (*mem) == 2) \
  49. __atg1_result = pre##_16_##post (mem, __VA_ARGS__); \
  50. else if (sizeof (*mem) == 4) \
  51. __atg1_result = pre##_32_##post (mem, __VA_ARGS__); \
  52. else if (sizeof (*mem) == 8) \
  53. __atg1_result = pre##_64_##post (mem, __VA_ARGS__); \
  54. else \
  55. abort (); \
  56. __atg1_result; \
  57. })
  58. #define __atomic_bool_bysize(pre, post, mem, ...) \
  59. ({ \
  60. int __atg2_result; \
  61. if (sizeof (*mem) == 1) \
  62. __atg2_result = pre##_8_##post (mem, __VA_ARGS__); \
  63. else if (sizeof (*mem) == 2) \
  64. __atg2_result = pre##_16_##post (mem, __VA_ARGS__); \
  65. else if (sizeof (*mem) == 4) \
  66. __atg2_result = pre##_32_##post (mem, __VA_ARGS__); \
  67. else if (sizeof (*mem) == 8) \
  68. __atg2_result = pre##_64_##post (mem, __VA_ARGS__); \
  69. else \
  70. abort (); \
  71. __atg2_result; \
  72. })
  73. /* Atomically store NEWVAL in *MEM if *MEM is equal to OLDVAL.
  74. Return the old *MEM value. */
  75. #if !defined atomic_compare_and_exchange_val_acq \
  76. && defined __arch_compare_and_exchange_val_32_acq
  77. # define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \
  78. __atomic_val_bysize (__arch_compare_and_exchange_val,acq, \
  79. mem, newval, oldval)
  80. #endif
  81. #ifndef catomic_compare_and_exchange_val_acq
  82. # ifdef __arch_c_compare_and_exchange_val_32_acq
  83. # define catomic_compare_and_exchange_val_acq(mem, newval, oldval) \
  84. __atomic_val_bysize (__arch_c_compare_and_exchange_val,acq, \
  85. mem, newval, oldval)
  86. # else
  87. # define catomic_compare_and_exchange_val_acq(mem, newval, oldval) \
  88. atomic_compare_and_exchange_val_acq (mem, newval, oldval)
  89. # endif
  90. #endif
  91. #ifndef catomic_compare_and_exchange_val_rel
  92. # ifndef atomic_compare_and_exchange_val_rel
  93. # define catomic_compare_and_exchange_val_rel(mem, newval, oldval) \
  94. catomic_compare_and_exchange_val_acq (mem, newval, oldval)
  95. # else
  96. # define catomic_compare_and_exchange_val_rel(mem, newval, oldval) \
  97. atomic_compare_and_exchange_val_rel (mem, newval, oldval)
  98. # endif
  99. #endif
  100. #ifndef atomic_compare_and_exchange_val_rel
  101. # define atomic_compare_and_exchange_val_rel(mem, newval, oldval) \
  102. atomic_compare_and_exchange_val_acq (mem, newval, oldval)
  103. #endif
  104. /* Atomically store NEWVAL in *MEM if *MEM is equal to OLDVAL.
  105. Return zero if *MEM was changed or non-zero if no exchange happened. */
  106. #ifndef atomic_compare_and_exchange_bool_acq
  107. # ifdef __arch_compare_and_exchange_bool_32_acq
  108. # define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
  109. __atomic_bool_bysize (__arch_compare_and_exchange_bool,acq, \
  110. mem, newval, oldval)
  111. # else
  112. # define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
  113. ({ /* Cannot use __oldval here, because macros later in this file might \
  114. call this macro with __oldval argument. */ \
  115. __typeof (oldval) __atg3_old = (oldval); \
  116. atomic_compare_and_exchange_val_acq (mem, newval, __atg3_old) \
  117. != __atg3_old; \
  118. })
  119. # endif
  120. #endif
  121. #ifndef catomic_compare_and_exchange_bool_acq
  122. # ifdef __arch_c_compare_and_exchange_bool_32_acq
  123. # define catomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
  124. __atomic_bool_bysize (__arch_c_compare_and_exchange_bool,acq, \
  125. mem, newval, oldval)
  126. # else
  127. # define catomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
  128. ({ /* Cannot use __oldval here, because macros later in this file might \
  129. call this macro with __oldval argument. */ \
  130. __typeof (oldval) __atg4_old = (oldval); \
  131. catomic_compare_and_exchange_val_acq (mem, newval, __atg4_old) \
  132. != __atg4_old; \
  133. })
  134. # endif
  135. #endif
  136. #ifndef catomic_compare_and_exchange_bool_rel
  137. # ifndef atomic_compare_and_exchange_bool_rel
  138. # define catomic_compare_and_exchange_bool_rel(mem, newval, oldval) \
  139. catomic_compare_and_exchange_bool_acq (mem, newval, oldval)
  140. # else
  141. # define catomic_compare_and_exchange_bool_rel(mem, newval, oldval) \
  142. atomic_compare_and_exchange_bool_rel (mem, newval, oldval)
  143. # endif
  144. #endif
  145. #ifndef atomic_compare_and_exchange_bool_rel
  146. # define atomic_compare_and_exchange_bool_rel(mem, newval, oldval) \
  147. atomic_compare_and_exchange_bool_acq (mem, newval, oldval)
  148. #endif
  149. /* Store NEWVALUE in *MEM and return the old value. */
  150. #ifndef atomic_exchange_acq
  151. # define atomic_exchange_acq(mem, newvalue) \
  152. ({ __typeof (*(mem)) __atg5_oldval; \
  153. __typeof (mem) __atg5_memp = (mem); \
  154. __typeof (*(mem)) __atg5_value = (newvalue); \
  155. \
  156. do \
  157. __atg5_oldval = *__atg5_memp; \
  158. while (__builtin_expect \
  159. (atomic_compare_and_exchange_bool_acq (__atg5_memp, __atg5_value, \
  160. __atg5_oldval), 0)); \
  161. \
  162. __atg5_oldval; })
  163. #endif
  164. #ifndef atomic_exchange_rel
  165. # define atomic_exchange_rel(mem, newvalue) atomic_exchange_acq (mem, newvalue)
  166. #endif
  167. /* Add VALUE to *MEM and return the old value of *MEM. */
  168. #ifndef atomic_exchange_and_add
  169. # define atomic_exchange_and_add(mem, value) \
  170. ({ __typeof (*(mem)) __atg6_oldval; \
  171. __typeof (mem) __atg6_memp = (mem); \
  172. __typeof (*(mem)) __atg6_value = (value); \
  173. \
  174. do \
  175. __atg6_oldval = *__atg6_memp; \
  176. while (__builtin_expect \
  177. (atomic_compare_and_exchange_bool_acq (__atg6_memp, \
  178. __atg6_oldval \
  179. + __atg6_value, \
  180. __atg6_oldval), 0)); \
  181. \
  182. __atg6_oldval; })
  183. #endif
  184. #ifndef catomic_exchange_and_add
  185. # define catomic_exchange_and_add(mem, value) \
  186. ({ __typeof (*(mem)) __atg7_oldv; \
  187. __typeof (mem) __atg7_memp = (mem); \
  188. __typeof (*(mem)) __atg7_value = (value); \
  189. \
  190. do \
  191. __atg7_oldv = *__atg7_memp; \
  192. while (__builtin_expect \
  193. (catomic_compare_and_exchange_bool_acq (__atg7_memp, \
  194. __atg7_oldv \
  195. + __atg7_value, \
  196. __atg7_oldv), 0)); \
  197. \
  198. __atg7_oldv; })
  199. #endif
  200. #ifndef atomic_max
  201. # define atomic_max(mem, value) \
  202. do { \
  203. __typeof (*(mem)) __atg8_oldval; \
  204. __typeof (mem) __atg8_memp = (mem); \
  205. __typeof (*(mem)) __atg8_value = (value); \
  206. do { \
  207. __atg8_oldval = *__atg8_memp; \
  208. if (__atg8_oldval >= __atg8_value) \
  209. break; \
  210. } while (__builtin_expect \
  211. (atomic_compare_and_exchange_bool_acq (__atg8_memp, __atg8_value,\
  212. __atg8_oldval), 0)); \
  213. } while (0)
  214. #endif
  215. #ifndef catomic_max
  216. # define catomic_max(mem, value) \
  217. do { \
  218. __typeof (*(mem)) __atg9_oldv; \
  219. __typeof (mem) __atg9_memp = (mem); \
  220. __typeof (*(mem)) __atg9_value = (value); \
  221. do { \
  222. __atg9_oldv = *__atg9_memp; \
  223. if (__atg9_oldv >= __atg9_value) \
  224. break; \
  225. } while (__builtin_expect \
  226. (catomic_compare_and_exchange_bool_acq (__atg9_memp, \
  227. __atg9_value, \
  228. __atg9_oldv), 0)); \
  229. } while (0)
  230. #endif
  231. #ifndef atomic_min
  232. # define atomic_min(mem, value) \
  233. do { \
  234. __typeof (*(mem)) __atg10_oldval; \
  235. __typeof (mem) __atg10_memp = (mem); \
  236. __typeof (*(mem)) __atg10_value = (value); \
  237. do { \
  238. __atg10_oldval = *__atg10_memp; \
  239. if (__atg10_oldval <= __atg10_value) \
  240. break; \
  241. } while (__builtin_expect \
  242. (atomic_compare_and_exchange_bool_acq (__atg10_memp, \
  243. __atg10_value, \
  244. __atg10_oldval), 0)); \
  245. } while (0)
  246. #endif
  247. #ifndef atomic_add
  248. # define atomic_add(mem, value) (void) atomic_exchange_and_add ((mem), (value))
  249. #endif
  250. #ifndef catomic_add
  251. # define catomic_add(mem, value) \
  252. (void) catomic_exchange_and_add ((mem), (value))
  253. #endif
  254. #ifndef atomic_increment
  255. # define atomic_increment(mem) atomic_add ((mem), 1)
  256. #endif
  257. #ifndef catomic_increment
  258. # define catomic_increment(mem) catomic_add ((mem), 1)
  259. #endif
  260. #ifndef atomic_increment_val
  261. # define atomic_increment_val(mem) (atomic_exchange_and_add ((mem), 1) + 1)
  262. #endif
  263. #ifndef catomic_increment_val
  264. # define catomic_increment_val(mem) (catomic_exchange_and_add ((mem), 1) + 1)
  265. #endif
  266. /* Add one to *MEM and return true iff it's now zero. */
  267. #ifndef atomic_increment_and_test
  268. # define atomic_increment_and_test(mem) \
  269. (atomic_exchange_and_add ((mem), 1) + 1 == 0)
  270. #endif
  271. #ifndef atomic_decrement
  272. # define atomic_decrement(mem) atomic_add ((mem), -1)
  273. #endif
  274. #ifndef catomic_decrement
  275. # define catomic_decrement(mem) catomic_add ((mem), -1)
  276. #endif
  277. #ifndef atomic_decrement_val
  278. # define atomic_decrement_val(mem) (atomic_exchange_and_add ((mem), -1) - 1)
  279. #endif
  280. #ifndef catomic_decrement_val
  281. # define catomic_decrement_val(mem) (catomic_exchange_and_add ((mem), -1) - 1)
  282. #endif
  283. /* Subtract 1 from *MEM and return true iff it's now zero. */
  284. #ifndef atomic_decrement_and_test
  285. # define atomic_decrement_and_test(mem) \
  286. (atomic_exchange_and_add ((mem), -1) == 1)
  287. #endif
  288. /* Decrement *MEM if it is > 0, and return the old value. */
  289. #ifndef atomic_decrement_if_positive
  290. # define atomic_decrement_if_positive(mem) \
  291. ({ __typeof (*(mem)) __atg11_oldval; \
  292. __typeof (mem) __atg11_memp = (mem); \
  293. \
  294. do \
  295. { \
  296. __atg11_oldval = *__atg11_memp; \
  297. if (__builtin_expect (__atg11_oldval <= 0, 0)) \
  298. break; \
  299. } \
  300. while (__builtin_expect \
  301. (atomic_compare_and_exchange_bool_acq (__atg11_memp, \
  302. __atg11_oldval - 1, \
  303. __atg11_oldval), 0)); \
  304. __atg11_oldval; })
  305. #endif
  306. #ifndef atomic_add_negative
  307. # define atomic_add_negative(mem, value) \
  308. ({ __typeof (value) __atg12_value = (value); \
  309. atomic_exchange_and_add (mem, __atg12_value) < -__atg12_value; })
  310. #endif
  311. #ifndef atomic_add_zero
  312. # define atomic_add_zero(mem, value) \
  313. ({ __typeof (value) __atg13_value = (value); \
  314. atomic_exchange_and_add (mem, __atg13_value) == -__atg13_value; })
  315. #endif
  316. #ifndef atomic_bit_set
  317. # define atomic_bit_set(mem, bit) \
  318. (void) atomic_bit_test_set(mem, bit)
  319. #endif
  320. #ifndef atomic_bit_test_set
  321. # define atomic_bit_test_set(mem, bit) \
  322. ({ __typeof (*(mem)) __atg14_old; \
  323. __typeof (mem) __atg14_memp = (mem); \
  324. __typeof (*(mem)) __atg14_mask = ((__typeof (*(mem))) 1 << (bit)); \
  325. \
  326. do \
  327. __atg14_old = (*__atg14_memp); \
  328. while (__builtin_expect \
  329. (atomic_compare_and_exchange_bool_acq (__atg14_memp, \
  330. __atg14_old | __atg14_mask,\
  331. __atg14_old), 0)); \
  332. \
  333. __atg14_old & __atg14_mask; })
  334. #endif
  335. /* Atomically *mem &= mask. */
  336. #ifndef atomic_and
  337. # define atomic_and(mem, mask) \
  338. do { \
  339. __typeof (*(mem)) __atg15_old; \
  340. __typeof (mem) __atg15_memp = (mem); \
  341. __typeof (*(mem)) __atg15_mask = (mask); \
  342. \
  343. do \
  344. __atg15_old = (*__atg15_memp); \
  345. while (__builtin_expect \
  346. (atomic_compare_and_exchange_bool_acq (__atg15_memp, \
  347. __atg15_old & __atg15_mask, \
  348. __atg15_old), 0)); \
  349. } while (0)
  350. #endif
  351. #ifndef catomic_and
  352. # define catomic_and(mem, mask) \
  353. do { \
  354. __typeof (*(mem)) __atg20_old; \
  355. __typeof (mem) __atg20_memp = (mem); \
  356. __typeof (*(mem)) __atg20_mask = (mask); \
  357. \
  358. do \
  359. __atg20_old = (*__atg20_memp); \
  360. while (__builtin_expect \
  361. (catomic_compare_and_exchange_bool_acq (__atg20_memp, \
  362. __atg20_old & __atg20_mask,\
  363. __atg20_old), 0)); \
  364. } while (0)
  365. #endif
  366. /* Atomically *mem &= mask and return the old value of *mem. */
  367. #ifndef atomic_and_val
  368. # define atomic_and_val(mem, mask) \
  369. ({ __typeof (*(mem)) __atg16_old; \
  370. __typeof (mem) __atg16_memp = (mem); \
  371. __typeof (*(mem)) __atg16_mask = (mask); \
  372. \
  373. do \
  374. __atg16_old = (*__atg16_memp); \
  375. while (__builtin_expect \
  376. (atomic_compare_and_exchange_bool_acq (__atg16_memp, \
  377. __atg16_old & __atg16_mask,\
  378. __atg16_old), 0)); \
  379. \
  380. __atg16_old; })
  381. #endif
  382. /* Atomically *mem |= mask and return the old value of *mem. */
  383. #ifndef atomic_or
  384. # define atomic_or(mem, mask) \
  385. do { \
  386. __typeof (*(mem)) __atg17_old; \
  387. __typeof (mem) __atg17_memp = (mem); \
  388. __typeof (*(mem)) __atg17_mask = (mask); \
  389. \
  390. do \
  391. __atg17_old = (*__atg17_memp); \
  392. while (__builtin_expect \
  393. (atomic_compare_and_exchange_bool_acq (__atg17_memp, \
  394. __atg17_old | __atg17_mask, \
  395. __atg17_old), 0)); \
  396. } while (0)
  397. #endif
  398. #ifndef catomic_or
  399. # define catomic_or(mem, mask) \
  400. do { \
  401. __typeof (*(mem)) __atg18_old; \
  402. __typeof (mem) __atg18_memp = (mem); \
  403. __typeof (*(mem)) __atg18_mask = (mask); \
  404. \
  405. do \
  406. __atg18_old = (*__atg18_memp); \
  407. while (__builtin_expect \
  408. (catomic_compare_and_exchange_bool_acq (__atg18_memp, \
  409. __atg18_old | __atg18_mask,\
  410. __atg18_old), 0)); \
  411. } while (0)
  412. #endif
  413. /* Atomically *mem |= mask and return the old value of *mem. */
  414. #ifndef atomic_or_val
  415. # define atomic_or_val(mem, mask) \
  416. ({ __typeof (*(mem)) __atg19_old; \
  417. __typeof (mem) __atg19_memp = (mem); \
  418. __typeof (*(mem)) __atg19_mask = (mask); \
  419. \
  420. do \
  421. __atg19_old = (*__atg19_memp); \
  422. while (__builtin_expect \
  423. (atomic_compare_and_exchange_bool_acq (__atg19_memp, \
  424. __atg19_old | __atg19_mask,\
  425. __atg19_old), 0)); \
  426. \
  427. __atg19_old; })
  428. #endif
  429. #ifndef atomic_full_barrier
  430. # define atomic_full_barrier() __asm__ ("" ::: "memory")
  431. #endif
  432. #ifndef atomic_read_barrier
  433. # define atomic_read_barrier() atomic_full_barrier ()
  434. #endif
  435. #ifndef atomic_write_barrier
  436. # define atomic_write_barrier() atomic_full_barrier ()
  437. #endif
  438. #ifndef atomic_forced_read
  439. # define atomic_forced_read(x) \
  440. ({ __typeof (x) __x; __asm__ ("" : "=r" (__x) : "0" (x)); __x; })
  441. #endif
  442. #ifndef atomic_delay
  443. # define atomic_delay() do { /* nothing */ } while (0)
  444. #endif
  445. #endif /* atomic.h */