From owner-freebsd-alpha@FreeBSD.ORG Thu Aug 7 11:55:09 2003 Return-Path: Delivered-To: freebsd-alpha@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 33E6637B401; Thu, 7 Aug 2003 11:55:09 -0700 (PDT) Received: from ns1.xcllnt.net (209-128-86-226.BAYAREA.NET [209.128.86.226]) by mx1.FreeBSD.org (Postfix) with ESMTP id 0CA4443FAF; Thu, 7 Aug 2003 11:55:08 -0700 (PDT) (envelope-from marcel@xcllnt.net) Received: from athlon.pn.xcllnt.net (athlon.pn.xcllnt.net [192.168.4.3]) by ns1.xcllnt.net (8.12.9/8.12.9) with ESMTP id h77It7wO046489; Thu, 7 Aug 2003 11:55:07 -0700 (PDT) (envelope-from marcel@piii.pn.xcllnt.net) Received: from athlon.pn.xcllnt.net (localhost [127.0.0.1]) by athlon.pn.xcllnt.net (8.12.9/8.12.9) with ESMTP id h77It7We000668; Thu, 7 Aug 2003 11:55:07 -0700 (PDT) (envelope-from marcel@athlon.pn.xcllnt.net) Received: (from marcel@localhost) by athlon.pn.xcllnt.net (8.12.9/8.12.9/Submit) id h77It7LO000667; Thu, 7 Aug 2003 11:55:07 -0700 (PDT) (envelope-from marcel) Date: Thu, 7 Aug 2003 11:55:07 -0700 From: Marcel Moolenaar To: deischen@freebsd.org Message-ID: <20030807185507.GA559@athlon.pn.xcllnt.net> References: Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.4i cc: "Portante, Peter" cc: alpha@freebsd.org Subject: Re: Atomic swap X-BeenThere: freebsd-alpha@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Porting FreeBSD to the Alpha List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 07 Aug 2003 18:55:09 -0000 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