xchg.h 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #ifndef _ALPHA_CMPXCHG_H
  3. #error Do not include xchg.h directly!
  4. #else
  5. /*
  6. * xchg/xchg_local and cmpxchg/cmpxchg_local share the same code
  7. * except that local version do not have the expensive memory barrier.
  8. * So this file is included twice from asm/cmpxchg.h.
  9. */
  10. /*
  11. * Atomic exchange.
  12. * Since it can be used to implement critical sections
  13. * it must clobber "memory" (also for interrupts in UP).
  14. */
  15. static inline unsigned long
  16. ____xchg(_u8, volatile char *m, unsigned long val)
  17. {
  18. unsigned long ret, tmp, addr64;
  19. __asm__ __volatile__(
  20. " andnot %4,7,%3\n"
  21. " insbl %1,%4,%1\n"
  22. "1: ldq_l %2,0(%3)\n"
  23. " extbl %2,%4,%0\n"
  24. " mskbl %2,%4,%2\n"
  25. " or %1,%2,%2\n"
  26. " stq_c %2,0(%3)\n"
  27. " beq %2,2f\n"
  28. ".subsection 2\n"
  29. "2: br 1b\n"
  30. ".previous"
  31. : "=&r" (ret), "=&r" (val), "=&r" (tmp), "=&r" (addr64)
  32. : "r" ((long)m), "1" (val) : "memory");
  33. return ret;
  34. }
  35. static inline unsigned long
  36. ____xchg(_u16, volatile short *m, unsigned long val)
  37. {
  38. unsigned long ret, tmp, addr64;
  39. __asm__ __volatile__(
  40. " andnot %4,7,%3\n"
  41. " inswl %1,%4,%1\n"
  42. "1: ldq_l %2,0(%3)\n"
  43. " extwl %2,%4,%0\n"
  44. " mskwl %2,%4,%2\n"
  45. " or %1,%2,%2\n"
  46. " stq_c %2,0(%3)\n"
  47. " beq %2,2f\n"
  48. ".subsection 2\n"
  49. "2: br 1b\n"
  50. ".previous"
  51. : "=&r" (ret), "=&r" (val), "=&r" (tmp), "=&r" (addr64)
  52. : "r" ((long)m), "1" (val) : "memory");
  53. return ret;
  54. }
  55. static inline unsigned long
  56. ____xchg(_u32, volatile int *m, unsigned long val)
  57. {
  58. unsigned long dummy;
  59. __asm__ __volatile__(
  60. "1: ldl_l %0,%4\n"
  61. " bis $31,%3,%1\n"
  62. " stl_c %1,%2\n"
  63. " beq %1,2f\n"
  64. ".subsection 2\n"
  65. "2: br 1b\n"
  66. ".previous"
  67. : "=&r" (val), "=&r" (dummy), "=m" (*m)
  68. : "rI" (val), "m" (*m) : "memory");
  69. return val;
  70. }
  71. static inline unsigned long
  72. ____xchg(_u64, volatile long *m, unsigned long val)
  73. {
  74. unsigned long dummy;
  75. __asm__ __volatile__(
  76. "1: ldq_l %0,%4\n"
  77. " bis $31,%3,%1\n"
  78. " stq_c %1,%2\n"
  79. " beq %1,2f\n"
  80. ".subsection 2\n"
  81. "2: br 1b\n"
  82. ".previous"
  83. : "=&r" (val), "=&r" (dummy), "=m" (*m)
  84. : "rI" (val), "m" (*m) : "memory");
  85. return val;
  86. }
  87. /* This function doesn't exist, so you'll get a linker error
  88. if something tries to do an invalid xchg(). */
  89. extern void __xchg_called_with_bad_pointer(void);
  90. static __always_inline unsigned long
  91. ____xchg(, volatile void *ptr, unsigned long x, int size)
  92. {
  93. switch (size) {
  94. case 1:
  95. return ____xchg(_u8, ptr, x);
  96. case 2:
  97. return ____xchg(_u16, ptr, x);
  98. case 4:
  99. return ____xchg(_u32, ptr, x);
  100. case 8:
  101. return ____xchg(_u64, ptr, x);
  102. }
  103. __xchg_called_with_bad_pointer();
  104. return x;
  105. }
  106. /*
  107. * Atomic compare and exchange. Compare OLD with MEM, if identical,
  108. * store NEW in MEM. Return the initial value in MEM. Success is
  109. * indicated by comparing RETURN with OLD.
  110. */
  111. static inline unsigned long
  112. ____cmpxchg(_u8, volatile char *m, unsigned char old, unsigned char new)
  113. {
  114. unsigned long prev, tmp, cmp, addr64;
  115. __asm__ __volatile__(
  116. " andnot %5,7,%4\n"
  117. " insbl %1,%5,%1\n"
  118. "1: ldq_l %2,0(%4)\n"
  119. " extbl %2,%5,%0\n"
  120. " cmpeq %0,%6,%3\n"
  121. " beq %3,2f\n"
  122. " mskbl %2,%5,%2\n"
  123. " or %1,%2,%2\n"
  124. " stq_c %2,0(%4)\n"
  125. " beq %2,3f\n"
  126. "2:\n"
  127. ".subsection 2\n"
  128. "3: br 1b\n"
  129. ".previous"
  130. : "=&r" (prev), "=&r" (new), "=&r" (tmp), "=&r" (cmp), "=&r" (addr64)
  131. : "r" ((long)m), "Ir" (old), "1" (new) : "memory");
  132. return prev;
  133. }
  134. static inline unsigned long
  135. ____cmpxchg(_u16, volatile short *m, unsigned short old, unsigned short new)
  136. {
  137. unsigned long prev, tmp, cmp, addr64;
  138. __asm__ __volatile__(
  139. " andnot %5,7,%4\n"
  140. " inswl %1,%5,%1\n"
  141. "1: ldq_l %2,0(%4)\n"
  142. " extwl %2,%5,%0\n"
  143. " cmpeq %0,%6,%3\n"
  144. " beq %3,2f\n"
  145. " mskwl %2,%5,%2\n"
  146. " or %1,%2,%2\n"
  147. " stq_c %2,0(%4)\n"
  148. " beq %2,3f\n"
  149. "2:\n"
  150. ".subsection 2\n"
  151. "3: br 1b\n"
  152. ".previous"
  153. : "=&r" (prev), "=&r" (new), "=&r" (tmp), "=&r" (cmp), "=&r" (addr64)
  154. : "r" ((long)m), "Ir" (old), "1" (new) : "memory");
  155. return prev;
  156. }
  157. static inline unsigned long
  158. ____cmpxchg(_u32, volatile int *m, int old, int new)
  159. {
  160. unsigned long prev, cmp;
  161. __asm__ __volatile__(
  162. "1: ldl_l %0,%5\n"
  163. " cmpeq %0,%3,%1\n"
  164. " beq %1,2f\n"
  165. " mov %4,%1\n"
  166. " stl_c %1,%2\n"
  167. " beq %1,3f\n"
  168. "2:\n"
  169. ".subsection 2\n"
  170. "3: br 1b\n"
  171. ".previous"
  172. : "=&r"(prev), "=&r"(cmp), "=m"(*m)
  173. : "r"((long) old), "r"(new), "m"(*m) : "memory");
  174. return prev;
  175. }
  176. static inline unsigned long
  177. ____cmpxchg(_u64, volatile long *m, unsigned long old, unsigned long new)
  178. {
  179. unsigned long prev, cmp;
  180. __asm__ __volatile__(
  181. "1: ldq_l %0,%5\n"
  182. " cmpeq %0,%3,%1\n"
  183. " beq %1,2f\n"
  184. " mov %4,%1\n"
  185. " stq_c %1,%2\n"
  186. " beq %1,3f\n"
  187. "2:\n"
  188. ".subsection 2\n"
  189. "3: br 1b\n"
  190. ".previous"
  191. : "=&r"(prev), "=&r"(cmp), "=m"(*m)
  192. : "r"((long) old), "r"(new), "m"(*m) : "memory");
  193. return prev;
  194. }
  195. /* This function doesn't exist, so you'll get a linker error
  196. if something tries to do an invalid cmpxchg(). */
  197. extern void __cmpxchg_called_with_bad_pointer(void);
  198. static __always_inline unsigned long
  199. ____cmpxchg(, volatile void *ptr, unsigned long old, unsigned long new,
  200. int size)
  201. {
  202. switch (size) {
  203. case 1:
  204. return ____cmpxchg(_u8, ptr, old, new);
  205. case 2:
  206. return ____cmpxchg(_u16, ptr, old, new);
  207. case 4:
  208. return ____cmpxchg(_u32, ptr, old, new);
  209. case 8:
  210. return ____cmpxchg(_u64, ptr, old, new);
  211. }
  212. __cmpxchg_called_with_bad_pointer();
  213. return old;
  214. }
  215. #endif