Atomic swap
Daniel Eischen
eischen at vigrid.com
Thu Aug 7 10:44:20 PDT 2003
On Thu, 7 Aug 2003, Portante, Peter wrote:
> Dan,
>
> I don't think you want to do the stq_c if the location already holds the
> same value. Instead, check the loaded value to see if it is the same as the
The purpose of the atomic swap is to make a FIFO queueing
list. The values should never be the same. It's not meant
to be used as test_and_set.
> value to be stored, and branch out of the loop returning the result if it is
> they are the same. And starting with EV56, the need to do the branch
> forward/branch back logic has been removed. And EV6 and later CPUs do such
> a good job predicting the branching that it is not worth the instruction
> stream space when that space can be used to avoid a stq_c.
>
> Additionally, the stq_c destroys the contents of %2, so you need to move the
> value in %2 into another register for use in the stq_c. I don't know how to
> do that in the ASM, so I just used raw register names below, highlighted in
> red.
How about this?
static __inline void
atomic_swap_long(volatile long *dst, long val, long *res)
{
u_int64_t result, temp;
__asm __volatile (
"1:\tldq %1, %3\n\t" /* load value to store */
"ldq_l %0, %2\n\t" /* load current value, asserting lock */
"stq_c %1, %2\n\t" /* attempt to store */
"beq %1, 2f\n\t" /* if the store failed, spin */
"br 3f\n" /* it worked, exit */
"2:\tbr 1b\n" /* *dst not updated, loop */
"3:\n" /* it worked */
: "=&r" (result), "=&r" (temp)
: "m" (*dst), "m" (val)
: "memory");
*res = result;
}
--
Dan Eischen
More information about the freebsd-alpha
mailing list