On Tue, 15 Aug 2000 10:30:25 -0600 (MDT), Ronald G Minnich <[EMAIL PROTECTED]> 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 [EMAIL PROTECTED]
with "unsubscribe freebsd-hackers" in the body of the message

Reply via email to