lkml.org 
[lkml]   [1999]   [Jan]   [14]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
SubjectRe: [PATCH] include/asm-i386/semaphore.h speedup
Philipp Rumpf wrote:
> On Wed, Jan 13, 1999 at 08:22:20PM -0700, Colin Plumb wrote:
>> Could someone please check out the following. In particular, is the
>> lock prefix required for cmpxchg, or is it already implicit?
>
> required.

Yes, thanks. It's XCHG where it's implicit.

>> +#ifdef CONFIG_M386
>
> lock incl is available on 386's, too. (you need incl only as there are no SMP 386).

Um, yes, but the other half is the cmpxchg instruction, which is only
available on the 486 and up. One won't work without the other.

>> unsigned long flags;
>>
>> spin_lock_irqsave(&semaphore_wake_lock, flags);
>> sem->waking++;
>> spin_unlock_irqrestore(&semaphore_wake_lock, flags);
>> +#else
>> + __asm__ __volatile__(
>> +#ifdef __SMP__
>> + "lock ; "
>> +#endif
>> + "incl %1"
>> + : "=m" (sem->waking) : "0" (sem->waking));
>> +#endif
>> }
>
>> +#if CONFIG_386
>
> cmpxchg is new to the Pentium ...

486, actualy. CMPXCHG8B is new to the Pentium.

>> + __asm__ __volatile__(
>> + "movl %2,%%eax\n"
>> + "1:\tmovl %%eax,%1\n\t"
>> + "decl %1\n\t"
>> + "jmi 2f\n\t"
>
> That is "js" on Intel normally.

Ah, right, thanks.

Um, in truth I just thought of a technique that should work on the 386
without the semaphore.

Remembering that the basic operation is

if (sem->waiting > 0) {
sem->waiting--;
return 1;
}
return 0;

I think that (with %0 being "=m" (sem->waiting)) : "0" (sem->waiting))
the following code ought to work.

1: lock; decl %0
jns 2f /* If result >= 0, success */
lock; incl %0 /* Went too far; go back */
jg 1b /* If result > 0, retry */
return 0;
2:
return 1;

Here, we're transiently letting sem->waiting drop below zero.
As long as nobody gets confused, that should be fine.

Imagine it's one and four processes land on this code at once.
The first one will decrement it to zero and succeed.
The other three will decrement it to -3 and all get negative
results (-1, -2 and -3, but only the sign bit is visible afterwards).
Now suppose somebody increments it in the meantime, so it's now -2.
The first two processes will increment it to -1 ans 0 respectively,
and fail (as they should). The last will increment it to one and
fall into the retry loop.

I think I've traced through all the paths and it works, but I'd like
a second set of eyes, if possible, to make sure I haven't missed anything.

Thanks!
--
-Colin

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2005-03-22 13:49    [W:0.027 / U:0.832 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site