aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-parisc/spinlock.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/asm-parisc/spinlock.h')
-rw-r--r--include/asm-parisc/spinlock.h258
1 files changed, 258 insertions, 0 deletions
diff --git a/include/asm-parisc/spinlock.h b/include/asm-parisc/spinlock.h
new file mode 100644
index 00000000000..679ea1c651e
--- /dev/null
+++ b/include/asm-parisc/spinlock.h
@@ -0,0 +1,258 @@
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. Moreover, at least on some PA processors,
8 * the semaphore address has to be 16-byte aligned.
9 */
10
11#ifndef CONFIG_DEBUG_SPINLOCK
12
13#define __SPIN_LOCK_UNLOCKED { { 1, 1, 1, 1 } }
14#undef SPIN_LOCK_UNLOCKED
15#define SPIN_LOCK_UNLOCKED (spinlock_t) __SPIN_LOCK_UNLOCKED
16
17#define spin_lock_init(x) do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)
18
19static inline int spin_is_locked(spinlock_t *x)
20{
21 volatile unsigned int *a = __ldcw_align(x);
22 return *a == 0;
23}
24
25#define spin_unlock_wait(x) do { barrier(); } while(spin_is_locked(x))
26#define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
27
28static inline void _raw_spin_lock(spinlock_t *x)
29{
30 volatile unsigned int *a;
31
32 mb();
33 a = __ldcw_align(x);
34 while (__ldcw(a) == 0)
35 while (*a == 0);
36 mb();
37}
38
39static inline void _raw_spin_unlock(spinlock_t *x)
40{
41 volatile unsigned int *a;
42 mb();
43 a = __ldcw_align(x);
44 *a = 1;
45 mb();
46}
47
48static inline int _raw_spin_trylock(spinlock_t *x)
49{
50 volatile unsigned int *a;
51 int ret;
52
53 mb();
54 a = __ldcw_align(x);
55 ret = __ldcw(a) != 0;
56 mb();
57
58 return ret;
59}
60
61#define spin_lock_own(LOCK, LOCATION) ((void)0)
62
63#else /* !(CONFIG_DEBUG_SPINLOCK) */
64
65#define SPINLOCK_MAGIC 0x1D244B3C
66
67#define __SPIN_LOCK_UNLOCKED { { 1, 1, 1, 1 }, SPINLOCK_MAGIC, 10, __FILE__ , NULL, 0, -1, NULL, NULL }
68#undef SPIN_LOCK_UNLOCKED
69#define SPIN_LOCK_UNLOCKED (spinlock_t) __SPIN_LOCK_UNLOCKED
70
71#define spin_lock_init(x) do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)
72
73#define CHECK_LOCK(x) \
74 do { \
75 if (unlikely((x)->magic != SPINLOCK_MAGIC)) { \
76 printk(KERN_ERR "%s:%d: spin_is_locked" \
77 " on uninitialized spinlock %p.\n", \
78 __FILE__, __LINE__, (x)); \
79 } \
80 } while(0)
81
82#define spin_is_locked(x) \
83 ({ \
84 CHECK_LOCK(x); \
85 volatile unsigned int *a = __ldcw_align(x); \
86 if (unlikely((*a == 0) && (x)->babble)) { \
87 (x)->babble--; \
88 printk("KERN_WARNING \
89 %s:%d: spin_is_locked(%s/%p) already" \
90 " locked by %s:%d in %s at %p(%d)\n", \
91 __FILE__,__LINE__, (x)->module, (x), \
92 (x)->bfile, (x)->bline, (x)->task->comm,\
93 (x)->previous, (x)->oncpu); \
94 } \
95 *a == 0; \
96 })
97
98#define spin_unlock_wait(x) \
99 do { \
100 CHECK_LOCK(x); \
101 volatile unsigned int *a = __ldcw_align(x); \
102 if (unlikely((*a == 0) && (x)->babble)) { \
103 (x)->babble--; \
104 printk("KERN_WARNING \
105 %s:%d: spin_unlock_wait(%s/%p)" \
106 " owned by %s:%d in %s at %p(%d)\n", \
107 __FILE__,__LINE__, (x)->module, (x), \
108 (x)->bfile, (x)->bline, (x)->task->comm,\
109 (x)->previous, (x)->oncpu); \
110 } \
111 barrier(); \
112 } while (*((volatile unsigned char *)(__ldcw_align(x))) == 0)
113
114extern void _dbg_spin_lock(spinlock_t *lock, const char *base_file, int line_no);
115extern void _dbg_spin_unlock(spinlock_t *lock, const char *, int);
116extern int _dbg_spin_trylock(spinlock_t * lock, const char *, int);
117
118#define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
119
120#define _raw_spin_unlock(lock) _dbg_spin_unlock(lock, __FILE__, __LINE__)
121#define _raw_spin_lock(lock) _dbg_spin_lock(lock, __FILE__, __LINE__)
122#define _raw_spin_trylock(lock) _dbg_spin_trylock(lock, __FILE__, __LINE__)
123
124/* just in case we need it */
125#define spin_lock_own(LOCK, LOCATION) \
126do { \
127 volatile unsigned int *a = __ldcw_align(LOCK); \
128 if (!((*a == 0) && ((LOCK)->oncpu == smp_processor_id()))) \
129 printk("KERN_WARNING \
130 %s: called on %d from %p but lock %s on %d\n", \
131 LOCATION, smp_processor_id(), \
132 __builtin_return_address(0), \
133 (*a == 0) ? "taken" : "freed", (LOCK)->on_cpu); \
134} while (0)
135
136#endif /* !(CONFIG_DEBUG_SPINLOCK) */
137
138/*
139 * Read-write spinlocks, allowing multiple readers
140 * but only one writer.
141 */
142typedef struct {
143 spinlock_t lock;
144 volatile int counter;
145#ifdef CONFIG_PREEMPT
146 unsigned int break_lock;
147#endif
148} rwlock_t;
149
150#define RW_LOCK_UNLOCKED (rwlock_t) { __SPIN_LOCK_UNLOCKED, 0 }
151
152#define rwlock_init(lp) do { *(lp) = RW_LOCK_UNLOCKED; } while (0)
153
154#define _raw_read_trylock(lock) generic_raw_read_trylock(lock)
155
156/* read_lock, read_unlock are pretty straightforward. Of course it somehow
157 * sucks we end up saving/restoring flags twice for read_lock_irqsave aso. */
158
159#ifdef CONFIG_DEBUG_RWLOCK
160extern void _dbg_read_lock(rwlock_t * rw, const char *bfile, int bline);
161#define _raw_read_lock(rw) _dbg_read_lock(rw, __FILE__, __LINE__)
162#else
163static __inline__ void _raw_read_lock(rwlock_t *rw)
164{
165 unsigned long flags;
166 local_irq_save(flags);
167 _raw_spin_lock(&rw->lock);
168
169 rw->counter++;
170
171 _raw_spin_unlock(&rw->lock);
172 local_irq_restore(flags);
173}
174#endif /* CONFIG_DEBUG_RWLOCK */
175
176static __inline__ void _raw_read_unlock(rwlock_t *rw)
177{
178 unsigned long flags;
179 local_irq_save(flags);
180 _raw_spin_lock(&rw->lock);
181
182 rw->counter--;
183
184 _raw_spin_unlock(&rw->lock);
185 local_irq_restore(flags);
186}
187
188/* write_lock is less trivial. We optimistically grab the lock and check
189 * if we surprised any readers. If so we release the lock and wait till
190 * they're all gone before trying again
191 *
192 * Also note that we don't use the _irqsave / _irqrestore suffixes here.
193 * If we're called with interrupts enabled and we've got readers (or other
194 * writers) in interrupt handlers someone fucked up and we'd dead-lock
195 * sooner or later anyway. prumpf */
196
197#ifdef CONFIG_DEBUG_RWLOCK
198extern void _dbg_write_lock(rwlock_t * rw, const char *bfile, int bline);
199#define _raw_write_lock(rw) _dbg_write_lock(rw, __FILE__, __LINE__)
200#else
201static __inline__ void _raw_write_lock(rwlock_t *rw)
202{
203retry:
204 _raw_spin_lock(&rw->lock);
205
206 if(rw->counter != 0) {
207 /* this basically never happens */
208 _raw_spin_unlock(&rw->lock);
209
210 while(rw->counter != 0);
211
212 goto retry;
213 }
214
215 /* got it. now leave without unlocking */
216 rw->counter = -1; /* remember we are locked */
217}
218#endif /* CONFIG_DEBUG_RWLOCK */
219
220/* write_unlock is absolutely trivial - we don't have to wait for anything */
221
222static __inline__ void _raw_write_unlock(rwlock_t *rw)
223{
224 rw->counter = 0;
225 _raw_spin_unlock(&rw->lock);
226}
227
228#ifdef CONFIG_DEBUG_RWLOCK
229extern int _dbg_write_trylock(rwlock_t * rw, const char *bfile, int bline);
230#define _raw_write_trylock(rw) _dbg_write_trylock(rw, __FILE__, __LINE__)
231#else
232static __inline__ int _raw_write_trylock(rwlock_t *rw)
233{
234 _raw_spin_lock(&rw->lock);
235 if (rw->counter != 0) {
236 /* this basically never happens */
237 _raw_spin_unlock(&rw->lock);
238
239 return 0;
240 }
241
242 /* got it. now leave without unlocking */
243 rw->counter = -1; /* remember we are locked */
244 return 1;
245}
246#endif /* CONFIG_DEBUG_RWLOCK */
247
248static __inline__ int is_read_locked(rwlock_t *rw)
249{
250 return rw->counter > 0;
251}
252
253static __inline__ int is_write_locked(rwlock_t *rw)
254{
255 return rw->counter < 0;
256}
257
258#endif /* __ASM_SPINLOCK_H */