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
This commit is contained in:
Kyle Evans 2019-10-02 15:13:40 +00:00
parent 8cdae52ef6
commit 22c2c971a6
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=353008

View File

@ -397,18 +397,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");
@ -508,17 +515,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");