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