1. 程式人生 > >uc/os-ii刪除任務

uc/os-ii刪除任務

uC/OS-II中與刪除任務相關的函式有兩個,刪除任務函式OSTaskDel() 和請求刪除任務函式OSTaskDelReq()

  • 刪除任務函式原始碼如下,主要工作:
    1. 判斷引數的有效性
    2. 把要刪除的任務從任務就緒表中刪除
    3. 使被刪除的任務不等待延時期滿 ,不會被ISR置於就緒狀態,ptcb->OSTCBDly = 0;
    4. 使被刪除的任務不被OSTaskResume()啟用 ptcb->OSTCBStat = OS_STAT_RDY;
    5. 從優先順序列表中刪除被刪除的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); }
  • 請求刪除任務函式原始碼如下,主要工作:
    1. prio == OS_PRIO_SELF,查詢當前任務的OSTCBCur->OSTCBDelReq標誌,返回是否有其它任務要求刪除當前任務。
    2. 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(),查詢是否收到刪除請求,若收到,釋放所有資源,並自我刪除;若沒有收到,則繼續執行其它使用者程式。