2 * Copyright (2004) Linus Torvalds
4 * Author: Zwane Mwaikambo <zwane@fsmlabs.com>
7 #include <linux/config.h>
8 #include <linux/linkage.h>
9 #include <linux/preempt.h>
10 #include <linux/spinlock.h>
11 #include <linux/interrupt.h>
12 #include <linux/module.h>
14 int __lockfunc
_spin_trylock(spinlock_t
*lock
)
17 if (_raw_spin_trylock(lock
))
23 EXPORT_SYMBOL(_spin_trylock
);
25 int __lockfunc
_write_trylock(rwlock_t
*lock
)
28 if (_raw_write_trylock(lock
))
34 EXPORT_SYMBOL(_write_trylock
);
38 * This could be a long-held lock. If another CPU holds it for a long time,
39 * and that CPU is not asked to reschedule then *this* CPU will spin on the
40 * lock for a long time, even if *this* CPU is asked to reschedule.
42 * So what we do here, in the slow (contended) path is to spin on the lock by
43 * hand while permitting preemption.
45 * Called inside preempt_disable().
47 static inline void __preempt_spin_lock(spinlock_t
*lock
)
49 if (preempt_count() > 1) {
56 while (spin_is_locked(lock
))
59 } while (!_raw_spin_trylock(lock
));
62 void __lockfunc
_spin_lock(spinlock_t
*lock
)
65 if (unlikely(!_raw_spin_trylock(lock
)))
66 __preempt_spin_lock(lock
);
69 static inline void __preempt_write_lock(rwlock_t
*lock
)
71 if (preempt_count() > 1) {
72 _raw_write_lock(lock
);
78 while (rwlock_is_locked(lock
))
81 } while (!_raw_write_trylock(lock
));
84 void __lockfunc
_write_lock(rwlock_t
*lock
)
87 if (unlikely(!_raw_write_trylock(lock
)))
88 __preempt_write_lock(lock
);
91 void __lockfunc
_spin_lock(spinlock_t
*lock
)
97 void __lockfunc
_write_lock(rwlock_t
*lock
)
100 _raw_write_lock(lock
);
103 EXPORT_SYMBOL(_spin_lock
);
104 EXPORT_SYMBOL(_write_lock
);
106 void __lockfunc
_read_lock(rwlock_t
*lock
)
109 _raw_read_lock(lock
);
111 EXPORT_SYMBOL(_read_lock
);
113 void __lockfunc
_spin_unlock(spinlock_t
*lock
)
115 _raw_spin_unlock(lock
);
118 EXPORT_SYMBOL(_spin_unlock
);
120 void __lockfunc
_write_unlock(rwlock_t
*lock
)
122 _raw_write_unlock(lock
);
125 EXPORT_SYMBOL(_write_unlock
);
127 void __lockfunc
_read_unlock(rwlock_t
*lock
)
129 _raw_read_unlock(lock
);
132 EXPORT_SYMBOL(_read_unlock
);
134 unsigned long __lockfunc
_spin_lock_irqsave(spinlock_t
*lock
)
138 local_irq_save(flags
);
140 _raw_spin_lock_flags(lock
, flags
);
143 EXPORT_SYMBOL(_spin_lock_irqsave
);
145 void __lockfunc
_spin_lock_irq(spinlock_t
*lock
)
149 _raw_spin_lock(lock
);
151 EXPORT_SYMBOL(_spin_lock_irq
);
153 void __lockfunc
_spin_lock_bh(spinlock_t
*lock
)
157 _raw_spin_lock(lock
);
159 EXPORT_SYMBOL(_spin_lock_bh
);
161 unsigned long __lockfunc
_read_lock_irqsave(rwlock_t
*lock
)
165 local_irq_save(flags
);
167 _raw_read_lock(lock
);
170 EXPORT_SYMBOL(_read_lock_irqsave
);
172 void __lockfunc
_read_lock_irq(rwlock_t
*lock
)
176 _raw_read_lock(lock
);
178 EXPORT_SYMBOL(_read_lock_irq
);
180 void __lockfunc
_read_lock_bh(rwlock_t
*lock
)
184 _raw_read_lock(lock
);
186 EXPORT_SYMBOL(_read_lock_bh
);
188 unsigned long __lockfunc
_write_lock_irqsave(rwlock_t
*lock
)
192 local_irq_save(flags
);
194 _raw_write_lock(lock
);
197 EXPORT_SYMBOL(_write_lock_irqsave
);
199 void __lockfunc
_write_lock_irq(rwlock_t
*lock
)
203 _raw_write_lock(lock
);
205 EXPORT_SYMBOL(_write_lock_irq
);
207 void __lockfunc
_write_lock_bh(rwlock_t
*lock
)
211 _raw_write_lock(lock
);
213 EXPORT_SYMBOL(_write_lock_bh
);
215 void __lockfunc
_spin_unlock_irqrestore(spinlock_t
*lock
, unsigned long flags
)
217 _raw_spin_unlock(lock
);
218 local_irq_restore(flags
);
221 EXPORT_SYMBOL(_spin_unlock_irqrestore
);
223 void __lockfunc
_spin_unlock_irq(spinlock_t
*lock
)
225 _raw_spin_unlock(lock
);
229 EXPORT_SYMBOL(_spin_unlock_irq
);
231 void __lockfunc
_spin_unlock_bh(spinlock_t
*lock
)
233 _raw_spin_unlock(lock
);
237 EXPORT_SYMBOL(_spin_unlock_bh
);
239 void __lockfunc
_read_unlock_irqrestore(rwlock_t
*lock
, unsigned long flags
)
241 _raw_read_unlock(lock
);
242 local_irq_restore(flags
);
245 EXPORT_SYMBOL(_read_unlock_irqrestore
);
247 void __lockfunc
_read_unlock_irq(rwlock_t
*lock
)
249 _raw_read_unlock(lock
);
253 EXPORT_SYMBOL(_read_unlock_irq
);
255 void __lockfunc
_read_unlock_bh(rwlock_t
*lock
)
257 _raw_read_unlock(lock
);
261 EXPORT_SYMBOL(_read_unlock_bh
);
263 void __lockfunc
_write_unlock_irqrestore(rwlock_t
*lock
, unsigned long flags
)
265 _raw_write_unlock(lock
);
266 local_irq_restore(flags
);
269 EXPORT_SYMBOL(_write_unlock_irqrestore
);
271 void __lockfunc
_write_unlock_irq(rwlock_t
*lock
)
273 _raw_write_unlock(lock
);
277 EXPORT_SYMBOL(_write_unlock_irq
);
279 void __lockfunc
_write_unlock_bh(rwlock_t
*lock
)
281 _raw_write_unlock(lock
);
285 EXPORT_SYMBOL(_write_unlock_bh
);
287 int __lockfunc
_spin_trylock_bh(spinlock_t
*lock
)
291 if (_raw_spin_trylock(lock
))
298 EXPORT_SYMBOL(_spin_trylock_bh
);
300 int in_lock_functions(unsigned long addr
)
302 /* Linker adds these: start and end of __lockfunc functions */
303 extern char __lock_text_start
[], __lock_text_end
[];
305 return addr
>= (unsigned long)__lock_text_start
306 && addr
< (unsigned long)__lock_text_end
;
308 EXPORT_SYMBOL(in_lock_functions
);