LiteOS-任務篇-源碼分析-刪除任務函數


前言

  • 20201009
  • LiteOS 2018
  • 需要會通用鏈表

筆錄草稿

源碼分析

LOS_TaskDelete函數源碼分析

完整源碼

  • 進入處理前,需要進入任務臨界
  • 通過任務ID來獲取任務句柄
  • 根據各種狀態進行處理
    • 處於 OS_TASK_STATUS_UNUSED (未使用) 狀態
      • 退出
    • 處於 OS_TASK_STATUS_RUNNING (運行態) 且調度被鎖定了
      • 解鎖任務調度
    • 處於 就緒態阻塞態阻塞隊列態
      • 處於 OS_TASK_STATUS_READY (就緒態)
        • 從就緒列表中刪除該節點
        • 取消該任務的就緒態
      • 處於 OS_TASK_STATUS_PEND(阻塞態) 或 OS_TASK_STATUS_PEND_QUEUE(阻塞隊列態)
        • 從就緒列表中刪除該節點
    • 處於 OS_TASK_STATUS_DELAY (延時態)或 OS_TASK_STATUS_TIMEOUT(超時態)
      • 從時間列表中刪除該任務
  • 被刪除的任務需要做一些複位處理
    • 初始化任務狀態
    • 初始化任務事件相關的一些變數
  • 被刪除的任務s是否處於運行態
      • 不能完全刪除該任務,因為,調度過程中需要該任務參與
      • 把當前任務插入到回收列表中,待運行創建任務函數時在進行回收處理。(其它RTOS都是在空閑任務中處理)
      • 把當前任務(被刪除的任務)copy到最低優先順序的任務中,即是比空閑任務還低一個優先順序的備用任務中,被賦給 g_stLosTask.pstRunTask,用於下main調度使用
      • 解鎖中斷
      • 調度
      • 標記為未使用狀態
      • 直接放到空閑列表中
      • 釋放任務堆空間
      • 初始化棧頂指針
  • 解鎖中斷
/*****************************************************************************
 Function : LOS_TaskDelete
 Description : Delete a task
 Input       : uwTaskID --- Task ID
 Output      : None
 Return      : LOS_OK on success or error code on failure
 *****************************************************************************/
LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskDelete(UINT32 uwTaskID)
{
    UINTPTR uvIntSave;  
    LOS_TASK_CB *pstTaskCB;
    UINT16 usTempStatus;
    UINT32 uwErrRet = OS_ERROR;

    CHECK_TASKID(uwTaskID); // 檢查任務 ID
    uvIntSave = LOS_IntLock(); // 鎖中斷

    pstTaskCB = OS_TCB_FROM_TID(uwTaskID);  // 通過任務 ID 獲取任務控制塊句柄

    usTempStatus = pstTaskCB->usTaskStatus; // 獲取任務狀態

    /* 判斷任務狀態是否處於 UNUSED (即未被創建) 狀態,若是則退出*/
    if (OS_TASK_STATUS_UNUSED & usTempStatus)
    {
        uwErrRet = LOS_ERRNO_TSK_NOT_CREATED;
        OS_GOTO_ERREND();
    }

    /* If the task is running and scheduler is locked then you can not delete it */
    if ((OS_TASK_STATUS_RUNNING & usTempStatus) && (g_usLosTaskLock != 0))
    {
        PRINT_INFO("In case of task lock, task deletion is not recommended\n");
        g_usLosTaskLock = 0;
    }

    /* 判斷任務狀態是否處於 READY (即就緒態) 狀態*/
    if (OS_TASK_STATUS_READY & usTempStatus) // 處於就緒態
    {
        osPriqueueDequeue(&pstTaskCB->stPendList); // 從對應鏈表中刪除該任務節點
        pstTaskCB->usTaskStatus &= (~OS_TASK_STATUS_READY); // 取消就緒態
    }
    else if ((OS_TASK_STATUS_PEND & usTempStatus) || (OS_TASK_STATUS_PEND_QUEUE & usTempStatus)) // 處於阻塞態
    {
        LOS_ListDelete(&pstTaskCB->stPendList); // 從對應鏈表中刪除該任務節點
    }

    if ((OS_TASK_STATUS_DELAY | OS_TASK_STATUS_TIMEOUT) & usTempStatus) // 處於任務延時會或超時狀態
    {
        osTimerListDelete(pstTaskCB); // 從對應鏈表中刪除該任務節點
    }

    pstTaskCB->usTaskStatus &= (~(OS_TASK_STATUS_SUSPEND)); // 取消掛起態
    pstTaskCB->usTaskStatus |= OS_TASK_STATUS_UNUSED; // 標為未使用狀態
    pstTaskCB->uwEvent.uwEventID = 0xFFFFFFFF; // 複位時間ID
    pstTaskCB->uwEventMask = 0;
#if (LOSCFG_BASE_CORE_CPUP == YES)
    (VOID)memset((VOID *)&g_pstCpup[pstTaskCB->uwTaskID], 0, sizeof(OS_CPUP_S));
#endif
    g_stLosTask.pstNewTask = LOS_DL_LIST_ENTRY(osPriqueueTop(), LOS_TASK_CB, stPendList); /*lint !e413*/ // 在就緒列表中尋找最高優先順序的任務,標為下一個需要運行的任務
    if (OS_TASK_STATUS_RUNNING & pstTaskCB->usTaskStatus) // 如果被刪除的任務為運行態
    {
        /*
         * 如果刪除的任務為運行態時,就不能完全刪除該任務,因為,調度過程中需要當前任務參與。
         * 需要把當前任務插入到回收列表中,待運行創建任務函數時在進行回收處理。(其它RTOS都是在空閑任務中處理)
         */
        LOS_ListTailInsert(&g_stTskRecyleList, &pstTaskCB->stPendList); // 把該任務插入回收列表
        g_stLosTask.pstRunTask = &g_pstTaskCBArray[g_uwTskMaxNum]; 
        g_stLosTask.pstRunTask->uwTaskID = uwTaskID; 
        g_stLosTask.pstRunTask->usTaskStatus = pstTaskCB->usTaskStatus;
        g_stLosTask.pstRunTask->uwTopOfStack = pstTaskCB->uwTopOfStack;
        g_stLosTask.pstRunTask->pcTaskName = pstTaskCB->pcTaskName;
        pstTaskCB->usTaskStatus = OS_TASK_STATUS_UNUSED;
        (VOID)LOS_IntRestore(uvIntSave); // 解鎖中斷
        osSchedule(); // 調度
        return LOS_OK;
    }
    else // 如果不為運行態
    {
        pstTaskCB->usTaskStatus = OS_TASK_STATUS_UNUSED; // 標為未使用
        LOS_ListAdd(&g_stLosFreeTask, &pstTaskCB->stPendList); // 插入到可用列表
        (VOID)LOS_MemFree(m_aucSysMem0, (VOID *)pstTaskCB->uwTopOfStack); // 釋放任務堆空間記憶體
        pstTaskCB->uwTopOfStack = (UINT32)NULL; // 標記棧頂為空
    }

    (VOID)LOS_IntRestore(uvIntSave); // 解鎖中斷
    return LOS_OK;

LOS_ERREND: // 錯誤
    (VOID)LOS_IntRestore(uvIntSave);
    return uwErrRet;
}

參考

鏈接