* Atomically compare the value stored at *p with cmpval and if the * two values are equal, update the value of *p with newval. Returns * zero if the compare failed, nonzero otherwise. */
| 395 | * zero if the compare failed, nonzero otherwise. |
| 396 | */ |
| 397 | static __inline int |
| 398 | atomic_fcmpset_32(__volatile uint32_t *p, uint32_t *cmpval, uint32_t newval) |
| 399 | { |
| 400 | int ret; |
| 401 | |
| 402 | /* |
| 403 | * The following sequence (similar to that in atomic_fcmpset_64) will |
| 404 | * attempt to update the value of *p with newval if the comparison |
| 405 | * succeeds. Note that they'll exit regardless of whether the store |
| 406 | * actually succeeded, leaving *cmpval untouched. This is in line with |
| 407 | * the documentation of atomic_fcmpset_<type>() in atomic(9) for ll/sc |
| 408 | * architectures. |
| 409 | */ |
| 410 | __asm __volatile ( |
| 411 | "ll %0, %1\n\t" /* load old value */ |
| 412 | "bne %0, %4, 1f\n\t" /* compare */ |
| 413 | "move %0, %3\n\t" /* value to store */ |
| 414 | "sc %0, %1\n\t" /* attempt to store */ |
| 415 | "j 2f\n\t" /* exit regardless of success */ |
| 416 | "nop\n\t" /* avoid delay slot accident */ |
| 417 | "1:\n\t" |
| 418 | "sw %0, %2\n\t" /* save old value */ |
| 419 | "li %0, 0\n\t" |
| 420 | "2:\n" |
| 421 | : "=&r" (ret), "+m" (*p), "=m" (*cmpval) |
| 422 | : "r" (newval), "r" (*cmpval) |
| 423 | : "memory"); |
| 424 | return ret; |
| 425 | } |
| 426 | |
| 427 | #define ATOMIC_CMPSET_ACQ_REL(WIDTH) \ |
| 428 | static __inline int \ |
no outgoing calls
no test coverage detected