μC/OS-II的任務(wù)管理
}else{
OSTCBPrioTbl[newprio]=(OS_TCB*)0;(17)
OS_EXIT_CRITICAL();
return(OS_PRIO_ERR);
}
}
}
4.7 掛起任務(wù),OSTaskSuspend()
有時候?qū)⑷蝿?wù)掛起是很有用的。掛起任務(wù)可通過調(diào)用OSTaskSuspend()函數(shù)來完成。被掛起的任務(wù)只能通過調(diào)用OSTaskResume()函數(shù)來恢復(fù)。任務(wù)掛起是一個附加功能。也就是說,如果任務(wù)在被掛起的同時也在等待延時的期滿,那么,掛起操作需要被取消,而任務(wù)繼續(xù)等待延時期滿,并轉(zhuǎn)入就緒狀態(tài)。任務(wù)可以掛起自己或者其它任務(wù)。
OSTaskSuspend()函數(shù)的代碼如程序清單L4.16所示。通常OSTaskSuspend()需要檢驗臨界條件。首先,OSTaskSuspend()要確保用戶的應(yīng)用程序不是在掛起空閑任務(wù)[L4.16(1)],接著確認(rèn)用戶指定優(yōu)先級是有效的[L4.16(2)]。記住最大的有效的優(yōu)先級數(shù)(即最低的優(yōu)先級)是OS_LOWEST_PRIO。注意,用戶可以掛起統(tǒng)計任務(wù)(statistic) ??赡苡脩粢呀?jīng)注意到了,第一個測試[L4.16(1)]在[L4.16(2)]中被重復(fù)了。筆者這樣做是為了能與μC/OS兼容。
第一個測試能夠被移除并可以節(jié)省一點程序處理的時間,但是,這樣做的意義不大,所以筆者決定留下它。
接著, OSTaskSuspend()檢驗用戶是否通過指定 OS_PRIO_SELF來掛起調(diào)用本函數(shù)的任務(wù)本身[L4.16(3)]。用戶也可以通過指定優(yōu)先級來掛起調(diào)用本函數(shù)的任務(wù)[L4.16(4)]。在這兩種情況下,任務(wù)調(diào)度程序都需要被調(diào)用。這就是筆者為什么要定義局部變量self的原因,該變量在適當(dāng)?shù)那闆r下會被測試。如果用戶沒有掛起調(diào)用本函數(shù)的任務(wù),OSTaskSuspend()就沒有必要運行任務(wù)調(diào)度程序,因為正在掛起的是較低優(yōu)先級的任務(wù)。
然后,OSTaskSuspend()檢驗要掛起的任務(wù)是否存在[L4.16(5)]。如果該任務(wù)存在的話,它就會從就緒表中被移除[L4.16(6)]。注意要被掛起的任務(wù)有可能沒有在就緒表中,因為它有可能在等待事件的發(fā)生或延時的期滿。在這種情況下,要被掛起的任務(wù)在OSRdyTbl[]中對應(yīng)的位已被清除了(即為0)。再次清除該位,要比先檢驗該位是否被清除了再在它沒被清除時清除它快得多,所以筆者沒有檢驗該位而直接清除它?,F(xiàn)在,OSTaskSuspend()就可以在任務(wù)的OS_TCB中設(shè)置OS_STAT_SUSPEND標(biāo)志了,以表明任務(wù)正在被掛起[L4.16(7)]。最后,OSTaskSuspend()只有在被掛起的任務(wù)是調(diào)用本函數(shù)的任務(wù)本身的情況下才調(diào)用任務(wù)調(diào)度程序[L4.16(8)]。
程序清單 L4.16 OSTaskSuspend().
INT8UOSTaskSuspend(INT8Uprio)
{
BOOLEANself;
OS_TCB*ptcb;
if(prio==OS_IDLE_PRIO){(1)
return(OS_TASK_SUSPEND_IDLE);
}
if(prio>=OS_LOWEST_PRIOprio!=OS_PRIO_SELF){
(2)
return(OS_PRIO_INVALID);
}
OS_ENTER_CRITICAL();
if(prio==OS_PRIO_SELF){(3)
prio=OSTCBCur->OSTCBPrio;
self=TRUE;
}elseif(prio==OSTCBCur->OSTCBPrio){(4)
self=TRUE;
}else{
self=FALSE;
}
if((ptcb=OSTCBPrioTbl[prio])==(OS_TCB*)0){(5)
OS_EXIT_CRITICAL();
return(OS_TASK_SUSPEND_PRIO);
}else{
if((OSRdyTbl[ptcb->OSTCBY]=~ptcb->OSTCBBitX)==0){(6)
OSRdyGrp=~ptcb->OSTCBBitY;
}
ptcb->OSTCBStat|=OS_STAT_SUSPEND;(7)
OS_EXIT_CRITICAL();
if(self==TRUE){(8)
OSSched();
}
return(OS_NO_ERR);
}
}
4.8 恢復(fù)任務(wù),OSTaskResume()
在上一節(jié)中曾提到過,被掛起的任務(wù)只有通過調(diào)用OSTaskResume()才能恢復(fù)。OSTaskResume()函數(shù)的代碼如程序清單L4.17所示。 因為OSTaskSuspend()不能掛起空閑任務(wù),所以必須得確認(rèn)用戶的應(yīng)用程序不是在恢復(fù)空閑任務(wù)[L4.17(1)]。注意,這個測試也可以確保用戶不是在恢復(fù)優(yōu)先級為OS_PRIO_SELF的任務(wù)(OS_PRIO_SELF被定義為0xFF,它總是比OS_LOWEST_PRIO大)。
要恢復(fù)的任務(wù)必須是存在的,因為用戶要需要操作它的任務(wù)控制塊OS_TCB[L4.17(2)],并且該任務(wù)必須是被掛起的[L4.17(3)]。OSTaskResume()是通過清除OSTCBStat域中的OS_STAT_SUSPEND位來取消掛起的[L4.17(4)]。要使任務(wù)處于就緒狀態(tài),OS_TCBDly域必須為0[L4.17(5)],這是因為在OSTCBStat中沒有任何標(biāo)志表明任務(wù)正在等待延時的期滿。只有當(dāng)以上兩個條件都滿足的時候,任務(wù)才處于就緒狀態(tài)[L4.17(6)]。最后,任務(wù)調(diào)度程序會檢查被恢復(fù)的任務(wù)擁有的優(yōu)先級是否比調(diào)用本函數(shù)的任務(wù)的優(yōu)先級高[L4.17(7)]。
程序清單 L4.17 OSTaskResume().
INT8UOSTaskResume(INT8Uprio)
{
OS_TCB*ptcb;
If(prio>=OS_LOWEST_PRIO){(1)
return(OS_PRIO_INVALID);
}
OS_ENTER_CRITICAL();
If((ptcb=OSTCBPrioTbl[prio])==(OS_TCB*)0){(2)
OS_EXIT_CRITICAL();
return(OS_TASK_RESUME_PRIO);
}else{
if(ptcb->OSTCBStatOS_STAT_SUSPEND){(3)
if(((ptcb->OSTCBStat=~OS_STAT_SUSPEND)==OS_STAT_RDY)(4)
(ptcb->OSTCBDly==0)){(5)
OSRdyGrp|=ptcb->OSTCBBitY;(6)
OSRdyTbl[ptcb->OSTCBY]|=ptcb->OSTCBBitX;
OS_EXIT_CRITICAL();
OSSched();(7)
}else{
OS_EXIT_CRITICAL();
}
return(OS_NO_ERR);
}else{
OS_EXIT_CRITICAL();
return(OS_TASK_NOT_SUSPENDED);
}
}
}
4.9 獲得有關(guān)任務(wù)的信息,OSTaskQuery()
用戶的應(yīng)用程序可以通過調(diào)用OSTaskQuery()來獲得自身或其它應(yīng)用任務(wù)的信息。實際上,OSTaskQuery()獲得的是對應(yīng)任務(wù)的 OS_TCB中內(nèi)容的拷貝。用戶能訪問的OS_TCB的數(shù)據(jù)域的多少決定于用戶的應(yīng)用程序的配置(參看OS_CFG.H)。由于μC/OS-Ⅱ是可裁剪的,它只包括那些用戶的應(yīng)用程序所要求的屬性和功能。
評論