atomic.h 11 KB

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