atomic.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /* Copyright (C) 2012 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3. The GNU C Library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Lesser General Public
  5. License as published by the Free Software Foundation; either
  6. version 2.1 of the License, or (at your option) any later version.
  7. The GNU C Library 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 GNU
  10. Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public
  12. License along with the GNU C Library; if not, see
  13. <http://www.gnu.org/licenses/>. */
  14. #ifndef _BITS_ATOMIC_H
  15. #define _BITS_ATOMIC_H 1
  16. #include <inttypes.h>
  17. typedef int32_t atomic32_t;
  18. typedef uint32_t uatomic32_t;
  19. typedef int_fast32_t atomic_fast32_t;
  20. typedef uint_fast32_t uatomic_fast32_t;
  21. typedef int64_t atomic64_t;
  22. typedef uint64_t uatomic64_t;
  23. typedef int_fast64_t atomic_fast64_t;
  24. typedef uint_fast64_t uatomic_fast64_t;
  25. typedef intptr_t atomicptr_t;
  26. typedef uintptr_t uatomicptr_t;
  27. typedef intmax_t atomic_max_t;
  28. typedef uintmax_t uatomic_max_t;
  29. /* Xtensa has only a 32-bit form of a store-conditional instruction. */
  30. #define __arch_compare_and_exchange_bool_8_acq(mem, newval, oldval) \
  31. (abort (), 0)
  32. #define __arch_compare_and_exchange_bool_16_acq(mem, newval, oldval) \
  33. (abort (), 0)
  34. #define __arch_compare_and_exchange_bool_8_rel(mem, newval, oldval) \
  35. (abort (), 0)
  36. #define __arch_compare_and_exchange_bool_16_rel(mem, newval, oldval) \
  37. (abort (), 0)
  38. /* Atomically store NEWVAL in *MEM if *MEM is equal to OLDVAL.
  39. Return the old *MEM value. */
  40. #define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \
  41. ({__typeof__(*(mem)) __tmp, __value; \
  42. __asm__ __volatile__( \
  43. "1: l32i %1, %2, 0 \n" \
  44. " bne %1, %4, 2f \n" \
  45. " wsr %1, SCOMPARE1 \n" \
  46. " mov %0, %1 \n" \
  47. " mov %1, %3 \n" \
  48. " s32c1i %1, %2, 0 \n" \
  49. " bne %0, %1, 1b \n" \
  50. "2: \n" \
  51. : "=&a" (__value), "=&a" (__tmp) \
  52. : "a" (mem), "a" (newval), "a" (oldval) \
  53. : "memory" ); \
  54. __tmp; \
  55. })
  56. /* Atomically store NEWVAL in *MEM if *MEM is equal to OLDVAL.
  57. Return zero if *MEM was changed or non-zero if no exchange happened. */
  58. #define __arch_compare_and_exchange_bool_32_acq(mem, newval, oldval) \
  59. ({__typeof__(*(mem)) __tmp, __value; \
  60. __asm__ __volatile__( \
  61. "1: l32i %0, %2, 0 \n" \
  62. " sub %1, %4, %0 \n" \
  63. " bnez %1, 2f \n" \
  64. " wsr %0, SCOMPARE1 \n" \
  65. " mov %1, %3 \n" \
  66. " s32c1i %1, %2, 0 \n" \
  67. " bne %0, %1, 1b \n" \
  68. " movi %1, 0 \n" \
  69. "2: \n" \
  70. : "=&a" (__value), "=&a" (__tmp) \
  71. : "a" (mem), "a" (newval), "a" (oldval) \
  72. : "memory" ); \
  73. __tmp != 0; \
  74. })
  75. /* Store NEWVALUE in *MEM and return the old value. */
  76. #define __arch_exchange_32_acq(mem, newval) \
  77. ({__typeof__(*(mem)) __tmp, __value; \
  78. __asm__ __volatile__( \
  79. "1: l32i %0, %2, 0 \n" \
  80. " wsr %0, SCOMPARE1 \n" \
  81. " mov %1, %3 \n" \
  82. " s32c1i %1, %2, 0 \n" \
  83. " bne %0, %1, 1b \n" \
  84. : "=&a" (__value), "=&a" (__tmp) \
  85. : "a" (mem), "a" (newval) \
  86. : "memory" ); \
  87. __tmp; \
  88. })
  89. /* Add VALUE to *MEM and return the old value of *MEM. */
  90. #define __arch_atomic_exchange_and_add_32(mem, value) \
  91. ({__typeof__(*(mem)) __tmp, __value; \
  92. __asm__ __volatile__( \
  93. "1: l32i %0, %2, 0 \n" \
  94. " wsr %0, SCOMPARE1 \n" \
  95. " add %1, %0, %3 \n" \
  96. " s32c1i %1, %2, 0 \n" \
  97. " bne %0, %1, 1b \n" \
  98. : "=&a" (__value), "=&a" (__tmp) \
  99. : "a" (mem), "a" (value) \
  100. : "memory" ); \
  101. __tmp; \
  102. })
  103. /* Subtract VALUE from *MEM and return the old value of *MEM. */
  104. #define __arch_atomic_exchange_and_sub_32(mem, value) \
  105. ({__typeof__(*(mem)) __tmp, __value; \
  106. __asm__ __volatile__( \
  107. "1: l32i %0, %2, 0 \n" \
  108. " wsr %0, SCOMPARE1 \n" \
  109. " sub %1, %0, %3 \n" \
  110. " s32c1i %1, %2, 0 \n" \
  111. " bne %0, %1, 1b \n" \
  112. : "=&a" (__value), "=&a" (__tmp) \
  113. : "a" (mem), "a" (value) \
  114. : "memory" ); \
  115. __tmp; \
  116. })
  117. /* Decrement *MEM if it is > 0, and return the old value. */
  118. #define __arch_atomic_decrement_if_positive_32(mem) \
  119. ({__typeof__(*(mem)) __tmp, __value; \
  120. __asm__ __volatile__( \
  121. "1: l32i %0, %2, 0 \n" \
  122. " blti %0, 1, 2f \n" \
  123. " wsr %0, SCOMPARE1 \n" \
  124. " addi %1, %0, -1 \n" \
  125. " s32c1i %1, %2, 0 \n" \
  126. " bne %0, %1, 1b \n" \
  127. "2: \n" \
  128. : "=&a" (__value), "=&a" (__tmp) \
  129. : "a" (mem) \
  130. : "memory" ); \
  131. __value; \
  132. })
  133. /* These are the preferred public interfaces: */
  134. #define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \
  135. ({ \
  136. if (sizeof (*mem) != 4) \
  137. abort(); \
  138. __arch_compare_and_exchange_val_32_acq(mem, newval, oldval); \
  139. })
  140. #define atomic_exchange_acq(mem, newval) \
  141. ({ \
  142. if (sizeof(*(mem)) != 4) \
  143. abort(); \
  144. __arch_exchange_32_acq(mem, newval); \
  145. })
  146. #define atomic_exchange_and_add(mem, newval) \
  147. ({ \
  148. if (sizeof(*(mem)) != 4) \
  149. abort(); \
  150. __arch_atomic_exchange_and_add_32(mem, newval); \
  151. })
  152. #define atomic_exchange_and_sub(mem, newval) \
  153. ({ \
  154. if (sizeof(*(mem)) != 4) \
  155. abort(); \
  156. __arch_atomic_exchange_and_sub_32(mem, newval); \
  157. })
  158. #define atomic_decrement_if_positive(mem) \
  159. ({ \
  160. if (sizeof(*(mem)) != 4) \
  161. abort(); \
  162. __arch_atomic_decrement_if_positive_32(mem); \
  163. })
  164. # define __arch_compare_and_exchange_bool_64_acq(mem, newval, oldval) \
  165. (abort (), 0)
  166. # define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \
  167. (abort (), (__typeof (*mem)) 0)
  168. # define __arch_compare_and_exchange_bool_64_rel(mem, newval, oldval) \
  169. (abort (), 0)
  170. # define __arch_compare_and_exchange_val_64_rel(mem, newval, oldval) \
  171. (abort (), (__typeof (*mem)) 0)
  172. # define __arch_atomic_exchange_64_acq(mem, value) \
  173. ({ abort (); (*mem) = (value); })
  174. # define __arch_atomic_exchange_64_rel(mem, value) \
  175. ({ abort (); (*mem) = (value); })
  176. # define __arch_atomic_exchange_and_add_64(mem, value) \
  177. ({ abort (); (*mem) = (value); })
  178. # define __arch_atomic_increment_val_64(mem) \
  179. ({ abort (); (*mem)++; })
  180. # define __arch_atomic_decrement_val_64(mem) \
  181. ({ abort (); (*mem)--; })
  182. # define __arch_atomic_decrement_if_positive_64(mem) \
  183. ({ abort (); (*mem)--; })
  184. #endif /* _BITS_ATOMIC_H */