前言

  • 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. OKR vs KPI

    OKR vs KPI refs xgqfrms 2012-2020 www.cnblogs.com 发布文章使用:只允许注册用户才可以访问!

  2. Jamstack Conf 2020

    Jamstack Conf 2020 Jamstack Conf Virtual https://jamstackconf.com/virtual/ Conf Schedule https://jam ...

  3. Android低功耗蓝牙(蓝牙4.0)——BLE开发(上)

    段时间,公司项目用到了手机APP和蓝牙设备的通讯开发,这里也正好对低功耗蓝牙(蓝牙4.0及以后标准)的开发,做一个总结. 蓝牙技术联盟在2010年6月30号公布了蓝牙4.0标准,4.0标准在蓝牙3.0 ...

  4. [JAVA学习笔记]JAVA基本程序设计结构

    一个简单的Java应用程序 public class FirstSample { public static void main(String[] args) { System.out.println ...

  5. JS相关基础

    1. ES5和ES6继承方式区别 ES5定义类以函数形式, 以prototype来实现继承 ES6以class形式定义类, 以extend形式继承 2. Generator了解 ES6 提供的一种异步 ...

  6. 无情面试官之包含min函数的栈

    0 我是一个无情的面试官. 面人无数,挂人无数. 若想过我的面试,标准只有一个,那就是公司很缺人. 招新人,填旧坑. 1 今天是我的第1001次当面试官,要求却不是千里挑一,而是一击必中. 因为我招聘 ...

  7. 【原创】Linux虚拟化KVM-Qemu分析(十)之virtio驱动

    背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: KVM版本:5.9 ...

  8. RocketMQ同一个消费者唯一Topic多个tag踩坑经历

    最近做的项目的一个版本需求中,需要用到MQ,对数据记录进行异步落库,这样可以减轻数据库的压力,同时可以抗住大量的数据落库.这里需要说明一下本人用到的MQ是公司自己在阿里的RokectMQ的基础上进行封 ...

  9. vue:表格中多选框的处理

    效果如下: template中代码如下: <el-table v-loading="listLoading" :data="list" element-l ...

  10. 微信小程序:解决小程序中有些格式如webpiPhone手机暂不支持的问题

    问题:小程序中有些格式是iPhone手机暂不支持的,如goods_introduce中的webp格式,在小程序的模拟器中是可以正常显示webp格式的,但是一旦你做真机调试,很可能某些iPhone手机是 ...