mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 03:00:34 +03:00
feat(coredump): improve the probability of accessing healthy TCBs
This commit is contained in:
@@ -912,10 +912,10 @@ static List_t * non_ready_task_lists[] = {
|
||||
/*----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Get the next task list to traverse
|
||||
* @brief Get the task list from state lists by index
|
||||
*
|
||||
* - Given a particular task list, this function returns the next task to traverse.
|
||||
* - The task lists are returned in the following precedence
|
||||
* - This function returns the task list based on the specified index.
|
||||
* - The index is relative to the below order of the task state lists
|
||||
* - Ready lists (highest to lowers priority)
|
||||
* - Pending ready list(s)
|
||||
* - Delayed list 1
|
||||
@@ -923,132 +923,133 @@ static List_t * non_ready_task_lists[] = {
|
||||
* - Waiting termination list
|
||||
* - Suspended list
|
||||
*
|
||||
* @param pxCurTaskList Previously traversed task list (or NULL if obtaining the first task list)
|
||||
* @return List_t* The next task list to traverse (or NULL of all task lists have been traversed)
|
||||
* @param uxListIndex The index of the desired task list.
|
||||
* @return A pointer to the task list at the specified index.
|
||||
* Returns NULL if the index is out of bounds or list is corrupted.
|
||||
*/
|
||||
static List_t * pxGetNextTaskList( List_t * pxCurTaskList )
|
||||
static List_t * pxGetTaskListByIndex( UBaseType_t uxListIndex )
|
||||
{
|
||||
List_t * pxNextTaskList = NULL;
|
||||
List_t * pxTaskList;
|
||||
const size_t xNonReadyTaskListsCnt = ( sizeof( non_ready_task_lists ) / sizeof( List_t * ) );
|
||||
|
||||
/* No Current List. Start from the highest priority ready task list */
|
||||
if( pxCurTaskList == NULL )
|
||||
if( uxListIndex < configMAX_PRIORITIES )
|
||||
{
|
||||
pxNextTaskList = &pxReadyTasksLists[ configMAX_PRIORITIES - 1 ];
|
||||
pxTaskList = &pxReadyTasksLists[ configMAX_PRIORITIES - 1 - uxListIndex ];
|
||||
}
|
||||
/* Current list is one of the ready task lists. Find the current priority, and return the next lower priority ready task list */
|
||||
else if( ( pxCurTaskList >= &pxReadyTasksLists[ 0 ] ) && ( pxCurTaskList <= &pxReadyTasksLists[ configMAX_PRIORITIES - 1 ] ) )
|
||||
else if( uxListIndex < configMAX_PRIORITIES + xNonReadyTaskListsCnt + 1 )
|
||||
{
|
||||
/* Find the current priority */
|
||||
int cur_priority;
|
||||
pxTaskList = non_ready_task_lists[ uxListIndex - configMAX_PRIORITIES ];
|
||||
}
|
||||
else
|
||||
{
|
||||
pxTaskList = NULL;
|
||||
}
|
||||
|
||||
for( cur_priority = configMAX_PRIORITIES - 1; cur_priority >= 0; cur_priority-- )
|
||||
/* sanity check */
|
||||
if( pxTaskList )
|
||||
{
|
||||
if( !portVALID_LIST_MEM( pxTaskList ) )
|
||||
{
|
||||
if( pxCurTaskList == &pxReadyTasksLists[ cur_priority ] )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the ready task list at (cur_priority - 1), or the pending ready task list */
|
||||
if( cur_priority > 0 )
|
||||
{
|
||||
pxNextTaskList = &pxReadyTasksLists[ cur_priority - 1 ];
|
||||
}
|
||||
/* We've reached the end of the Ready Task Lists. We get the next list from the non-ready task lists */
|
||||
else if( cur_priority == 0 )
|
||||
{
|
||||
pxNextTaskList = non_ready_task_lists[ 0 ];
|
||||
}
|
||||
else
|
||||
{
|
||||
abort(); /* This should never occur */
|
||||
pxTaskList = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Current list is one of the non-ready task lists. Fetch the next non-ready task list */
|
||||
if( pxNextTaskList == NULL )
|
||||
{
|
||||
int cur_list_idx;
|
||||
const int num_non_ready_task_lists = ( sizeof( non_ready_task_lists ) / sizeof( List_t * ) );
|
||||
|
||||
/* Note: - 1 so that if the current list is the last on non_ready_task_lists[], the next list will return NULL */
|
||||
for( cur_list_idx = 0; cur_list_idx < num_non_ready_task_lists - 1; cur_list_idx++ )
|
||||
{
|
||||
if( pxCurTaskList == non_ready_task_lists[ cur_list_idx ] )
|
||||
{
|
||||
pxNextTaskList = non_ready_task_lists[ cur_list_idx + 1 ];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pxNextTaskList;
|
||||
return pxTaskList;
|
||||
}
|
||||
/*----------------------------------------------------------*/
|
||||
|
||||
TaskHandle_t pxTaskGetNext( TaskHandle_t pxTask )
|
||||
/**
|
||||
* @brief Get the total count of task lists.
|
||||
*
|
||||
* The count includes both the ready task lists (based on priority) and non-ready task lists.
|
||||
*
|
||||
* @return The total count of task lists.
|
||||
*
|
||||
*/
|
||||
static inline UBaseType_t pxGetTaskListCount( void )
|
||||
{
|
||||
TCB_t * pxTCB = ( TCB_t * ) pxTask;
|
||||
return configMAX_PRIORITIES + ( sizeof( non_ready_task_lists ) / sizeof( List_t * ) );
|
||||
}
|
||||
/*----------------------------------------------------------*/
|
||||
|
||||
/* Check current task is valid */
|
||||
if( ( pxTCB != NULL ) && !portVALID_TCB_MEM( pxTCB ) )
|
||||
/**
|
||||
* @brief Get the next task using the task iterator.
|
||||
*
|
||||
* This function retrieves the next task in the traversal sequence.
|
||||
*
|
||||
* @param xIterator Pointer to the task iterator structure.
|
||||
*
|
||||
* @return Index of the current task list. Returns -1 if all tasks have been traversed.
|
||||
*
|
||||
* @note The task iterator keeps track of the current state during task traversal,
|
||||
* including the index of the current task list and the pointer of the next task list item.
|
||||
* When all tasks have been traversed, this function returns -1.
|
||||
* If a broken or corrupted task is encountered, the task handle is set to NULL.
|
||||
*/
|
||||
int xTaskGetNext( TaskIterator_t * xIterator )
|
||||
{
|
||||
if( !xIterator )
|
||||
{
|
||||
return NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
List_t * pxCurTaskList;
|
||||
const ListItem_t * pxCurListItem;
|
||||
ListItem_t * pxNextListItem = xIterator->pxNextListItem;
|
||||
UBaseType_t uxCurListIdx = xIterator->uxCurrentListIndex;
|
||||
UBaseType_t uxMaxListIdx = pxGetTaskListCount();
|
||||
|
||||
if( pxTCB == NULL )
|
||||
for( ; uxCurListIdx < uxMaxListIdx; ++uxCurListIdx )
|
||||
{
|
||||
/* Starting traversal for the first time */
|
||||
pxCurTaskList = pxGetNextTaskList( NULL );
|
||||
pxCurListItem = listGET_END_MARKER( pxCurTaskList );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Continuing traversal */
|
||||
pxCurTaskList = listLIST_ITEM_CONTAINER( &pxTCB->xStateListItem );
|
||||
pxCurListItem = &pxTCB->xStateListItem;
|
||||
}
|
||||
List_t * pxCurrentTaskList = pxGetTaskListByIndex( uxCurListIdx );
|
||||
|
||||
ListItem_t * pxNextListItem = NULL;
|
||||
|
||||
if( pxCurListItem->pxNext == listGET_END_MARKER( pxCurTaskList ) )
|
||||
{
|
||||
List_t * pxNextTaskList = pxGetNextTaskList( pxCurTaskList );
|
||||
|
||||
while( pxNextTaskList != NULL )
|
||||
if( !pxCurrentTaskList || ( listCURRENT_LIST_LENGTH( pxCurrentTaskList ) == 0 ) )
|
||||
{
|
||||
if( !listLIST_IS_EMPTY( pxNextTaskList ) )
|
||||
{
|
||||
/* Get the first item in the next task list */
|
||||
pxNextListItem = listGET_HEAD_ENTRY( pxNextTaskList );
|
||||
break;
|
||||
}
|
||||
|
||||
/* Task list is empty. Get the next task list */
|
||||
pxNextTaskList = pxGetNextTaskList( pxNextTaskList );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*There are still more items in the current task list. Get the next item */
|
||||
pxNextListItem = listGET_NEXT( pxCurListItem );
|
||||
|
||||
const ListItem_t * pxCurrListItem = listGET_END_MARKER( pxCurrentTaskList );
|
||||
|
||||
if( !pxNextListItem )
|
||||
{
|
||||
/* We are here if the traversal starts from the beginning or when we finish traversing
|
||||
* for one of the state lists
|
||||
*/
|
||||
pxNextListItem = listGET_NEXT( pxCurrListItem );
|
||||
}
|
||||
|
||||
if( !portVALID_LIST_MEM( pxNextListItem ) )
|
||||
{
|
||||
/* Nothing to do with the corrupted list item. We will skip to the next task state list.
|
||||
* pxNextListItem should be NULL at the beggining of each task list.
|
||||
*/
|
||||
pxNextListItem = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
TCB_t * pxTCB = ( TCB_t * ) listGET_LIST_ITEM_OWNER( pxNextListItem );
|
||||
|
||||
if( !portVALID_TCB_MEM( pxTCB ) )
|
||||
{
|
||||
pxTCB = NULL;
|
||||
}
|
||||
|
||||
xIterator->pxTaskHandle = pxTCB;
|
||||
xIterator->uxCurrentListIndex = uxCurListIdx;
|
||||
|
||||
if( pxCurrListItem->pxPrevious == pxNextListItem )
|
||||
{
|
||||
/* If this is the last item of the current state list */
|
||||
xIterator->uxCurrentListIndex++;
|
||||
xIterator->pxNextListItem = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
xIterator->pxNextListItem = listGET_NEXT( pxNextListItem );
|
||||
}
|
||||
|
||||
return uxCurListIdx;
|
||||
}
|
||||
|
||||
TCB_t * pxNextTCB;
|
||||
|
||||
if( pxNextListItem == NULL )
|
||||
{
|
||||
pxNextTCB = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
pxNextTCB = ( TCB_t * ) listGET_LIST_ITEM_OWNER( pxNextListItem );
|
||||
}
|
||||
|
||||
return pxNextTCB;
|
||||
return -1; /* end of the task list */
|
||||
}
|
||||
/*----------------------------------------------------------*/
|
||||
|
||||
@@ -1074,34 +1075,13 @@ UBaseType_t uxTaskGetSnapshotAll( TaskSnapshot_t * const pxTaskSnapshotArray,
|
||||
{
|
||||
UBaseType_t uxArrayNumFilled = 0;
|
||||
|
||||
/*Traverse all of the tasks lists */
|
||||
List_t * pxCurTaskList = pxGetNextTaskList( NULL ); /*Get the first task list */
|
||||
/* Traverse all of the tasks lists */
|
||||
TaskIterator_t xTaskIter = { 0 }; /* Point to the first task list */
|
||||
|
||||
while( pxCurTaskList != NULL && uxArrayNumFilled < uxArrayLength )
|
||||
while( xTaskGetNext( &xTaskIter ) != -1 && uxArrayNumFilled < uxArrayLength )
|
||||
{
|
||||
if( !listLIST_IS_EMPTY( pxCurTaskList ) )
|
||||
{
|
||||
const ListItem_t * pxCurListItem;
|
||||
/*Walk each task on the current task list */
|
||||
pxCurListItem = listGET_HEAD_ENTRY( pxCurTaskList );
|
||||
|
||||
while( pxCurListItem != listGET_END_MARKER( pxCurTaskList ) )
|
||||
{
|
||||
TCB_t * pxTCB = ( TCB_t * ) listGET_LIST_ITEM_OWNER( pxCurListItem );
|
||||
vTaskGetSnapshot( ( TaskHandle_t ) pxTCB, &pxTaskSnapshotArray[ uxArrayNumFilled ] );
|
||||
uxArrayNumFilled++;
|
||||
|
||||
if( !( uxArrayNumFilled < uxArrayLength ) )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
pxCurListItem = listGET_NEXT( pxCurListItem );
|
||||
}
|
||||
}
|
||||
|
||||
/*Get the next task list */
|
||||
pxCurTaskList = pxGetNextTaskList( pxCurTaskList );
|
||||
vTaskGetSnapshot( xTaskIter.pxTaskHandle, &pxTaskSnapshotArray[ uxArrayNumFilled ] );
|
||||
uxArrayNumFilled++;
|
||||
}
|
||||
|
||||
*pxTCBSize = sizeof( TCB_t );
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -37,18 +37,33 @@ typedef struct xTASK_SNAPSHOT
|
||||
} TaskSnapshot_t;
|
||||
|
||||
/**
|
||||
* @brief Iterate over all tasks in the system
|
||||
* @brief Task Snapshot iterator
|
||||
*
|
||||
* - This function can be used to iterate over every task in the system
|
||||
* - The first call to this function must set pxTask to NULL
|
||||
* - When all functions have been iterated, this function will return NULL.
|
||||
*
|
||||
* @note This function should only be called when FreeRTOS is no longer running (e.g., during a panic) as this function
|
||||
* does not acquire any locks.
|
||||
* @param pxTask Handle of the previous task (or NULL on the first call of this function)
|
||||
* @return TaskHandle_t Handle of the next task (or NULL when all tasks have been iterated over)
|
||||
* Used in xTaskGetNext(). Must be zero/null initialized on the first call.
|
||||
*/
|
||||
TaskHandle_t pxTaskGetNext( TaskHandle_t pxTask );
|
||||
typedef struct TaskIterator
|
||||
{
|
||||
UBaseType_t uxCurrentListIndex; /**< Current task list index being traversed. */
|
||||
ListItem_t * pxNextListItem; /**< Next task list item will being traversed. */
|
||||
TaskHandle_t pxTaskHandle; /**< Current task handle being traversed. */
|
||||
} TaskIterator_t;
|
||||
|
||||
/**
|
||||
* @brief Get the next task using the task iterator.
|
||||
*
|
||||
* This function retrieves the next task in the traversal sequence.
|
||||
*
|
||||
* @param xIterator Pointer to the task iterator structure.
|
||||
*
|
||||
* @return Index of the current task list. Returns -1 if all tasks have been traversed.
|
||||
*
|
||||
* @note The task iterator keeps track of the current state during task traversal,
|
||||
* including the index of the current task list and the pointer of the next task list item.
|
||||
* When all tasks have been traversed, this function returns -1.
|
||||
* If a broken or corrupted task is encountered, the task handle is set to NULL.
|
||||
*
|
||||
*/
|
||||
int xTaskGetNext( TaskIterator_t * xIterator );
|
||||
|
||||
/**
|
||||
* @brief Fill a TaskSnapshot_t structure for specified task.
|
||||
|
||||
Reference in New Issue
Block a user