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