svn commit: r315718 - in head: share/man/man9 sys/amd64/include sys/i386/include

Mark Johnston markj at FreeBSD.org
Wed Mar 22 17:29:06 UTC 2017


Author: markj
Date: Wed Mar 22 17:29:04 2017
New Revision: 315718
URL: https://svnweb.freebsd.org/changeset/base/315718

Log:
  Add support for 8- and 16-bit atomic_(f)cmpset to x86.
  
  Reviewed by:	kib
  MFC after:	2 weeks
  Differential Revision:	https://reviews.freebsd.org/D10068

Modified:
  head/share/man/man9/atomic.9
  head/sys/amd64/include/atomic.h
  head/sys/i386/include/atomic.h

Modified: head/share/man/man9/atomic.9
==============================================================================
--- head/share/man/man9/atomic.9	Wed Mar 22 17:28:53 2017	(r315717)
+++ head/share/man/man9/atomic.9	Wed Mar 22 17:29:04 2017	(r315718)
@@ -23,7 +23,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd Jan 3, 2017
+.Dd March 22, 2017
 .Dt ATOMIC 9
 .Os
 .Sh NAME
@@ -226,9 +226,9 @@ if (*dst == old) {
 .Ed
 .El
 .Pp
-The
+Some architectures do not implement the
 .Fn atomic_cmpset
-functions are not implemented for the types
+functions for the types
 .Dq Li char ,
 .Dq Li short ,
 .Dq Li 8 ,
@@ -265,9 +265,9 @@ function also returns
 despite
 .Dl *old == *dst .
 .Pp
-The
+Some architectures do not implement the
 .Fn atomic_fcmpset
-functions are not implemented for the types
+functions for the types
 .Dq Li char ,
 .Dq Li short ,
 .Dq Li 8 ,

Modified: head/sys/amd64/include/atomic.h
==============================================================================
--- head/sys/amd64/include/atomic.h	Wed Mar 22 17:28:53 2017	(r315717)
+++ head/sys/amd64/include/atomic.h	Wed Mar 22 17:29:04 2017	(r315718)
@@ -97,8 +97,13 @@
 void atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v);	\
 void atomic_##NAME##_barr_##TYPE(volatile u_##TYPE *p, u_##TYPE v)
 
+int	atomic_cmpset_char(volatile u_char *dst, u_char expect, u_char src);
+int	atomic_cmpset_short(volatile u_short *dst, u_short expect, u_short src);
 int	atomic_cmpset_int(volatile u_int *dst, u_int expect, u_int src);
 int	atomic_cmpset_long(volatile u_long *dst, u_long expect, u_long src);
+int	atomic_fcmpset_char(volatile u_char *dst, u_char *expect, u_char src);
+int	atomic_fcmpset_short(volatile u_short *dst, u_short *expect,
+	    u_short src);
 int	atomic_fcmpset_int(volatile u_int *dst, u_int *expect, u_int src);
 int	atomic_fcmpset_long(volatile u_long *dst, u_long *expect, u_long src);
 u_int	atomic_fetchadd_int(volatile u_int *p, u_int v);
@@ -155,84 +160,61 @@ atomic_##NAME##_barr_##TYPE(volatile u_#
 struct __hack
 
 /*
- * Atomic compare and set, used by the mutex functions
+ * Atomic compare and set, used by the mutex functions.
  *
- * if (*dst == expect) *dst = src (all 32 bit words)
+ * cmpset:
+ *	if (*dst == expect)
+ *		*dst = src
  *
- * Returns 0 on failure, non-zero on success
+ * fcmpset:
+ *	if (*dst == *expect)
+ *		*dst = src
+ *	else
+ *		*expect = *dst
+ *
+ * Returns 0 on failure, non-zero on success.
  */
-
-static __inline int
-atomic_cmpset_int(volatile u_int *dst, u_int expect, u_int src)
-{
-	u_char res;
-
-	__asm __volatile(
-	"	" MPLOCKED "		"
-	"	cmpxchgl %3,%1 ;	"
-	"       sete	%0 ;		"
-	"# atomic_cmpset_int"
-	: "=q" (res),			/* 0 */
-	  "+m" (*dst),			/* 1 */
-	  "+a" (expect)			/* 2 */
-	: "r" (src)			/* 3 */
-	: "memory", "cc");
-	return (res);
-}
-
-static __inline int
-atomic_cmpset_long(volatile u_long *dst, u_long expect, u_long src)
-{
-	u_char res;
-
-	__asm __volatile(
-	"	" MPLOCKED "		"
-	"	cmpxchgq %3,%1 ;	"
-	"       sete	%0 ;		"
-	"# atomic_cmpset_long"
-	: "=q" (res),			/* 0 */
-	  "+m" (*dst),			/* 1 */
-	  "+a" (expect)			/* 2 */
-	: "r" (src)			/* 3 */
-	: "memory", "cc");
-	return (res);
-}
-
-static __inline int
-atomic_fcmpset_int(volatile u_int *dst, u_int *expect, u_int src)
-{
-	u_char res;
-
-	__asm __volatile(
-	"	" MPLOCKED "		"
-	"	cmpxchgl %3,%1 ;	"
-	"       sete	%0 ;		"
-	"# atomic_fcmpset_int"
-	: "=r" (res),			/* 0 */
-	  "+m" (*dst),			/* 1 */
-	  "+a" (*expect)		/* 2 */
-	: "r" (src)			/* 3 */
-	: "memory", "cc");
-	return (res);
+#define	ATOMIC_CMPSET(TYPE)				\
+static __inline int					\
+atomic_cmpset_##TYPE(volatile u_##TYPE *dst, u_##TYPE expect, u_##TYPE src) \
+{							\
+	u_char res;					\
+							\
+	__asm __volatile(				\
+	"	" MPLOCKED "		"		\
+	"	cmpxchg %3,%1 ;	"			\
+	"	sete	%0 ;		"		\
+	"# atomic_cmpset_" #TYPE "	"		\
+	: "=q" (res),			/* 0 */		\
+	  "+m" (*dst),			/* 1 */		\
+	  "+a" (expect)			/* 2 */		\
+	: "r" (src)			/* 3 */		\
+	: "memory", "cc");				\
+	return (res);					\
+}							\
+							\
+static __inline int					\
+atomic_fcmpset_##TYPE(volatile u_##TYPE *dst, u_##TYPE *expect, u_##TYPE src) \
+{							\
+	u_char res;					\
+							\
+	__asm __volatile(				\
+	"	" MPLOCKED "		"		\
+	"	cmpxchg %3,%1 ;		"		\
+	"	sete	%0 ;		"		\
+	"# atomic_fcmpset_" #TYPE "	"		\
+	: "=q" (res),			/* 0 */		\
+	  "+m" (*dst),			/* 1 */		\
+	  "+a" (*expect)		/* 2 */		\
+	: "r" (src)			/* 3 */		\
+	: "memory", "cc");				\
+	return (res);					\
 }
 
-static __inline int
-atomic_fcmpset_long(volatile u_long *dst, u_long *expect, u_long src)
-{
-	u_char res;
-
-	__asm __volatile(
-	"	" MPLOCKED "		"
-	"	cmpxchgq %3,%1 ;	"
-	"       sete	%0 ;		"
-	"# atomic_fcmpset_long"
-	: "=r" (res),			/* 0 */
-	  "+m" (*dst),			/* 1 */
-	  "+a" (*expect)		/* 2 */
-	: "r" (src)			/* 3 */
-	: "memory", "cc");
-	return (res);
-}
+ATOMIC_CMPSET(char);
+ATOMIC_CMPSET(short);
+ATOMIC_CMPSET(int);
+ATOMIC_CMPSET(long);
 
 /*
  * Atomically add the value of v to the integer pointed to by p and return
@@ -522,6 +504,10 @@ u_long	atomic_swap_long(volatile u_long 
 #define	atomic_add_rel_char		atomic_add_barr_char
 #define	atomic_subtract_acq_char	atomic_subtract_barr_char
 #define	atomic_subtract_rel_char	atomic_subtract_barr_char
+#define	atomic_cmpset_acq_char		atomic_cmpset_char
+#define	atomic_cmpset_rel_char		atomic_cmpset_char
+#define	atomic_fcmpset_acq_char		atomic_fcmpset_char
+#define	atomic_fcmpset_rel_char		atomic_fcmpset_char
 
 #define	atomic_set_acq_short		atomic_set_barr_short
 #define	atomic_set_rel_short		atomic_set_barr_short
@@ -531,6 +517,10 @@ u_long	atomic_swap_long(volatile u_long 
 #define	atomic_add_rel_short		atomic_add_barr_short
 #define	atomic_subtract_acq_short	atomic_subtract_barr_short
 #define	atomic_subtract_rel_short	atomic_subtract_barr_short
+#define	atomic_cmpset_acq_short		atomic_cmpset_short
+#define	atomic_cmpset_rel_short		atomic_cmpset_short
+#define	atomic_fcmpset_acq_short	atomic_fcmpset_short
+#define	atomic_fcmpset_rel_short	atomic_fcmpset_short
 
 #define	atomic_set_acq_int		atomic_set_barr_int
 #define	atomic_set_rel_int		atomic_set_barr_int
@@ -542,8 +532,8 @@ u_long	atomic_swap_long(volatile u_long 
 #define	atomic_subtract_rel_int		atomic_subtract_barr_int
 #define	atomic_cmpset_acq_int		atomic_cmpset_int
 #define	atomic_cmpset_rel_int		atomic_cmpset_int
-#define	atomic_fcmpset_acq_int	atomic_fcmpset_int
-#define	atomic_fcmpset_rel_int	atomic_fcmpset_int
+#define	atomic_fcmpset_acq_int		atomic_fcmpset_int
+#define	atomic_fcmpset_rel_int		atomic_fcmpset_int
 
 #define	atomic_set_acq_long		atomic_set_barr_long
 #define	atomic_set_rel_long		atomic_set_barr_long
@@ -555,8 +545,8 @@ u_long	atomic_swap_long(volatile u_long 
 #define	atomic_subtract_rel_long	atomic_subtract_barr_long
 #define	atomic_cmpset_acq_long		atomic_cmpset_long
 #define	atomic_cmpset_rel_long		atomic_cmpset_long
-#define	atomic_fcmpset_acq_long	atomic_fcmpset_long
-#define	atomic_fcmpset_rel_long	atomic_fcmpset_long
+#define	atomic_fcmpset_acq_long		atomic_fcmpset_long
+#define	atomic_fcmpset_rel_long		atomic_fcmpset_long
 
 #define	atomic_readandclear_int(p)	atomic_swap_int(p, 0)
 #define	atomic_readandclear_long(p)	atomic_swap_long(p, 0)
@@ -576,6 +566,12 @@ u_long	atomic_swap_long(volatile u_long 
 #define	atomic_subtract_rel_8	atomic_subtract_rel_char
 #define	atomic_load_acq_8	atomic_load_acq_char
 #define	atomic_store_rel_8	atomic_store_rel_char
+#define	atomic_cmpset_8		atomic_cmpset_char
+#define	atomic_cmpset_acq_8	atomic_cmpset_acq_char
+#define	atomic_cmpset_rel_8	atomic_cmpset_rel_char
+#define	atomic_fcmpset_8	atomic_fcmpset_char
+#define	atomic_fcmpset_acq_8	atomic_fcmpset_acq_char
+#define	atomic_fcmpset_rel_8	atomic_fcmpset_rel_char
 
 /* Operations on 16-bit words. */
 #define	atomic_set_16		atomic_set_short
@@ -592,6 +588,12 @@ u_long	atomic_swap_long(volatile u_long 
 #define	atomic_subtract_rel_16	atomic_subtract_rel_short
 #define	atomic_load_acq_16	atomic_load_acq_short
 #define	atomic_store_rel_16	atomic_store_rel_short
+#define	atomic_cmpset_16	atomic_cmpset_short
+#define	atomic_cmpset_acq_16	atomic_cmpset_acq_short
+#define	atomic_cmpset_rel_16	atomic_cmpset_rel_short
+#define	atomic_fcmpset_16	atomic_fcmpset_short
+#define	atomic_fcmpset_acq_16	atomic_fcmpset_acq_short
+#define	atomic_fcmpset_rel_16	atomic_fcmpset_rel_short
 
 /* Operations on 32-bit double words. */
 #define	atomic_set_32		atomic_set_int

Modified: head/sys/i386/include/atomic.h
==============================================================================
--- head/sys/i386/include/atomic.h	Wed Mar 22 17:28:53 2017	(r315717)
+++ head/sys/i386/include/atomic.h	Wed Mar 22 17:29:04 2017	(r315718)
@@ -105,7 +105,12 @@ __mbu(void)
 void atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v);	\
 void atomic_##NAME##_barr_##TYPE(volatile u_##TYPE *p, u_##TYPE v)
 
+int	atomic_cmpset_char(volatile u_char *dst, u_char expect, u_char src);
+int	atomic_cmpset_short(volatile u_short *dst, u_short expect, u_short src);
 int	atomic_cmpset_int(volatile u_int *dst, u_int expect, u_int src);
+int	atomic_fcmpset_char(volatile u_char *dst, u_char *expect, u_char src);
+int	atomic_fcmpset_short(volatile u_short *dst, u_short *expect,
+	    u_short src);
 int	atomic_fcmpset_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);
@@ -163,48 +168,60 @@ atomic_##NAME##_barr_##TYPE(volatile u_#
 struct __hack
 
 /*
- * Atomic compare and set, used by the mutex functions
+ * Atomic compare and set, used by the mutex functions.
  *
- * if (*dst == expect) *dst = src (all 32 bit words)
+ * cmpset:
+ *	if (*dst == expect)
+ *		*dst = src
  *
- * Returns 0 on failure, non-zero on success
+ * fcmpset:
+ *	if (*dst == *expect)
+ *		*dst = src
+ *	else
+ *		*expect = *dst
+ *
+ * Returns 0 on failure, non-zero on success.
  */
-
-static __inline int
-atomic_cmpset_int(volatile u_int *dst, u_int expect, u_int src)
-{
-	u_char res;
-
-	__asm __volatile(
-	"	" MPLOCKED "		"
-	"	cmpxchgl %3,%1 ;	"
-	"       sete	%0 ;		"
-	"# atomic_cmpset_int"
-	: "=q" (res),			/* 0 */
-	  "+m" (*dst),			/* 1 */
-	  "+a" (expect)			/* 2 */
-	: "r" (src)			/* 3 */
-	: "memory", "cc");
-	return (res);
+#define	ATOMIC_CMPSET(TYPE)				\
+static __inline int					\
+atomic_cmpset_##TYPE(volatile u_##TYPE *dst, u_##TYPE expect, u_##TYPE src) \
+{							\
+	u_char res;					\
+							\
+	__asm __volatile(				\
+	"	" MPLOCKED "		"		\
+	"	cmpxchg	%3,%1 ;		"		\
+	"	sete	%0 ;		"		\
+	"# atomic_cmpset_" #TYPE "	"		\
+	: "=q" (res),			/* 0 */		\
+	  "+m" (*dst),			/* 1 */		\
+	  "+a" (expect)			/* 2 */		\
+	: "r" (src)			/* 3 */		\
+	: "memory", "cc");				\
+	return (res);					\
+}							\
+							\
+static __inline int					\
+atomic_fcmpset_##TYPE(volatile u_##TYPE *dst, u_##TYPE *expect, u_##TYPE src) \
+{							\
+	u_char res;					\
+							\
+	__asm __volatile(				\
+	"	" MPLOCKED "		"		\
+	"	cmpxchg	%3,%1 ;		"		\
+	"	sete	%0 ;		"		\
+	"# atomic_fcmpset_" #TYPE "	"		\
+	: "=q" (res),			/* 0 */		\
+	  "+m" (*dst),			/* 1 */		\
+	  "+a" (*expect)		/* 2 */		\
+	: "r" (src)			/* 3 */		\
+	: "memory", "cc");				\
+	return (res);					\
 }
 
-static __inline int
-atomic_fcmpset_int(volatile u_int *dst, u_int *expect, u_int src)
-{
-	u_char res;
-
-	__asm __volatile(
-	"	" MPLOCKED "		"
-	"	cmpxchgl %3,%1 ;	"
-	"       sete	%0 ;		"
-	"# atomic_cmpset_int"
-	: "=q" (res),			/* 0 */
-	  "+m" (*dst),			/* 1 */
-	  "+a" (*expect)		/* 2 */
-	: "r" (src)			/* 3 */
-	: "memory", "cc");
-	return (res);
-}
+ATOMIC_CMPSET(char);
+ATOMIC_CMPSET(short);
+ATOMIC_CMPSET(int);
 
 /*
  * Atomically add the value of v to the integer pointed to by p and return
@@ -654,6 +671,10 @@ u_long	atomic_swap_long(volatile u_long 
 #define	atomic_add_rel_char		atomic_add_barr_char
 #define	atomic_subtract_acq_char	atomic_subtract_barr_char
 #define	atomic_subtract_rel_char	atomic_subtract_barr_char
+#define	atomic_cmpset_acq_char		atomic_cmpset_char
+#define	atomic_cmpset_rel_char		atomic_cmpset_char
+#define	atomic_fcmpset_acq_char		atomic_fcmpset_char
+#define	atomic_fcmpset_rel_char		atomic_fcmpset_char
 
 #define	atomic_set_acq_short		atomic_set_barr_short
 #define	atomic_set_rel_short		atomic_set_barr_short
@@ -663,6 +684,10 @@ u_long	atomic_swap_long(volatile u_long 
 #define	atomic_add_rel_short		atomic_add_barr_short
 #define	atomic_subtract_acq_short	atomic_subtract_barr_short
 #define	atomic_subtract_rel_short	atomic_subtract_barr_short
+#define	atomic_cmpset_acq_short		atomic_cmpset_short
+#define	atomic_cmpset_rel_short		atomic_cmpset_short
+#define	atomic_fcmpset_acq_short	atomic_fcmpset_short
+#define	atomic_fcmpset_rel_short	atomic_fcmpset_short
 
 #define	atomic_set_acq_int		atomic_set_barr_int
 #define	atomic_set_rel_int		atomic_set_barr_int
@@ -708,6 +733,12 @@ u_long	atomic_swap_long(volatile u_long 
 #define	atomic_subtract_rel_8	atomic_subtract_rel_char
 #define	atomic_load_acq_8	atomic_load_acq_char
 #define	atomic_store_rel_8	atomic_store_rel_char
+#define	atomic_cmpset_8		atomic_cmpset_char
+#define	atomic_cmpset_acq_8	atomic_cmpset_acq_char
+#define	atomic_cmpset_rel_8	atomic_cmpset_rel_char
+#define	atomic_fcmpset_8	atomic_fcmpset_char
+#define	atomic_fcmpset_acq_8	atomic_fcmpset_acq_char
+#define	atomic_fcmpset_rel_8	atomic_fcmpset_rel_char
 
 /* Operations on 16-bit words. */
 #define	atomic_set_16		atomic_set_short
@@ -724,6 +755,12 @@ u_long	atomic_swap_long(volatile u_long 
 #define	atomic_subtract_rel_16	atomic_subtract_rel_short
 #define	atomic_load_acq_16	atomic_load_acq_short
 #define	atomic_store_rel_16	atomic_store_rel_short
+#define	atomic_cmpset_16	atomic_cmpset_short
+#define	atomic_cmpset_acq_16	atomic_cmpset_acq_short
+#define	atomic_cmpset_rel_16	atomic_cmpset_rel_short
+#define	atomic_fcmpset_16	atomic_fcmpset_short
+#define	atomic_fcmpset_acq_16	atomic_fcmpset_acq_short
+#define	atomic_fcmpset_rel_16	atomic_fcmpset_rel_short
 
 /* Operations on 32-bit double words. */
 #define	atomic_set_32		atomic_set_int


More information about the svn-src-all mailing list