File: /usr/src/linux/include/asm-parisc/spinlock.h

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