使一个任务进入就绪态,OSEventTaskRdy()

时间:2021-07-26 08:06:15

程序清单 L6.6是函数OSEventTaskRdy()的源代码。当发生了某个事件,该事件等待任务列表中的最高优先级任务(Highest Priority Task – HPT)要置于就绪态时,该事件对应的OSSemPost(),OSMboxPost(),OSQPost(),和OSQPostFront()函数调用OSEventTaskRdy()实现该操作。换句话说,该函数从等待任务队列中删除HPT任务(Highest Priority Task),并把该任务置于就绪态。图 F6.4给出了OSEventTaskRdy()函数最开始的4个动作。

该函数首先计算HPT任务在.OSEventTbl[]中的字节索引[L6.6/F6.4(1)],其结果是一个从0到OS_LOWEST_PRIO/8+1之间的数,并利用该索引得到该优先级任务在.OSEventGrp中的位屏蔽码[L6.6/F6.4(2)](从表T6.1可以得到该值)。然后,OSEventTaskRdy()函数判断HPT任务在.OSEventTbl[]中相应位的位置[L6.6/F6.4(3)],其结果是一个从0到OS_LOWEST_PRIO/8+1之间的数,以及相应的位屏蔽码[L6.6/F6.4(4)]。根据以上结果,OSEventTaskRdy()函数计算出HPT任务的优先级[L6.6(5)],然后就可以从等待任务列表中删除该任务了[L6.6(6)]。

任务的任务控制块中包含有需要改变的信息。知道了HPT任务的优先级,就可以得到指向该任务的任务控制块的指针[L6.6(7)]。因为最高优先级任务运行条件已经得到满足,必须停止OSTimeTick()函数对.OSTCBDly域的递减操作,所以OSEventTaskRdy()直接将该域清澈0[L6.6(8)]。因为该任务不再等待该事件的发生,所以OSEventTaskRdy()函数将其任务控制块中指向事件控制块的指针指向NULL[L6.6(9)]。如果OSEventTaskRdy()是由OSMboxPost()或者OSQPost()调用的,该函数还要将相应的消息传递给HPT,放在它的任务控制块中[L6.6(10)]。另外,当OSEventTaskRdy()被调用时,位屏蔽码msk作为参数传递给它。该参数是用于对任务控制块中的位清零的位屏蔽码,和所发生事件的类型相对应[L6.6(11)]。最后,根据.OSTCBStat判断该任务是否已处于就绪状态[L6.6(12)]。如果是,则将HPT插入到µC/OS-II的就绪任务列表中[L6.6(13)]。注意,HPT任务得到该事件后不一定进入就绪状态,也许该任务已经由于其它原因挂起了。[见4.07节,挂起一个任务,OSTaskSuspend(),和4.08节,恢复一个任务,OSTaskResume()]。

另外,.OSEventTaskRdy()函数要在中断禁止的情况下调用。

程序清单 L6.6 使一个任务进入就绪状态

void OSEventTaskRdy (OS_EVENT *pevent, void *msg, INT8U msk)

{

    OS_TCB *ptcb;

    INT8U   x;

    INT8U   y;

    INT8U   bitx;

    INT8U   bity;

    INT8U   prio;

 

 

    y    = OSUnMapTbl[pevent->OSEventGrp];                          (1)

    bity = OSMapTbl[y];                                             (2)

    x    = OSUnMapTbl[pevent->OSEventTbl[y]];                       (3)

    bitx = OSMapTbl[x];                                             (4)

    prio = (INT8U)((y << 3) + x);                                   (5)

    if ((pevent->OSEventTbl[y] &= ~bitx) == 0) {                   (6)

        pevent->OSEventGrp &= ~bity;

    }

    ptcb                 =  OSTCBPrioTbl[prio];                     (7)

    ptcb->OSTCBDly       =  0;                                      (8)

    ptcb->OSTCBEventPtr  = (OS_EVENT *)0;                           (9)

#if (OS_Q_EN && (OS_MAX_QS >= 2)) || OS_MBOX_EN

    ptcb->OSTCBMsg       = msg;                                    (10)

#else

    msg                  = msg;

#endif

    ptcb->OSTCBStat     &= ~msk;                                   (11)

    if (ptcb->OSTCBStat == OS_STAT_RDY) {                          (12)

        OSRdyGrp        |=  bity;                                  (13)

        OSRdyTbl[y]     |=  bitx;

    }

}

使一个任务进入就绪态,OSEventTaskRdy()