uC/OS中鎖調度器爲什麼比關中斷效率更高

uC/OS中鎖調度器爲什麼比關中斷效率更高

1. 背景

今天看《μC/OS-III源碼分析筆記》的時候學習了通過使用鎖調度器代替關中斷,並使用中斷延遲提交,能夠大大節省關中斷的時間,提高運行效率。但是效率具體是如何提高的,書中的說明我沒有太看明白,於是我就把書中提到的函數的源代碼找出來分析了一下,希望能夠理解鎖調度器關中斷兩者之間的區別。uC/OS完整源代碼可以從官網我的Github上下載。

2. 優化原因

使用關中斷進入臨界區以後,系統不會響應中斷請求,如果臨界區裏需要做一些如I/O、與外設交互等需要進入較長時間的等待狀態的任務,此時CPU就處於忙等狀態,不能夠響應中斷去運行中斷處理程序,這就降低了系統的運行效率。

鎖調度器的方式可以保證當前運行的任務不會被其他任務搶佔,使任務進入了臨界區。

但是鎖住調度器之後還可以響應中斷,減少了關中斷的時間,使得CPU不會長時間處於忙等狀態,提高了系統的實時性和運行效率。

3. 關中斷和鎖調度器

3.1. 概念

  • 中斷:中斷機制是處理器的重要基礎設施,用來應對各種事件的響應和處理。當外設或者處理器自身有事件發生時,處理器會暫停執行當前的代碼,並轉向處理這些中斷事務。中斷可分爲外部中斷、內部中斷和軟件中斷1

  • 搶佔:通過調度器實現,搶佔的發生可能是因爲有更高優先級的任務進入就緒隊列(優先級搶佔機制)或該任務的時間片已結束(時間片輪轉機制)。搶佔可分爲用戶搶佔和內核搶佔。

  • 關中斷:進入臨界段,禁止其他中斷操作,關中斷以後產生的中斷請求會被掛起,等待開中斷以後再響應。

  • 開中斷:退出臨界段,允許中斷操作。

  • 鎖調度器:鎖住調度器(Lock the scheduler),不允許其他任務搶佔當前任務。

  • 開啓調度器:解鎖調度器(Unlock the scheduler),允許其他任務搶佔當前任務。

  • RTOS:實時操作系統(Real Time Operating System)。

  • ISR:中斷服務程序(Interrupt Service Routine)。在CPU保護中斷現場之後,RTOS進入,進行中斷預處理,記錄當前中斷嵌套深度,查找用戶登記的中斷服務程序,然後CPU開始執行中斷服務程序1

3.2. 源代碼

3.2.1. 開/關中斷

這裏有兩種方式通過關中斷進入臨界段

  • CPU_INT_DIS()
  • CPU_CRITICAL_ENTER()

CPU_CFG_INT_DIS_MEAS_EN標記爲False,兩個函數完全一致,後者只是將前者封裝了一下。

CPU_CFG_INT_DIS_MEAS_EN標記爲True,CPU_CRITICAL_ENTER()會記錄關中斷的時間。


#define  CPU_INT_DIS() do { CPU_IntDis(); } while (0)
/* Disable interrupts. */
#define  CPU_INT_EN() do { CPU_IntEn();  } while (0)
/* Enable  interrupts.*/

#ifdef   CPU_CFG_INT_DIS_MEAS_EN
/* Disable interrupts, ...                      */
/* & start interrupts disabled time measurement.*/
#define  CPU_CRITICAL_ENTER()  do { CPU_INT_DIS();         \
                                    CPU_IntDisMeasStart(); } while (0)
/* Stop & measure   interrupts disabled time,   */
/* ...  & re-enable interrupts.                 */
#define  CPU_CRITICAL_EXIT()   do { CPU_IntDisMeasStop();  \
                                    CPU_INT_EN();          } while (0)
/* -------------------------------------------- */
#else

#define  CPU_CRITICAL_ENTER()  do { CPU_INT_DIS(); } while (0)
/* Disable   interrupts.*/
#define  CPU_CRITICAL_EXIT()   do { CPU_INT_EN();  } while (0)
/* Re-enable interrupts.*/
#endif

3.2.2. 鎖調度器

  • OS_CFG_ISR_POST_DEFERRED_EN:標記是否使用中斷延遲提交
// os_cfg.h
#define OS_CFG_ISR_POST_DEFERRED_EN     0u
/* Enable (1) or Disable (0) Deferred ISR posts*/

這裏有兩種方式進入臨界段

  1. 調用OS_CRITICAL_ENTER()鎖調度器。
  2. 先調用CPU_CRITICAL_ENTER()關中斷,再調用OS_CRITICAL_ENTER_CPU_EXIT()鎖調度器並開中斷。
  • OS_CFG_ISR_POST_DEFERRED_EN標記爲False,OS_CRITICAL_ENTER()實現的是關中斷,OS_CRITICAL_ENTER_CPU_EXIT()是一個空函數。

  • CPU_CFG_INT_DIS_MEAS_EN標記爲True,這裏的兩個函數都能實現鎖調度器的功能。


// os.h
#if (OS_CFG_ISR_POST_DEFERRED_EN == DEF_ENABLED)
/* Deferred ISR Posts */
/* Lock the scheduler*/
#define  OS_CRITICAL_ENTER()                                       \
         do {                                                      \
             CPU_CRITICAL_ENTER();                                 \
             OSSchedLockNestingCtr++;                              \
             if (OSSchedLockNestingCtr == 1u) {                    \
                 OS_SCHED_LOCK_TIME_MEAS_START();                  \
             }                                                     \
             CPU_CRITICAL_EXIT();                                  \
         } while (0)
/* Lock the scheduler but re-enable interrupts */
#define  OS_CRITICAL_ENTER_CPU_EXIT()                              \
         do {                                                      \
             OSSchedLockNestingCtr++;                              \
                                                                   \
             if (OSSchedLockNestingCtr == 1u) {                    \
                 OS_SCHED_LOCK_TIME_MEAS_START();                  \
             }                                                     \
             CPU_CRITICAL_EXIT();                                  \
         } while (0)

/* Scheduling occurs only if an interrupt occurs*/
#define  OS_CRITICAL_EXIT()                                        \
         do {                                                      \
             CPU_CRITICAL_ENTER();                                 \
             OSSchedLockNestingCtr--;                              \
             if (OSSchedLockNestingCtr == (OS_NESTING_CTR)0) {     \
                 OS_SCHED_LOCK_TIME_MEAS_STOP();                   \
                 if (OSIntQNbrEntries > (OS_OBJ_QTY)0) {           \
                     CPU_CRITICAL_EXIT();                          \
                     OS_Sched0();                                  \
                 } else {                                          \
                     CPU_CRITICAL_EXIT();                          \
                 }                                                 \
             } else {                                              \
                 CPU_CRITICAL_EXIT();                              \
             }                                                     \
         } while (0)

#define  OS_CRITICAL_EXIT_NO_SCHED()                               \
         do {                                                      \
             CPU_CRITICAL_ENTER();                                 \
             OSSchedLockNestingCtr--;                              \
             if (OSSchedLockNestingCtr == (OS_NESTING_CTR)0) {     \
                 OS_SCHED_LOCK_TIME_MEAS_STOP();                   \
             }                                                     \
             CPU_CRITICAL_EXIT();                                  \
         } while (0)

#else
/* Direct ISR Posts */

#define  OS_CRITICAL_ENTER()                    CPU_CRITICAL_ENTER()

#define  OS_CRITICAL_ENTER_CPU_EXIT()

#define  OS_CRITICAL_EXIT()                     CPU_CRITICAL_EXIT()

#define  OS_CRITICAL_EXIT_NO_SCHED()            CPU_CRITICAL_EXIT()

#endif

4. 參考文獻

[1] 劉旭明. 嵌入式實時操作系統原理與最佳實踐. 機械工業出版社, 2014.

聯繫郵箱:[email protected]

Github:https://github.com/CurrenWong

歡迎轉載/Star/Fork,有問題歡迎通過郵箱交流。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章