git: 5bf3f2498ade - stable/12 - mips: fcmpset: do not spin on sc failure

From: Kyle Evans <kevans_at_FreeBSD.org>
Date: Wed, 06 Oct 2021 19:46:52 UTC
The branch stable/12 has been updated by kevans:

URL: https://cgit.FreeBSD.org/src/commit/?id=5bf3f2498adea0087a3ac1e3eaffdfc412b9dfe3

commit 5bf3f2498adea0087a3ac1e3eaffdfc412b9dfe3
Author:     Kyle Evans <kevans@FreeBSD.org>
AuthorDate: 2019-10-02 15:13:40 +0000
Commit:     Kyle Evans <kevans@FreeBSD.org>
CommitDate: 2021-10-06 19:46:06 +0000

    mips: fcmpset: do not spin on sc failure
    
    For ll/sc architectures, atomic(9) allows failure modes where *old == val
    due to write failure and callers should compensate for this. Do not retry on
    failure, just leave 0 in ret and fail the operation if we couldn't sc it.
    This lets the caller determine if it should retry or not.
    
    (cherry picked from commit 22c2c971a614a72875787e0fd0001906451ee245)
---
 sys/mips/include/atomic.h | 30 ++++++++++++++++++------------
 1 file changed, 18 insertions(+), 12 deletions(-)

diff --git a/sys/mips/include/atomic.h b/sys/mips/include/atomic.h
index 9fe1439b721f..506c686169e4 100644
--- a/sys/mips/include/atomic.h
+++ b/sys/mips/include/atomic.h
@@ -411,18 +411,25 @@ atomic_fcmpset_32(__volatile uint32_t *p, uint32_t *cmpval, uint32_t newval)
 {
 	int ret;
 
+	/*
+	 * The following sequence (similar to that in atomic_fcmpset_64) will
+	 * attempt to update the value of *p with newval if the comparison
+	 * succeeds.  Note that they'll exit regardless of whether the store
+	 * actually succeeded, leaving *cmpval untouched.  This is in line with
+	 * the documentation of atomic_fcmpset_<type>() in atomic(9) for ll/sc
+	 * architectures.
+	 */
 	__asm __volatile (
-		"1:\n\t"
 		"ll	%0, %1\n\t"		/* load old value */
-		"bne	%0, %4, 2f\n\t"		/* compare */
+		"bne	%0, %4, 1f\n\t"		/* compare */
 		"move	%0, %3\n\t"		/* value to store */
 		"sc	%0, %1\n\t"		/* attempt to store */
-		"beqz	%0, 1b\n\t"		/* if it failed, spin */
-		"j	3f\n\t"
-		"2:\n\t"
+		"j	2f\n\t"			/* exit regardless of success */
+		"nop\n\t"			/* avoid delay slot accident */
+		"1:\n\t"
 		"sw	%0, %2\n\t"		/* save old value */
 		"li	%0, 0\n\t"
-		"3:\n"
+		"2:\n"
 		: "=&r" (ret), "+m" (*p), "=m" (*cmpval)
 		: "r" (newval), "r" (*cmpval)
 		: "memory");
@@ -522,17 +529,16 @@ atomic_fcmpset_64(__volatile uint64_t *p, uint64_t *cmpval, uint64_t newval)
         int ret;
 
         __asm __volatile (
-                "1:\n\t"
 		"lld	%0, %1\n\t"		/* load old value */
-                "bne	%0, %4, 2f\n\t"		/* compare */
+                "bne	%0, %4, 1f\n\t"		/* compare */
                 "move	%0, %3\n\t"		/* value to store */
                 "scd	%0, %1\n\t"		/* attempt to store */
-                "beqz	%0, 1b\n\t"		/* if it failed, spin */
-                "j	3f\n\t"
-                "2:\n\t"
+		"j	2f\n\t"			/* exit regardless of success */
+		"nop\n\t"			/* avoid delay slot accident */
+                "1:\n\t"
                 "sd	%0, %2\n\t"		/* save old value */
                 "li	%0, 0\n\t"
-                "3:\n"
+                "2:\n"
                 : "=&r" (ret), "+m" (*p), "=m" (*cmpval)
                 : "r" (newval), "r" (*cmpval)
                 : "memory");