From owner-freebsd-hackers Tue Aug 15 21:53:37 2000 Delivered-To: freebsd-hackers@freebsd.org Received: from alcanet.com.au (mail.alcanet.com.au [203.62.196.10]) by hub.freebsd.org (Postfix) with SMTP id 3F30D37B5AD for ; Tue, 15 Aug 2000 21:53:29 -0700 (PDT) (envelope-from jeremyp@gsmx07.alcatel.com.au) Received: by border.alcanet.com.au id <115207>; Wed, 16 Aug 2000 14:53:24 +1000 Content-return: prohibited Date: Wed, 16 Aug 2000 14:53:19 +1000 From: Peter Jeremy Subject: Re: IPC, shared memory, syncronization AND threads... To: rminnich@lanl.gov Cc: freebsd-hackers@freebsd.org Message-Id: <00Aug16.145324est.115207@border.alcanet.com.au> MIME-version: 1.0 Content-type: text/plain; charset=us-ascii Content-disposition: inline User-Agent: Mutt/1.2.4i Sender: owner-freebsd-hackers@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG On Tue, 15 Aug 2000 10:30:25 -0600 (MDT), Ronald G Minnich wrote: >The idea is simple: tset is the fastest, but you only want to spin so >long. Then you want to drop into the kernel, and wait for someone to wake >you up. Agreed. >Here's a simple test-and-set function for the 386 (tested and works): > >int >tset(int *i, int lockval, int unlockval) >{ > int j = 0; > asm("movl 16(%ebp), %eax"); > asm("movl 8(%ebp),%ecx"); > asm("movl 12(%ebp),%edx"); > asm("cmpxchg %edx, (%ecx)"); > asm("jne failed"); > asm("movl %eax, -4(%ebp)"); > asm("jmp done"); > asm("failed: movl %eax, -4(%ebp)"); > asm("done:"); > return j; >} Actually, this isn't particularly good coding. It isn't SMP-safe. If you compile it with -fomit-frame-pointer or -fomit-leaf-frame-pointer, it won't work (and will corrupt some innocent, probably stack, memory). When the code is optimised, it works as much by accident as design. And the documentation for gcc indicates that sequences of asm statements can be re-ordered. Something like the following should be somewhat safer. It returns unlockval if the semaphore was not locked, otherwise it returns the current contents of the semaphore (which seems to be the same as your code). int tset(int *i, int lockval, int unlockval) { int j; __asm__("lock cmpxchg %2, (%3)" : "=a" (j) : "0" (unlockval), "r" (lockval), "r" (i) : "memory", "cc"); return j; } Peter To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message