uc/os-ii刪除任務
阿新 • • 發佈:2019-01-23
uC/OS-II中與刪除任務相關的函式有兩個,刪除任務函式OSTaskDel()
和請求刪除任務函式OSTaskDelReq()
。
- 刪除任務函式原始碼如下,主要工作:
- 判斷引數的有效性
- 把要刪除的任務從任務就緒表中刪除
- 使被刪除的任務不等待延時期滿 ,不會被ISR置於就緒狀態,
ptcb->OSTCBDly = 0;
- 使被刪除的任務不被
OSTaskResume()
,啟用 ptcb->OSTCBStat = OS_STAT_RDY;
- 從優先順序列表中刪除被刪除的TCB,在雙向連結串列中去掉被刪除的TCB 。
INT8U OSTaskDel (INT8U prio)
{
#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)
OS_FLAG_NODE *pnode;
#endif
OS_TCB *ptcb;
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0;
#endif
if (OSIntNesting > 0) { /* See if trying to delete from ISR */
return (OS_ERR_TASK_DEL_ISR);
}
if (prio == OS_TASK_IDLE_PRIO) { /* Not allowed to delete idle task */
return (OS_ERR_TASK_DEL_IDLE);
}
#if OS_ARG_CHK_EN > 0
if (prio >= OS_LOWEST_PRIO) { /* Task priority valid ? */
if (prio != OS_PRIO_SELF) {
return (OS_ERR_PRIO_INVALID);
}
}
#endif
OS_ENTER_CRITICAL();
if (prio == OS_PRIO_SELF) { /* See if requesting to delete self */
prio = OSTCBCur->OSTCBPrio; /* Set priority to delete to current */
}
ptcb = OSTCBPrioTbl[prio];
if (ptcb == (OS_TCB *)0) { /* Task to delete must exist */
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_NOT_EXIST);
}
if (ptcb == OS_TCB_RESERVED) { /* Must not be assigned to Mutex */
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_DEL);
}
OSRdyTbl[ptcb->OSTCBY] &= ~ptcb->OSTCBBitX;
if (OSRdyTbl[ptcb->OSTCBY] == 0) { /* Make task not ready */
OSRdyGrp &= ~ptcb->OSTCBBitY;
}
#if (OS_EVENT_EN)
if (ptcb->OSTCBEventPtr != (OS_EVENT *)0) {
OS_EventTaskRemove(ptcb, ptcb->OSTCBEventPtr); /* Remove this task from any event wait list */
}
#if (OS_EVENT_MULTI_EN > 0)
if (ptcb->OSTCBEventMultiPtr != (OS_EVENT **)0) { /* Remove this task from any events' wait lists*/
OS_EventTaskRemoveMulti(ptcb, ptcb->OSTCBEventMultiPtr);
}
#endif
#endif
#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)
pnode = ptcb->OSTCBFlagNode;
if (pnode != (OS_FLAG_NODE *)0) { /* If task is waiting on event flag */
OS_FlagUnlink(pnode); /* Remove from wait list */
}
#endif
ptcb->OSTCBDly = 0; /* Prevent OSTimeTick() from updating */
ptcb->OSTCBStat = OS_STAT_RDY; /* Prevent task from being resumed */
ptcb->OSTCBStatPend = OS_STAT_PEND_OK;
if (OSLockNesting < 255u) { /* Make sure we don't context switch */
OSLockNesting++;
}
OS_EXIT_CRITICAL(); /* Enabling INT. ignores next instruc. */
OS_Dummy(); /* ... Dummy ensures that INTs will be */
OS_ENTER_CRITICAL(); /* ... disabled HERE! */
if (OSLockNesting > 0) { /* Remove context switch lock */
OSLockNesting--;
}
OSTaskDelHook(ptcb); /* Call user defined hook */
OSTaskCtr--; /* One less task being managed */
OSTCBPrioTbl[prio] = (OS_TCB *)0; /* Clear old priority entry */
if (ptcb->OSTCBPrev == (OS_TCB *)0) { /* Remove from TCB chain */
ptcb->OSTCBNext->OSTCBPrev = (OS_TCB *)0;
OSTCBList = ptcb->OSTCBNext;
} else {
ptcb->OSTCBPrev->OSTCBNext = ptcb->OSTCBNext;
ptcb->OSTCBNext->OSTCBPrev = ptcb->OSTCBPrev;
}
ptcb->OSTCBNext = OSTCBFreeList; /* Return TCB to free TCB list */
OSTCBFreeList = ptcb;
#if OS_TASK_NAME_SIZE > 1
ptcb->OSTCBTaskName[0] = '?'; /* Unknown name */
ptcb->OSTCBTaskName[1] = OS_ASCII_NUL;
#endif
OS_EXIT_CRITICAL();
if (OSRunning == OS_TRUE) {
OS_Sched(); /* Find new highest priority task */
}
return (OS_ERR_NONE);
}
- 請求刪除任務函式原始碼如下,主要工作:
- 當
prio == OS_PRIO_SELF
,查詢當前任務的OSTCBCur->OSTCBDelReq
標誌,返回是否有其它任務要求刪除當前任務。 - 當
prio != OS_PRIO_SELF
,設定要求刪除任務的OSTCBCur->OSTCBDelReq
標誌
- 當
ptcb = OSTCBPrioTbl[prio];
ptcb->OSTCBDelReq = OS_ERR_TASK_DEL_REQ;
INT8U OSTaskDelReq (INT8U prio)
{
INT8U stat;
OS_TCB *ptcb;
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0;
#endif
if (prio == OS_TASK_IDLE_PRIO) { /* Not allowed to delete idle task */
return (OS_ERR_TASK_DEL_IDLE);
}
#if OS_ARG_CHK_EN > 0
if (prio >= OS_LOWEST_PRIO) { /* Task priority valid ? */
if (prio != OS_PRIO_SELF) {
return (OS_ERR_PRIO_INVALID);
}
}
#endif
if (prio == OS_PRIO_SELF) { /* See if a task is requesting to ... */
OS_ENTER_CRITICAL(); /* ... this task to delete itself */
stat = OSTCBCur->OSTCBDelReq; /* Return request status to caller */
OS_EXIT_CRITICAL();
return (stat);
}
OS_ENTER_CRITICAL();
ptcb = OSTCBPrioTbl[prio];
if (ptcb == (OS_TCB *)0) { /* Task to delete must exist */
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_NOT_EXIST); /* Task must already be deleted */
}
if (ptcb == OS_TCB_RESERVED) { /* Must NOT be assigned to a Mutex */
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_DEL);
}
ptcb->OSTCBDelReq = OS_ERR_TASK_DEL_REQ; /* Set flag indicating task to be DEL. */
OS_EXIT_CRITICAL();
return (OS_ERR_NONE);
}
假設任務A擁有如訊號量之類的資源,如果任務B想刪除該任務,那麼這些資源就可能因為沒被釋放而丟失。面對這種情況,使用者就必須想辦法讓擁有這些資源的任務在使用完資源後,先釋放資源,再刪除。要實現這個功能,B任務可以通過OSTaskDelReq()
函式請求刪除A任務,A任務呼叫OSTaskDel()
刪除自己。
void TaskB (void *pdata)
{
INT8U err;
for (; ;)
{
應用程式程式碼;
if( TaskA需要被刪除 ) (1)
{
while(OSTaskDelReq(PrioA)!=OS_TASK_NOT_EXIST) (2)
{
OSTimeDly(1); (3)
}
}
應用程式程式碼;
} }
void TaskA (void *pdata)
{
INT8U err;
for (; ;)
{
應用程式程式碼;
if( OSTaskDelReq(OS_PRIO_SELF)==OS_TASK_DEL_REQ ) (4)
{
釋放佔有的資源
OSTaskDel(OS_PRIO_SELF);
}
else
{
應用程式程式碼;
}
} }
分析上面的程式:
1. 任務B決定是否需要請求刪除任務。
2. 如果符合刪除條件,則以被刪除任務的優先順序為引數呼叫OSTaskDelReq()
函式。如果OSTaskDelReq()返回OS_TASK_NOT_EXIST
,則表明要被刪除的任務可能已被刪除,也可能尚未建立,所以退出迴圈。
3. 如果OSTaskDelReq()
返回OS_NO_ERR
,表明請求已被接受但任務還沒被刪除,則通過一個延時呼叫掛起任務B自身,以便使任務A得以執行,如果需要,延時可以更長一些。等到任務B重新執行的時候,OSTaskDelReq()
函式必然返回OS_TASK_NOT_EXIST
,從而退出迴圈。
4. 任務A呼叫OSTaskDelReq()
,查詢是否收到刪除請求,若收到,釋放所有資源,並自我刪除;若沒有收到,則繼續執行其它使用者程式。