Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 23 Jun 2016 02:21:37 +0000 (UTC)
From:      Sepherosa Ziehau <sephe@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r302108 - in stable/10: share/man/man9 sys/amd64/include sys/i386/include
Message-ID:  <201606230221.u5N2Lbtp010582@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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) \



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201606230221.u5N2Lbtp010582>