svn commit: r302108 - in stable/10: share/man/man9 sys/amd64/include sys/i386/include
Sepherosa Ziehau
sephe at FreeBSD.org
Thu Jun 23 02:21:38 UTC 2016
Author: sephe
Date: Thu Jun 23 02:21:37 2016
New Revision: 302108
URL: https://svnweb.freebsd.org/changeset/base/302108
Log:
MFC 299912
atomic: Add testandclear on i386/amd64
Reviewed by: kib
Sponsored by: Microsoft OSTC
Differential Revision: https://reviews.freebsd.org/D6381
Modified:
stable/10/share/man/man9/atomic.9
stable/10/sys/amd64/include/atomic.h
stable/10/sys/i386/include/atomic.h
Directory Properties:
stable/10/ (props changed)
Modified: stable/10/share/man/man9/atomic.9
==============================================================================
--- stable/10/share/man/man9/atomic.9 Thu Jun 23 01:47:30 2016 (r302107)
+++ stable/10/share/man/man9/atomic.9 Thu Jun 23 02:21:37 2016 (r302108)
@@ -23,7 +23,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd August 14, 2015
+.Dd May 12, 2016
.Dt ATOMIC 9
.Os
.Sh NAME
@@ -65,6 +65,8 @@
.Ft <type>
.Fn atomic_swap_<type> "volatile <type> *p" "<type> v"
.Ft int
+.Fn atomic_testandclear_<type> "volatile <type> *p" "u_int v"
+.Ft int
.Fn atomic_testandset_<type> "volatile <type> *p" "u_int v"
.Sh DESCRIPTION
Each of the atomic operations is guaranteed to be atomic across multiple
@@ -313,6 +315,15 @@ and
.Dq Li 16
and do not have any variants with memory barriers at this time.
.Bl -hang
+.It Fn atomic_testandclear p v
+.Bd -literal -compact
+bit = 1 << (v % (sizeof(*p) * NBBY));
+tmp = (*p & bit) != 0;
+*p &= ~bit;
+return (tmp);
+.Ed
+.El
+.Bl -hang
.It Fn atomic_testandset p v
.Bd -literal -compact
bit = 1 << (v % (sizeof(*p) * NBBY));
@@ -324,6 +335,8 @@ return (tmp);
.Pp
The
.Fn atomic_testandset
+and
+.Fn atomic_testandclear
functions are only implemented for the types
.Dq Li int ,
.Dq Li long
@@ -352,6 +365,8 @@ and
functions return the value at the specified address.
The
.Fn atomic_testandset
+and
+.Fn atomic_testandclear
function returns the result of the test operation.
.Sh EXAMPLES
This example uses the
@@ -429,3 +444,6 @@ and
.Fn atomic_testandset
operations were added in
.Fx 10.0 .
+.Fn atomic_testandclear
+operation was added in
+.Fx 11.0 .
Modified: stable/10/sys/amd64/include/atomic.h
==============================================================================
--- stable/10/sys/amd64/include/atomic.h Thu Jun 23 01:47:30 2016 (r302107)
+++ stable/10/sys/amd64/include/atomic.h Thu Jun 23 02:21:37 2016 (r302108)
@@ -84,6 +84,8 @@ u_int atomic_fetchadd_int(volatile u_int
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 *
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
#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
#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
Modified: stable/10/sys/i386/include/atomic.h
==============================================================================
--- stable/10/sys/i386/include/atomic.h Thu Jun 23 01:47:30 2016 (r302107)
+++ stable/10/sys/i386/include/atomic.h Thu Jun 23 02:21:37 2016 (r302108)
@@ -86,6 +86,7 @@ void atomic_##NAME##_barr_##TYPE(volatil
int atomic_cmpset_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);
#define ATOMIC_LOAD(TYPE, LOP) \
u_##TYPE atomic_load_acq_##TYPE(volatile u_##TYPE *p)
@@ -224,6 +225,23 @@ atomic_testandset_int(volatile u_int *p,
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);
+}
+
/*
* We assume that a = b will do atomic loads and stores. Due to the
* IA32 memory model, a simple store guarantees release semantics.
@@ -549,6 +567,13 @@ atomic_testandset_long(volatile u_long *
return (atomic_testandset_int((volatile u_int *)p, v));
}
+static __inline int
+atomic_testandclear_long(volatile u_long *p, u_int v)
+{
+
+ return (atomic_testandclear_int((volatile u_int *)p, v));
+}
+
/* Read the current value and store a new value in the destination. */
#ifdef __GNUCLIKE_ASM
@@ -675,6 +700,7 @@ u_long atomic_swap_long(volatile u_long
#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 pointers. */
#define atomic_set_ptr(p, v) \
More information about the svn-src-all
mailing list