Date: Thu, 7 Aug 2003 15:06:33 -0400 From: "Portante, Peter" <peter.portante@hp.com> To: "Marcel Moolenaar" <marcel@xcllnt.net> Cc: alpha@freebsd.org Subject: RE: Atomic swap Message-ID: <B24FABB430F7C94D942D6386447C93DC0512B560@tayexc17.americas.cpqcorp.net>
index | next in thread | raw e-mail
Marcel,
> ----------
> From: Marcel Moolenaar
> Sent: Thursday, August 7, 2003 2:55 PM
> To: deischen@freebsd.org
> Cc: Portante, Peter; alpha@freebsd.org
> Subject: Re: Atomic swap
>
> On Thu, Aug 07, 2003 at 01:44:18PM -0400, Daniel Eischen wrote:
> > 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;
> > }
>
> The first instruction is wrong. "val" isn't memory. Also,
> forget about the branch prediction optimization. It just
> makes the code unreadable and we don't even know if it
> makes a difference.
>
> The following has been written down without testing (I
> dropped the cosmetic \t and instead indented by hand to
> make the source code readable, not what is given to the
> assembler (per se):
>
> static __inline void
> atomic_swap_long(volatile long *dst, long val, long *res)
> {
> __asm ( "1: ldq_l t0,%0\n"
> " mov %1,t1\n"
> " stq_c t1,%0\n"
> " beq t1,1b\n"
> " stq t0,%3\n"
> :: "m"(*dst), "r"(val), "m"(*res) : "memory");
> }
>
> In words:
> o Read the current value at *dst in register t0 and lock the address.
> o Since stq_c clobbers it's input and we may need to loop, save val
> in temporary register t1.
> o Store val at *dst (by means of t1) and if the lock failed, retry.
> o Write the old value in register t0 to *res.
>
A word of caution on performing that stq without an MB before it: another processor cannot read that location and the destination location and assume anything about their contents based on what they read unless an MB is between them.
> --
> Marcel Moolenaar USPA: A-39004 marcel@xcllnt.net
> _______________________________________________
> freebsd-alpha@freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/freebsd-alpha
> To unsubscribe, send any mail to "freebsd-alpha-unsubscribe@freebsd.org"
>
>
home |
help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?B24FABB430F7C94D942D6386447C93DC0512B560>
