μC/OS-II的任務管理
(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改變任務的優(yōu)先級,OSTaskChangePrio()
在用戶建立任務的時候會分配給任務一個優(yōu)先級。在程序運行期間,用戶可以通過調用OSTaskChangePrio()來改變任務的優(yōu)先級。換句話說,就是μC/OS-Ⅱ允許用戶動態(tài)的改變任務的優(yōu)先級。
OSTaskChangePrio()的代碼如程序清單L4.15所示。用戶不能改變空閑任務的優(yōu)先級[L4.15(1)],但用戶可以改變調用本函數的任務或者其它任務的優(yōu)先級。為了改變調用本函數的任務的優(yōu)先級,用戶可以指定該任務當前的優(yōu)先級或OS_PRIO_SELF,
OSTaskChangePrio()會決定該任務的優(yōu)先級。用戶還必須指定任務的新(即想要的)優(yōu)先級。因為μC/OS-Ⅱ不允許多個任務具有相同的優(yōu)先級,所以OSTaskChangePrio()需要檢驗新優(yōu)先級是否是合法的(即不存在具有新優(yōu)先級的任務)[L4.15(2)]。如果新優(yōu)先級是合法的,μC/OS-Ⅱ通過將某些東西儲存到OSTCBPrioTbl[newprio]中保留這個優(yōu)先級[L4.15(3)]。如此就使得OSTaskChangePrio()可以重新允許中斷,因為此時其它任務已經不可能建立擁有該優(yōu)先級的任務,也不能通過指定相同的新優(yōu)先級來調用OSTaskChangePrio()。接下來OSTaskChangePrio()可以預先計算新優(yōu)先級任務的OS_TCB中的某些值[L4.15(4)]。而這些值用來將任務放入就緒表或從該表中移除(參看3.04,就緒表)。
接著,OSTaskChangePrio()檢驗目前的任務是否想改變它的優(yōu)先級[L4.15(5)]。然后,TaskChangePrio()檢查想要改變優(yōu)先級的任務是否存在[L4.15(6)]。很明顯,如果要改變優(yōu)先級的任務就是當前任務,這個測試就會成功。但是,如果OSTaskChangePrio()想要改變優(yōu)先級的任務不存在,它必須將保留的新優(yōu)先級放回到優(yōu)先級表OSTCBPrioTbl[]中[L4.15(17)],并返回給調用者一個錯誤碼。
現在, OSTaskChangePrio()可以通過插入NULL指針將指向當前任務OS_TCB的指針從優(yōu)先級表中移除了[L4.15(7)]。這就使得當前任務的舊的優(yōu)先級可以重新使用了。接著,我們檢驗一下OSTaskChangePrio()想要改變優(yōu)先級的任務是否就緒[L4.15(8)]。如果該任務處于就緒狀態(tài),它必須在當前的優(yōu)先級下從就緒表中移除[L4.15(9)],然后在新的優(yōu)先級下插入到就緒表中[L4.15(10)]。這兒需要注意的是,OSTaskChangePrio()所用的是重新計算的值[L4.15(4)]將任務插入就緒表中的。
如果任務已經就緒,它可能會正在等待一個信號量、一封郵件或是一個消息隊列。如果OSTCBEventPtr非空(不等于NULL)[L4.15(8)],OSTaskChangePrio()就會知道任務正在等待以上的某件事。如果任務在等待某一事件的發(fā)生,OSTaskChangePrio()必須將任務從事件控制塊(參看6.00,事件控制塊)的等待隊列(在舊的優(yōu)先級下)中移除。并在新的優(yōu)先級下將事件插入到等待隊列中[L4.15(12)]。 任務也有可能正在等待延時的期滿(參看第五章-任務管理)或是被掛起(參看4.07,掛起任務,OSTaskSuspend())。在這些情況下,從L4.15(8)到L4.15(12)這幾行可以略過。
接著,OSTaskChangePrio()將指向任務OS_TCB的指針存到OSTCBPrioTbl[]中[L4.15(13)]。 新的優(yōu)先級被保存在OS_TCB中[L4.15(14)], 重新計算的值也被保存在OS_TCB中[L4.15(15)]。OSTaskChangePrio()完成了關鍵性的步驟后,在新的優(yōu)先級高于舊的優(yōu)先級或新的優(yōu)先級高于調用本函數的任務的優(yōu)先級情況下,任務調度程序就會被調用[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);
評論