1 /*
2 * lib/kernel_lock.c
3 *
4 * This is the traditional BKL - big kernel lock. Largely
5 * relegated to obsolescence, but used by various less
6 * important (or lazy) subsystems.
7 */
8 #include <linux/smp_lock.h>
9 #include <linux/module.h>
10 #include <linux/kallsyms.h>
11
12 /*
13 * The 'big kernel semaphore'
14 *
15 * This mutex is taken and released recursively by lock_kernel()
16 * and unlock_kernel(). It is transparently dropped and reacquired
17 * over schedule(). It is used to protect legacy code that hasn't
18 * been migrated to a proper locking design yet.
19 *
20 * Note: code locked by this semaphore will only be serialized against
21 * other code using the same locking facility. The code guarantees that
22 * the task remains on the same CPU.
23 *
24 * Don't use in new code.
25 */
26 DECLARE_MUTEX(kernel_sem);
27
28 /*
29 * Re-acquire the kernel semaphore.
30 *
31 * This function is called with preemption off.
32 *
33 * We are executing in schedule() so the code must be extremely careful
34 * about recursion, both due to the down() and due to the enabling of
35 * preemption. schedule() will re-check the preemption flag after
36 * reacquiring the semaphore.
37 *
38 * Called with interrupts disabled.
39 */
40 int __lockfunc __reacquire_kernel_lock(void)
41 {
42 struct task_struct *task = current;
43 int saved_lock_depth = task->lock_depth;
44
45 local_irq_enable();
46 BUG_ON(saved_lock_depth < 0);
47
48 task->lock_depth = -1;
49
50 down(&kernel_sem);
51
52 task->lock_depth = saved_lock_depth;
53
54 local_irq_disable();
55
56 return 0;
57 }
58
59 void __lockfunc __release_kernel_lock(void)
60 {
61 up(&kernel_sem);
62 }
63
64 /*
65 * Getting the big kernel semaphore.
66 */
67 void __lockfunc lock_kernel(void)
68 {
69 struct task_struct *task = current;
70 int depth = task->lock_depth + 1;
71
72 if (likely(!depth)) {
73 /*
74 * No recursion worries - we set up lock_depth _after_
75 */
76 down(&kernel_sem);
77 #ifdef CONFIG_DEBUG_RT_MUTEXES
78 current->last_kernel_lock = __builtin_return_address(0);
79 #endif
80 }
81
82 task->lock_depth = depth;
83 }
84
85 void __lockfunc unlock_kernel(void)
86 {
87 struct task_struct *task = current;
88
89 BUG_ON(task->lock_depth < 0);
90
91 if (likely(--task->lock_depth == -1)) {
92 #ifdef CONFIG_DEBUG_RT_MUTEXES
93 current->last_kernel_lock = NULL;
94 #endif
95 up(&kernel_sem);
96 }
97 }
98
99 EXPORT_SYMBOL(lock_kernel);
100 EXPORT_SYMBOL(unlock_kernel);
101
102
|
This page was automatically generated by the
LXR engine.
|