LiteOS解读_第三篇:任务的快速定位

如果上一篇文章看明白了,看代码的速度应该会加快很多。

上篇文章写了LiteOS是建立了一个大的任务数组,任务的ID也可以通过数组唯一指定,那通过索引可以快速定位要看的任务。

同时,在不同状态间进行切换时,LiteOS通过两个双向链表实现,这两个双向链表也是能快速理解代码的关键。

下面我们通过一些实例看看它的应用。

首先,我们看看任务结构体的定义:

结构的定义是在文件:Los_tast.ph中(和本文无关的信息,作者删掉了,如果看详细信息请查看源码)

typedef struct tagTaskCB
{
    VOID                        *pStackPointer;             /**< Task stack pointer                 */
    ..........
    CHAR                        *pcTaskName;                /**< Task name                     */
    LOS_DL_LIST                 stPendList;
    LOS_DL_LIST                 stTimerList;
    ....................................
} LOS_TASK_CB;

这个结构体重,有两个双向链表:stPendList、stTimerList,这篇文章,我们重点讲的就是这两个。

下面我们通过:LOS_TaskCreate和LOS_TaskCreateOnly来讲解。

//LOS_TaskCreateOnly函数

LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskCreateOnly(UINT32 *puwTaskID, TSK_INIT_PARAM_S *pstInitParam)
{
  .............................

    //申请堆栈,8字节对齐
    pstInitParam->uwStackSize = ALIGN(pstInitParam->uwStackSize , 8);

    ................................

    //查看待回收的任务列表是不是空的
    //如果非空,则把相关任务列表放到g_stLosFreeTask
    //同时释放任务堆栈空间
    while (!LOS_ListEmpty(&g_stTskRecyleList))
    {
        pstTaskCB = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&g_stTskRecyleList)); /*lint !e413*/
        LOS_ListDelete(LOS_DL_LIST_FIRST(&g_stTskRecyleList));
        LOS_ListAdd(&g_stLosFreeTask, &pstTaskCB->stPendList);
        (VOID)LOS_MemFree(m_aucSysMem0, (VOID *)pstTaskCB->uwTopOfStack);
    }

    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*/
    LOS_ListDelete(LOS_DL_LIST_FIRST(&g_stLosFreeTask));
    (VOID)LOS_IntRestore(uvIntSave);
    uwTaskID = pstTaskCB->uwTaskID;  //取任务编号,即数组的索引
    //分配堆栈空间
    pTopStack = (void *)LOS_MemAllocAlign(m_aucSysMem0, pstInitParam->uwStackSize, 8);
    //分配失败,则将任务放回g_stLosFreeTask
    if (NULL == pTopStack)
    {
        uvIntSave = LOS_IntLock();
        LOS_ListAdd(&g_stLosFreeTask, &pstTaskCB->stPendList);
        uwErrRet = LOS_ERRNO_TSK_NO_MEMORY;
        OS_GOTO_ERREND();
    }
    //任务堆栈初始化,并获取堆栈信息
    pStackPtr = osTskStackInit(uwTaskID, pstInitParam->uwStackSize, pTopStack);
  .....................................................
    pstTaskCB->pcTaskName   = pstInitParam->pcName;//传入的任务名不能是局部变量
 

    *puwTaskID = uwTaskID;//返回任务编号,这任务号就是创建任务时传入的那个全局变量或者局部变量;
 ...................................................

}

在上面的代码中,有一个While循环:

 while (!LOS_ListEmpty(&g_stTskRecyleList))
    {
        pstTaskCB = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&g_stTskRecyleList)); /*lint !e413*/
        LOS_ListDelete(LOS_DL_LIST_FIRST(&g_stTskRecyleList));
        LOS_ListAdd(&g_stLosFreeTask, &pstTaskCB->stPendList);
        (VOID)LOS_MemFree(m_aucSysMem0, (VOID *)pstTaskCB->uwTopOfStack);
    }

看到我们的主角了吧:stPendList

整个代码中,这个变量贯穿始终,所有对任务状态切换的管理都是通过stPendList和stTimerList俩实现的。

其中stTimerList主要是用来管理同步过程中的timer状态的。这个链表加入了

stPendList在不运行时,加入了g_stTskRecyleList和g_stLosFreeTask;

其中在LOS_TaskDelete过程中,stPendList加入g_stTskRecyleList中,用于资源回收,表明有可回收的任务列表

g_stLosFreeTask则是我们申请创建任务获取任务资源的链表,从上面的代码我们也可以看到,当获取堆栈资源失败时,我们又把已经取出来的任务放回到了这个链表中。

我们另一个主角stTimerList是在进行任务同步时,加入了g_stTskSortLink。感兴趣的小伙伴可以自己查看osTaskAdd2TimerList

或者等我后续给大家慢慢写。

 

觉得文章有用的小伙伴,给留言或者点赞吧。

你可能感兴趣的:(LiteOS)