From owner-freebsd-hackers Tue Oct 3 0: 1:39 2000 Delivered-To: freebsd-hackers@freebsd.org Received: from mail.rdc1.va.home.com (ha1.rdc1.va.home.com [24.2.32.66]) by hub.freebsd.org (Postfix) with ESMTP id 6D1E337B502 for ; Tue, 3 Oct 2000 00:01:36 -0700 (PDT) Received: from laptop.baldwin.cx ([24.6.244.187]) by mail.rdc1.va.home.com (InterMail vM.4.01.03.00 201-229-121) with ESMTP id <20001003070136.MWAT26082.mail.rdc1.va.home.com@laptop.baldwin.cx>; Tue, 3 Oct 2000 00:01:36 -0700 Content-Length: 1651 Message-ID: X-Mailer: XFMail 1.4.0 on FreeBSD X-Priority: 3 (Normal) Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 8bit MIME-Version: 1.0 In-Reply-To: <00b701c0273b$39f7aaa0$0901a8c0@haym.transactionsite.com> Date: Tue, 03 Oct 2000 00:01:39 -0700 (PDT) From: John Baldwin To: Jan Mikkelsen Subject: Re: atomic operations Cc: FreeBSD Hackers , Cc: FreeBSD Hackers , Kevin Mills Sender: owner-freebsd-hackers@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG On 25-Sep-00 Jan Mikkelsen wrote: > Kevin Mills wrote: >>I found the atomic_* functions in , but noticed that they >>have no return value. What I need is a function that increments/decrements >>the given value *and* returns the new value in an atomic operation. I >>suppose this is possible, yes? How would one modify the assembly to make >>this work? > > > Atomic decrement, in the Intel style: > > long atomic_decrement(volatile long* address) > { > asm { > mov ecx, [address] > mov eax, -1 > lock xadd [ecx], eax > dec eax > } > /* Return value in EAX */ > } > > An untested conversion into the GNU/AT&T style: > > long atomic_decrement(volatile long* address) > { > asm("movl 8(%ebp),%ecx"); > asm("movl $-1, %eax"); > asm("lock xaddl %eax,(%ecx)"); > asm("decl %eax"); > /* Return value in %eax */ > } Uh, there is no xaddl instruction in the x86 instruction set. There is a fetchadd instruction in ia64, but that doesn't help much here. You can use a loop with the atomic_cmpset_* primitives though to achieve this. e.g.: volatile int value; int save, increment; value = 3; increment = 4; do { save = value; } while (atomic_cmpset_int(&value, save, save + increment) == 0); foo = some_array[save + increment]; You can use this to control access to a circular buffer w/o needing a lock to obtain new entries for example. This will only work with -current though. -- John Baldwin -- http://www.FreeBSD.org/~jhb/ PGP Key: http://www.baldwin.cx/~john/pgpkey.asc "Power Users Use the Power to Serve!" - http://www.FreeBSD.org/ To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message