--- linux/include/asm-x86_64/spinlock.h.p 2007-04-01 23:49:04.000000000 -0400 +++ linux/include/asm-x86_64/spinlock.h 2007-04-02 00:34:24.000000000 -0400 @@ -19,67 +19,36 @@ static inline int __raw_spin_is_locked(raw_spinlock_t *lock) { - return *(volatile signed int *)(&(lock)->slock) <= 0; + return unlikely(lock->qhead != lock->qtail); } static inline void __raw_spin_lock(raw_spinlock_t *lock) { - asm volatile( - "\n1:\t" - LOCK_PREFIX " ; decl %0\n\t" - "jns 2f\n" - "3:\n" - "rep;nop\n\t" - "cmpl $0,%0\n\t" - "jle 3b\n\t" - "jmp 1b\n" - "2:\t" : "=m" (lock->slock) : : "memory"); -} + unsigned int pos = 1; -/* - * Same as __raw_spin_lock, but reenable interrupts during spinning. - */ -#ifndef CONFIG_PROVE_LOCKING -static inline void __raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long flags) -{ asm volatile( - "\n1:\t" - LOCK_PREFIX " ; decl %0\n\t" - "jns 5f\n" - "testl $0x200, %1\n\t" /* interrupts were disabled? */ - "jz 4f\n\t" - "sti\n" - "3:\t" + LOCK_PREFIX "xaddl %0, %1\n\t" + "1:\n\t" + "cmpl %0, %2\n\t" + "je 2f\n\t" "rep;nop\n\t" - "cmpl $0, %0\n\t" - "jle 3b\n\t" - "cli\n\t" - "jmp 1b\n" - "4:\t" - "rep;nop\n\t" - "cmpl $0, %0\n\t" - "jg 1b\n\t" - "jmp 4b\n" - "5:\n\t" - : "+m" (lock->slock) : "r" ((unsigned)flags) : "memory"); + "jmp 1b\n\t" + "2:\n\t" + : "+r" (pos), "+m" (lock->qhead) + : "m" (lock->qtail) : "memory"); } -#endif + +#define __raw_spin_lock_flags(a,b) __raw_spin_lock(a) static inline int __raw_spin_trylock(raw_spinlock_t *lock) { - int oldval; - - asm volatile( - "xchgl %0,%1" - :"=q" (oldval), "=m" (lock->slock) - :"0" (0) : "memory"); - - return oldval > 0; + unsigned int qtail = lock->qtail; + return likely(cmpxchg(&lock->qhead, qtail, qtail+1) == qtail); } static inline void __raw_spin_unlock(raw_spinlock_t *lock) { - asm volatile("movl $1,%0" :"=m" (lock->slock) :: "memory"); + asm volatile("addl $1,%0" :"=m" (lock->qtail) :: "memory"); } static inline void __raw_spin_unlock_wait(raw_spinlock_t *lock) --- linux/include/asm-x86_64/spinlock_types.h.p 2007-04-01 23:49:10.000000000 -0400 +++ linux/include/asm-x86_64/spinlock_types.h 2007-04-01 23:49:21.000000000 -0400 @@ -6,10 +6,11 @@ #endif typedef struct { - unsigned int slock; + unsigned int qhead; + unsigned int qtail; } raw_spinlock_t; -#define __RAW_SPIN_LOCK_UNLOCKED { 1 } +#define __RAW_SPIN_LOCK_UNLOCKED { 0, 0 } typedef struct { unsigned int lock;