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行-2386行
void 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;
}