Date: Thu, 7 Aug 2003 13:44:18 -0400 (EDT) From: Daniel Eischen <eischen@vigrid.com> To: "Portante, Peter" <peter.portante@hp.com> Cc: alpha@freebsd.org Subject: RE: Atomic swap Message-ID: <Pine.GSO.4.10.10308071320370.9489-100000@pcnet5.pcnet.com> In-Reply-To: <B24FABB430F7C94D942D6386447C93DC0512B55D@tayexc17.americas.cpqcorp.net>
next in thread | previous in thread | raw e-mail | index | archive | help
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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.GSO.4.10.10308071320370.9489-100000>