μC/OS-II的任務(wù)管理
(2)
return(OS_PRIO_INVALID);
}
if(prio==OS_PRIO_SELF){(3)
OS_ENTER_CRITICAL();
stat=OSTCBCur->OSTCBDelReq;
OS_EXIT_CRITICAL();
return(stat);
}
else{
OS_ENTER_CRITICAL();
if((ptcb=OSTCBPrioTbl[prio])!=(OS_TCB*)0){(4)
ptcb->OSTCBDelReq=OS_TASK_DEL_REQ;(5)
err=OS_NO_ERR;
}else{
err=OS_TASK_NOT_EXIST;(6)
}
OS_EXIT_CRITICAL();
return(err);
}
}
4.6改變?nèi)蝿?wù)的優(yōu)先級(jí),OSTaskChangePrio()
在用戶建立任務(wù)的時(shí)候會(huì)分配給任務(wù)一個(gè)優(yōu)先級(jí)。在程序運(yùn)行期間,用戶可以通過調(diào)用OSTaskChangePrio()來改變?nèi)蝿?wù)的優(yōu)先級(jí)。換句話說,就是μC/OS-Ⅱ允許用戶動(dòng)態(tài)的改變?nèi)蝿?wù)的優(yōu)先級(jí)。
OSTaskChangePrio()的代碼如程序清單L4.15所示。用戶不能改變空閑任務(wù)的優(yōu)先級(jí)[L4.15(1)],但用戶可以改變調(diào)用本函數(shù)的任務(wù)或者其它任務(wù)的優(yōu)先級(jí)。為了改變調(diào)用本函數(shù)的任務(wù)的優(yōu)先級(jí),用戶可以指定該任務(wù)當(dāng)前的優(yōu)先級(jí)或OS_PRIO_SELF,
OSTaskChangePrio()會(huì)決定該任務(wù)的優(yōu)先級(jí)。用戶還必須指定任務(wù)的新(即想要的)優(yōu)先級(jí)。因?yàn)?mu;C/OS-Ⅱ不允許多個(gè)任務(wù)具有相同的優(yōu)先級(jí),所以O(shè)STaskChangePrio()需要檢驗(yàn)新優(yōu)先級(jí)是否是合法的(即不存在具有新優(yōu)先級(jí)的任務(wù))[L4.15(2)]。如果新優(yōu)先級(jí)是合法的,μC/OS-Ⅱ通過將某些東西儲(chǔ)存到OSTCBPrioTbl[newprio]中保留這個(gè)優(yōu)先級(jí)[L4.15(3)]。如此就使得OSTaskChangePrio()可以重新允許中斷,因?yàn)榇藭r(shí)其它任務(wù)已經(jīng)不可能建立擁有該優(yōu)先級(jí)的任務(wù),也不能通過指定相同的新優(yōu)先級(jí)來調(diào)用OSTaskChangePrio()。接下來OSTaskChangePrio()可以預(yù)先計(jì)算新優(yōu)先級(jí)任務(wù)的OS_TCB中的某些值[L4.15(4)]。而這些值用來將任務(wù)放入就緒表或從該表中移除(參看3.04,就緒表)。
接著,OSTaskChangePrio()檢驗(yàn)?zāi)壳暗娜蝿?wù)是否想改變它的優(yōu)先級(jí)[L4.15(5)]。然后,TaskChangePrio()檢查想要改變優(yōu)先級(jí)的任務(wù)是否存在[L4.15(6)]。很明顯,如果要改變優(yōu)先級(jí)的任務(wù)就是當(dāng)前任務(wù),這個(gè)測(cè)試就會(huì)成功。但是,如果OSTaskChangePrio()想要改變優(yōu)先級(jí)的任務(wù)不存在,它必須將保留的新優(yōu)先級(jí)放回到優(yōu)先級(jí)表OSTCBPrioTbl[]中[L4.15(17)],并返回給調(diào)用者一個(gè)錯(cuò)誤碼。
現(xiàn)在, OSTaskChangePrio()可以通過插入NULL指針將指向當(dāng)前任務(wù)OS_TCB的指針從優(yōu)先級(jí)表中移除了[L4.15(7)]。這就使得當(dāng)前任務(wù)的舊的優(yōu)先級(jí)可以重新使用了。接著,我們檢驗(yàn)一下OSTaskChangePrio()想要改變優(yōu)先級(jí)的任務(wù)是否就緒[L4.15(8)]。如果該任務(wù)處于就緒狀態(tài),它必須在當(dāng)前的優(yōu)先級(jí)下從就緒表中移除[L4.15(9)],然后在新的優(yōu)先級(jí)下插入到就緒表中[L4.15(10)]。這兒需要注意的是,OSTaskChangePrio()所用的是重新計(jì)算的值[L4.15(4)]將任務(wù)插入就緒表中的。
如果任務(wù)已經(jīng)就緒,它可能會(huì)正在等待一個(gè)信號(hào)量、一封郵件或是一個(gè)消息隊(duì)列。如果OSTCBEventPtr非空(不等于NULL)[L4.15(8)],OSTaskChangePrio()就會(huì)知道任務(wù)正在等待以上的某件事。如果任務(wù)在等待某一事件的發(fā)生,OSTaskChangePrio()必須將任務(wù)從事件控制塊(參看6.00,事件控制塊)的等待隊(duì)列(在舊的優(yōu)先級(jí)下)中移除。并在新的優(yōu)先級(jí)下將事件插入到等待隊(duì)列中[L4.15(12)]。 任務(wù)也有可能正在等待延時(shí)的期滿(參看第五章-任務(wù)管理)或是被掛起(參看4.07,掛起任務(wù),OSTaskSuspend())。在這些情況下,從L4.15(8)到L4.15(12)這幾行可以略過。
接著,OSTaskChangePrio()將指向任務(wù)OS_TCB的指針存到OSTCBPrioTbl[]中[L4.15(13)]。 新的優(yōu)先級(jí)被保存在OS_TCB中[L4.15(14)], 重新計(jì)算的值也被保存在OS_TCB中[L4.15(15)]。OSTaskChangePrio()完成了關(guān)鍵性的步驟后,在新的優(yōu)先級(jí)高于舊的優(yōu)先級(jí)或新的優(yōu)先級(jí)高于調(diào)用本函數(shù)的任務(wù)的優(yōu)先級(jí)情況下,任務(wù)調(diào)度程序就會(huì)被調(diào)用[L4.15(16)]。
程序清單 L4.15 OSTaskChangePrio().
INT8UOSTaskChangePrio(INT8Uoldprio,INT8Unewprio)
{
OS_TCB*ptcb;
OS_EVENT*pevent;
INT8Ux;
INT8Uy;
INT8Ubitx;
INT8Ubity;
if((oldprio>=OS_LOWEST_PRIOoldprio!=OS_PRIO_SELF)||(1)
newprio>=OS_LOWEST_PRIO){
return(OS_PRIO_INVALID);
}
OS_ENTER_CRITICAL();
if(OSTCBPrioTbl[newprio]!=(OS_TCB*)0){(2)
OS_EXIT_CRITICAL();
return(OS_PRIO_EXIST);
}else{
OSTCBPrioTbl[newprio]=(OS_TCB*)1;(3)
OS_EXIT_CRITICAL();
y=newprio>>3;(4)
bity=OSMapTbl[y];
x=newprio0x07;
bitx=OSMapTbl[x];
OS_ENTER_CRITICAL();
if(oldprio==OS_PRIO_SELF){(5)
oldprio=OSTCBCur->OSTCBPrio;
}
if((ptcb=OSTCBPrioTbl[oldprio])!=(OS_TCB*)0){(6)
OSTCBPrioTbl[oldprio]=(OS_TCB*)0;(7)
if(OSRdyTbl[ptcb->OSTCBY]ptcb->OSTCBBitX){(8)
if((OSRdyTbl[ptcb->OSTCBY]=~ptcb->OSTCBBitX)==0){(9)
OSRdyGrp=~ptcb->OSTCBBitY;
}
OSRdyGrp|=bity;(10)
OSRdyTbl[y]|=bitx;
}else{
if((pevent=ptcb->OSTCBEventPtr)!=(OS_EVENT*)0){(11)
if((pevent->OSEventTbl[ptcb->OSTCBY]=
~ptcb->OSTCBBitX)==0){
pevent->OSEventGrp=~ptcb->OSTCBBitY;
}
pevent->OSEventGrp|=bity;(12)
pevent->OSEventTbl[y]|=bitx;
}
}
OSTCBPrioTbl[newprio]=ptcb;(13)
ptcb->OSTCBPrio=newprio;(14)
ptcb->OSTCBY=y;(15)
ptcb->OSTCBX=x;
ptcb->OSTCBBitY=bity;
ptcb->OSTCBBitX=bitx;
OS_EXIT_CRITICAL();
OSSched();(16)
return(OS_NO_ERR);
評(píng)論