entType!=OS_EVENT_TYPE_SEM){ OS_EXIT_CRITICAL(); *err=OS_ERR_EVENT_TYPE; } if(pevent->OSEventCnt>0){ pevent->OSEventCnt--; OS_EXIT_CRITICAL(); *err=OS_NO_ERR; }else if(OSIntNesting>0){ OS_EXIT_CRITICAL(); *err=OS_ERR_PEND_ISR; }else{ OSTCBCur->OSTCBStat|=OS_STAT_SEM; OSTCBCur->OSTCBDly=timeout; OSEventTaskWait(pevent); OS_EXIT_CRITICAL(); OSSched(); OS_ENTER_CRITICAL(); if(OSTCBCur->OSTCBStat&OS_STAT_SEM){ //(5) OSEventTo(pevent); OS_EXIT_CRITICAL(); *err=OS_TIMEOUT; }else{ //(6) OSTCBCur->OSTCBEventPtr=(OS_EVENT*0); OS_EXIT_CRITICAL(); *err=OS_NO_ERR; } } } void OSEventTo(OS_EVENT *pevent) { if((pevent->OSEventTbl[OSTCBCur->OSTCBY]&=~OSTCBCur->OSTCBBitX)==0) { pevent->OSEventGrp&=~OSTCBBitY; } OSTCBCur->OSTCBStat=OS_STAT_RDY;v OSTCBCur->OSTCBEventPtr=(OS_EVENT*0);} 如果任务T由于超时进入就绪态,到T获得执行权之前,仍没有获取到资源R,将运行语句(5)处的条件代码,由函数OSEventTo()可以看出,此时任务T才被从等待表中删除,最后返回超时状态。 通过分析开放源码的nucleus内核,发现nucleus在超时到期时执行定时器的一个回调函数,此回调函数马上将等待任务从等待链表中删除,将返回状态定性为超时。这样在任务获得执行权前,即使资源到达,该任务也不会得到。这样一来,uC/OS-II内核只要在时钟节拍函数里增加代码将延时期满的任务从相应的资源等待列表中删除即可。这一工作很容易实现,内核任务控制块有指向所等待的信号量,消息等事件控制块的指针,事件控制块里有相应的等待表。对于uC/OS-II新引进的事件标志组[2],任务控制块有指向相应的等待节点的指针,等待节点有指向相应的事件标志组控制块的指针,删除一个等待节点也能实现。
4 结论
uC/OS-II其它资源的等待机制,比如消息以及包括2.5.2版引入的事件标志组的实现都存在上述的超时时间不严格的问题,这是由中断节拍函数OSTimeTick()决定的,该函数只负责将任务移入就绪表,而不处理相应的等待表。
参考文献:[1]Labrosse Jean J.uc/OS-II-源码公开的实时嵌入式操作系统[M].北京:中国电力出版社,2001.[2]Labrosse Jean J. 嵌入式实时操作系统uc/OS-II[M].北京:北京航空航天大学出版社,2003.上一页 [1] [2]