From owner-freebsd-hackers Thu Jul 26 14:43:39 2001 Delivered-To: freebsd-hackers@freebsd.org Received: from mail.wrs.com (unknown-1-11.windriver.com [147.11.1.11]) by hub.freebsd.org (Postfix) with ESMTP id EFCE037B406 for ; Thu, 26 Jul 2001 14:43:35 -0700 (PDT) (envelope-from jhb@FreeBSD.org) Received: from laptop.baldwin.cx (john@[147.11.46.217]) by mail.wrs.com (8.9.3/8.9.1) with ESMTP id OAA24980; Thu, 26 Jul 2001 14:43:27 -0700 (PDT) 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: <20010726135913.A23052@sharmas.dhs.org> Date: Thu, 26 Jul 2001 14:43:24 -0700 (PDT) From: John Baldwin To: Arun Sharma Subject: RE: Need a clean room implementation of this function Cc: hackers@FreeBSD.org Sender: owner-freebsd-hackers@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG On 26-Jul-01 Arun Sharma wrote: > I'm porting a BSD licensed Java VM from Linux to FreeBSD and ran into > the following Linux function which is not implemented in BSDs. > > To avoid GPL contamination issues, can someone complete[1] the following > method in inlined IA-32 assembly ? Intel instruction reference documents > an instruction called BTS, which does just this. You might be able to rewrite the code to use atomic_cmpset() instead of test_and_set_bit() (which you can steal from machine/atomic.h in -current). You can emulate this exact operation with a loop using atomic_cmpset* if needed: { int val; do { val = *(int *)addr; } while (atomic_cmpset_int(addr, val, val | (1 << nr) == 0); return (val & (1 << nr)); } If the code in question is just using a single bit in a word as a spinlock like so: while (test_and_set_bit(0, &lock_var)) ; then you can replace that with an atomic_cmpset loop: while (atomic_cmpset_int(&lock_var, 0, 1) == 0) ; However, you will want to use appropriate memory barriers for this to work well on SMP systems (and if you want this portable to other archs at all). In that case you should use an 'acquire' barrier to acquire the lock, and a 'release' barrier to release the lock. Thus: /* lock critical region */ while (atomic_cmpset_acq_int(&lock_var, 0, 1) == 0) ; /* spin */ ... /* release lock */ atomic_store_rel_int(&lock_var, 0); -- 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