Atomic swap
Andrew Gallatin
gallatin at cs.duke.edu
Thu Aug 7 07:33:07 PDT 2003
Daniel Eischen writes:
> [ I'm not subscribed to alpha@; please keep me on the CC ]
>
> I need an atomic swap function for libpthread. Here's my hack
> of an implementation:
>
> /*
> * Atomic swap:
> * Atomic (tmp = *dst, *dst = val), then *res = tmp
> *
> * void atomic_swap_long(long *dst, long val, long *res);
> */
> static __inline
> void atomic_swap_long(volatile long *dst, long val, long *res)
> {
> u_int64_t result;
>
> __asm __volatile (
> "1:\tldq_l %0,%1\n\t"
> "stq_c %2,%1\n\t"
> "beq %2,2f\n\t" /* Why is this beq instead of bne 1b? */
> "br 3f\n"
> "2:\tbr 1b\n"
> "3:\n"
> : "=&r" (result)
> : "m" (*dst), "r" (val)
> : "memory");
>
> *res = result;
> }
>
> As annotated above, there seems to be one more branch than
> necessary.
Its actually an optimization. Alphas predict that backward branches
will always be taken (think loops). If you were to branch directly
back to 1:, then if the store succeeds (which it nearly always
should), then the cpu would have been betting on taking the branch,
and that would slow things down.
> Can someone look this over for me? I really don't quite
> know what I'm doing when it comes to inline assembly.
I think it looks OK, but I'm also terrible at inline asm.
Drew
More information about the freebsd-alpha
mailing list