在SylixOS中,在就緒線程和運行線程之間還存在候選運行線程。線程就緒後會被放置到就緒表中,而最須要運行(優先級最高)的線程會被放置到候選表,正常狀況下CPU當前任務結束後,會運行候選表裏的線程。函數
就緒表存放了SylixOS中除了"候選表中的線程"外,全部就緒沒運行的線程。spa
每個CPU的結構體裏面都有一個候選運行表,每個候選表裏最多有一個候選運行線程。候選運行表結構如程序清單 11所示。線程
程序清單 11 候選運行表結構code
/************************************************************************************************* 候選運行表結構 *************************************************************************************************/ #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;
如圖 11所示,優先級卷繞是CPU結構體裏面的候選表裏的標誌位CAND_bNeedRotate。it
圖 11 候選運行表基本操做io
當候選表不爲空時,有一個優先級高於"候選表中線程"的線程就緒時,會產生優先級卷繞並將CPU的優先級卷繞標誌位設置爲1。具體流程如圖 12所示。class
圖 12 優先級卷繞產生的流程object
系統主要在退出內核和退出中斷時嘗試進行線程調度。嘗試進行線程調度的主要函數有:__kernelExit函數、__kernelExitIrq函數、__kernelSched函數和__kernelSchedInt函數。這裏以__kernelExit函數爲例介紹線程調度。date
SylixOS線程調度流程如圖 21所示。map
圖 21 線程調度流程
嘗試調度,檢查當前執行線程可否調度。(中斷中或者在內核中執行, 不容許調度;當前線程就緒且被鎖定, 不容許調度。)如程序清單 21所示。
若是當前執行線程不能調度,繼續運行當前線程,不產生調度。
若是當前執行線程能調度,繼續判斷是否產生了優先級卷繞。
程序清單 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)); } }
優先級卷繞的處理,如程序清單 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; /* 清除優先級卷繞標誌 */ }