Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  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.