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