本文档的主要内容是分析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平台,若发现相关错误或者建议,请及时联系文档创建者进行修订和更新。
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。