前言

  • 20201009
  • LiteOS 2018
  • 需要会通用链表

链接

参考

  • 上面链接

笔录草稿

部分源码分析

源码分析

LOS_TaskCreate函数

  • 需要一个 任务初始化参数结构体 TSK_INIT_PARAM_S 和 一个任务句柄。
  • TSK_INIT_PARAM_S 源码
/**
* @ingroup los_task
* Define the structure of the parameters used for task creation.
*
* Information of specified parameters passed in during task creation.
*/
typedef struct tagTskInitParam
{
TSK_ENTRY_FUNC pfnTaskEntry; /**< Task entrance function */
UINT16 usTaskPrio; /**< Task priority */
UINT32 uwArg; /**< Task parameters */
UINT32 uwStackSize; /**< Task stack size */
CHAR *pcName; /**< Task name */
UINT32 uwResved; /**< Reserved */
} TSK_INIT_PARAM_S;
  • LOS_TaskCreate 函数源码

    • 内含解读
/*****************************************************************************
Function : LOS_TaskCreate
Description : Create a task
Input : pstInitParam --- Task init parameters
Output : puwTaskID --- Save task ID
Return : LOS_OK on success or error code on failure
*****************************************************************************/
LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskCreate(UINT32 *puwTaskID, TSK_INIT_PARAM_S *pstInitParam)
{
UINT32 uwRet = LOS_OK;
UINTPTR uvIntSave;
LOS_TASK_CB *pstTaskCB; // 定义一个任务控制块 uwRet = LOS_TaskCreateOnly(puwTaskID, pstInitParam); // 以挂起的方式创建一个新的任务(即是阻塞态)
if (LOS_OK != uwRet)
{
return uwRet;
}
pstTaskCB = OS_TCB_FROM_TID(*puwTaskID); // 通过任务 ID 获取 TCB 句柄 uvIntSave = LOS_IntLock(); // 锁任务
pstTaskCB->usTaskStatus &= (~OS_TASK_STATUS_SUSPEND);
pstTaskCB->usTaskStatus |= OS_TASK_STATUS_READY; // 解除阻塞-->进入就绪 #if (LOSCFG_BASE_CORE_CPUP == YES) // CPU 利用率模块代码段
g_pstCpup[pstTaskCB->uwTaskID].uwID = pstTaskCB->uwTaskID;
g_pstCpup[pstTaskCB->uwTaskID].usStatus = pstTaskCB->usTaskStatus;
#endif osPriqueueEnqueue(&pstTaskCB->stPendList, pstTaskCB->usPriority); // 将该任务插入 优先级队列 ,即是 就绪列表
g_stLosTask.pstNewTask = LOS_DL_LIST_ENTRY(osPriqueueTop(), LOS_TASK_CB, stPendList); /*lint !e413*/ /* 找出已经创建的任务中最高优先级、最先插入的 TCB */ /* 以下只是判断是否需要调度而已 */
/* 如果系统开启了调度,且,锁任务关闭,则,进入二次判断 */
if ((g_bTaskScheduled) && (g_usLosTaskLock == 0))
{
/* 如果最高优先级、最先插入的任务不在运行态,则进行调度 */
if (g_stLosTask.pstRunTask != g_stLosTask.pstNewTask)
{
if (LOS_CHECK_SCHEDULE)
{
(VOID)LOS_IntRestore(uvIntSave);
osSchedule();
return LOS_OK;
}
}
}
/* 解锁任务调度 */
(VOID)LOS_IntRestore(uvIntSave);
return LOS_OK;
}

LOS_TaskCreateOnly函数

  • g_stTskRecyleList

    • 任务可回收链表
  • g_stLosFreeTask
    • 任务可用链表
/*****************************************************************************
Function : LOS_TaskCreateOnly
Description : Create a task and suspend
Input : pstInitParam --- Task init parameters
Output : puwTaskID --- Save task ID
Return : LOS_OK on success or error code on failure
*****************************************************************************/
LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskCreateOnly(UINT32 *puwTaskID, TSK_INIT_PARAM_S *pstInitParam)
{
UINT32 uwTaskID = 0;
UINTPTR uvIntSave;
VOID *pTopStack;
VOID *pStackPtr;
LOS_TASK_CB *pstTaskCB;
UINT32 uwErrRet = OS_ERROR; /* 元素合法检查 [start][A] */
if (NULL == puwTaskID)
{
return LOS_ERRNO_TSK_ID_INVALID;
} if (NULL == pstInitParam)
{
return LOS_ERRNO_TSK_PTR_NULL;
} if (NULL == pstInitParam->pcName)
{
return LOS_ERRNO_TSK_NAME_EMPTY;
} if (NULL == pstInitParam->pfnTaskEntry)
{
return LOS_ERRNO_TSK_ENTRY_NULL;
} if ((pstInitParam->usTaskPrio) > OS_TASK_PRIORITY_LOWEST)
{
return LOS_ERRNO_TSK_PRIOR_ERROR;
} if (((pstInitParam->usTaskPrio) == OS_TASK_PRIORITY_LOWEST)
&& (pstInitParam->pfnTaskEntry != OS_IDLE_TASK_ENTRY))
{
return LOS_ERRNO_TSK_PRIOR_ERROR;
} if (pstInitParam->uwStackSize > OS_SYS_MEM_SIZE)
{
return LOS_ERRNO_TSK_STKSZ_TOO_LARGE;
} if (0 == pstInitParam->uwStackSize)
{
pstInitParam->uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
}
pstInitParam->uwStackSize = ALIGN(pstInitParam->uwStackSize , 8); if (pstInitParam->uwStackSize < LOSCFG_BASE_CORE_TSK_MIN_STACK_SIZE)
{
return LOS_ERRNO_TSK_STKSZ_TOO_SMALL;
}
/* 元素合法检查 [end][A] */ uvIntSave = LOS_IntLock(); // 锁任务
/* 处理任务可回收链表,释放出可用任务空间 */
while (!LOS_ListEmpty(&g_stTskRecyleList))
{
pstTaskCB = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&g_stTskRecyleList)); /*lint !e413*/ /* 获取任务 可回收链表 中的 第一个 TCB。 *后面有源码分析* */
LOS_ListDelete(LOS_DL_LIST_FIRST(&g_stTskRecyleList)); // 从该链表中删除该节点
LOS_ListAdd(&g_stLosFreeTask, &pstTaskCB->stPendList); // 把该任块放到 可用链表 中
(VOID)LOS_MemFree(m_aucSysMem0, (VOID *)pstTaskCB->uwTopOfStack); // 释放该任务申请的任务栈空间
pstTaskCB->uwTopOfStack = (UINT32)NULL;// 初始化该任务块栈顶指针
} /* 判断是否还有可用任务块使用,若没有,则,退出 */
if (LOS_ListEmpty(&g_stLosFreeTask))
{
uwErrRet = LOS_ERRNO_TSK_TCB_UNAVAILABLE;
OS_GOTO_ERREND();
} pstTaskCB = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&g_stLosFreeTask)); /*lint !e413*/ /* 获取 可用链表 中第一个节点对应的 TCB。*后面有源码分析* */
LOS_ListDelete(LOS_DL_LIST_FIRST(&g_stLosFreeTask)); // 上面获取后,便从 可用链表 中删除该节点。
(VOID)LOS_IntRestore(uvIntSave); // 解锁任务
uwTaskID = pstTaskCB->uwTaskID; // 获取 ID pTopStack = (VOID *)LOS_MemAllocAlign(m_aucSysMem0, pstInitParam->uwStackSize, 8); // 申请动态内存,8 字节对齐 if (NULL == pTopStack) // 申请失败
{
uvIntSave = LOS_IntLock();
LOS_ListAdd(&g_stLosFreeTask, &pstTaskCB->stPendList);
uwErrRet = LOS_ERRNO_TSK_NO_MEMORY;
OS_GOTO_ERREND();
}
/* 申请成功 */ /* 初始化 TCB */
pStackPtr = osTskStackInit(uwTaskID, pstInitParam->uwStackSize, pTopStack);
pstTaskCB->pStackPointer = pStackPtr;
pstTaskCB->uwArg = pstInitParam->uwArg;
pstTaskCB->uwTopOfStack = (UINT32)pTopStack;
pstTaskCB->uwStackSize = pstInitParam->uwStackSize;
pstTaskCB->pTaskSem = NULL;
pstTaskCB->pTaskMux = NULL;
pstTaskCB->usTaskStatus = OS_TASK_STATUS_SUSPEND;
pstTaskCB->usPriority = pstInitParam->usTaskPrio;
pstTaskCB->pfnTaskEntry = pstInitParam->pfnTaskEntry;
pstTaskCB->uwEvent.uwEventID = 0xFFFFFFFF;
pstTaskCB->uwEventMask = 0;
pstTaskCB->pcTaskName = pstInitParam->pcName;
pstTaskCB->puwMsg = NULL; *puwTaskID = uwTaskID; /* 更新 ID,返回给上层 */
return LOS_OK; /* 创建成功 */ LOS_ERREND:
(VOID)LOS_IntRestore(uvIntSave);
return uwErrRet;
}

OS_TCB_FROM_PENDLIST 和 宏 LOS_DL_LIST_FIRST

  • OS_TCB_FROM_PENDLIST

    • 获取 链接因子 ptr 中所在的任务控制块的首地址
    • 意思就是:获取某条 stPendList 链表 中 ptr 节点的 TCB句柄
/**
* @ingroup los_task
* @brief Obtain the pointer to a task control block.
* @par Description:
* This API is used to obtain the pointer to a task control block using a corresponding parameter.
* @param ptr [IN] Parameter used for obtaining the task control block.
* @retval Pointer to the task control block.
*/
#define OS_TCB_FROM_PENDLIST(ptr) LOS_DL_LIST_ENTRY(ptr, LOS_TASK_CB, stPendList)
  • LOS_DL_LIST_ENTRY

    • 通用链表的算法
    • 获取链接因子 item 所在的数据块的首地址
/**
*@ingroup los_list
*@brief Obtain the pointer to a structure that contains a doubly linked list.
*@par Description:
*This API is used to obtain the pointer to a structure that contains a doubly linked list.
*@param item [IN] Current node's pointer to the next node.
*@param type [IN] Structure name.
*@param member [IN] Member name of the doubly linked list in the structure.
*@retval Pointer to the structure that contains the doubly linked list.
*/
#define LOS_DL_LIST_ENTRY(item, type, member) \
((type *)((char *)item - LOS_OFF_SET_OF(type, member))) \
  • LOS_OFF_SET_OF

    • 通用链表的算法
    • 算出 结构体首地址成员 之间的便宜。
/**
*@ingroup los_list
*@brief Obtain the pointer to a doubly linked list in a structure.
*@par Description:
*This API is used to obtain the pointer to a doubly linked list in a structure.
*@param type [IN] Structure name.
*@param member [IN] Member name of the doubly linked list in the structure.
*@retval Pointer to the doubly linked list in the structure.
*/
#define LOS_OFF_SET_OF(type, member) ((long)&((type *)0)->member) /*lint -e(413) */

任务控制块 LOS_TASK_CB

/**
* @ingroup los_task
* Define the task control block structure.
*/
typedef struct tagTaskCB
{
VOID *pStackPointer; /**< Task stack pointer */
UINT16 usTaskStatus;
UINT16 usPriority;
UINT32 uwStackSize; /**< Task stack size */
UINT32 uwTopOfStack; /**< Task stack top */
UINT32 uwTaskID; /**< Task ID */
TSK_ENTRY_FUNC pfnTaskEntry; /**< Task entrance function */
VOID *pTaskSem; /**< Task-held semaphore */
VOID *pTaskMux; /**< Task-held mutex */
UINT32 uwArg; /**< Parameter */
CHAR *pcTaskName; /**< Task name */
LOS_DL_LIST stPendList;
LOS_DL_LIST stTimerList;
UINT32 uwIdxRollNum;
EVENT_CB_S uwEvent;
UINT32 uwEventMask; /**< Event mask */
UINT32 uwEventMode; /**< Event mode */
VOID *puwMsg; /**< Memory allocated to queues */
} LOS_TASK_CB;

【LiteOS】LiteOS任务篇-源码分析-创建任务函数的更多相关文章

  1. LiteOS-任务篇-源码分析-删除任务函数

    目录 前言 笔录草稿 源码分析 LOS_TaskDelete函数源码分析 完整源码 参考 链接 前言 20201009 LiteOS 2018 需要会通用链表 笔录草稿 源码分析 LOS_TaskDe ...

  2. Spring AOP 源码分析 - 创建代理对象

    1.简介 在上一篇文章中,我分析了 Spring 是如何为目标 bean 筛选合适的通知器的.现在通知器选好了,接下来就要通过代理的方式将通知器(Advisor)所持有的通知(Advice)织入到 b ...

  3. Spring IOC 容器源码分析 - 创建原始 bean 对象

    1. 简介 本篇文章是上一篇文章(创建单例 bean 的过程)的延续.在上一篇文章中,我们从战略层面上领略了doCreateBean方法的全过程.本篇文章,我们就从战术的层面上,详细分析doCreat ...

  4. Spring IOC 容器源码分析 - 创建单例 bean 的过程

    1. 简介 在上一篇文章中,我比较详细的分析了获取 bean 的方法,也就是getBean(String)的实现逻辑.对于已实例化好的单例 bean,getBean(String) 方法并不会再一次去 ...

  5. LiteOS-任务篇-源码分析-系统启动函数

    目录 前言 链接 参考 开启调度 LOS_Start 函数源码 osTickStart 函数源码 LOS_StartToRun 函数源码 前言 20201009 移植好内核后,开始实战内核. 源码分析 ...

  6. LiteOS-任务篇-源码分析-任务调度函数

    目录 前言 笔录草稿 核心源码分析 osTaskSchedule函数源码分析 osPendSV函数源码分析 TaskSwitch函数源码分析 调度上层源码分析 osSchedule函数源码分析 LOS ...

  7. SequoiaDB 系列之五 :源码分析之main函数

    好久好久没有写博客了,因为一直要做各种事,工作上的,生活上的,这一下就是半年. 时光如梭. 这两天回头看了看写的博客,感觉都是贻笑大方. 但是还是想坚持把SequoiaDB系列写完. 初步的打算已经确 ...

  8. jQuery 源码分析(五) map函数 $.map和$.fn.map函数 详解

    $.map() 函数用于使用指定函数处理数组中的每个元素(或对象的每个属性),并将处理结果封装为新的数组返回,该函数有三个参数,如下: elems Array/Object类型 指定的需要处理的数组或 ...

  9. jQuery 源码分析(四) each函数 $.each和$.fn.each方法 详解

    $.each一般用来遍历一个数组或对象,$.fn.each()就是指jQuery实例可以执行的操作(因为$.fn是jQuery对象的原型) $.each用来遍历一个数组或对象,并依次执行回掉函数,最后 ...

随机推荐

  1. React Gatsby 最新教程

    React Gatsby 最新教程 https://www.gatsbyjs.com/docs/quick-start/ https://www.gatsbyjs.com/docs/tutorial/ ...

  2. infinite scroll blogs

    infinite scroll blogs 无限滚动 blogs beacon api https://www.sitepoint.com/introduction-beacon-api/ Histo ...

  3. React Hooks vs React Class vs React Function All In One

    React Hooks vs React Class vs React Function All In One React Component Types React Hooks Component ...

  4. ES6 Set vs ES5 Array

    ES6 Set vs ES5 Array Set https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Ob ...

  5. how to write string to file in bash

    how to write string to file in bash https://stackoverflow.com/questions/22713667/shell-script-how-to ...

  6. lua调用dll导出的函数

    参考手册 hello.dll #include "pch.h" #include "lua.hpp" #pragma comment(lib, "lu ...

  7. 谁手握账本?趣讲 ZK 的内存模型

    本文作者:HelloGitHub-老荀 Hi,这里是 HelloGitHub 推出的 HelloZooKeeper 系列,免费开源.有趣.入门级的 ZooKeeper 教程,面向有编程基础的新手. 本 ...

  8. SpringBoot 配置文件以及依赖 加上跨域配置文件

    配置目录: application.properties的配置 #设置服务端口号 server.port = 8090 #配置数据源 spring.datasource.driver-class-na ...

  9. 小公举comm,快速比较两个排序文件

    前言 我们经常会有需求比较一个文件里的内容是否在另一个文件存在.假如我有一份监控列表的IP写入在了file1,我所有的机器IP写入在了file2,我要找出还有哪些机器没有在监控列表.以前的做法是写个两 ...

  10. es6 快速入门 系列

    es6 快速入门(未完结,持续更新中...) 前言 为什么要学习es6 es6对于所有javaScript开发者来说,非常重要 未来,es6将构成javaScript应用程序的基础 es6中很多特性, ...