-
概念
在SylixOS中,在就緒線程和運行線程之間還存在候選運行線程。線程就緒後會被放置到就緒表中,而最需要運行(優先級最高)的線程會被放置到候選表,正常情況下CPU當前任務結束後,會運行候選表裏的線程。
-
就緒表
就緒表存放了SylixOS中除了"候選表中的線程"外,所有就緒沒運行的線程。
-
候選表
每一個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;
-
優先級卷繞
如圖 11所示,優先級卷繞是CPU結構體裏面的候選表裏的標誌位CAND_bNeedRotate。
圖 11候選運行表基本操作
-
優先級卷繞的產生
當候選表不爲空時,有一個優先級高於"候選表中線程"的線程就緒時,會產生優先級卷繞並將CPU的優先級卷繞標誌位設置爲1。具體流程如圖 12所示。
圖 12優先級卷繞產生的流程
-
線程調度
系統主要在退出內核和退出中斷時嘗試進行線程調度。嘗試進行線程調度的主要函數有:__kernelExit函數、__kernelExitIrq函數、__kernelSched函數和__kernelSchedInt函數。這裏以__kernelExit函數爲例介紹線程調度。
-
線程調度流程
SylixOS線程調度流程如圖 21所示。
圖 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; /* 清除優先級卷繞標誌 */
SylixOS線程調度淺析
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.