Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 7 Aug 2003 11:55:07 -0700
From:      Marcel Moolenaar <marcel@xcllnt.net>
To:        deischen@freebsd.org
Cc:        alpha@freebsd.org
Subject:   Re: Atomic swap
Message-ID:  <20030807185507.GA559@athlon.pn.xcllnt.net>
In-Reply-To: <Pine.GSO.4.10.10308071320370.9489-100000@pcnet5.pcnet.com>
References:  <B24FABB430F7C94D942D6386447C93DC0512B55D@tayexc17.americas.cpqcorp.net> <Pine.GSO.4.10.10308071320370.9489-100000@pcnet5.pcnet.com>

next in thread | previous in thread | raw e-mail | index | archive | help

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.

-- 
 Marcel Moolenaar	  USPA: A-39004		 marcel@xcllnt.net



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030807185507.GA559>