1.任务管理的数据结构
#define OS_RDY_TBL_SIZE ((OS_LOWEST_PRIO) / 8 + 1)
OS_EXT INT8U OSRdyTbl[OS_RDY_TBL_SIZE];//创建一个8位数组
4.任务就绪表的初始化
首先我们调用了OSInit();
然后:
void OSInit (void) { .............. /*初始化就绪任务表及相关变量*/ OS_InitRdyList(); ................. }
static void OS_InitRdyList (void) { INT8U i; INT8U *prdytbl; OSRdyGrp = 0x00; /* Clear the ready list */ prdytbl = &OSRdyTbl[0]; for (i = 0; i < OS_RDY_TBL_SIZE; i++) { *prdytbl++ = 0x00; } OSPrioCur = 0; OSPrioHighRdy = 0; OSTCBHighRdy = (OS_TCB *)0; OSTCBCur = (OS_TCB *)0; }
就是初始化就绪表了
5.在OSTaskCreate() 中创建
OSTaskCreate(),首先对由参数prio传递进来的优先级别进行一系列判断,确认优先级合法且未被使用,随之调用函数OSTaskStkInit,OS_TCBInit对任务堆栈和TCB进行初始化。
再看OS_TCBInit中对就绪任务表的登记:
INT8U OS_TCBInit (INT8U prio, OS_STK *ptos, OS_STK *pbos, INT16U id, INT32U stk_size, void *pext, INT16U opt) { OS_TCB *ptcb; /*新任务的tcb*/ ……. ptcb->OSTCBY = (INT8U)(prio >> 3); /*取y */ ptcb->OSTCBBitY = OSMapTbl[ptcb->OSTCBY]; /*取得就绪表的行*/ ptcb->OSTCBX = (INT8U)(prio & 0x07); /*取x*/ ptcb->OSTCBBitX = OSMapTbl[ptcb->OSTCBX];/*取得就绪表的所在列*/ ……. OS_ENTER_CRITICAL(); OSTCBPrioTbl[prio] = ptcb; ptcb->OSTCBNext = OSTCBList; /* Link into TCB chain */ ptcb->OSTCBPrev = (OS_TCB *)0; if (OSTCBList != (OS_TCB *)0) { OSTCBList->OSTCBPrev = ptcb; } OSTCBList = ptcb; /*任务就绪表登记*/ OSRdyGrp |= ptcb->OSTCBBitY; /* Make task ready to run */ OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX; OSTaskCtr++; /* Increment the #tasks counter */ OS_EXIT_CRITICAL(); return (OS_NO_ERR); }
2.根据优先级来找到就绪表的位置
7|6 | 5| 4 | 3| 2| 1| 0|
x|x|1/0|1/0|1/0|1/0|1/0|1/0|
| y | x |
高3位 (3/4/5) 指明OSRdyGrp
地3位 指明数组元素中具体位置
3.就绪表操作:
以下的就续表操作会在调度程序中频繁看到,需要细细研读!
a.登记任务(变为就绪状态):
先看这个数组:
INT8U const OSMapTbl[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
是为了加速访问而定义的数组
登记语句(脱离就绪状态):
Prio为优先级
OSRdyGrp |= OSMapTabl[prio>>3]; //prio右移3位即是y ,访问到组 OSRdyTbl[prio>>3] |=OSMapTbl[prio & 0x07]; //访问组中该处数组元素,取低3位,即是x,并且登记为1
b.删除任务:
代码如下:
//这里可谓“一箭双雕”,先取消对应优先级的登记,然后判断所在组是否还有任务在登记 //若没有,就把OSRdyGrp的对应标志取消 If( ( OSRdyTbl[prio>>3] &=~ OSMapTbl[prio & 0x07]) == 0) //把OSRdyGrp的对应标志取消 OSRdyGrp &= ~OSMapTbl[prio >> 3];
c.获取最高级别就绪任务
代码:
//取行 Y = OSUnMapTbl[OSRdyGrp]; //获得优先级 Prio = (INT8U) ( (y << 3) + OSUnMapTbl[OSRdyTbl[y]]); INT8U const OSUnMapTbl[256] = { 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 }; //这个数组其实就是算最低非0位,系统可以根据任务查表快速找到最高级任务
OSRdyTbl数组中每一个数据成员为8bit数据,故可以构成8*n的状态,规定1为就绪状态,0位非就绪状态,为方便对就绪表查找,又定义了一个8bit变量OSRdyGrp,对应着OSRdyTbl[bitx],该位为1表示OSRdyTbl[bitx]有任务就绪。最多可管理64个任务。