svn commit: r253875 - in projects/atomic64/sys: amd64/include i386/include
Jung-uk Kim
jkim at FreeBSD.org
Thu Aug 1 23:51:21 UTC 2013
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) \
More information about the svn-src-projects
mailing list