您好,登錄后才能下訂單哦!
本文檔的主要內容是分析SylixOS線程創建的流程,詳細介紹了SylixOS的線程創建函數API_ThreadCreate。
在SylixOS中,線程的創建函數不能在中斷中調用。且在線程的創建時,系統會對線程的堆棧大小、優先級和名字等參數做有效性檢查,一旦參數出錯,則線程創建失敗。當參數有效性檢查完畢后,系統調用_Allocate_Tcb_Object函數,從空閑TCB控件池中取出一個空閑的TCB資源(TCB是線程控制塊)。具體的代碼實現如程序清單 2-1所示。
程序清單 2-1線程創建的環境和參數檢查
/********************************************************************************************************* ** 函數名稱: API_ThreadCreate ** 功能描述: 建立一個線程 ** 輸 入 : pcName 線程名 ** pfuncThread 指線程代碼段起始地址 ** pthreadattr 線程屬性集合指針 ** pulId 線程生成的ID指針 可以為 NULL ** 輸 出 : pulId 線程句柄 同 ID 一個概念 *********************************************************************************************************/ LW_API LW_OBJECT_HANDLE API_ThreadCreate (CPCHAR pcName, PTHREAD_START_ROUTINE pfuncThread, PLW_CLASS_THREADATTR pthreadattr, LW_OBJECT_ID *pulId) { if (LW_CPU_GET_CUR_NESTING()) { /* 不能在中斷中調用 */ return (LW_OBJECT_HANDLE_INVALID); } if (threadattrDefault.THREADATTR_stStackByteSize == 0) { threadattrDefault = API_ThreadAttrGetDefault(); /* 初始化默認屬性 */ } if (pthreadattr == LW_NULL) { pthreadattr = &threadattrDefault; /* 使用默認屬性 */ } /* 默認屬性總是使用自動分配堆棧*/ #if LW_CFG_ARG_CHK_EN > 0 if (!pfuncThread) { /* 指線程代碼段起始地址為空 */ return (LW_OBJECT_HANDLE_INVALID); } if (_StackSizeCheck(pthreadattr->THREADATTR_stStackByteSize)) { /* 堆棧大小不正確 */ return (LW_OBJECT_HANDLE_INVALID); } if (_PriorityCheck(pthreadattr->THREADATTR_ucPriority)) { /* 優先級錯誤 */ return (LW_OBJECT_HANDLE_INVALID); } #endif if (_Object_Name_Invalid(pcName)) { /* 檢查名字有效性 */ return (LW_OBJECT_HANDLE_INVALID); } __KERNEL_MODE_PROC( ptcb = _Allocate_Tcb_Object(); /* 獲得一個 TCB */ ); if (!ptcb) { /* 檢查是否可以建立線程 */ return (LW_OBJECT_HANDLE_INVALID); }
如程序清單 3-1所示,在SylixOS中,系統對線程創建的環境和參數檢查完畢后,會進入安全模式,安全模式的主要作用是保護主線程在創建新線程時不被刪除。
在第2小節中提到"當參數有效性檢查完畢后,系統調用_Allocate_Tcb_Object函數,從空閑TCB控件池中取出一個空閑的TCB資源",需要注意這里只是簡單的獲得一個TCB資源。當系統調用_TCBBuild函數,對TCB結構體的成員進行賦值后,才真正完成TCB的構建。
程序清單 3-1線程創建的安全模式
if (LW_SYS_STATUS_IS_RUNNING()) { _ThreadSafeInternal(); /* 進入安全模式 */ } lib_bzero(&ptcb->TCB_pstkStackTop, sizeof(LW_CLASS_TCB) - _LIST_OFFSETOF(LW_CLASS_TCB, TCB_pstkStackTop)); /* TCB 清零 */ ulIdTemp = _MakeObjectId(_OBJECT_THREAD, LW_CFG_PROCESSOR_NUMBER, ptcb->TCB_usIndex); /* 構建對象 id */ /* 初始化堆棧,SHELL */ pstkFristFree = archTaskCtxCreate((PTHREAD_START_ROUTINE)_ThreadShell, (PVOID)pfuncThread, /* 真正的可執行代碼體 */ pstkTop, pthreadattr->THREADATTR_ulOption); ulError = _TCBBuildExt(ptcb); /* 首先先初始化擴展結構 */ if (ulError) { iErrLevel = 2; _ErrorHandle(ulError); goto __error_handle; } _TCBBuild(pthreadattr->THREADATTR_ucPriority, /* 構建 TCB */ pstkFristFree, /* 空閑棧區地址 */ pstkTop, /* 主棧區地址 */ pstkButtom, /* 棧底 */ pstkGuard, pthreadattr->THREADATTR_pvExt, pstkLowAddress, stStackSize, /* 相對于字對齊的堆棧大小 */ ulIdTemp, pthreadattr->THREADATTR_ulOption, pfuncThread, ptcb, pthreadattr->THREADATTR_pvArg); if (!(pthreadattr->THREADATTR_ulOption & LW_OPTION_THREAD_INIT)) { /* 非僅初始化 */ _TCBTryRun(ptcb); /* 嘗試運行新任務 */ } if (pulId) { *pulId = ulIdTemp; /* 記錄 ID */ } if (LW_SYS_STATUS_IS_RUNNING()) { _ThreadUnsafeInternal(); /* 退出安全模式 */ } return (LW_OBJECT_HANDLE_INVALID); }
在安全模式中,當TCB構建完成后,會調用_TCBTryRun函數,嘗試將新創建的線程加入候選表中。若候選表非空且新創建的線程優先級高于候選表里的線程時,會產生優先級卷繞。當CPU下次調度,檢測到有優先級卷繞時,CPU會從就緒表中尋找一個最適合運行的線程去運行。
內部交流文檔,僅針對SylixOS平臺,若發現相關錯誤或者建議,請及時聯系文檔創建者進行修訂和更新。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。