be2net: Fix memset() arg ordering.
[linux-2.6/mini2440.git] / kernel / spinlock.c
blob5ddab730cb2fb61d664a83d73792792ef9048432
1 /*
2 * Copyright (2004) Linus Torvalds
4 * Author: Zwane Mwaikambo <zwane@fsmlabs.com>
6 * Copyright (2004, 2005) Ingo Molnar
8 * This file contains the spinlock/rwlock implementations for the
9 * SMP and the DEBUG_SPINLOCK cases. (UP-nondebug inlines them)
11 * Note that some architectures have special knowledge about the
12 * stack frames of these functions in their profile_pc. If you
13 * change anything significant here that could change the stack
14 * frame contact the architecture maintainers.
17 #include <linux/linkage.h>
18 #include <linux/preempt.h>
19 #include <linux/spinlock.h>
20 #include <linux/interrupt.h>
21 #include <linux/debug_locks.h>
22 #include <linux/module.h>
24 #ifndef _spin_trylock
25 int __lockfunc _spin_trylock(spinlock_t *lock)
27 return __spin_trylock(lock);
29 EXPORT_SYMBOL(_spin_trylock);
30 #endif
32 #ifndef _read_trylock
33 int __lockfunc _read_trylock(rwlock_t *lock)
35 return __read_trylock(lock);
37 EXPORT_SYMBOL(_read_trylock);
38 #endif
40 #ifndef _write_trylock
41 int __lockfunc _write_trylock(rwlock_t *lock)
43 return __write_trylock(lock);
45 EXPORT_SYMBOL(_write_trylock);
46 #endif
49 * If lockdep is enabled then we use the non-preemption spin-ops
50 * even on CONFIG_PREEMPT, because lockdep assumes that interrupts are
51 * not re-enabled during lock-acquire (which the preempt-spin-ops do):
53 #if !defined(CONFIG_GENERIC_LOCKBREAK) || defined(CONFIG_DEBUG_LOCK_ALLOC)
55 #ifndef _read_lock
56 void __lockfunc _read_lock(rwlock_t *lock)
58 __read_lock(lock);
60 EXPORT_SYMBOL(_read_lock);
61 #endif
63 #ifndef _spin_lock_irqsave
64 unsigned long __lockfunc _spin_lock_irqsave(spinlock_t *lock)
66 return __spin_lock_irqsave(lock);
68 EXPORT_SYMBOL(_spin_lock_irqsave);
69 #endif
71 #ifndef _spin_lock_irq
72 void __lockfunc _spin_lock_irq(spinlock_t *lock)
74 __spin_lock_irq(lock);
76 EXPORT_SYMBOL(_spin_lock_irq);
77 #endif
79 #ifndef _spin_lock_bh
80 void __lockfunc _spin_lock_bh(spinlock_t *lock)
82 __spin_lock_bh(lock);
84 EXPORT_SYMBOL(_spin_lock_bh);
85 #endif
87 #ifndef _read_lock_irqsave
88 unsigned long __lockfunc _read_lock_irqsave(rwlock_t *lock)
90 return __read_lock_irqsave(lock);
92 EXPORT_SYMBOL(_read_lock_irqsave);
93 #endif
95 #ifndef _read_lock_irq
96 void __lockfunc _read_lock_irq(rwlock_t *lock)
98 __read_lock_irq(lock);
100 EXPORT_SYMBOL(_read_lock_irq);
101 #endif
103 #ifndef _read_lock_bh
104 void __lockfunc _read_lock_bh(rwlock_t *lock)
106 __read_lock_bh(lock);
108 EXPORT_SYMBOL(_read_lock_bh);
109 #endif
111 #ifndef _write_lock_irqsave
112 unsigned long __lockfunc _write_lock_irqsave(rwlock_t *lock)
114 return __write_lock_irqsave(lock);
116 EXPORT_SYMBOL(_write_lock_irqsave);
117 #endif
119 #ifndef _write_lock_irq
120 void __lockfunc _write_lock_irq(rwlock_t *lock)
122 __write_lock_irq(lock);
124 EXPORT_SYMBOL(_write_lock_irq);
125 #endif
127 #ifndef _write_lock_bh
128 void __lockfunc _write_lock_bh(rwlock_t *lock)
130 __write_lock_bh(lock);
132 EXPORT_SYMBOL(_write_lock_bh);
133 #endif
135 #ifndef _spin_lock
136 void __lockfunc _spin_lock(spinlock_t *lock)
138 __spin_lock(lock);
140 EXPORT_SYMBOL(_spin_lock);
141 #endif
143 #ifndef _write_lock
144 void __lockfunc _write_lock(rwlock_t *lock)
146 __write_lock(lock);
148 EXPORT_SYMBOL(_write_lock);
149 #endif
151 #else /* CONFIG_PREEMPT: */
154 * This could be a long-held lock. We both prepare to spin for a long
155 * time (making _this_ CPU preemptable if possible), and we also signal
156 * towards that other CPU that it should break the lock ASAP.
158 * (We do this in a function because inlining it would be excessive.)
161 #define BUILD_LOCK_OPS(op, locktype) \
162 void __lockfunc _##op##_lock(locktype##_t *lock) \
164 for (;;) { \
165 preempt_disable(); \
166 if (likely(_raw_##op##_trylock(lock))) \
167 break; \
168 preempt_enable(); \
170 if (!(lock)->break_lock) \
171 (lock)->break_lock = 1; \
172 while (!op##_can_lock(lock) && (lock)->break_lock) \
173 _raw_##op##_relax(&lock->raw_lock); \
175 (lock)->break_lock = 0; \
178 EXPORT_SYMBOL(_##op##_lock); \
180 unsigned long __lockfunc _##op##_lock_irqsave(locktype##_t *lock) \
182 unsigned long flags; \
184 for (;;) { \
185 preempt_disable(); \
186 local_irq_save(flags); \
187 if (likely(_raw_##op##_trylock(lock))) \
188 break; \
189 local_irq_restore(flags); \
190 preempt_enable(); \
192 if (!(lock)->break_lock) \
193 (lock)->break_lock = 1; \
194 while (!op##_can_lock(lock) && (lock)->break_lock) \
195 _raw_##op##_relax(&lock->raw_lock); \
197 (lock)->break_lock = 0; \
198 return flags; \
201 EXPORT_SYMBOL(_##op##_lock_irqsave); \
203 void __lockfunc _##op##_lock_irq(locktype##_t *lock) \
205 _##op##_lock_irqsave(lock); \
208 EXPORT_SYMBOL(_##op##_lock_irq); \
210 void __lockfunc _##op##_lock_bh(locktype##_t *lock) \
212 unsigned long flags; \
214 /* */ \
215 /* Careful: we must exclude softirqs too, hence the */ \
216 /* irq-disabling. We use the generic preemption-aware */ \
217 /* function: */ \
218 /**/ \
219 flags = _##op##_lock_irqsave(lock); \
220 local_bh_disable(); \
221 local_irq_restore(flags); \
224 EXPORT_SYMBOL(_##op##_lock_bh)
227 * Build preemption-friendly versions of the following
228 * lock-spinning functions:
230 * _[spin|read|write]_lock()
231 * _[spin|read|write]_lock_irq()
232 * _[spin|read|write]_lock_irqsave()
233 * _[spin|read|write]_lock_bh()
235 BUILD_LOCK_OPS(spin, spinlock);
236 BUILD_LOCK_OPS(read, rwlock);
237 BUILD_LOCK_OPS(write, rwlock);
239 #endif /* CONFIG_PREEMPT */
241 #ifdef CONFIG_DEBUG_LOCK_ALLOC
243 void __lockfunc _spin_lock_nested(spinlock_t *lock, int subclass)
245 preempt_disable();
246 spin_acquire(&lock->dep_map, subclass, 0, _RET_IP_);
247 LOCK_CONTENDED(lock, _raw_spin_trylock, _raw_spin_lock);
249 EXPORT_SYMBOL(_spin_lock_nested);
251 unsigned long __lockfunc _spin_lock_irqsave_nested(spinlock_t *lock, int subclass)
253 unsigned long flags;
255 local_irq_save(flags);
256 preempt_disable();
257 spin_acquire(&lock->dep_map, subclass, 0, _RET_IP_);
258 LOCK_CONTENDED_FLAGS(lock, _raw_spin_trylock, _raw_spin_lock,
259 _raw_spin_lock_flags, &flags);
260 return flags;
262 EXPORT_SYMBOL(_spin_lock_irqsave_nested);
264 void __lockfunc _spin_lock_nest_lock(spinlock_t *lock,
265 struct lockdep_map *nest_lock)
267 preempt_disable();
268 spin_acquire_nest(&lock->dep_map, 0, 0, nest_lock, _RET_IP_);
269 LOCK_CONTENDED(lock, _raw_spin_trylock, _raw_spin_lock);
271 EXPORT_SYMBOL(_spin_lock_nest_lock);
273 #endif
275 #ifndef _spin_unlock
276 void __lockfunc _spin_unlock(spinlock_t *lock)
278 __spin_unlock(lock);
280 EXPORT_SYMBOL(_spin_unlock);
281 #endif
283 #ifndef _write_unlock
284 void __lockfunc _write_unlock(rwlock_t *lock)
286 __write_unlock(lock);
288 EXPORT_SYMBOL(_write_unlock);
289 #endif
291 #ifndef _read_unlock
292 void __lockfunc _read_unlock(rwlock_t *lock)
294 __read_unlock(lock);
296 EXPORT_SYMBOL(_read_unlock);
297 #endif
299 #ifndef _spin_unlock_irqrestore
300 void __lockfunc _spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags)
302 __spin_unlock_irqrestore(lock, flags);
304 EXPORT_SYMBOL(_spin_unlock_irqrestore);
305 #endif
307 #ifndef _spin_unlock_irq
308 void __lockfunc _spin_unlock_irq(spinlock_t *lock)
310 __spin_unlock_irq(lock);
312 EXPORT_SYMBOL(_spin_unlock_irq);
313 #endif
315 #ifndef _spin_unlock_bh
316 void __lockfunc _spin_unlock_bh(spinlock_t *lock)
318 __spin_unlock_bh(lock);
320 EXPORT_SYMBOL(_spin_unlock_bh);
321 #endif
323 #ifndef _read_unlock_irqrestore
324 void __lockfunc _read_unlock_irqrestore(rwlock_t *lock, unsigned long flags)
326 __read_unlock_irqrestore(lock, flags);
328 EXPORT_SYMBOL(_read_unlock_irqrestore);
329 #endif
331 #ifndef _read_unlock_irq
332 void __lockfunc _read_unlock_irq(rwlock_t *lock)
334 __read_unlock_irq(lock);
336 EXPORT_SYMBOL(_read_unlock_irq);
337 #endif
339 #ifndef _read_unlock_bh
340 void __lockfunc _read_unlock_bh(rwlock_t *lock)
342 __read_unlock_bh(lock);
344 EXPORT_SYMBOL(_read_unlock_bh);
345 #endif
347 #ifndef _write_unlock_irqrestore
348 void __lockfunc _write_unlock_irqrestore(rwlock_t *lock, unsigned long flags)
350 __write_unlock_irqrestore(lock, flags);
352 EXPORT_SYMBOL(_write_unlock_irqrestore);
353 #endif
355 #ifndef _write_unlock_irq
356 void __lockfunc _write_unlock_irq(rwlock_t *lock)
358 __write_unlock_irq(lock);
360 EXPORT_SYMBOL(_write_unlock_irq);
361 #endif
363 #ifndef _write_unlock_bh
364 void __lockfunc _write_unlock_bh(rwlock_t *lock)
366 __write_unlock_bh(lock);
368 EXPORT_SYMBOL(_write_unlock_bh);
369 #endif
371 #ifndef _spin_trylock_bh
372 int __lockfunc _spin_trylock_bh(spinlock_t *lock)
374 return __spin_trylock_bh(lock);
376 EXPORT_SYMBOL(_spin_trylock_bh);
377 #endif
379 notrace int in_lock_functions(unsigned long addr)
381 /* Linker adds these: start and end of __lockfunc functions */
382 extern char __lock_text_start[], __lock_text_end[];
384 return addr >= (unsigned long)__lock_text_start
385 && addr < (unsigned long)__lock_text_end;
387 EXPORT_SYMBOL(in_lock_functions);