1#ifndef __ASM_SPINLOCK_H 2#define __ASM_SPINLOCK_H 3 4#include <asm/system.h> 5 6/* we seem to be the only architecture that uses 0 to mean locked - but we 7 * have to. prumpf */ 8 9#undef SPIN_LOCK_UNLOCKED 10#define SPIN_LOCK_UNLOCKED (spinlock_t) { 1 } 11 12#define spin_lock_init(x) do { (x)->lock = 1; } while(0) 13 14#define spin_unlock_wait(x) do { barrier(); } while(((volatile spinlock_t *)(x))->lock == 1) 15 16#define spin_lock(x) \ 17 do { while(__ldcw(&(x)->lock) == 0); } while(0) 18 19#define spin_unlock(x) \ 20 do { (x)->lock = 1; } while(0) 21 22#define spin_trylock(x) (__ldcw(&(x)->lock) == 1) 23 24/* 25 * Read-write spinlocks, allowing multiple readers 26 * but only one writer. 27 */ 28typedef struct { 29 spinlock_t lock; 30 volatile int counter; 31} rwlock_t; 32 33#define RW_LOCK_UNLOCKED (rwlock_t) { SPIN_LOCK_UNLOCKED, 0 } 34 35/* read_lock, read_unlock are pretty straightforward. Of course it somehow 36 * sucks we end up saving/restoring flags twice for read_lock_irqsave aso. */ 37 38static inline void read_lock(rwlock_t *rw) 39{ 40 unsigned long flags; 41 spin_lock_irqsave(&rw->lock, flags); 42 43 rw->counter++; 44 45 spin_unlock_irqrestore(&rw->lock, flags); 46} 47 48static inline void read_unlock(rwlock_t *rw) 49{ 50 unsigned long flags; 51 spin_lock_irqsave(&rw->lock, flags); 52 53 rw->counter--; 54 55 spin_unlock_irqrestore(&rw->lock, flags); 56} 57 58/* write_lock is less trivial. We optimistically grab the lock and check 59 * if we surprised any readers. If so we release the lock and wait till 60 * they're all gone before trying again 61 * 62 * Also note that we don't use the _irqsave / _irqrestore suffixes here. 63 * If we're called with interrupts enabled and we've got readers (or other 64 * writers) in interrupt handlers someone fucked up and we'd dead-lock 65 * sooner or later anyway. prumpf */ 66 67static inline void write_lock(rwlock_t *rw) 68{ 69retry: 70 spin_lock(&rw->lock); 71 72 if(rw->counter != 0) { 73 /* this basically never happens */ 74 spin_unlock(&rw->lock); 75 76 while(rw->counter != 0); 77 78 goto retry; 79 } 80 81 /* got it. now leave without unlocking */ 82} 83 84/* write_unlock is absolutely trivial - we don't have to wait for anything */ 85 86static inline void write_unlock(rwlock_t *rw) 87{ 88 spin_unlock(&rw->lock); 89} 90 91#endif /* __ASM_SPINLOCK_H */ 92

