diff options
author | mjg <mjg@FreeBSD.org> | 2017-03-16 06:00:27 +0000 |
---|---|---|
committer | mjg <mjg@FreeBSD.org> | 2017-03-16 06:00:27 +0000 |
commit | b8af6b78be197b6a24bf372442dcb6e044d729b3 (patch) | |
tree | 0496f4e01ec297971a9b02afb62b80c63b0dd969 /sys/amd64/include/atomic.h | |
parent | 3100d6f6dfd7bea82a2fe7136cf72d8423b715bd (diff) | |
download | FreeBSD-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/amd64/include/atomic.h')
-rw-r--r-- | sys/amd64/include/atomic.h | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/sys/amd64/include/atomic.h b/sys/amd64/include/atomic.h index c9526f4..09a5f9c 100644 --- a/sys/amd64/include/atomic.h +++ b/sys/amd64/include/atomic.h @@ -99,6 +99,8 @@ 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_cmpset_long(volatile u_long *dst, u_long expect, u_long src); +int atomic_fcmpset_int(volatile u_int *dst, u_int *expect, u_int src); +int atomic_fcmpset_long(volatile u_long *dst, u_long *expect, u_long src); u_int atomic_fetchadd_int(volatile u_int *p, u_int v); u_long atomic_fetchadd_long(volatile u_long *p, u_long v); int atomic_testandset_int(volatile u_int *p, u_int v); @@ -196,6 +198,42 @@ atomic_cmpset_long(volatile u_long *dst, u_long expect, u_long 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_fcmpset_int" + : "=r" (res), /* 0 */ + "+m" (*dst), /* 1 */ + "+a" (*expect) /* 2 */ + : "r" (src) /* 3 */ + : "memory", "cc"); + return (res); +} + +static __inline int +atomic_fcmpset_long(volatile u_long *dst, u_long *expect, u_long src) +{ + u_char res; + + __asm __volatile( + " " MPLOCKED " " + " cmpxchgq %3,%1 ; " + " sete %0 ; " + "# atomic_fcmpset_long" + : "=r" (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. @@ -504,6 +542,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 @@ -515,6 +555,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) @@ -569,6 +611,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 @@ -593,6 +638,9 @@ u_long atomic_swap_long(volatile u_long *p, u_long v); #define atomic_cmpset_64 atomic_cmpset_long #define atomic_cmpset_acq_64 atomic_cmpset_acq_long #define atomic_cmpset_rel_64 atomic_cmpset_rel_long +#define atomic_fcmpset_64 atomic_fcmpset_long +#define atomic_fcmpset_acq_64 atomic_fcmpset_acq_long +#define atomic_fcmpset_rel_64 atomic_fcmpset_rel_long #define atomic_swap_64 atomic_swap_long #define atomic_readandclear_64 atomic_readandclear_long #define atomic_fetchadd_64 atomic_fetchadd_long @@ -617,6 +665,9 @@ u_long atomic_swap_long(volatile u_long *p, u_long v); #define atomic_cmpset_ptr atomic_cmpset_long #define atomic_cmpset_acq_ptr atomic_cmpset_acq_long #define atomic_cmpset_rel_ptr atomic_cmpset_rel_long +#define atomic_fcmpset_ptr atomic_fcmpset_long +#define atomic_fcmpset_acq_ptr atomic_fcmpset_acq_long +#define atomic_fcmpset_rel_ptr atomic_fcmpset_rel_long #define atomic_swap_ptr atomic_swap_long #define atomic_readandclear_ptr atomic_readandclear_long |