uC/OS-III之任务就绪表学习总结

来源:互联网 发布:同轴圆柱形电容器算法 编辑:程序博客网 时间:2024/05/19 07:08

1.任务就绪表包含两部分:一个就绪优先级位映射表OSPrioTbl[],用来标明哪个优先级下有任务就绪;一个就绪任务列表OSRdyList[],其中包含指向各个就绪任务的指针。

2.就绪优先级位映射表OSPrioTbl[]

// 就绪优先级位映射表的大小,由定义在文件os.h的164行#define  OS_PRIO_TBL_SIZE          (((OS_CFG_PRIO_MAX - 1u) / DEF_INT_CPU_NBR_BITS) + 1u)// 就绪优先级位映射表,定义在文件os_prio.c的40行CPU_DATA   OSPrioTbl[OS_PRIO_TBL_SIZE];         // 以下函数来自于文件os_proc.c,58行-155行void  OS_PrioInit (void)                        // 初始化优先级位映射表{    CPU_DATA  i;    for (i = 0u; i < OS_PRIO_TBL_SIZE; i++) {         OSPrioTbl[i] = (CPU_DATA)0;    }}OS_PRIO  OS_PrioGetHighest (void)               // 查找就绪的最高优先级{    CPU_DATA  *p_tbl;    OS_PRIO    prio;    prio  = (OS_PRIO)0;    p_tbl = &OSPrioTbl[0];    while (*p_tbl == (CPU_DATA)0) {             // 查找非零项        prio += DEF_INT_CPU_NBR_BITS;           // 计算优先级        p_tbl++;    }    prio += (OS_PRIO)CPU_CntLeadZeros(*p_tbl);  // 查找第一个不为零的项    return (prio);}void  OS_PrioInsert (OS_PRIO  prio)             // 置位就绪优先级位映射表中对应的优先级位{    CPU_DATA  bit;    CPU_DATA  bit_nbr;    OS_PRIO   ix;    ix             = prio / DEF_INT_CPU_NBR_BITS;                  // 计算优先级在就绪优先级映射表中的表项位置    bit_nbr        = (CPU_DATA)prio & (DEF_INT_CPU_NBR_BITS - 1u);  // 计算优先级在表项中的偏移位置    bit            = 1u;    bit          <<= (DEF_INT_CPU_NBR_BITS - 1u) - bit_nbr;    OSPrioTbl[ix] |= bit;}void  OS_PrioRemove (OS_PRIO  prio)             // 清零就绪优先级位映射表中对应优先级的位{    CPU_DATA  bit;    CPU_DATA  bit_nbr;    OS_PRIO   ix;    ix             = prio / DEF_INT_CPU_NBR_BITS;                   // 计算优先级在就绪优先级映射表中的表项位置     bit_nbr        = (CPU_DATA)prio & (DEF_INT_CPU_NBR_BITS - 1u);  // 计算优先级在表项中的偏移位置    bit            = 1u;    bit          <<= (DEF_INT_CPU_NBR_BITS - 1u) - bit_nbr;    OSPrioTbl[ix] &= ~bit;}

3.就绪任务列表OSRdyList[]

// 就绪表的表项,定义在os.h文件的690行,该表项可以与任务控制块TCB构成双向链表struct  os_rdy_list {      OS_TCB              *HeadPtr;               // 指向对应优先级下就绪任务表的头部    OS_TCB              *TailPtr;               // 指向对应优先级下就绪任务表的尾部    OS_OBJ_QTY           NbrEntries;            // 对应优先级下就绪任务的数量};// 就绪表的定义位于os.h文件的1116行。每一个表项对应一个优先级,就绪表的索引号就是任务对应的优先级OS_EXT    OS_RDY_LIST    OSRdyList[OS_CFG_PRIO_MAX];// 以下函数来自于os_core.c文件,1965行-2386void  OS_RdyListInit (void)                     // 初始化并清空就绪表{    OS_PRIO       i;    OS_RDY_LIST  *p_rdy_list;    for (i = 0u; i < OS_CFG_PRIO_MAX; i++) {    // 清空就绪表        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;    }}void  OS_RdyListInsert (OS_TCB *p_tcb)          // 在就绪表中插入一个任务控制块{    OS_PrioInsert(p_tcb->Prio);                 // 在优先级位映射表中置位与该任务的优先级对应的位    if (p_tcb->Prio == OSPrioCur) {        OS_RdyListInsertTail(p_tcb);            // 该任务与当前正在执行的任务处于同一优先级,那么就把它插入到双向链表的尾部    } else {        OS_RdyListInsertHead(p_tcb);            // 该任务与当前正在执行的任务处于不同优先级,那么就把它插入到双向链表的头部    }}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;    }}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;    }}void  OS_RdyListMoveHeadToTail (OS_RDY_LIST  *p_rdy_list)  // 将一个任务控制块TCB从双向链表的头部移到尾部{    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;    }}void  OS_RdyListRemove (OS_TCB *p_tcb)  // 将任务控制块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;}
原创粉丝点击