svn commit: r312925 - in head/sys: arm/include arm64/include
Olivier Houchard
cognet at FreeBSD.org
Sat Jan 28 16:24:07 UTC 2017
Author: cognet
Date: Sat Jan 28 16:24:06 2017
New Revision: 312925
URL: https://svnweb.freebsd.org/changeset/base/312925
Log:
Implement atomic_fcmpset_* for arm and arm64.
Modified:
head/sys/arm/include/atomic-v4.h
head/sys/arm/include/atomic-v6.h
head/sys/arm/include/atomic.h
head/sys/arm64/include/atomic.h
Modified: head/sys/arm/include/atomic-v4.h
==============================================================================
--- head/sys/arm/include/atomic-v4.h Sat Jan 28 15:44:14 2017 (r312924)
+++ head/sys/arm/include/atomic-v4.h Sat Jan 28 16:24:06 2017 (r312925)
@@ -112,6 +112,43 @@ atomic_clear_64(volatile uint64_t *addre
__with_interrupts_disabled(*address &= ~clearmask);
}
+static __inline int
+atomic_fcmpset_32(volatile u_int32_t *p, volatile u_int32_t *cmpval, volatile u_int32_t newval)
+{
+ u_int32_t ret;
+
+ __with_interrupts_disabled(
+ {
+ ret = *p;
+ if (*p == *cmpval) {
+ *p = newval;
+ ret = 1;
+ } else {
+ *cmpval = *p;
+ ret = 0;
+ }
+ });
+ return (ret);
+}
+
+static __inline int
+atomic_fcmpset_64(volatile u_int64_t *p, volatile u_int64_t *cmpval, volatile u_int64_t newval)
+{
+ u_int64_t ret;
+
+ __with_interrupts_disabled(
+ {
+ if (*p == *cmpval) {
+ *p = newval;
+ ret = 1;
+ } else {
+ *cmpval = *p;
+ ret = 0;
+ }
+ });
+ return (ret);
+}
+
static __inline u_int32_t
atomic_cmpset_32(volatile u_int32_t *p, volatile u_int32_t cmpval, volatile u_int32_t newval)
{
@@ -370,6 +407,12 @@ atomic_swap_32(volatile u_int32_t *p, u_
return (__swp(v, p));
}
+#define atomic_fcmpset_rel_32 atomic_fcmpset_32
+#define atomic_fcmpset_acq_32 atomic_fcmpset_32
+#define atomic_fcmpset_rel_64 atomic_fcmpset_64
+#define atomic_fcmpset_acq_64 atomic_fcmpset_64
+#define atomic_fcmpset_acq_long atomic_fcmpset_long
+#define atomic_fcmpset_rel_long atomic_fcmpset_long
#define atomic_cmpset_rel_32 atomic_cmpset_32
#define atomic_cmpset_acq_32 atomic_cmpset_32
#define atomic_cmpset_rel_64 atomic_cmpset_64
@@ -421,6 +464,14 @@ atomic_cmpset_long(volatile u_long *dst,
}
static __inline u_long
+atomic_fcmpset_long(volatile u_long *dst, u_long *old, u_long newe)
+{
+
+ return (atomic_fcmpset_32((volatile uint32_t *)dst,
+ (uint32_t *)old, newe));
+}
+
+static __inline u_long
atomic_fetchadd_long(volatile u_long *p, u_long v)
{
Modified: head/sys/arm/include/atomic-v6.h
==============================================================================
--- head/sys/arm/include/atomic-v6.h Sat Jan 28 15:44:14 2017 (r312924)
+++ head/sys/arm/include/atomic-v6.h Sat Jan 28 16:24:06 2017 (r312925)
@@ -190,6 +190,116 @@ ATOMIC_ACQ_REL(clear, 32)
ATOMIC_ACQ_REL(clear, 64)
ATOMIC_ACQ_REL_LONG(clear)
+static __inline int
+atomic_fcmpset_32(volatile uint32_t *p, uint32_t *cmpval, uint32_t newval)
+{
+ uint32_t tmp;
+ uint32_t _cmpval = *cmpval;
+ int ret;
+
+ __asm __volatile(
+ "1: mov %0, #1 \n"
+ " ldrex %1, [%2] \n"
+ " cmp %1, %3 \n"
+ " it ne \n"
+ " bne 2f \n"
+ " strex %0, %4, [%2] \n"
+ "2:"
+ : "=&r" (ret), "=&r" (tmp), "+r" (p), "+r" (_cmpval), "+r" (newval)
+ : : "cc", "memory");
+ *cmpval = tmp;
+ return (!ret);
+}
+
+static __inline uint64_t
+atomic_fcmpset_64(volatile uint64_t *p, uint64_t *cmpval, uint64_t newval)
+{
+ uint64_t tmp;
+ uint64_t _cmpval = *cmpval;
+ int ret;
+
+ __asm __volatile(
+ "1: mov %[ret], #1 \n"
+ " ldrexd %Q[tmp], %R[tmp], [%[ptr]] \n"
+ " teq %Q[tmp], %Q[_cmpval] \n"
+ " itee eq \n"
+ " teqeq %R[tmp], %R[_cmpval] \n"
+ " bne 2f \n"
+ " strexd %[ret], %Q[newval], %R[newval], [%[ptr]]\n"
+ "2: \n"
+ : [ret] "=&r" (ret),
+ [tmp] "=&r" (tmp)
+ : [ptr] "r" (p),
+ [_cmpval] "r" (_cmpval),
+ [newval] "r" (newval)
+ : "cc", "memory");
+ *cmpval = tmp;
+ return (!ret);
+}
+
+static __inline u_long
+atomic_fcmpset_long(volatile u_long *p, u_long *cmpval, u_long newval)
+{
+
+ return (atomic_fcmpset_32((volatile uint32_t *)p,
+ (uint32_t *)cmpval, newval));
+}
+
+static __inline uint64_t
+atomic_fcmpset_acq_64(volatile uint64_t *p, uint64_t *cmpval, uint64_t newval)
+{
+ uint64_t ret;
+
+ ret = atomic_fcmpset_64(p, cmpval, newval);
+ dmb();
+ return (ret);
+}
+
+static __inline u_long
+atomic_fcmpset_acq_long(volatile u_long *p, u_long *cmpval, u_long newval)
+{
+ u_long ret;
+
+ ret = atomic_fcmpset_long(p, cmpval, newval);
+ dmb();
+ return (ret);
+}
+
+static __inline uint32_t
+atomic_fcmpset_acq_32(volatile uint32_t *p, uint32_t *cmpval, uint32_t newval)
+{
+
+ uint32_t ret;
+
+ ret = atomic_fcmpset_32(p, cmpval, newval);
+ dmb();
+ return (ret);
+}
+
+static __inline uint32_t
+atomic_fcmpset_rel_32(volatile uint32_t *p, uint32_t *cmpval, uint32_t newval)
+{
+
+ dmb();
+ return (atomic_fcmpset_32(p, cmpval, newval));
+}
+
+static __inline uint64_t
+atomic_fcmpset_rel_64(volatile uint64_t *p, uint64_t *cmpval, uint64_t newval)
+{
+
+ dmb();
+ return (atomic_fcmpset_64(p, cmpval, newval));
+}
+
+static __inline u_long
+atomic_fcmpset_rel_long(volatile u_long *p, u_long *cmpval, u_long newval)
+{
+
+ dmb();
+ return (atomic_fcmpset_long(p, cmpval, newval));
+}
+
static __inline uint32_t
atomic_cmpset_32(volatile uint32_t *p, uint32_t cmpval, uint32_t newval)
{
Modified: head/sys/arm/include/atomic.h
==============================================================================
--- head/sys/arm/include/atomic.h Sat Jan 28 15:44:14 2017 (r312924)
+++ head/sys/arm/include/atomic.h Sat Jan 28 16:24:06 2017 (r312925)
@@ -84,6 +84,9 @@ atomic_store_long(volatile u_long *dst,
#define atomic_set_ptr atomic_set_32
#define atomic_set_acq_ptr atomic_set_acq_32
#define atomic_set_rel_ptr atomic_set_rel_32
+#define atomic_fcmpset_ptr atomic_fcmpset_32
+#define atomic_fcmpset_rel_ptr atomic_fcmpset_rel_32
+#define atomic_fcmpset_acq_ptr atomic_fcmpset_acq_32
#define atomic_cmpset_ptr atomic_cmpset_32
#define atomic_cmpset_acq_ptr atomic_cmpset_acq_32
#define atomic_cmpset_rel_ptr atomic_cmpset_rel_32
@@ -105,6 +108,9 @@ atomic_store_long(volatile u_long *dst,
#define atomic_set_int atomic_set_32
#define atomic_set_acq_int atomic_set_acq_32
#define atomic_set_rel_int atomic_set_rel_32
+#define atomic_fcmpset_int atomic_fcmpset_32
+#define atomic_fcmpset_acq_int atomic_fcmpset_acq_32
+#define atomic_fcmpset_rel_int atomic_fcmpset_rel_32
#define atomic_cmpset_int atomic_cmpset_32
#define atomic_cmpset_acq_int atomic_cmpset_acq_32
#define atomic_cmpset_rel_int atomic_cmpset_rel_32
Modified: head/sys/arm64/include/atomic.h
==============================================================================
--- head/sys/arm64/include/atomic.h Sat Jan 28 15:44:14 2017 (r312924)
+++ head/sys/arm64/include/atomic.h Sat Jan 28 16:24:06 2017 (r312925)
@@ -98,6 +98,61 @@ ATOMIC(clear, bic)
ATOMIC(set, orr)
ATOMIC(subtract, sub)
+#define ATOMIC_FCMPSET(bar, a, l) \
+static __inline int \
+atomic_fcmpset_##bar##32(volatile uint32_t *p, uint32_t *cmpval, \
+ uint32_t newval) \
+{ \
+ uint32_t tmp; \
+ uint32_t _cmpval = *cmpval; \
+ int res; \
+ \
+ __asm __volatile( \
+ "1: mov %w1, #1 \n" \
+ " ld"#a"xr %w0, [%2] \n" \
+ " cmp %w0, %w3 \n" \
+ " b.ne 2f \n" \
+ " st"#l"xr %w1, %w4, [%2] \n" \
+ "2:" \
+ : "=&r"(tmp), "=&r"(res) \
+ : "r" (p), "r" (_cmpval), "r" (newval) \
+ : "cc", "memory" \
+ ); \
+ *cmpval = tmp; \
+ \
+ return (!res); \
+} \
+ \
+static __inline int \
+atomic_fcmpset_##bar##64(volatile uint64_t *p, uint64_t *cmpval, \
+ uint64_t newval) \
+{ \
+ uint64_t tmp; \
+ uint64_t _cmpval = *cmpval; \
+ int res; \
+ \
+ __asm __volatile( \
+ "1: mov %w1, #1 \n" \
+ " ld"#a"xr %0, [%2] \n" \
+ " cmp %0, %3 \n" \
+ " b.ne 2f \n" \
+ " st"#l"xr %w1, %4, [%2] \n" \
+ "2:" \
+ : "=&r"(tmp), "=&r"(res) \
+ : "r" (p), "r" (_cmpval), "r" (newval) \
+ : "cc", "memory" \
+ ); \
+ *cmpval = tmp; \
+ \
+ return (!res); \
+}
+
+ATOMIC_FCMPSET( , , )
+ATOMIC_FCMPSET(acq_, a, )
+ATOMIC_FCMPSET(rel_, ,l)
+
+#undef ATOMIC_FCMPSET
+
#define ATOMIC_CMPSET(bar, a, l) \
static __inline int \
atomic_cmpset_##bar##32(volatile uint32_t *p, uint32_t cmpval, \
@@ -311,6 +366,7 @@ atomic_store_rel_64(volatile uint64_t *p
#define atomic_add_int atomic_add_32
+#define atomic_fcmpset_int atomic_fcmpset_32
#define atomic_clear_int atomic_clear_32
#define atomic_cmpset_int atomic_cmpset_32
#define atomic_fetchadd_int atomic_fetchadd_32
@@ -320,6 +376,7 @@ atomic_store_rel_64(volatile uint64_t *p
#define atomic_subtract_int atomic_subtract_32
#define atomic_add_acq_int atomic_add_acq_32
+#define atomic_fcmpset_acq_int atomic_fcmpset_acq_32
#define atomic_clear_acq_int atomic_clear_acq_32
#define atomic_cmpset_acq_int atomic_cmpset_acq_32
#define atomic_load_acq_int atomic_load_acq_32
@@ -327,6 +384,7 @@ atomic_store_rel_64(volatile uint64_t *p
#define atomic_subtract_acq_int atomic_subtract_acq_32
#define atomic_add_rel_int atomic_add_rel_32
+#define atomic_fcmpset_rel_int atomic_fcmpset_rel_32
#define atomic_clear_rel_int atomic_add_rel_32
#define atomic_cmpset_rel_int atomic_cmpset_rel_32
#define atomic_set_rel_int atomic_set_rel_32
@@ -334,6 +392,7 @@ atomic_store_rel_64(volatile uint64_t *p
#define atomic_store_rel_int atomic_store_rel_32
#define atomic_add_long atomic_add_64
+#define atomic_fcmpset_long atomic_fcmpset_64
#define atomic_clear_long atomic_clear_64
#define atomic_cmpset_long atomic_cmpset_64
#define atomic_fetchadd_long atomic_fetchadd_64
@@ -343,6 +402,7 @@ atomic_store_rel_64(volatile uint64_t *p
#define atomic_subtract_long atomic_subtract_64
#define atomic_add_ptr atomic_add_64
+#define atomic_fcmpset_ptr atomic_fcmpset_64
#define atomic_clear_ptr atomic_clear_64
#define atomic_cmpset_ptr atomic_cmpset_64
#define atomic_fetchadd_ptr atomic_fetchadd_64
@@ -352,6 +412,7 @@ atomic_store_rel_64(volatile uint64_t *p
#define atomic_subtract_ptr atomic_subtract_64
#define atomic_add_acq_long atomic_add_acq_64
+#define atomic_fcmpset_acq_long atomic_fcmpset_acq_64
#define atomic_clear_acq_long atomic_add_acq_64
#define atomic_cmpset_acq_long atomic_cmpset_acq_64
#define atomic_load_acq_long atomic_load_acq_64
@@ -359,6 +420,7 @@ atomic_store_rel_64(volatile uint64_t *p
#define atomic_subtract_acq_long atomic_subtract_acq_64
#define atomic_add_acq_ptr atomic_add_acq_64
+#define atomic_fcmpset_acq_ptr atomic_fcmpset_acq_64
#define atomic_clear_acq_ptr atomic_add_acq_64
#define atomic_cmpset_acq_ptr atomic_cmpset_acq_64
#define atomic_load_acq_ptr atomic_load_acq_64
@@ -366,6 +428,7 @@ atomic_store_rel_64(volatile uint64_t *p
#define atomic_subtract_acq_ptr atomic_subtract_acq_64
#define atomic_add_rel_long atomic_add_rel_64
+#define atomic_fcmpset_rel_long atomic_fcmpset_rel_64
#define atomic_clear_rel_long atomic_clear_rel_64
#define atomic_cmpset_rel_long atomic_cmpset_rel_64
#define atomic_set_rel_long atomic_set_rel_64
@@ -373,6 +436,7 @@ atomic_store_rel_64(volatile uint64_t *p
#define atomic_store_rel_long atomic_store_rel_64
#define atomic_add_rel_ptr atomic_add_rel_64
+#define atomic_fcmpset_rel_ptr atomic_fcmpset_rel_64
#define atomic_clear_rel_ptr atomic_clear_rel_64
#define atomic_cmpset_rel_ptr atomic_cmpset_rel_64
#define atomic_set_rel_ptr atomic_set_rel_64
More information about the svn-src-all
mailing list