Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 7 Aug 2003 15:05:28 -0400 (EDT)
From:      Daniel Eischen <eischen@vigrid.com>
To:        Marcel Moolenaar <marcel@xcllnt.net>
Cc:        alpha@freebsd.org
Subject:   Re: Atomic swap
Message-ID:  <Pine.GSO.4.10.10308071500390.29641-100000@pcnet5.pcnet.com>
In-Reply-To: <20030807185507.GA559@athlon.pn.xcllnt.net>

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

On Thu, 7 Aug 2003, Marcel Moolenaar wrote:

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

If I swap the first 2 instructions:

	__asm ( "1: mov     %1,t1\n"
		    ldq_l   t0,%0\n"

that eliminates 1 instruction from between the locked
instructions.  Is there anything wrong with doing that?

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

So it's OK to hardcode registers (t0, t1) in inline assembly?

-- 
Dan Eischen



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.GSO.4.10.10308071500390.29641-100000>