自学内容网 自学内容网

FreeRTOS之vTaskDelete实现分析

1 函数接口

1.1 函数接口

void vTaskDelete( TaskHandle_t xTaskToDelete )

1.2 函数参数简介

  • TaskHandle_t xTaskToDelete 要删除任务的句柄,但这个句柄其实就是我们申请任务时创建的TCB,这个参数在传入的时候可以设置为NULL,表示要删除的是自己当前的任务。

2 vTaskDelete的调用关系

2.1 调用关系

|- vTaskDelete
|- pxTCB = prvGetTCBFromHandle( xTaskToDelete );
|- uxListRemove( &( pxTCB->xStateListItem ) )
|- taskRESET_READY_PRIORITY( pxTCB->uxPriority );
|- vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xStateListItem ) );
|- taskYIELD_WITHIN_API();

2.2 调用关系示意图

3 函数源码分析

3.1 vTaskDelete

  • pxTCB = prvGetTCBFromHandle( xTaskToDelete ); 获取要删除任务的TCB
  • uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 将当前要删除的任务从pxReadyTasksLists对应优先级的链表里面删除,并判断该优先级的任务数是不是为0了,如果当前该优先级的链表里已经没有任务则需要调用taskRESET_READY_PRIORITY( pxTCB->uxPriority );去做重置将该优先级在uxTopReadyPriority中mask掉。
  • vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xStateListItem ) ); 如果当前的任务处于运行状态,则将当前要删除的任务放入到xTasksWaitingTermination列表,等到idle task执行的时候再去执行删除操作。任务是否处于调度状态的判断依据是xSchedulerRunning是否是pdTRUE,该状态位在执行vTaskStartScheduler函数时被置位,在执行vTaskEndScheduler函数时被置位pdFALSE,因此只要是当前的系统调度没有停就需要将要删除的任务的TCB加入到xTasksWaitingTermination链表中。
  • ++uxDeletedTasksWaitingCleanUp 记录等待清理任务的数量,在idle task或者vTaskEndScheduler执行时,以该全局变量作为清理数量的标准。
  • xDeleteTCBInIdleTask = pdTRUE; 标记当前任务要再idle task里面做删除工作。
  • taskYIELD_WITHIN_API();或者prvYieldCore( pxTCB->xTaskRunState ); 将处理器让出去,调度其他的任务。
void vTaskDelete( TaskHandle_t xTaskToDelete )
{
TCB_t * pxTCB;
BaseType_t xDeleteTCBInIdleTask = pdFALSE;
BaseType_t xTaskIsRunningOrYielding;

traceENTER_vTaskDelete( xTaskToDelete );

taskENTER_CRITICAL();
{
获取当前要删除任务的TCB,如果xTaskToDelete 为空则表示要删除当前正在运行的任务,否则就找到对应任务的TCB。
pxTCB = prvGetTCBFromHandle( xTaskToDelete );
configASSERT( pxTCB != NULL );

把当前要删除的任务从ready/delayed 链表中删除,并判断任务优先级的链表任务数是否为0
if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
{
如果当前要删除的任务优先级所对应的链表任务数为0,则将该优先级在uxTopReadyPriority中mask掉。
taskRESET_READY_PRIORITY( pxTCB->uxPriority );
}
else
{
mtCOVERAGE_TEST_MARKER();
}

判断当前的任务是否在一个event的链表,如果是则通过uxListRemove将其移除
if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
{
( void ) uxListRemove( &( pxTCB->xEventListItem ) );
}
else
{
mtCOVERAGE_TEST_MARKER();
}

/* Increment the uxTaskNumber also so kernel aware debuggers can
 * detect that the task lists need re-generating.  This is done before
 * portPRE_TASK_DELETE_HOOK() as in the Windows port that macro will
 * not return. */
uxTaskNumber++;

通过taskTASK_IS_RUNNING_OR_SCHEDULED_TO_YIELD来判断当前的任务是否在运行状态,如果其xTaskRunState被设置为-1则表明其不处于运行状态,正常运行的任务其xTaskRunState值会被设置为所运行的core的id。
xTaskIsRunningOrYielding = taskTASK_IS_RUNNING_OR_SCHEDULED_TO_YIELD( pxTCB );

根据xSchedulerRunning 来判断当前的是否还处于正常的调度状态,该全局变量在vTaskStartScheduler函数被执行时设置为pdTRUE,在vTaskEndScheduler时被设置为pdFALSE
if( ( xSchedulerRunning != pdFALSE ) && ( xTaskIsRunningOrYielding != pdFALSE ) )
{
为了防止该任务在其他core上还有运行的,所以将该任务添加到xTasksWaitingTermination链表上,等idle task运行时再做清理工作。
vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xStateListItem ) );

标记当前需要做清理的任务数
++uxDeletedTasksWaitingCleanUp;

/* Call the delete hook before portPRE_TASK_DELETE_HOOK() as
 * portPRE_TASK_DELETE_HOOK() does not return in the Win32 port. */
traceTASK_DELETE( pxTCB );

用以标记有任务需要删除,如果需要设置为pdTRUE,则在后面会调用prvDeleteTCB( pxTCB );释放掉这块内存空间。
xDeleteTCBInIdleTask = pdTRUE;

/* The pre-delete hook is primarily for the Windows simulator,
 * in which Windows specific clean up operations are performed,
 * after which it is not possible to yield away from this task -
 * hence xYieldPending is used to latch that a context switch is
 * required. */
#if ( configNUMBER_OF_CORES == 1 )
portPRE_TASK_DELETE_HOOK( pxTCB, &( xYieldPendings[ 0 ] ) );
#else
portPRE_TASK_DELETE_HOOK( pxTCB, &( xYieldPendings[ pxTCB->xTaskRunState ] ) );
#endif

在SMP系统给按任务让出CPU,让其他任务去运行
#if ( configNUMBER_OF_CORES > 1 )
{
if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE )
{
if( pxTCB->xTaskRunState == ( BaseType_t ) portGET_CORE_ID() )
{
configASSERT( uxSchedulerSuspended == 0 );
taskYIELD_WITHIN_API();
}
else
{
prvYieldCore( pxTCB->xTaskRunState );
}
}
}
#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
}
else
{
--uxCurrentNumberOfTasks;
traceTASK_DELETE( pxTCB );

/* Reset the next expected unblock time in case it referred to
 * the task that has just been deleted. */
prvResetNextTaskUnblockTime();
}
}
taskEXIT_CRITICAL();

/* If the task is not deleting itself, call prvDeleteTCB from outside of
 * critical section. If a task deletes itself, prvDeleteTCB is called
 * from prvCheckTasksWaitingTermination which is called from Idle task. */
if( xDeleteTCBInIdleTask != pdTRUE )
{
prvDeleteTCB( pxTCB );
}

/* Force a reschedule if it is the currently running task that has just
 * been deleted. */
#if ( configNUMBER_OF_CORES == 1 )
{
if( xSchedulerRunning != pdFALSE )
{
if( pxTCB == pxCurrentTCB )
{
configASSERT( uxSchedulerSuspended == 0 );
taskYIELD_WITHIN_API();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
}
#endif /* #if ( configNUMBER_OF_CORES == 1 ) */

traceRETURN_vTaskDelete();
}

3.2 uxListRemove

  • pxList = pxItemToRemove->pxContainer; 通过pxContainer找到当前任务优先级所对应链表的链表头
  • pxList->uxNumberOfItems 返回当前任务优先级链表还剩余的任务数,一般用于判断链表所挂任务是否为0,用以来确定当前任务的优先级是否需要mask掉。
UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
{
    /* The list item knows which list it is in.  Obtain the list from the list
     * item. */
    List_t * const pxList = pxItemToRemove->pxContainer;

    traceENTER_uxListRemove( pxItemToRemove );

    pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;
    pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;

    /* Only used during decision coverage testing. */
    mtCOVERAGE_TEST_DELAY();

    /* Make sure the index is left pointing to a valid item. */
    if( pxList->pxIndex == pxItemToRemove )
    {
        pxList->pxIndex = pxItemToRemove->pxPrevious;
    }
    else
    {
        mtCOVERAGE_TEST_MARKER();
    }

    pxItemToRemove->pxContainer = NULL;
    ( pxList->uxNumberOfItems ) = ( UBaseType_t ) ( pxList->uxNumberOfItems - 1U );

    traceRETURN_uxListRemove( pxList->uxNumberOfItems );

    return pxList->uxNumberOfItems;
}

原文地址:https://blog.csdn.net/u014100559/article/details/143984565

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!