本文档的主要内容是分析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进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。