Author: kevans
Date: Wed Oct  2 15:13:40 2019
New Revision: 353008
URL: https://svnweb.freebsd.org/changeset/base/353008

Log:
  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.
  
  Reviewed by:  kib
  Looks ok:     imp
  Differential Revision:        https://reviews.freebsd.org/D21836

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

Modified: head/sys/mips/include/atomic.h
==============================================================================
--- head/sys/mips/include/atomic.h      Wed Oct  2 13:46:40 2019        
(r353007)
+++ head/sys/mips/include/atomic.h      Wed Oct  2 15:13:40 2019        
(r353008)
@@ -397,18 +397,25 @@ atomic_fcmpset_32(__volatile uint32_t *p, uint32_t *cm
 {
        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");
@@ -508,17 +515,16 @@ atomic_fcmpset_64(__volatile uint64_t *p, uint64_t *cm
         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");
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to