cmpxchg.h 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /*
  2. * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License version 2 as
  6. * published by the Free Software Foundation.
  7. */
  8. #ifndef __ASM_ARC_CMPXCHG_H
  9. #define __ASM_ARC_CMPXCHG_H
  10. #include <linux/types.h>
  11. #include <asm/barrier.h>
  12. #include <asm/smp.h>
  13. #ifdef CONFIG_ARC_HAS_LLSC
  14. static inline unsigned long
  15. __cmpxchg(volatile void *ptr, unsigned long expected, unsigned long new)
  16. {
  17. unsigned long prev;
  18. /*
  19. * Explicit full memory barrier needed before/after as
  20. * LLOCK/SCOND thmeselves don't provide any such semantics
  21. */
  22. smp_mb();
  23. __asm__ __volatile__(
  24. "1: llock %0, [%1] \n"
  25. " brne %0, %2, 2f \n"
  26. " scond %3, [%1] \n"
  27. " bnz 1b \n"
  28. "2: \n"
  29. : "=&r"(prev) /* Early clobber, to prevent reg reuse */
  30. : "r"(ptr), /* Not "m": llock only supports reg direct addr mode */
  31. "ir"(expected),
  32. "r"(new) /* can't be "ir". scond can't take LIMM for "b" */
  33. : "cc", "memory"); /* so that gcc knows memory is being written here */
  34. smp_mb();
  35. return prev;
  36. }
  37. #elif !defined(CONFIG_ARC_PLAT_EZNPS)
  38. static inline unsigned long
  39. __cmpxchg(volatile void *ptr, unsigned long expected, unsigned long new)
  40. {
  41. unsigned long flags;
  42. int prev;
  43. volatile unsigned long *p = ptr;
  44. /*
  45. * spin lock/unlock provide the needed smp_mb() before/after
  46. */
  47. atomic_ops_lock(flags);
  48. prev = *p;
  49. if (prev == expected)
  50. *p = new;
  51. atomic_ops_unlock(flags);
  52. return prev;
  53. }
  54. #else /* CONFIG_ARC_PLAT_EZNPS */
  55. static inline unsigned long
  56. __cmpxchg(volatile void *ptr, unsigned long expected, unsigned long new)
  57. {
  58. /*
  59. * Explicit full memory barrier needed before/after
  60. */
  61. smp_mb();
  62. write_aux_reg(CTOP_AUX_GPA1, expected);
  63. __asm__ __volatile__(
  64. " mov r2, %0\n"
  65. " mov r3, %1\n"
  66. " .word %2\n"
  67. " mov %0, r2"
  68. : "+r"(new)
  69. : "r"(ptr), "i"(CTOP_INST_EXC_DI_R2_R2_R3)
  70. : "r2", "r3", "memory");
  71. smp_mb();
  72. return new;
  73. }
  74. #endif /* CONFIG_ARC_HAS_LLSC */
  75. #define cmpxchg(ptr, o, n) ({ \
  76. (typeof(*(ptr)))__cmpxchg((ptr), \
  77. (unsigned long)(o), \
  78. (unsigned long)(n)); \
  79. })
  80. /*
  81. * atomic_cmpxchg is same as cmpxchg
  82. * LLSC: only different in data-type, semantics are exactly same
  83. * !LLSC: cmpxchg() has to use an external lock atomic_ops_lock to guarantee
  84. * semantics, and this lock also happens to be used by atomic_*()
  85. */
  86. #define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
  87. #ifndef CONFIG_ARC_PLAT_EZNPS
  88. /*
  89. * xchg (reg with memory) based on "Native atomic" EX insn
  90. */
  91. static inline unsigned long __xchg(unsigned long val, volatile void *ptr,
  92. int size)
  93. {
  94. extern unsigned long __xchg_bad_pointer(void);
  95. switch (size) {
  96. case 4:
  97. smp_mb();
  98. __asm__ __volatile__(
  99. " ex %0, [%1] \n"
  100. : "+r"(val)
  101. : "r"(ptr)
  102. : "memory");
  103. smp_mb();
  104. return val;
  105. }
  106. return __xchg_bad_pointer();
  107. }
  108. #define _xchg(ptr, with) ((typeof(*(ptr)))__xchg((unsigned long)(with), (ptr), \
  109. sizeof(*(ptr))))
  110. /*
  111. * xchg() maps directly to ARC EX instruction which guarantees atomicity.
  112. * However in !LLSC config, it also needs to be use @atomic_ops_lock spinlock
  113. * due to a subtle reason:
  114. * - For !LLSC, cmpxchg() needs to use that lock (see above) and there is lot
  115. * of kernel code which calls xchg()/cmpxchg() on same data (see llist.h)
  116. * Hence xchg() needs to follow same locking rules.
  117. *
  118. * Technically the lock is also needed for UP (boils down to irq save/restore)
  119. * but we can cheat a bit since cmpxchg() atomic_ops_lock() would cause irqs to
  120. * be disabled thus can't possibly be interrpted/preempted/clobbered by xchg()
  121. * Other way around, xchg is one instruction anyways, so can't be interrupted
  122. * as such
  123. */
  124. #if !defined(CONFIG_ARC_HAS_LLSC) && defined(CONFIG_SMP)
  125. #define xchg(ptr, with) \
  126. ({ \
  127. unsigned long flags; \
  128. typeof(*(ptr)) old_val; \
  129. \
  130. atomic_ops_lock(flags); \
  131. old_val = _xchg(ptr, with); \
  132. atomic_ops_unlock(flags); \
  133. old_val; \
  134. })
  135. #else
  136. #define xchg(ptr, with) _xchg(ptr, with)
  137. #endif
  138. #else /* CONFIG_ARC_PLAT_EZNPS */
  139. static inline unsigned long __xchg(unsigned long val, volatile void *ptr,
  140. int size)
  141. {
  142. extern unsigned long __xchg_bad_pointer(void);
  143. switch (size) {
  144. case 4:
  145. /*
  146. * Explicit full memory barrier needed before/after
  147. */
  148. smp_mb();
  149. __asm__ __volatile__(
  150. " mov r2, %0\n"
  151. " mov r3, %1\n"
  152. " .word %2\n"
  153. " mov %0, r2\n"
  154. : "+r"(val)
  155. : "r"(ptr), "i"(CTOP_INST_XEX_DI_R2_R2_R3)
  156. : "r2", "r3", "memory");
  157. smp_mb();
  158. return val;
  159. }
  160. return __xchg_bad_pointer();
  161. }
  162. #define xchg(ptr, with) ({ \
  163. (typeof(*(ptr)))__xchg((unsigned long)(with), \
  164. (ptr), \
  165. sizeof(*(ptr))); \
  166. })
  167. #endif /* CONFIG_ARC_PLAT_EZNPS */
  168. /*
  169. * "atomic" variant of xchg()
  170. * REQ: It needs to follow the same serialization rules as other atomic_xxx()
  171. * Since xchg() doesn't always do that, it would seem that following defintion
  172. * is incorrect. But here's the rationale:
  173. * SMP : Even xchg() takes the atomic_ops_lock, so OK.
  174. * LLSC: atomic_ops_lock are not relevant at all (even if SMP, since LLSC
  175. * is natively "SMP safe", no serialization required).
  176. * UP : other atomics disable IRQ, so no way a difft ctxt atomic_xchg()
  177. * could clobber them. atomic_xchg() itself would be 1 insn, so it
  178. * can't be clobbered by others. Thus no serialization required when
  179. * atomic_xchg is involved.
  180. */
  181. #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
  182. #endif