RTOS学习(9)--就绪列表

UCOS操作系统使用就序列表来管理准备好运行的任务,该列表是一个基于优先级的数组结构。OS_RDY_LIST包含头指针、尾指针和任务数量,用于插入、移除和管理任务。OS_RdyListInit初始化列表,OS_RdyListInsertHead和OS_RdyListInsertTail分别用于在头部和尾部插入任务,而OS_RdyListRemove则用于移除任务。这些函数确保了系统的高效调度。
摘要由CSDN通过智能技术生成

目录

就序列表的定义

数组定义

OS_RDY_LIST

相关函数

OS_RdyListInit函数

 OS_RdyListInsertHead函数

OS_RdyListInsertTail函数

OS_RdyListInsert函数

OS_RdyListMoveHeadToTail函数

OS_RdyListRemove函数


与优先级列表相似,在UCOS中还有另一个列表,就序列表。就序列表中存放准备好运行的TCB,方便系统调度运行。

就序列表的定义

数组定义

归根到底,就序列表是一个数组,具体定义如下

OS_EXT            OS_RDY_LIST               OSRdyList[OS_CFG_PRIO_MAX]; /* Table of tasks ready to run                */

        可以看出就绪列表在代码的层面上看是一个 OS_RDY_LIST 数据类型的数组,数组名为 OSRdyList,数组的大小由宏 OS_CFG_PRIO_MAX 决定。OS_CFG_PRIO_MAX表示优先级的最大值,也就是说有多少个优先级数组就有多大。实际上任务的优先级与 OSRdyList[] 的索引是一一对应的,也就是说优先级为2的任务的 TCB 会被放到 OSRdyList[2]中。

OS_RDY_LIST

数据类型OS_RDY_LIST定义在os.h中,具体如下

struct  os_rdy_list {
    OS_TCB              *HeadPtr;                           /* Pointer to task that will run at selected priority     */
    OS_TCB              *TailPtr;                           /* Pointer to last task          at selected priority     */
    OS_OBJ_QTY           NbrEntries;                        /* Number of entries             at selected priority     */
};

其中,

*HeadPtr表示头指针

*TailPtr表示为尾指针

NbrEntries表示在该索引下任务的个数

相关函数

OS_RdyListInit函数

该函数的作用是将就序列表里面的内容清零,比较简单。

void  OS_RdyListInit (void)
{
    OS_PRIO       i;
    OS_RDY_LIST  *p_rdy_list;



    for (i = 0u; i < OS_CFG_PRIO_MAX; i++) {                /* Initialize the array of OS_RDY_LIST at each priority   */
        p_rdy_list = &OSRdyList[i];
        p_rdy_list->NbrEntries = (OS_OBJ_QTY)0;
        p_rdy_list->HeadPtr    = (OS_TCB   *)0;
        p_rdy_list->TailPtr    = (OS_TCB   *)0;
    }
}

 OS_RdyListInsertHead函数

该函数的作用是,将一个任务插入到就序列表对应优先级索引链表的头。分两种情况,一种是该索引链表里面没有TCB,另一种就是有TCB。如果有TCB的话,就会用的p_tcb2这个指针用来中介。

void  OS_RdyListInsertHead (OS_TCB  *p_tcb)
{
    OS_RDY_LIST  *p_rdy_list;
    OS_TCB       *p_tcb2;



    p_rdy_list = &OSRdyList[p_tcb->Prio];
    if (p_rdy_list->NbrEntries == (OS_OBJ_QTY)0) {          /* CASE 0: Insert when there are no entries               */
        p_rdy_list->NbrEntries =  (OS_OBJ_QTY)1;            /*         This is the first entry                        */
        p_tcb->NextPtr         =  (OS_TCB   *)0;            /*         No other OS_TCBs in the list                   */
        p_tcb->PrevPtr         =  (OS_TCB   *)0;
        p_rdy_list->HeadPtr    =  p_tcb;                    /*         Both list pointers point to this OS_TCB        */
        p_rdy_list->TailPtr    =  p_tcb;
    } else {                                                /* CASE 1: Insert BEFORE the current head of list         */
        p_rdy_list->NbrEntries++;                           /*         One more OS_TCB in the list                    */
        p_tcb->NextPtr         = p_rdy_list->HeadPtr;       /*         Adjust new OS_TCBs links                       */
        p_tcb->PrevPtr         = (OS_TCB    *)0;
        p_tcb2                 = p_rdy_list->HeadPtr;       /*         Adjust old head of list's links                */
        p_tcb2->PrevPtr        = p_tcb;
        p_rdy_list->HeadPtr    = p_tcb;
    }
}

OS_RdyListInsertTail函数

该函数的作用是,将一个任务插入到就序列表对应优先级索引链表的尾部。和插入到头部相似,也是分两种情况。

void  OS_RdyListInsertTail (OS_TCB  *p_tcb)
{
    OS_RDY_LIST  *p_rdy_list;
    OS_TCB       *p_tcb2;



    p_rdy_list = &OSRdyList[p_tcb->Prio];
    if (p_rdy_list->NbrEntries == (OS_OBJ_QTY)0) {          /* CASE 0: Insert when there are no entries               */
        p_rdy_list->NbrEntries  = (OS_OBJ_QTY)1;            /*         This is the first entry                        */
        p_tcb->NextPtr          = (OS_TCB   *)0;            /*         No other OS_TCBs in the list                   */
        p_tcb->PrevPtr          = (OS_TCB   *)0;
        p_rdy_list->HeadPtr     = p_tcb;                    /*         Both list pointers point to this OS_TCB        */
        p_rdy_list->TailPtr     = p_tcb;
    } else {                                                /* CASE 1: Insert AFTER the current tail of list          */
        p_rdy_list->NbrEntries++;                           /*         One more OS_TCB in the list                    */
        p_tcb->NextPtr          = (OS_TCB   *)0;            /*         Adjust new OS_TCBs links                       */
        p_tcb2                  = p_rdy_list->TailPtr;
        p_tcb->PrevPtr          = p_tcb2;
        p_tcb2->NextPtr         = p_tcb;                    /*         Adjust old tail of list's links                */
        p_rdy_list->TailPtr     = p_tcb;
    }
}

OS_RdyListInsert函数

这个函数的作用是添加任务到就序列表,如果要添加的任务与当前运行的任务优先级相等,就插入到链表的尾部,反之就插入到头部。

void  OS_RdyListInsert (OS_TCB  *p_tcb)
{
    OS_PrioInsert(p_tcb->Prio);
    if (p_tcb->Prio == OSPrioCur) {                         /* Are we readying a task at the same prio?               */
        OS_RdyListInsertTail(p_tcb);                        /* Yes, insert readied task at the end of the list        */
    } else {
        OS_RdyListInsertHead(p_tcb);                        /* No,  insert readied task at the beginning of the list  */
    }

#if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN > 0u))
        TRACE_OS_TASK_READY(p_tcb);                         /* Record the event.                                      */
#endif
}

OS_RdyListMoveHeadToTail函数

该函数的作用是将 TCB 从就绪列表的头部移到尾部,移动的时候分四种情况,第一种是链表为空,无事可做;第二种是链表只有一个节点,也是无事可做;第三种是链表只有两个节点;第四种是链表有两个以上节点。

void  OS_RdyListMoveHeadToTail (OS_RDY_LIST  *p_rdy_list)
{
    OS_TCB  *p_tcb1;
    OS_TCB  *p_tcb2;
    OS_TCB  *p_tcb3;



    switch (p_rdy_list->NbrEntries) {
        case 0:
        case 1:
             break;

        case 2:                                             /* SWAP the TCBs                                          */
             p_tcb1              = p_rdy_list->HeadPtr;     /* Point to current head                                  */
             p_tcb2              = p_rdy_list->TailPtr;     /* Point to current tail                                  */
             p_tcb1->PrevPtr     = p_tcb2;
             p_tcb1->NextPtr     = (OS_TCB *)0;
             p_tcb2->PrevPtr     = (OS_TCB *)0;
             p_tcb2->NextPtr     = p_tcb1;
             p_rdy_list->HeadPtr = p_tcb2;
             p_rdy_list->TailPtr = p_tcb1;
             break;

        default:                                            /* Move only if there are more than 2 OS_TCBs in the list */
             p_tcb1              = p_rdy_list->HeadPtr;     /* Point to current head                                  */
             p_tcb2              = p_rdy_list->TailPtr;     /* Point to current tail                                  */
             p_tcb3              = p_tcb1->NextPtr;         /* Point to new list head                                 */
             p_tcb3->PrevPtr     = (OS_TCB *)0;             /* Adjust back    link of new list head                   */
             p_tcb1->NextPtr     = (OS_TCB *)0;             /* Adjust forward link of new list tail                   */
             p_tcb1->PrevPtr     = p_tcb2;                  /* Adjust back    link of new list tail                   */
             p_tcb2->NextPtr     = p_tcb1;                  /* Adjust forward link of old list tail                   */
             p_rdy_list->HeadPtr = p_tcb3;                  /* Adjust new list head and tail pointers                 */
             p_rdy_list->TailPtr = p_tcb1;
             break;
    }
}

OS_RdyListRemove函数

该函数用于从链表中移除一个节点,移除的时候分为三种情况,第一种是链表 为空,无事可做;第二种是链表只有一个节点;第三种是链表有两个以上节点。

如果链表里面一个节点的前一个结点为零,说明他是第一个节点,该节点的后面的节点为零,说明他是尾节点,两个都为零说明这个链表里面只有一个节点。

如果只有一个节点,在删除该节点的同时,还有清除优先级列表的对应位。如果删除的是头结点,后面的节点自动成为头结点,删除的为节点,前一个节点自动成为尾节点。删除中间的节点的话,要把该节点的前一个节点和后一个节点联系起来。

void  OS_RdyListRemove (OS_TCB  *p_tcb)
{
    OS_RDY_LIST  *p_rdy_list;
    OS_TCB       *p_tcb1;
    OS_TCB       *p_tcb2;



    p_rdy_list = &OSRdyList[p_tcb->Prio];
    p_tcb1     = p_tcb->PrevPtr;                            /* Point to next and previous OS_TCB in the list          */
    p_tcb2     = p_tcb->NextPtr;
    if (p_tcb1 == (OS_TCB *)0) {                            /* Was the OS_TCB to remove was at the head?              */
        if (p_tcb2 == (OS_TCB *)0) {                        /* Yes, was it the only OS_TCB?                           */
            p_rdy_list->NbrEntries = (OS_OBJ_QTY)0;         /*      Yes, no more entries                              */
            p_rdy_list->HeadPtr    = (OS_TCB   *)0;
            p_rdy_list->TailPtr    = (OS_TCB   *)0;
            OS_PrioRemove(p_tcb->Prio);
        } else {
            p_rdy_list->NbrEntries--;                       /*      No,  one less entry                               */
            p_tcb2->PrevPtr        = (OS_TCB   *)0;         /*           adjust back link of new list head            */
            p_rdy_list->HeadPtr    = p_tcb2;                /*           adjust OS_RDY_LIST's new head                */
        }
    } else {
        p_rdy_list->NbrEntries--;                           /* No,  one less entry                                    */
        p_tcb1->NextPtr = p_tcb2;
        if (p_tcb2 == (OS_TCB *)0) {
            p_rdy_list->TailPtr = p_tcb1;                   /*      Removing the TCB at the tail, adj the tail ptr    */
        } else {
            p_tcb2->PrevPtr     = p_tcb1;
        }
    }
    p_tcb->PrevPtr = (OS_TCB *)0;
    p_tcb->NextPtr = (OS_TCB *)0;

#if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN > 0u))
    TRACE_OS_TASK_SUSPEND(p_tcb);                           /* Record the event.                                      */
#endif
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

苦瓜人生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值