歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Linux啟動過程中init/main.c中的start_kernel()函數中的lock_kernel()函數

  1. #ifndef __LINUX_SMPLOCK_H  
  2. #define __LINUX_SMPLOCK_H  
  3.   
  4. #ifdef CONFIG_LOCK_KERNEL   

//判斷內核是否支持內核鎖
//而s3c2410中arch/arm/configs/s3c2410的Code maturity level options下沒有定義,所以lock_kernel()什麼也不做

  1. #include <linux/sched.h>  
  2. #include <linux/spinlock.h>  
  3.   
  4. #define kernel_locked()     (current->lock_depth >= 0)  
  5.   
  6. extern int __lockfunc __reacquire_kernel_lock(void);  
  7. extern void __lockfunc __release_kernel_lock(void);  
  8.   
  9. /*  
  10.  * Release/re-acquire global kernel lock for the scheduler  
  11.  */  
  12. #define release_kernel_lock(tsk) do {       \  
  13.     if (unlikely((tsk)->lock_depth >= 0)) \  
  14.         __release_kernel_lock();    \  
  15. } while (0)  
  16.   
  17. /*  
  18.  * Non-SMP kernels will never block on the kernel lock,  
  19.  * so we are better off returning a constant zero from  
  20.  * reacquire_kernel_lock() so that the compiler can see  
  21.  * it at compile-time.  
  22.  */  
  23. #if defined(CONFIG_SMP) && !defined(CONFIG_PREEMPT_BKL)  
  24. # define return_value_on_smp return  
  25. #else  
  26. # define return_value_on_smp  
  27. #endif  
  28.   
  29. static inline int reacquire_kernel_lock(struct task_struct *task)  
  30. {  
  31.     if (unlikely(task->lock_depth >= 0))  
  32.         return_value_on_smp __reacquire_kernel_lock();  
  33.     return 0;  
  34. }  
  35.   
  36. extern void __lockfunc lock_kernel(void)    __acquires(kernel_lock);  
  37. extern void __lockfunc unlock_kernel(void)  __releases(kernel_lock);  
  38.   
  39. #else  
  40.   
  41. #define lock_kernel()               do { } while(0)  
  42. #define unlock_kernel()             do { } while(0)  
  43. #define release_kernel_lock(task)       do { } while(0)  
  44. #define reacquire_kernel_lock(task)     0  
  45. #define kernel_locked()             1  
  46.   
  47. #endif /* CONFIG_LOCK_KERNEL */  
  48. #endif /* __LINUX_SMPLOCK_H */  

//如果定義了CONFIG_LOCK_KERNEL,則轉到下面代碼

//判斷是使用big kernel semaphore還是big kernel lock
//而s3c2410中arch/arm/configs/s3c2410中沒有定義

  1. #ifdef CONFIG_PREEMPT_BKL  //判斷是使用big kernel semaphore還是big kernel lock  
  2. //而s3c2410中arch/arm/configs/s3c2410中沒有定義  
  3. /*  
  4.  * The 'big kernel semaphore'  
  5.  *  
  6.  * This mutex is taken and released recursively by lock_kernel()  
  7.  * and unlock_kernel().  It is transparently dropped and reacquired  
  8.  * over schedule().  It is used to protect legacy code that hasn't  
  9.  * been migrated to a proper locking design yet.  
  10.  *  
  11.  * Note: code locked by this semaphore will only be serialized against  
  12.  * other code using the same locking facility. The code guarantees that  
  13.  * the task remains on the same CPU.  
  14.  *  
  15.  * Don't use in new code.  
  16.  */  
  17. static DECLARE_MUTEX(kernel_sem);  
  18.   
  19. /*  
  20.  * Re-acquire the kernel semaphore.  
  21.  *  
  22.  * This function is called with preemption off.  
  23.  *  
  24.  * We are executing in schedule() so the code must be extremely careful  
  25.  * about recursion, both due to the down() and due to the enabling of  
  26.  * preemption. schedule() will re-check the preemption flag after  
  27.  * reacquiring the semaphore.  
  28.  */  
  29. int __lockfunc __reacquire_kernel_lock(void)  
  30. {  
  31.     struct task_struct *task = current;  
  32.     int saved_lock_depth = task->lock_depth;  
  33.   
  34.     BUG_ON(saved_lock_depth < 0);  
  35.   
  36.     task->lock_depth = -1;  
  37.     preempt_enable_no_resched();  
  38.   
  39.     down(&kernel_sem);  
  40.   
  41.     preempt_disable();  
  42.     task->lock_depth = saved_lock_depth;  
  43.   
  44.     return 0;  
  45. }  
  46.   
  47. void __lockfunc __release_kernel_lock(void)  
  48. {  
  49.     up(&kernel_sem);  
  50. }  
  51.   
  52. /*  
  53.  * Getting the big kernel semaphore.  
  54.  */  
  55. void __lockfunc lock_kernel(void)  
  56. {  
  57.     struct task_struct *task = current;  
  58.     int depth = task->lock_depth + 1;  
  59.   
  60.     if (likely(!depth))  
  61.         /*  
  62.          * No recursion worries - we set up lock_depth _after_  
  63.          */  
  64.         down(&kernel_sem);  
  65.   
  66.     task->lock_depth = depth;  
  67. }  
  68.   
  69. void __lockfunc unlock_kernel(void)  
  70. {  
  71.     struct task_struct *task = current;  
  72.   
  73.     BUG_ON(task->lock_depth < 0);  
  74.   
  75.     if (likely(--task->lock_depth < 0))  
  76.         up(&kernel_sem);  
  77. }  
  78.   
  79. #else  
  80.   
  81. /*  
  82.  * The 'big kernel lock'  
  83.  *  
  84.  * This spinlock is taken and released recursively by lock_kernel()  
  85.  * and unlock_kernel().  It is transparently dropped and reacquired  
  86.  * over schedule().  It is used to protect legacy code that hasn't  
  87.  * been migrated to a proper locking design yet.  
  88.  *  
  89.  * Don't use in new code.  
  90.  */  
  91. static  __cacheline_aligned_in_smp DEFINE_SPINLOCK(kernel_flag);  
  92.   
  93.   
  94. /*  
  95.  * Acquire/release the underlying lock from the scheduler.  
  96.  *  
  97.  * This is called with preemption disabled, and should  
  98.  * return an error value if it cannot get the lock and  
  99.  * TIF_NEED_RESCHED gets set.  
  100.  *  
  101.  * If it successfully gets the lock, it should increment  
  102.  * the preemption count like any spinlock does.  
  103.  *  
  104.  * (This works on UP too - _raw_spin_trylock will never  
  105.  * return false in that case)  
  106.  */  
  107. int __lockfunc __reacquire_kernel_lock(void)  
  108. {  
  109.     while (!_raw_spin_trylock(&kernel_flag)) {  
  110.         if (test_thread_flag(TIF_NEED_RESCHED))  
  111.             return -EAGAIN;  
  112.         cpu_relax();  
  113.     }  
  114.     preempt_disable();  
  115.     return 0;  
  116. }  
  117.   
  118. void __lockfunc __release_kernel_lock(void)  
  119. {  
  120.     _raw_spin_unlock(&kernel_flag);  
  121.     preempt_enable_no_resched();  
  122. }  
  123.   
  124. /*  
  125.  * These are the BKL spinlocks - we try to be polite about preemption.   
  126.  * If SMP is not on (ie UP preemption), this all goes away because the  
  127.  * _raw_spin_trylock() will always succeed.  
  128.  */  
  129. #ifdef CONFIG_PREEMPT   

 //使用big kernel lock的情況下,判斷內核是否支持搶占式調度,支持則執行下面的代碼
//而我們使用的s3c2410是單處理器的,不存在多個CPU競爭資源的情況,所以不需要用大內核鎖/信號量來解決資源競爭的問題
//CONFIG_PREEMPT在arch/arm/configs/s3c2410_deconfig中Kernel Features下,在s3c2410中定義為# CONFIG_PREEMPT is not set

Copyright © Linux教程網 All Rights Reserved