return a_ctz_l(y);
}
+#if ((__ARM_ARCH_6__ || __ARM_ARCH_6K__ || __ARM_ARCH_6ZK__) && !__thumb__) \
+ || __ARM_ARCH_7A__ || __ARM_ARCH_7R__ || __ARM_ARCH >= 7
+
+#if __ARM_ARCH_7A__ || __ARM_ARCH_7R__ || __ARM_ARCH >= 7
+#define MEM_BARRIER "dmb ish"
+#else
+#define MEM_BARRIER "mcr p15,0,r0,c7,c10,5"
+#endif
+
+static inline int __k_cas(int t, int s, volatile int *p)
+{
+ int ret;
+ __asm__(
+ " " MEM_BARRIER "\n"
+ "1: ldrex %0,%3\n"
+ " subs %0,%0,%1\n"
+#ifdef __thumb__
+ " itt eq\n"
+#endif
+ " strexeq %0,%2,%3\n"
+ " teqeq %0,#1\n"
+ " beq 1b\n"
+ " " MEM_BARRIER "\n"
+ : "=&r"(ret)
+ : "r"(t), "r"(s), "Q"(*p)
+ : "memory", "cc" );
+ return ret;
+}
+#else
+#define __k_cas ((int (*)(int, int, volatile int *))0xffff0fc0)
+#endif
+
static inline int a_cas(volatile int *p, int t, int s)
{
int old;
for (;;) {
- if (!((int (*)(int, int, volatile int *))0xffff0fc0)(t, s, p))
+ if (!__k_cas(t, s, p))
return t;
if ((old=*p) != t)
return old;
return (void *)a_cas(p, (int)t, (int)s);
}
-static inline long a_cas_l(volatile void *p, long t, long s)
-{
- return a_cas(p, t, s);
-}
-
static inline int a_swap(volatile int *x, int v)
{
int old;
do old = *x;
- while (a_cas(x, old, v) != old);
+ while (__k_cas(old, v, x));
return old;
}
{
int old;
do old = *x;
- while (a_cas(x, old, old+v) != old);
+ while (__k_cas(old, old+v, x));
return old;
}
static inline void a_store(volatile int *p, int x)
{
- *p=x;
+ while (__k_cas(*p, x, p));
}
static inline void a_spin()
{
int old;
do old = *p;
- while (a_cas(p, old, old&v) != old);
+ while (__k_cas(old, old&v, p));
}
static inline void a_or(volatile int *p, int v)
{
int old;
do old = *p;
- while (a_cas(p, old, old|v) != old);
+ while (__k_cas(old, old|v, p));
+}
+
+static inline void a_or_l(volatile void *p, long v)
+{
+ a_or(p, v);
}
static inline void a_and_64(volatile uint64_t *p, uint64_t v)
{
- a_and((int *)p, v);
- a_and((int *)p+1, v>>32);
+ union { uint64_t v; uint32_t r[2]; } u = { v };
+ a_and((int *)p, u.r[0]);
+ a_and((int *)p+1, u.r[1]);
}
static inline void a_or_64(volatile uint64_t *p, uint64_t v)
{
- a_or((int *)p, v);
- a_or((int *)p+1, v>>32);
+ union { uint64_t v; uint32_t r[2]; } u = { v };
+ a_or((int *)p, u.r[0]);
+ a_or((int *)p+1, u.r[1]);
}
#endif