summaryrefslogtreecommitdiffstats
path: root/sys/i386
diff options
context:
space:
mode:
authormjg <mjg@FreeBSD.org>2017-03-16 06:00:27 +0000
committermjg <mjg@FreeBSD.org>2017-03-16 06:00:27 +0000
commitb8af6b78be197b6a24bf372442dcb6e044d729b3 (patch)
tree0496f4e01ec297971a9b02afb62b80c63b0dd969 /sys/i386
parent3100d6f6dfd7bea82a2fe7136cf72d8423b715bd (diff)
downloadFreeBSD-src-b8af6b78be197b6a24bf372442dcb6e044d729b3.zip
FreeBSD-src-b8af6b78be197b6a24bf372442dcb6e044d729b3.tar.gz
MFC r311169,r311898,r312925,r312973,r312975,r313007,r313040,r313080,
r313254,r313341 amd64: add atomic_fcmpset == sparc64: add atomic_fcmpset == Implement atomic_fcmpset_* for arm and arm64. == Add atomic_fcmpset_*() inlines for powerpc Summary: atomic_fcmpset_*() is analogous to atomic_cmpset(), but saves off the read value from the target memory location into the 'old' pointer in the case of failure. == i386: add atomic_fcmpset == Don't retry a lost reservation in atomic_fcmpset() The desired behavior of atomic_fcmpset_() is to always exit on error. Instead of retrying on lost reservation, leave the retry to the caller, and return == Add atomic_fcmpset_*() inlines for MIPS atomic_fcmpset_*() is analogous to atomic_cmpset(), but saves off the read value from the target memory location into the 'old' pointer. == i386: fixup fcmpset An incorrect output specifier was used which worked with clang by accident, but breaks with the in-tree gcc version. While here plug a whitespace nit. == Implement atomic_fcmpset_*() for RISC-V. == Use 64bit store instruction in atomic_fcmpset_64.
Diffstat (limited to 'sys/i386')
-rw-r--r--sys/i386/include/atomic.h34
1 files changed, 34 insertions, 0 deletions
diff --git a/sys/i386/include/atomic.h b/sys/i386/include/atomic.h
index e92e94b..cb1b6a3 100644
--- a/sys/i386/include/atomic.h
+++ b/sys/i386/include/atomic.h
@@ -106,6 +106,7 @@ void atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v); \
void atomic_##NAME##_barr_##TYPE(volatile u_##TYPE *p, u_##TYPE v)
int atomic_cmpset_int(volatile u_int *dst, u_int expect, u_int src);
+int atomic_fcmpset_int(volatile u_int *dst, u_int *expect, u_int src);
u_int atomic_fetchadd_int(volatile u_int *p, u_int v);
int atomic_testandset_int(volatile u_int *p, u_int v);
int atomic_testandclear_int(volatile u_int *p, u_int v);
@@ -187,6 +188,24 @@ atomic_cmpset_int(volatile u_int *dst, u_int expect, u_int src)
return (res);
}
+static __inline int
+atomic_fcmpset_int(volatile u_int *dst, u_int *expect, u_int src)
+{
+ u_char res;
+
+ __asm __volatile(
+ " " MPLOCKED " "
+ " cmpxchgl %3,%1 ; "
+ " sete %0 ; "
+ "# atomic_cmpset_int"
+ : "=q" (res), /* 0 */
+ "+m" (*dst), /* 1 */
+ "+a" (*expect) /* 2 */
+ : "r" (src) /* 3 */
+ : "memory", "cc");
+ return (res);
+}
+
/*
* Atomically add the value of v to the integer pointed to by p and return
* the previous value of *p.
@@ -655,6 +674,8 @@ u_long atomic_swap_long(volatile u_long *p, u_long v);
#define atomic_subtract_rel_int atomic_subtract_barr_int
#define atomic_cmpset_acq_int atomic_cmpset_int
#define atomic_cmpset_rel_int atomic_cmpset_int
+#define atomic_fcmpset_acq_int atomic_fcmpset_int
+#define atomic_fcmpset_rel_int atomic_fcmpset_int
#define atomic_set_acq_long atomic_set_barr_long
#define atomic_set_rel_long atomic_set_barr_long
@@ -666,6 +687,8 @@ u_long atomic_swap_long(volatile u_long *p, u_long v);
#define atomic_subtract_rel_long atomic_subtract_barr_long
#define atomic_cmpset_acq_long atomic_cmpset_long
#define atomic_cmpset_rel_long atomic_cmpset_long
+#define atomic_fcmpset_acq_long atomic_fcmpset_long
+#define atomic_fcmpset_rel_long atomic_fcmpset_long
#define atomic_readandclear_int(p) atomic_swap_int(p, 0)
#define atomic_readandclear_long(p) atomic_swap_long(p, 0)
@@ -720,6 +743,9 @@ u_long atomic_swap_long(volatile u_long *p, u_long v);
#define atomic_cmpset_32 atomic_cmpset_int
#define atomic_cmpset_acq_32 atomic_cmpset_acq_int
#define atomic_cmpset_rel_32 atomic_cmpset_rel_int
+#define atomic_fcmpset_32 atomic_fcmpset_int
+#define atomic_fcmpset_acq_32 atomic_fcmpset_acq_int
+#define atomic_fcmpset_rel_32 atomic_fcmpset_rel_int
#define atomic_swap_32 atomic_swap_int
#define atomic_readandclear_32 atomic_readandclear_int
#define atomic_fetchadd_32 atomic_fetchadd_int
@@ -763,6 +789,14 @@ u_long atomic_swap_long(volatile u_long *p, u_long v);
#define atomic_cmpset_rel_ptr(dst, old, new) \
atomic_cmpset_rel_int((volatile u_int *)(dst), (u_int)(old), \
(u_int)(new))
+#define atomic_fcmpset_ptr(dst, old, new) \
+ atomic_fcmpset_int((volatile u_int *)(dst), (u_int *)(old), (u_int)(new))
+#define atomic_fcmpset_acq_ptr(dst, old, new) \
+ atomic_fcmpset_acq_int((volatile u_int *)(dst), (u_int *)(old), \
+ (u_int)(new))
+#define atomic_fcmpset_rel_ptr(dst, old, new) \
+ atomic_fcmpset_rel_int((volatile u_int *)(dst), (u_int *)(old), \
+ (u_int)(new))
#define atomic_swap_ptr(p, v) \
atomic_swap_int((volatile u_int *)(p), (u_int)(v))
#define atomic_readandclear_ptr(p) \
OpenPOWER on IntegriCloud