The branch stable/12 has been updated by kevans:

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

commit 5bf3f2498adea0087a3ac1e3eaffdfc412b9dfe3
Author:     Kyle Evans <[email protected]>
AuthorDate: 2019-10-02 15:13:40 +0000
Commit:     Kyle Evans <[email protected]>
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");

Reply via email to