Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 30 Jan 2017 02:15:54 +0000 (UTC)
From:      Justin Hibbits <jhibbits@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r312973 - head/sys/powerpc/include
Message-ID:  <201701300215.v0U2Fsl0006455@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhibbits
Date: Mon Jan 30 02:15:54 2017
New Revision: 312973
URL: https://svnweb.freebsd.org/changeset/base/312973

Log:
  Add atomic_fcmpset_*() inlines for powerpc
  
  Summary:
  atomic_fcmpset_*() is analogous to atomic_cmpset(), but saves off the read value
  from the target memory location into the 'old' pointer in the case of failure.
  
  Requested by:	 mjg
  Differential Revision: https://reviews.freebsd.org/D9325

Modified:
  head/sys/powerpc/include/atomic.h

Modified: head/sys/powerpc/include/atomic.h
==============================================================================
--- head/sys/powerpc/include/atomic.h	Mon Jan 30 01:11:30 2017	(r312972)
+++ head/sys/powerpc/include/atomic.h	Mon Jan 30 02:15:54 2017	(r312973)
@@ -674,6 +674,129 @@ atomic_cmpset_rel_long(volatile u_long *
 #define	atomic_cmpset_rel_ptr	atomic_cmpset_rel_int
 #endif
 
+/*
+ * Atomically compare the value stored at *p with *cmpval and if the
+ * two values are equal, update the value of *p with newval. Returns
+ * zero if the compare failed and sets *cmpval to the read value from *p,
+ * nonzero otherwise.
+ */
+static __inline int
+atomic_fcmpset_int(volatile u_int *p, u_int *cmpval, u_int newval)
+{
+	int	ret;
+
+#ifdef __GNUCLIKE_ASM
+	__asm __volatile (
+		"1:\tlwarx %0, 0, %3\n\t"	/* load old value */
+		"cmplw %4, %0\n\t"		/* compare */
+		"bne 2f\n\t"			/* exit if not equal */
+		"stwcx. %5, 0, %3\n\t"      	/* attempt to store */
+		"bne- 1b\n\t"			/* spin if failed */
+		"li %0, 1\n\t"			/* success - retval = 1 */
+		"b 3f\n\t"			/* we've succeeded */
+		"2:\n\t"
+		"stwcx. %0, 0, %3\n\t"       	/* clear reservation (74xx) */
+		"stwx %0, 0, %7\n\t"
+		"li %0, 0\n\t"			/* failure - retval = 0 */
+		"3:\n\t"
+		: "=&r" (ret), "=m" (*p), "=m" (*cmpval)
+		: "r" (p), "r" (*cmpval), "r" (newval), "m" (*p), "r"(cmpval)
+		: "cr0", "memory");
+#endif
+
+	return (ret);
+}
+static __inline int
+atomic_fcmpset_long(volatile u_long *p, u_long *cmpval, u_long newval)
+{
+	int ret;
+
+#ifdef __GNUCLIKE_ASM
+	__asm __volatile (
+	    #ifdef __powerpc64__
+		"1:\tldarx %0, 0, %3\n\t"	/* load old value */
+		"cmpld %4, %0\n\t"		/* compare */
+		"bne 2f\n\t"			/* exit if not equal */
+		"stdcx. %5, 0, %3\n\t"		/* attempt to store */
+	    #else
+		"1:\tlwarx %0, 0, %3\n\t"	/* load old value */
+		"cmplw %4, %0\n\t"		/* compare */
+		"bne 2f\n\t"			/* exit if not equal */
+		"stwcx. %5, 0, %3\n\t"		/* attempt to store */
+	    #endif
+		"bne- 1b\n\t"			/* spin if failed */
+		"li %0, 1\n\t"			/* success - retval = 1 */
+		"b 3f\n\t"			/* we've succeeded */
+		"2:\n\t"
+	    #ifdef __powerpc64__
+		"stdcx. %0, 0, %3\n\t"		/* clear reservation (74xx) */
+		"stdx %0, 0, %7\n\t"
+	    #else
+		"stwcx. %0, 0, %3\n\t"		/* clear reservation (74xx) */
+		"stwx %0, 0, %7\n\t"
+	    #endif
+		"li %0, 0\n\t"			/* failure - retval = 0 */
+		"3:\n\t"
+		: "=&r" (ret), "=m" (*p), "=m" (*cmpval)
+		: "r" (p), "r" (*cmpval), "r" (newval), "m" (*p), "r"(cmpval)
+		: "cr0", "memory");
+#endif
+
+	return (ret);
+}
+
+static __inline int
+atomic_fcmpset_acq_int(volatile u_int *p, u_int *cmpval, u_int newval)
+{
+	int retval;
+
+	retval = atomic_fcmpset_int(p, cmpval, newval);
+	__ATOMIC_ACQ();
+	return (retval);
+}
+
+static __inline int
+atomic_fcmpset_rel_int(volatile u_int *p, u_int *cmpval, u_int newval)
+{
+	__ATOMIC_REL();
+	return (atomic_fcmpset_int(p, cmpval, newval));
+}
+
+static __inline int
+atomic_fcmpset_acq_long(volatile u_long *p, u_long *cmpval, u_long newval)
+{
+	u_long retval;
+
+	retval = atomic_fcmpset_long(p, cmpval, newval);
+	__ATOMIC_ACQ();
+	return (retval);
+}
+
+static __inline int
+atomic_fcmpset_rel_long(volatile u_long *p, u_long *cmpval, u_long newval)
+{
+	__ATOMIC_REL();
+	return (atomic_fcmpset_long(p, cmpval, newval));
+}
+
+#define	atomic_fcmpset_32	atomic_fcmpset_int
+#define	atomic_fcmpset_acq_32	atomic_fcmpset_acq_int
+#define	atomic_fcmpset_rel_32	atomic_fcmpset_rel_int
+
+#ifdef __powerpc64__
+#define	atomic_fcmpset_64	atomic_fcmpset_long
+#define	atomic_fcmpset_acq_64	atomic_fcmpset_acq_long
+#define	atomic_fcmpset_rel_64	atomic_fcmpset_rel_long
+
+#define	atomic_fcmpset_ptr	atomic_fcmpset_long
+#define	atomic_fcmpset_acq_ptr	atomic_fcmpset_acq_long
+#define	atomic_fcmpset_rel_ptr	atomic_fcmpset_rel_long
+#else
+#define	atomic_fcmpset_ptr	atomic_fcmpset_int
+#define	atomic_fcmpset_acq_ptr	atomic_fcmpset_acq_int
+#define	atomic_fcmpset_rel_ptr	atomic_fcmpset_rel_int
+#endif
+
 static __inline u_int
 atomic_fetchadd_int(volatile u_int *p, u_int v)
 {



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