本文檔的主要內容是分析SylixOS線程建立的流程,詳細介紹了SylixOS的線程建立函數API_ThreadCreate。安全
在SylixOS中,線程的建立函數不能在中斷中調用。且在線程的建立時,系統會對線程的堆棧大小、優先級和名字等參數作有效性檢查,一旦參數出錯,則線程建立失敗。當參數有效性檢查完畢後,系統調用_Allocate_Tcb_Object函數,從空閒TCB控件池中取出一個空閒的TCB資源(TCB是線程控制塊)。具體的代碼實現如程序清單 2-1所示。函數
程序清單 2-1線程建立的環境和參數檢查ui
/********************************************************************************************************* ** 函數名稱: 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中,系統對線程建立的環境和參數檢查完畢後,會進入安全模式,安全模式的主要做用是保護主線程在建立新線程時不被刪除。spa
在第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會從就緒表中尋找一個最適合運行的線程去運行。code
內部交流文檔,僅針對SylixOS平臺,若發現相關錯誤或者建議,請及時聯繫文檔建立者進行修訂和更新。對象