|
@@ -16,6 +16,7 @@
|
|
|
|
|
|
#include <linux/types.h>
|
|
#include <linux/types.h>
|
|
#include <asm/spr-regs.h>
|
|
#include <asm/spr-regs.h>
|
|
|
|
+#include <asm/system.h>
|
|
|
|
|
|
#ifdef CONFIG_SMP
|
|
#ifdef CONFIG_SMP
|
|
#error not SMP safe
|
|
#error not SMP safe
|
|
@@ -258,85 +259,23 @@ extern uint32_t __xchg_32(uint32_t i, volatile void *v);
|
|
|
|
|
|
#define tas(ptr) (xchg((ptr), 1))
|
|
#define tas(ptr) (xchg((ptr), 1))
|
|
|
|
|
|
-/*****************************************************************************/
|
|
|
|
-/*
|
|
|
|
- * compare and conditionally exchange value with memory
|
|
|
|
- * - if (*ptr == test) then orig = *ptr; *ptr = test;
|
|
|
|
- * - if (*ptr != test) then orig = *ptr;
|
|
|
|
- */
|
|
|
|
-#ifndef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS
|
|
|
|
-
|
|
|
|
-#define cmpxchg(ptr, test, new) \
|
|
|
|
-({ \
|
|
|
|
- __typeof__(ptr) __xg_ptr = (ptr); \
|
|
|
|
- __typeof__(*(ptr)) __xg_orig, __xg_tmp; \
|
|
|
|
- __typeof__(*(ptr)) __xg_test = (test); \
|
|
|
|
- __typeof__(*(ptr)) __xg_new = (new); \
|
|
|
|
- \
|
|
|
|
- switch (sizeof(__xg_orig)) { \
|
|
|
|
- case 4: \
|
|
|
|
- asm volatile( \
|
|
|
|
- "0: \n" \
|
|
|
|
- " orcc gr0,gr0,gr0,icc3 \n" \
|
|
|
|
- " ckeq icc3,cc7 \n" \
|
|
|
|
- " ld.p %M0,%1 \n" \
|
|
|
|
- " orcr cc7,cc7,cc3 \n" \
|
|
|
|
- " sub%I4cc %1,%4,%2,icc0 \n" \
|
|
|
|
- " bne icc0,#0,1f \n" \
|
|
|
|
- " cst.p %3,%M0 ,cc3,#1 \n" \
|
|
|
|
- " corcc gr29,gr29,gr0 ,cc3,#1 \n" \
|
|
|
|
- " beq icc3,#0,0b \n" \
|
|
|
|
- "1: \n" \
|
|
|
|
- : "+U"(*__xg_ptr), "=&r"(__xg_orig), "=&r"(__xg_tmp) \
|
|
|
|
- : "r"(__xg_new), "NPr"(__xg_test) \
|
|
|
|
- : "memory", "cc7", "cc3", "icc3", "icc0" \
|
|
|
|
- ); \
|
|
|
|
- break; \
|
|
|
|
- \
|
|
|
|
- default: \
|
|
|
|
- __xg_orig = 0; \
|
|
|
|
- asm volatile("break"); \
|
|
|
|
- break; \
|
|
|
|
- } \
|
|
|
|
- \
|
|
|
|
- __xg_orig; \
|
|
|
|
-})
|
|
|
|
-
|
|
|
|
-#else
|
|
|
|
-
|
|
|
|
-extern uint32_t __cmpxchg_32(uint32_t *v, uint32_t test, uint32_t new);
|
|
|
|
-
|
|
|
|
-#define cmpxchg(ptr, test, new) \
|
|
|
|
-({ \
|
|
|
|
- __typeof__(ptr) __xg_ptr = (ptr); \
|
|
|
|
- __typeof__(*(ptr)) __xg_orig; \
|
|
|
|
- __typeof__(*(ptr)) __xg_test = (test); \
|
|
|
|
- __typeof__(*(ptr)) __xg_new = (new); \
|
|
|
|
- \
|
|
|
|
- switch (sizeof(__xg_orig)) { \
|
|
|
|
- case 4: __xg_orig = __cmpxchg_32(__xg_ptr, __xg_test, __xg_new); break; \
|
|
|
|
- default: \
|
|
|
|
- __xg_orig = 0; \
|
|
|
|
- asm volatile("break"); \
|
|
|
|
- break; \
|
|
|
|
- } \
|
|
|
|
- \
|
|
|
|
- __xg_orig; \
|
|
|
|
-})
|
|
|
|
-
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
#define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), old, new))
|
|
#define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), old, new))
|
|
#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
|
|
#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
|
|
|
|
|
|
-#define atomic_add_unless(v, a, u) \
|
|
|
|
-({ \
|
|
|
|
- int c, old; \
|
|
|
|
- c = atomic_read(v); \
|
|
|
|
- while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \
|
|
|
|
- c = old; \
|
|
|
|
- c != (u); \
|
|
|
|
-})
|
|
|
|
|
|
+static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
|
|
|
|
+{
|
|
|
|
+ int c, old;
|
|
|
|
+ c = atomic_read(v);
|
|
|
|
+ for (;;) {
|
|
|
|
+ if (unlikely(c == (u)))
|
|
|
|
+ break;
|
|
|
|
+ old = atomic_cmpxchg((v), c, c + (a));
|
|
|
|
+ if (likely(old == c))
|
|
|
|
+ break;
|
|
|
|
+ c = old;
|
|
|
|
+ }
|
|
|
|
+ return c != (u);
|
|
|
|
+}
|
|
|
|
|
|
#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
|
|
#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
|
|
|
|
|