From ee9748f41f5818197d95b210279c755ad824dba7 Mon Sep 17 00:00:00 2001 From: sephe Date: Thu, 23 Jun 2016 02:21:37 +0000 Subject: MFC 299912 atomic: Add testandclear on i386/amd64 Reviewed by: kib Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D6381 --- sys/amd64/include/atomic.h | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'sys/amd64') diff --git a/sys/amd64/include/atomic.h b/sys/amd64/include/atomic.h index bb93835..cdcc7b8 100644 --- a/sys/amd64/include/atomic.h +++ b/sys/amd64/include/atomic.h @@ -84,6 +84,8 @@ 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); int atomic_testandset_long(volatile u_long *p, u_int v); +int atomic_testandclear_int(volatile u_int *p, u_int v); +int atomic_testandclear_long(volatile u_long *p, u_int v); #define ATOMIC_LOAD(TYPE, LOP) \ u_##TYPE atomic_load_acq_##TYPE(volatile u_##TYPE *p) @@ -241,6 +243,40 @@ atomic_testandset_long(volatile u_long *p, u_int v) return (res); } +static __inline int +atomic_testandclear_int(volatile u_int *p, u_int v) +{ + u_char res; + + __asm __volatile( + " " MPLOCKED " " + " btrl %2,%1 ; " + " setc %0 ; " + "# atomic_testandclear_int" + : "=q" (res), /* 0 */ + "+m" (*p) /* 1 */ + : "Ir" (v & 0x1f) /* 2 */ + : "cc"); + return (res); +} + +static __inline int +atomic_testandclear_long(volatile u_long *p, u_int v) +{ + u_char res; + + __asm __volatile( + " " MPLOCKED " " + " btrq %2,%1 ; " + " setc %0 ; " + "# atomic_testandclear_long" + : "=q" (res), /* 0 */ + "+m" (*p) /* 1 */ + : "Jr" ((u_long)(v & 0x3f)) /* 2 */ + : "cc"); + return (res); +} + /* * We assume that a = b will do atomic loads and stores. Due to the * IA32 memory model, a simple store guarantees release semantics. @@ -462,6 +498,7 @@ u_long atomic_swap_long(volatile u_long *p, u_long v); #define atomic_readandclear_32 atomic_readandclear_int #define atomic_fetchadd_32 atomic_fetchadd_int #define atomic_testandset_32 atomic_testandset_int +#define atomic_testandclear_32 atomic_testandclear_int /* Operations on 64-bit quad words. */ #define atomic_set_64 atomic_set_long @@ -485,6 +522,7 @@ u_long atomic_swap_long(volatile u_long *p, u_long v); #define atomic_readandclear_64 atomic_readandclear_long #define atomic_fetchadd_64 atomic_fetchadd_long #define atomic_testandset_64 atomic_testandset_long +#define atomic_testandclear_64 atomic_testandclear_long /* Operations on pointers. */ #define atomic_set_ptr atomic_set_long -- cgit v1.1