Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 11 Oct 2019 17:01:03 +0000 (UTC)
From:      Andriy Gapon <avg@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r353442 - head/sys/cddl/compat/opensolaris/sys
Message-ID:  <201910111701.x9BH13wd093368@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: avg
Date: Fri Oct 11 17:01:02 2019
New Revision: 353442
URL: https://svnweb.freebsd.org/changeset/base/353442

Log:
  fix up r353340, don't assume that fcmpset has strong semantics
  
  fcmpset can have two kinds of semantics, weak and strong.
  For practical purposes, strong semantics means that if fcmpset fails
  then the reported current value is always different from the expected
  value.  Weak semantics means that the reported current value may be the
  same as the expected value even though fcmpset failed.  That's a so
  called "sporadic" failure.
  
  I originally implemented atomic_cas expecting strong semantics, but many
  platforms actually have weak one.
  
  Reported by:	pkubaj (not confirmed if same issue)
  Discussed with:	kib, mjg
  MFC after:	19 days
  X-MFC with:	r353340

Modified:
  head/sys/cddl/compat/opensolaris/sys/atomic.h

Modified: head/sys/cddl/compat/opensolaris/sys/atomic.h
==============================================================================
--- head/sys/cddl/compat/opensolaris/sys/atomic.h	Fri Oct 11 16:28:46 2019	(r353441)
+++ head/sys/cddl/compat/opensolaris/sys/atomic.h	Fri Oct 11 17:01:02 2019	(r353442)
@@ -36,6 +36,11 @@
 #define	I386_HAVE_ATOMIC64
 #endif
 
+#if defined(__i386__) || defined(__amd64__) || defined(__arm__)
+/* No spurious failures from fcmpset. */
+#define	STRONG_FCMPSET
+#endif
+
 #if !defined(__LP64__) && !defined(__mips_n32) && \
     !defined(ARM_HAVE_ATOMIC64) && !defined(I386_HAVE_ATOMIC64)
 extern void atomic_add_64(volatile uint64_t *target, int64_t delta);
@@ -89,7 +94,16 @@ atomic_dec_32_nv(volatile uint32_t *target)
 static inline uint32_t
 atomic_cas_32(volatile uint32_t *target, uint32_t cmp, uint32_t newval)
 {
+#ifdef STRONG_FCMPSET
 	(void)atomic_fcmpset_32(target, &cmp, newval);
+#else
+	uint32_t expected = cmp;
+
+	do {
+		if (atomic_fcmpset_32(target, &cmp, newval))
+			break;
+	} while (cmp == expected);
+#endif
 	return (cmp);
 }
 #endif
@@ -112,7 +126,16 @@ atomic_add_64_nv(volatile uint64_t *target, int64_t de
 static inline uint64_t
 atomic_cas_64(volatile uint64_t *target, uint64_t cmp, uint64_t newval)
 {
+#ifdef STRONG_FCMPSET
 	(void)atomic_fcmpset_64(target, &cmp, newval);
+#else
+	uint64_t expected = cmp;
+
+	do {
+		if (atomic_fcmpset_64(target, &cmp, newval))
+			break;
+	} while (cmp == expected);
+#endif
 	return (cmp);
 }
 #endif



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