當前位置:首頁 > 嵌入式培訓(xùn) > 嵌入式學(xué)習(xí) > 講師博文 > SylixOS源碼分析
修訂歷史
版本 日期 原因
V1.00 2017/01/20 創(chuàng)建文檔
目 錄
1. 概念 1
1.1 就緒表 1
1.2 候選表 1
1.3 優(yōu)先級卷繞 1
1.3.1 優(yōu)先級卷繞的產(chǎn)生 1
2. 線程調(diào)度 2
2.1 線程調(diào)度流程 2
2.1.1 嘗試調(diào)度 3
2.1.2 優(yōu)先級卷繞處理 4
1. 概念
在SylixOS中,在就緒線程和運行線程之間還存在候選運行線程。線程就緒后會被放置到就緒表中,而需要運行(優(yōu)先級高)的線程會被放置到候選表,正常情況下CPU當前任務(wù)結(jié)束后,會運行候選表里的線程。
1.1 就緒表
就緒表存放了SylixOS中除了“候選表中的線程”外,所有就緒沒運行的線程。
1.2 候選表
每一個CPU的結(jié)構(gòu)體里面都有一個候選運行表,每一個候選表里多有一個候選運行線程。候選運行表結(jié)構(gòu)如程序清單 1 1所示。
程序清單 1 1 候選運行表結(jié)構(gòu)
/*********************************************************************************************************
候選運行表結(jié)構(gòu)
*********************************************************************************************************/
#ifdef __SYLIXOS_KERNEL
typedef struct {
volatile PLW_CLASS_TCB CAND_ptcbCand; /* 候選運行線程 */
volatile BOOL CAND_bNeedRotate; /* 可能產(chǎn)生了優(yōu)先級卷繞 */
} LW_CLASS_CAND;
typedef LW_CLASS_CAND *PLW_CLASS_CAND;
1.3 優(yōu)先級卷繞
優(yōu)先級卷繞是CPU結(jié)構(gòu)體里面的候選表里的標志位CAND_bNeedRotate。
1.3.1 優(yōu)先級卷繞的產(chǎn)生
當候選表不為空時,有一個優(yōu)先級高于“候選表中線程”的線程就緒時,會產(chǎn)生優(yōu)先級卷繞并將CPU的優(yōu)先級卷繞標志位設(shè)置為1。
2. 線程調(diào)度
系統(tǒng)主要在退出內(nèi)核和退出中斷時嘗試進行線程調(diào)度。嘗試進行線程調(diào)度的主要函數(shù)有:__kernelExit函數(shù)、__kernelExitIrq函數(shù)、__kernelSched函數(shù)和__kernelSchedInt函數(shù)。這里以__kernelExit函數(shù)為例介紹線程調(diào)度。
2.1 線程調(diào)度流程
2.1.1 嘗試調(diào)度
嘗試調(diào)度,檢查當前執(zhí)行線程能否調(diào)度。(中斷中或者在內(nèi)核中執(zhí)行, 不允許調(diào)度;當前線程就緒且被鎖定, 不允許調(diào)度。)如程序清單 2 1所示。
1) 如果當前執(zhí)行線程不能調(diào)度,繼續(xù)運行當前線程,不產(chǎn)生調(diào)度。
2) 如果當前執(zhí)行線程能調(diào)度,繼續(xù)判斷是否產(chǎn)生了優(yōu)先級卷繞。
程序清單 2 1 _SchedGetCand函數(shù)
PLW_CLASS_TCB _SchedGetCand (PLW_CLASS_CPU pcpuCur, ULONG ulCurMaxLock)
{
if (!__COULD_SCHED(pcpuCur, ulCurMaxLock)) { /* 當前執(zhí)行線程不能調(diào)度 */
return (pcpuCur->CPU_ptcbTCBCur);
} else { /* 可以執(zhí)行線程切換 */
if (LW_CAND_ROT(pcpuCur)) { /* 判斷是否產(chǎn)生優(yōu)先級卷繞 */
_CandTableUpdate(pcpuCur);
}
return (LW_CAND_TCB(pcpuCur));
}
}
2.1.2 優(yōu)先級卷繞處理
優(yōu)先級卷繞的處理,如程序清單 2 2所示。
第一步,如果產(chǎn)生了優(yōu)先級卷繞,判斷候選表是否為空。
第二步,如果候選表不為空,判斷就緒線程是否存在更加需要運行的線程。
第三步,如果存在更加需要運行的線程,清空候選表(被清空的線程,會被插到對應(yīng)就緒表的頭部,下次優(yōu)先調(diào)用),重新選擇一個更需要運行的線程放入候選表,進行線程上下文切換,執(zhí)行候選表中線程。
程序清單 2 2 優(yōu)先級就卷繞處理函數(shù)
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 必須為激活狀態(tài) */
return;
}
ptcbCand = LW_CAND_TCB(pcpu);
if (ptcbCand == LW_NULL) { /* 當前沒有候選線程 */
_CandTableFill(pcpu);
goto __update_done;
}
ppcbbmap = _SchedSeekPriority(pcpu, &ucPriority); /* 當前就緒表中高優(yōu)先級 */
if (ppcbbmap == LW_NULL) {
LW_CAND_ROT(pcpu) = LW_FALSE; /* 清除優(yōu)先級卷繞標志 */
return;
}
if (ptcbCand->TCB_usSchedCounter == 0) { /* 已經(jīng)沒有時間片了 */
if (LW_PRIO_IS_HIGH_OR_EQU(ucPriority,
ptcbCand->TCB_ucPriority)) { /* 是否需要輪轉(zhuǎn) */
bNeedRotate = LW_TRUE;
}
} else {
if (LW_PRIO_IS_HIGH(ucPriority,
ptcbCand->TCB_ucPriority)) {
bNeedRotate = LW_TRUE;
}
}
if (bNeedRotate) { /* 存在更需要運行的線程 */
_CandTableEmpty(pcpu); /* 清空候選表 */
_CandTableResel(pcpu, ppcbbmap, ucPriority); /* 重新選擇任務(wù)執(zhí)行 */
}
__update_done:
LW_CAND_ROT(pcpu) = LW_FALSE; /* 清除優(yōu)先級卷繞標志 */
}