# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.1033 -> 1.1034 # include/linux/spinlock.h 1.22 -> 1.23 # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 03/04/05 lethal@lemmiwinks.internal.linux-sh.org 1.1034 # First-pass implementation of a generic spinlock interface modelled # after Dekker's algorithm for SMP platforms lacking atomic # instructions. # -------------------------------------------- # diff -Nru a/include/linux/spinlock.h b/include/linux/spinlock.h --- a/include/linux/spinlock.h Sat Apr 5 20:12:47 2003 +++ b/include/linux/spinlock.h Sat Apr 5 20:12:47 2003 @@ -37,6 +37,96 @@ #ifdef CONFIG_SMP #include +/* + * Check for generic non-atomic spinlocks + */ +#if defined(CONFIG_NON_ATOMIC_SPINLOCK) && !defined(CONFIG_PREEMPT) +/* + * For platforms that lack atomic instructions, we use a rough implementation + * of Dekker's algorithm to deal with the locking. + * + * This implementation has a number of drawbacks, including not beeing preempt + * safe, and being generally ineffecient/unsafe with a large number of CPUs. + */ +typedef struct { + volatile unsigned int lock[NR_CPUS]; + volatile int user; +} spinlock_t; + +#define SPIN_LOCK_UNLOCKED 0 +#define SPIN_LOCK_LOCKED 1 + +static inline void spin_lock_init(spinlock_t *lock) +{ + int cpu; + + for (cpu = 0; cpu < NR_CPUS; cpu++) + lock->lock[cpu] = SPIN_LOCK_UNLOCKED; + + lock->user = -1; +} + +static inline void _raw_spin_lock(spinlock_t *lock) +{ + int cpu, this_cpu = smp_processor_id(); + + /* Try to grab the lock */ + lock->lock[this_cpu] = SPIN_LOCK_LOCKED; + + /* + * Spin through the list of online processors to see if anyone else + * currently has the lock. + */ + for (cpu = 0; cpu < NR_CPUS && cpu_online(cpu); cpu++) { + while (lock->lock[cpu] == SPIN_LOCK_LOCKED) { + /* + * If the lock isn't available yet, hold off on the + * lock request until the lock is relinquished. + */ + if (lock->user != this_cpu || lock->user != -1) { + lock->lock[this_cpu] = SPIN_LOCK_UNLOCKED; + + /* Wait for it .. */ + while (lock->user == cpu) + ; + + /* Try to grab the lock again */ + lock->lock[this_cpu] = SPIN_LOCK_LOCKED; + } + } + } + + /* We have the lock, let everyone else know. */ + lock->user = this_cpu; +} + +static inline int _raw_spin_trylock(spinlock_t *lock) +{ + /* + * Check to see if the lock is available. + */ + if (lock->user == -1) { + int cpu = smp_processor_id(); + + /* Grab it */ + lock->user = cpu; + lock->lock[cpu] = SPIN_LOCK_LOCKED; + + /* Got it */ + return 1; + } + + /* Already in use .. */ + return 0; +} + +static inline void _raw_spin_unlock(spinlock_t *lock) +{ + lock->lock[smp_processor_id()] = SPIN_LOCK_UNLOCKED; + lock->user = -1; +} +#endif /* CONFIG_NON_ATOMIC_SPINLOCK */ + #else #if !defined(CONFIG_PREEMPT) && !defined(CONFIG_DEBUG_SPINLOCK)