Atomic swap

Portante, Peter peter.portante at hp.com
Thu Aug 7 08:11:10 PDT 2003


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 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.

-Peter

> /*
>  * 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"
			"mov %2,r1\n\t"		/* Hide under the load latency */
			"cmpeq %0,%2,r0\n\t"
			"bne r0,3f\n\t"		/* Branches out are ok, but not to targets within ld_l/st_c */
> 		"stq_c r1,%1\n\t"
> 		"beq r1,1b\n\t"
> 		"3:\n"
> 		: "=&r" (result)
> 		: "m" (*dst), "r" (val)
> 		: "memory");
> 
> 	*res = result;
> }
> 


More information about the freebsd-alpha mailing list