Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 1 Aug 2013 23:51:20 +0000 (UTC)
From:      Jung-uk Kim <jkim@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r253875 - in projects/atomic64/sys: amd64/include i386/include
Message-ID:  <201308012351.r71NpKxk092536@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jkim
Date: Thu Aug  1 23:51:20 2013
New Revision: 253875
URL: http://svnweb.freebsd.org/changeset/base/253875

Log:
  Add a new atomic operation atomic_testandset for x86.  This operation
  atomically tests and sets a bit, i. e.,
  
  	tmp = (*p & v) != 0; *p |= v; return (tmp)
  
  where
  
  	v = (<type>)1 << s % (sizeof(<type>) * NBBY)

Modified:
  projects/atomic64/sys/amd64/include/atomic.h
  projects/atomic64/sys/i386/include/atomic.h

Modified: projects/atomic64/sys/amd64/include/atomic.h
==============================================================================
--- projects/atomic64/sys/amd64/include/atomic.h	Thu Aug  1 23:38:57 2013	(r253874)
+++ projects/atomic64/sys/amd64/include/atomic.h	Thu Aug  1 23:51:20 2013	(r253875)
@@ -82,6 +82,8 @@ int	atomic_cmpset_int(volatile u_int *ds
 int	atomic_cmpset_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, int v);
+int	atomic_testandset_long(volatile u_long *p, int v);
 
 #define	ATOMIC_LOAD(TYPE, LOP)					\
 u_##TYPE	atomic_load_acq_##TYPE(volatile u_##TYPE *p)
@@ -211,6 +213,42 @@ atomic_fetchadd_long(volatile u_long *p,
 	return (v);
 }
 
+static __inline int
+atomic_testandset_int(volatile u_int *p, int v)
+{
+	u_char res;
+
+	__asm __volatile(
+	"	" MPLOCKED "		"
+	"	btsl	%2, %1 ;	"
+	"	setc	%0 ;		"
+	"# atomic_testandset_int"
+	: "=r" (res),			/* 0 */
+	  "=m" (*p)			/* 1 */
+	: "r" (v),			/* 2 */
+	  "m" (*p)			/* 3 */
+	: "cc");
+	return (res);
+}
+
+static __inline int
+atomic_testandset_long(volatile u_long *p, int v)
+{
+	u_char res;
+
+	__asm __volatile(
+	"	" MPLOCKED "		"
+	"	btsq	%2, %1 ;	"
+	"	setc	%0 ;		"
+	"# atomic_testandset_long"
+	: "=r" (res),			/* 0 */
+	  "=m" (*p)			/* 1 */
+	: "r" ((u_long)v),		/* 2 */
+	  "m" (*p)			/* 3 */
+	: "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.
@@ -435,6 +473,7 @@ u_long	atomic_swap_long(volatile u_long 
 #define	atomic_swap_32		atomic_swap_int
 #define	atomic_readandclear_32	atomic_readandclear_int
 #define	atomic_fetchadd_32	atomic_fetchadd_int
+#define	atomic_testandset_32	atomic_testandset_int
 
 /* Operations on 64-bit quad words. */
 #define	atomic_set_64		atomic_set_long
@@ -456,6 +495,7 @@ u_long	atomic_swap_long(volatile u_long 
 #define	atomic_cmpset_rel_64	atomic_cmpset_rel_long
 #define	atomic_swap_64		atomic_swap_long
 #define	atomic_readandclear_64	atomic_readandclear_long
+#define	atomic_testandset_64	atomic_testandset_long
 
 /* Operations on pointers. */
 #define	atomic_set_ptr		atomic_set_long

Modified: projects/atomic64/sys/i386/include/atomic.h
==============================================================================
--- projects/atomic64/sys/i386/include/atomic.h	Thu Aug  1 23:38:57 2013	(r253874)
+++ projects/atomic64/sys/i386/include/atomic.h	Thu Aug  1 23:51:20 2013	(r253875)
@@ -80,6 +80,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, int v);
 
 #define	ATOMIC_LOAD(TYPE, LOP)					\
 u_##TYPE	atomic_load_acq_##TYPE(volatile u_##TYPE *p)
@@ -282,6 +283,24 @@ atomic_fetchadd_int(volatile u_int *p, u
 	return (v);
 }
 
+static __inline int
+atomic_testandset_int(volatile u_int *p, int v)
+{
+	u_char res;
+
+	__asm __volatile(
+	"	" MPLOCKED "		"
+	"	btsl	%2, %1 ;	"
+	"	setc	%0 ;		"
+	"# atomic_testandset_int"
+	: "=r" (res),			/* 0 (result) */
+	  "=m" (*p)			/* 1 */
+	: "r" (v),			/* 2 */
+	  "m" (*p)			/* 3 */
+	: "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.
@@ -394,6 +413,13 @@ atomic_fetchadd_long(volatile u_long *p,
 	return (atomic_fetchadd_int((volatile u_int *)p, (u_int)v));
 }
 
+static __inline int
+atomic_testandset_long(volatile u_long *p, int v)
+{
+
+	return (atomic_testandset_int((volatile u_int *)p, v));
+}
+
 /* Read the current value and store a new value in the destination. */
 #ifdef __GNUCLIKE_ASM
 
@@ -520,6 +546,7 @@ u_long	atomic_swap_long(volatile u_long 
 #define	atomic_swap_32		atomic_swap_int
 #define	atomic_readandclear_32	atomic_readandclear_int
 #define	atomic_fetchadd_32	atomic_fetchadd_int
+#define	atomic_testandset_32	atomic_testandset_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?201308012351.r71NpKxk092536>