at v2.6.12-rc3 5.7 kB view raw
1/* 2 * lib/kernel_lock.c 3 * 4 * This is the traditional BKL - big kernel lock. Largely 5 * relegated to obsolescense, 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#if defined(CONFIG_PREEMPT) && defined(__smp_processor_id) && \ 13 defined(CONFIG_DEBUG_PREEMPT) 14 15/* 16 * Debugging check. 17 */ 18unsigned int smp_processor_id(void) 19{ 20 unsigned long preempt_count = preempt_count(); 21 int this_cpu = __smp_processor_id(); 22 cpumask_t this_mask; 23 24 if (likely(preempt_count)) 25 goto out; 26 27 if (irqs_disabled()) 28 goto out; 29 30 /* 31 * Kernel threads bound to a single CPU can safely use 32 * smp_processor_id(): 33 */ 34 this_mask = cpumask_of_cpu(this_cpu); 35 36 if (cpus_equal(current->cpus_allowed, this_mask)) 37 goto out; 38 39 /* 40 * It is valid to assume CPU-locality during early bootup: 41 */ 42 if (system_state != SYSTEM_RUNNING) 43 goto out; 44 45 /* 46 * Avoid recursion: 47 */ 48 preempt_disable(); 49 50 if (!printk_ratelimit()) 51 goto out_enable; 52 53 printk(KERN_ERR "BUG: using smp_processor_id() in preemptible [%08x] code: %s/%d\n", preempt_count(), current->comm, current->pid); 54 print_symbol("caller is %s\n", (long)__builtin_return_address(0)); 55 dump_stack(); 56 57out_enable: 58 preempt_enable_no_resched(); 59out: 60 return this_cpu; 61} 62 63EXPORT_SYMBOL(smp_processor_id); 64 65#endif /* PREEMPT && __smp_processor_id && DEBUG_PREEMPT */ 66 67#ifdef CONFIG_PREEMPT_BKL 68/* 69 * The 'big kernel semaphore' 70 * 71 * This mutex is taken and released recursively by lock_kernel() 72 * and unlock_kernel(). It is transparently dropped and reaquired 73 * over schedule(). It is used to protect legacy code that hasn't 74 * been migrated to a proper locking design yet. 75 * 76 * Note: code locked by this semaphore will only be serialized against 77 * other code using the same locking facility. The code guarantees that 78 * the task remains on the same CPU. 79 * 80 * Don't use in new code. 81 */ 82static DECLARE_MUTEX(kernel_sem); 83 84/* 85 * Re-acquire the kernel semaphore. 86 * 87 * This function is called with preemption off. 88 * 89 * We are executing in schedule() so the code must be extremely careful 90 * about recursion, both due to the down() and due to the enabling of 91 * preemption. schedule() will re-check the preemption flag after 92 * reacquiring the semaphore. 93 */ 94int __lockfunc __reacquire_kernel_lock(void) 95{ 96 struct task_struct *task = current; 97 int saved_lock_depth = task->lock_depth; 98 99 BUG_ON(saved_lock_depth < 0); 100 101 task->lock_depth = -1; 102 preempt_enable_no_resched(); 103 104 down(&kernel_sem); 105 106 preempt_disable(); 107 task->lock_depth = saved_lock_depth; 108 109 return 0; 110} 111 112void __lockfunc __release_kernel_lock(void) 113{ 114 up(&kernel_sem); 115} 116 117/* 118 * Getting the big kernel semaphore. 119 */ 120void __lockfunc lock_kernel(void) 121{ 122 struct task_struct *task = current; 123 int depth = task->lock_depth + 1; 124 125 if (likely(!depth)) 126 /* 127 * No recursion worries - we set up lock_depth _after_ 128 */ 129 down(&kernel_sem); 130 131 task->lock_depth = depth; 132} 133 134void __lockfunc unlock_kernel(void) 135{ 136 struct task_struct *task = current; 137 138 BUG_ON(task->lock_depth < 0); 139 140 if (likely(--task->lock_depth < 0)) 141 up(&kernel_sem); 142} 143 144#else 145 146/* 147 * The 'big kernel lock' 148 * 149 * This spinlock is taken and released recursively by lock_kernel() 150 * and unlock_kernel(). It is transparently dropped and reaquired 151 * over schedule(). It is used to protect legacy code that hasn't 152 * been migrated to a proper locking design yet. 153 * 154 * Don't use in new code. 155 */ 156static __cacheline_aligned_in_smp DEFINE_SPINLOCK(kernel_flag); 157 158 159/* 160 * Acquire/release the underlying lock from the scheduler. 161 * 162 * This is called with preemption disabled, and should 163 * return an error value if it cannot get the lock and 164 * TIF_NEED_RESCHED gets set. 165 * 166 * If it successfully gets the lock, it should increment 167 * the preemption count like any spinlock does. 168 * 169 * (This works on UP too - _raw_spin_trylock will never 170 * return false in that case) 171 */ 172int __lockfunc __reacquire_kernel_lock(void) 173{ 174 while (!_raw_spin_trylock(&kernel_flag)) { 175 if (test_thread_flag(TIF_NEED_RESCHED)) 176 return -EAGAIN; 177 cpu_relax(); 178 } 179 preempt_disable(); 180 return 0; 181} 182 183void __lockfunc __release_kernel_lock(void) 184{ 185 _raw_spin_unlock(&kernel_flag); 186 preempt_enable_no_resched(); 187} 188 189/* 190 * These are the BKL spinlocks - we try to be polite about preemption. 191 * If SMP is not on (ie UP preemption), this all goes away because the 192 * _raw_spin_trylock() will always succeed. 193 */ 194#ifdef CONFIG_PREEMPT 195static inline void __lock_kernel(void) 196{ 197 preempt_disable(); 198 if (unlikely(!_raw_spin_trylock(&kernel_flag))) { 199 /* 200 * If preemption was disabled even before this 201 * was called, there's nothing we can be polite 202 * about - just spin. 203 */ 204 if (preempt_count() > 1) { 205 _raw_spin_lock(&kernel_flag); 206 return; 207 } 208 209 /* 210 * Otherwise, let's wait for the kernel lock 211 * with preemption enabled.. 212 */ 213 do { 214 preempt_enable(); 215 while (spin_is_locked(&kernel_flag)) 216 cpu_relax(); 217 preempt_disable(); 218 } while (!_raw_spin_trylock(&kernel_flag)); 219 } 220} 221 222#else 223 224/* 225 * Non-preemption case - just get the spinlock 226 */ 227static inline void __lock_kernel(void) 228{ 229 _raw_spin_lock(&kernel_flag); 230} 231#endif 232 233static inline void __unlock_kernel(void) 234{ 235 _raw_spin_unlock(&kernel_flag); 236 preempt_enable(); 237} 238 239/* 240 * Getting the big kernel lock. 241 * 242 * This cannot happen asynchronously, so we only need to 243 * worry about other CPU's. 244 */ 245void __lockfunc lock_kernel(void) 246{ 247 int depth = current->lock_depth+1; 248 if (likely(!depth)) 249 __lock_kernel(); 250 current->lock_depth = depth; 251} 252 253void __lockfunc unlock_kernel(void) 254{ 255 BUG_ON(current->lock_depth < 0); 256 if (likely(--current->lock_depth < 0)) 257 __unlock_kernel(); 258} 259 260#endif 261 262EXPORT_SYMBOL(lock_kernel); 263EXPORT_SYMBOL(unlock_kernel); 264