SylixOS線程調度淺析

  1. 概念

    SylixOS中,在就緒線程和運行線程之間還存在候選運行線程。線程就緒後會被放置到就緒表中,而最需要運行(優先級最高)的線程會被放置到候選表,正常情況下CPU當前任務結束後,會運行候選表裏的線程。

  2. 就緒表

    就緒表存放了SylixOS中除了"候選表中的線程"外,所有就緒沒運行的線程。

  3. 候選表

    每一個CPU的結構體裏面都有一個候選運行表,每一個候選表裏最多有一個候選運行線程。候選運行表結構如程序清單 11所示。

    程序清單 11候選運行表結構

    /*********************************************************************************************************
      候選運行表結構
    *********************************************************************************************************/
    #ifdef __SYLIXOS_KERNEL
    
    typedef struct {
        volatile PLW_CLASS_TCB  CAND_ptcbCand;                              /*  候選運行線程                */
        volatile BOOL           CAND_bNeedRotate;                           /*  可能產生了優先級卷繞        */
    } LW_CLASS_CAND;
    typedef LW_CLASS_CAND      *PLW_CLASS_CAND;
  4. 優先級卷繞

    如圖 11所示,優先級卷繞是CPU結構體裏面的候選表裏的標誌位CAND_bNeedRotate。

    11候選運行表基本操作

  5. 優先級卷繞的產生

    當候選表不爲空時,有一個優先級高於"候選表中線程"的線程就緒時,會產生優先級卷繞並將CPU的優先級卷繞標誌位設置爲1。具體流程如圖 12所示。

    12優先級卷繞產生的流程

     

  6. 線程調度

    系統主要在退出內核和退出中斷時嘗試進行線程調度。嘗試進行線程調度的主要函數有:__kernelExit函數、__kernelExitIrq函數、__kernelSched函數和__kernelSchedInt函數。這裏以__kernelExit函數爲例介紹線程調度。

  7. 線程調度流程

    SylixOS線程調度流程如圖 21所示。

    21線程調度流程

  8. 嘗試調度

    嘗試調度,檢查當前執行線程能否調度。(中斷中或者在內核中執行, 不允許調度;當前線程就緒且被鎖定, 不允許調度。)如程序清單 21所示。

    1. 如果當前執行線程不能調度,繼續運行當前線程,不產生調度。
    2. 如果當前執行線程能調度,繼續判斷是否產生了優先級卷繞。

    程序清單 21 _SchedGetCand函數 

    PLW_CLASS_TCB  _SchedGetCand (PLW_CLASS_CPU  pcpuCur, ULONG  ulCurMaxLock)
    {
        if (!__COULD_SCHED(pcpuCur, ulCurMaxLock)) {                        /*  當前執行線程不能調度        */
            return  (pcpuCur->CPU_ptcbTCBCur);
            
        } else {                                                            /*  可以執行線程切換            */
            if (LW_CAND_ROT(pcpuCur)) {                                     /*  判斷是否產生優先級卷繞      */
                _CandTableUpdate(pcpuCur);
            }
            return  (LW_CAND_TCB(pcpuCur));
        }
    }
    

  9. 優先級卷繞處理

    優先級卷繞的處理,如程序清單 22所示。

    第一步,如果產生了優先級卷繞,判斷候選表是否爲空。

    第二步,如果候選表不爲空,判斷就緒線程是否存在更加需要運行的線程。

    第三步,如果存在更加需要運行的線程,清空候選表(被清空的線程,會被插到對應就緒表的頭部,下次優先調用),重新選擇一個更需要運行的線程放入候選表,進行線程上下文切換,執行候選表中線程。

    程序清單 22優先級就卷繞處理函數

    VOID _CandTableUpdate (PLW_CLASS_CPU   pcpu)
    {
                 UINT8              ucPriority;
        REGISTER PLW_CLASS_TCB      ptcbCand;
                 PLW_CLASS_PCBBMAP  ppcbbmap;
                 BOOL               bNeedRotate = LW_FALSE;
    
        if (!LW_CPU_IS_ACTIVE(pcpu)) {                                      /*  CPU 必須爲激活狀態          */
            return;
        }
        
        ptcbCand = LW_CAND_TCB(pcpu);
        if (ptcbCand == LW_NULL) {                                          /*  當前沒有候選線程            */
            _CandTableFill(pcpu);
            goto    __update_done;
        }
        
        ppcbbmap = _SchedSeekPriority(pcpu, &ucPriority);                   /*  當前就緒表中最高優先級      */
        if (ppcbbmap == LW_NULL) {
            LW_CAND_ROT(pcpu) = LW_FALSE;                                   /*  清除優先級卷繞標誌          */
            return;
        }
        
        if (ptcbCand->TCB_usSchedCounter == 0) {                            /*  已經沒有時間片了            */
            if (LW_PRIO_IS_HIGH_OR_EQU(ucPriority, 
                                       ptcbCand->TCB_ucPriority)) {         /*  是否需要輪轉                */
                bNeedRotate = LW_TRUE;
            }
        } else {
            if (LW_PRIO_IS_HIGH(ucPriority, 
                                ptcbCand->TCB_ucPriority)) {
                bNeedRotate = LW_TRUE;
            }
        }
        
        if (bNeedRotate) {                                                  /*  存在更需要運行的線程        */
            _CandTableEmpty(pcpu);                                          /*  清空候選表                  */
            _CandTableResel(pcpu, ppcbbmap, ucPriority);                    /*  重新選擇任務執行            */
        }
        
    __update_done:
        LW_CAND_ROT(pcpu) = LW_FALSE;                                       /*  清除優先級卷繞標誌          */
發佈了27 篇原創文章 · 獲贊 50 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章