mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2026-08-03 21:41:46 +02:00
Add uxTaskCallForEachTask, and refactor uxTaskGetSystemState to use it. (#1439)
--------- Co-authored-by: Anubhav Rawal <rawalexe@amazon.com> Co-authored-by: Kody Stribrny <kstribrn@amazon.com>
This commit is contained in:
parent
78069a79ea
commit
5706e10cb4
@ -184,6 +184,13 @@ typedef struct xTASK_STATUS
|
|||||||
#endif
|
#endif
|
||||||
} TaskStatus_t;
|
} TaskStatus_t;
|
||||||
|
|
||||||
|
/* Callback type used by uxTaskCallForEachTask(). The callback receives one
|
||||||
|
* task handle and state at a time, plus an opaque caller-supplied context
|
||||||
|
* pointer. The callback may call vTaskGetInfo() if it needs a TaskStatus_t. */
|
||||||
|
typedef void (* TaskStatusCallbackFunction_t)( TaskHandle_t xTask,
|
||||||
|
eTaskState eState,
|
||||||
|
void * pvCallbackContext );
|
||||||
|
|
||||||
/* Possible return values for eTaskConfirmSleepModeStatus(). */
|
/* Possible return values for eTaskConfirmSleepModeStatus(). */
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
@ -2210,7 +2217,38 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION;
|
|||||||
UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray,
|
UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray,
|
||||||
const UBaseType_t uxArraySize,
|
const UBaseType_t uxArraySize,
|
||||||
configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) PRIVILEGED_FUNCTION;
|
configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) PRIVILEGED_FUNCTION;
|
||||||
#endif
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For each task, call pxCallbackFunction with the task's handle and state,
|
||||||
|
* and the provided context.
|
||||||
|
*
|
||||||
|
* NOTE: This function is intended for debugging use only as it suspends
|
||||||
|
* the scheduler for an extended period. The callback runs while the
|
||||||
|
* scheduler is suspended, so it must return quickly and must not perform
|
||||||
|
* blocking operations.
|
||||||
|
*
|
||||||
|
* NOTE: This API is privileged-only (it invokes a user callback from
|
||||||
|
* privileged context).
|
||||||
|
*
|
||||||
|
* @param pxCallbackFunction Callback to invoke once for each task (passing
|
||||||
|
* the task's handle, state, and the pvCallbackContext).
|
||||||
|
*
|
||||||
|
* @param pvCallbackContext Opaque caller-provided context passed through to
|
||||||
|
* each callback invocation.
|
||||||
|
*
|
||||||
|
* @param pulTotalRunTime If configGENERATE_RUN_TIME_STATS is set to 1 in
|
||||||
|
* FreeRTOSConfig.h then *pulTotalRunTime is set to the total run time since
|
||||||
|
* boot. pulTotalRunTime can be set to NULL to omit the total run time
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* @return The number tasks provided to the callback.
|
||||||
|
*/
|
||||||
|
UBaseType_t uxTaskCallForEachTask( TaskStatusCallbackFunction_t pxCallbackFunction,
|
||||||
|
void * pvCallbackContext,
|
||||||
|
configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
#endif /* if ( configUSE_TRACE_FACILITY == 1 ) */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* task. h
|
* task. h
|
||||||
|
|||||||
183
tasks.c
183
tasks.c
@ -643,22 +643,6 @@ STATIC void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION;
|
|||||||
STATIC void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait,
|
STATIC void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait,
|
||||||
const BaseType_t xCanBlockIndefinitely ) PRIVILEGED_FUNCTION;
|
const BaseType_t xCanBlockIndefinitely ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
/*
|
|
||||||
* Fills an TaskStatus_t structure with information on each task that is
|
|
||||||
* referenced from the pxList list (which may be a ready list, a delayed list,
|
|
||||||
* a suspended list, etc.).
|
|
||||||
*
|
|
||||||
* THIS FUNCTION IS INTENDED FOR DEBUGGING ONLY, AND SHOULD NOT BE CALLED FROM
|
|
||||||
* NORMAL APPLICATION CODE.
|
|
||||||
*/
|
|
||||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
|
||||||
|
|
||||||
STATIC UBaseType_t prvListTasksWithinSingleList( TaskStatus_t * pxTaskStatusArray,
|
|
||||||
List_t * pxList,
|
|
||||||
eTaskState eState ) PRIVILEGED_FUNCTION;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Searches pxList for a task with name pcNameToQuery - returning a handle to
|
* Searches pxList for a task with name pcNameToQuery - returning a handle to
|
||||||
* the task if it is found, or NULL if the task is not found.
|
* the task if it is found, or NULL if the task is not found.
|
||||||
@ -3695,7 +3679,7 @@ STATIC BaseType_t prvCreateIdleTasks( void )
|
|||||||
{
|
{
|
||||||
xIdleTaskHandles[ xCoreID ]->uxCoreAffinityMask = ( ( UBaseType_t ) 1U << ( UBaseType_t ) xCoreID );
|
xIdleTaskHandles[ xCoreID ]->uxCoreAffinityMask = ( ( UBaseType_t ) 1U << ( UBaseType_t ) xCoreID );
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* #if ( ( configIDLE_AFFINITY == 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */
|
||||||
}
|
}
|
||||||
#endif /* if ( configNUMBER_OF_CORES == 1 ) */
|
#endif /* if ( configNUMBER_OF_CORES == 1 ) */
|
||||||
}
|
}
|
||||||
@ -4457,11 +4441,107 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery )
|
|||||||
|
|
||||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||||
|
|
||||||
|
STATIC UBaseType_t prvForEachTaskInList( List_t * pxList,
|
||||||
|
eTaskState eState,
|
||||||
|
TaskStatusCallbackFunction_t pxCallbackFunction,
|
||||||
|
void * pvCallbackContext );
|
||||||
|
|
||||||
|
/* for uxTaskGetSystemState callback context: current write position into TaskStatusArray */
|
||||||
|
typedef struct xTASK_STATUS_ARRAY_WRITER_CONTEXT
|
||||||
|
{
|
||||||
|
TaskStatus_t * pxTaskStatusArray;
|
||||||
|
UBaseType_t uxIndex;
|
||||||
|
} TaskStatusArrayWriterContext_t;
|
||||||
|
|
||||||
|
/* callback for uxTaskGetSystemState: write one task's status into TaskStatusArray */
|
||||||
|
STATIC void prvTaskStatusArrayWriter( TaskHandle_t xTask,
|
||||||
|
eTaskState eState,
|
||||||
|
void * pvCallbackContext )
|
||||||
|
{
|
||||||
|
TaskStatusArrayWriterContext_t * pxContext = ( TaskStatusArrayWriterContext_t * ) pvCallbackContext;
|
||||||
|
|
||||||
|
vTaskGetInfo( xTask, &( pxContext->pxTaskStatusArray[ pxContext->uxIndex++ ] ), pdTRUE, eState );
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC void prvGetTotalRunTime( configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime )
|
||||||
|
{
|
||||||
|
if( pulTotalRunTime != NULL )
|
||||||
|
{
|
||||||
|
#if ( configGENERATE_RUN_TIME_STATS == 1 )
|
||||||
|
#ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
|
||||||
|
portALT_GET_RUN_TIME_COUNTER_VALUE( ( *pulTotalRunTime ) );
|
||||||
|
#else
|
||||||
|
*pulTotalRunTime = ( configRUN_TIME_COUNTER_TYPE ) portGET_RUN_TIME_COUNTER_VALUE();
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
*pulTotalRunTime = 0;
|
||||||
|
#endif /* if ( configGENERATE_RUN_TIME_STATS == 1 ) */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For each task, call the provided callback function (passing the provided context). */
|
||||||
|
/* Caller must suspend the scheduler around use of this function. */
|
||||||
|
STATIC UBaseType_t prvCallForEachTask( TaskStatusCallbackFunction_t pxCallbackFunction,
|
||||||
|
void * pvCallbackContext )
|
||||||
|
{
|
||||||
|
UBaseType_t uxTask = 0, uxQueue = configMAX_PRIORITIES;
|
||||||
|
|
||||||
|
/* Visit each task in the Ready state. */
|
||||||
|
do
|
||||||
|
{
|
||||||
|
uxQueue--;
|
||||||
|
uxTask = ( UBaseType_t ) ( uxTask + prvForEachTaskInList( &( pxReadyTasksLists[ uxQueue ] ), eReady, pxCallbackFunction, pvCallbackContext ) );
|
||||||
|
} while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY );
|
||||||
|
|
||||||
|
/* Visit each task in the Blocked state. */
|
||||||
|
uxTask = ( UBaseType_t ) ( uxTask + prvForEachTaskInList( ( List_t * ) pxDelayedTaskList, eBlocked, pxCallbackFunction, pvCallbackContext ) );
|
||||||
|
uxTask = ( UBaseType_t ) ( uxTask + prvForEachTaskInList( ( List_t * ) pxOverflowDelayedTaskList, eBlocked, pxCallbackFunction, pvCallbackContext ) );
|
||||||
|
|
||||||
|
#if ( INCLUDE_vTaskDelete == 1 )
|
||||||
|
{
|
||||||
|
/* Visit each task that has been deleted but not yet cleaned up. */
|
||||||
|
uxTask = ( UBaseType_t ) ( uxTask + prvForEachTaskInList( &xTasksWaitingTermination, eDeleted, pxCallbackFunction, pvCallbackContext ) );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ( INCLUDE_vTaskSuspend == 1 )
|
||||||
|
{
|
||||||
|
/* Visit each task in the Suspended state. */
|
||||||
|
uxTask = ( UBaseType_t ) ( uxTask + prvForEachTaskInList( &xSuspendedTaskList, eSuspended, pxCallbackFunction, pvCallbackContext ) );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return uxTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
UBaseType_t uxTaskCallForEachTask( TaskStatusCallbackFunction_t pxCallbackFunction,
|
||||||
|
void * pvCallbackContext,
|
||||||
|
configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime )
|
||||||
|
{
|
||||||
|
UBaseType_t uxTask;
|
||||||
|
|
||||||
|
configASSERT( pxCallbackFunction != NULL );
|
||||||
|
|
||||||
|
if( pxCallbackFunction == NULL )
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
vTaskSuspendAll();
|
||||||
|
{
|
||||||
|
uxTask = prvCallForEachTask( pxCallbackFunction, pvCallbackContext );
|
||||||
|
prvGetTotalRunTime( pulTotalRunTime );
|
||||||
|
}
|
||||||
|
( void ) xTaskResumeAll();
|
||||||
|
|
||||||
|
return uxTask;
|
||||||
|
}
|
||||||
|
|
||||||
UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray,
|
UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray,
|
||||||
const UBaseType_t uxArraySize,
|
const UBaseType_t uxArraySize,
|
||||||
configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime )
|
configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime )
|
||||||
{
|
{
|
||||||
UBaseType_t uxTask = 0, uxQueue = configMAX_PRIORITIES;
|
UBaseType_t uxTask = 0;
|
||||||
|
|
||||||
traceENTER_uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, pulTotalRunTime );
|
traceENTER_uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, pulTotalRunTime );
|
||||||
|
|
||||||
@ -4470,54 +4550,11 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery )
|
|||||||
/* Is there a space in the array for each task in the system? */
|
/* Is there a space in the array for each task in the system? */
|
||||||
if( uxArraySize >= uxCurrentNumberOfTasks )
|
if( uxArraySize >= uxCurrentNumberOfTasks )
|
||||||
{
|
{
|
||||||
/* Fill in an TaskStatus_t structure with information on each
|
TaskStatusArrayWriterContext_t xContext;
|
||||||
* task in the Ready state. */
|
xContext.pxTaskStatusArray = pxTaskStatusArray;
|
||||||
do
|
xContext.uxIndex = 0;
|
||||||
{
|
uxTask = prvCallForEachTask( prvTaskStatusArrayWriter, &xContext );
|
||||||
uxQueue--;
|
prvGetTotalRunTime( pulTotalRunTime );
|
||||||
uxTask = ( UBaseType_t ) ( uxTask + prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[ uxQueue ] ), eReady ) );
|
|
||||||
} while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY );
|
|
||||||
|
|
||||||
/* Fill in an TaskStatus_t structure with information on each
|
|
||||||
* task in the Blocked state. */
|
|
||||||
uxTask = ( UBaseType_t ) ( uxTask + prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxDelayedTaskList, eBlocked ) );
|
|
||||||
uxTask = ( UBaseType_t ) ( uxTask + prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxOverflowDelayedTaskList, eBlocked ) );
|
|
||||||
|
|
||||||
#if ( INCLUDE_vTaskDelete == 1 )
|
|
||||||
{
|
|
||||||
/* Fill in an TaskStatus_t structure with information on
|
|
||||||
* each task that has been deleted but not yet cleaned up. */
|
|
||||||
uxTask = ( UBaseType_t ) ( uxTask + prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xTasksWaitingTermination, eDeleted ) );
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if ( INCLUDE_vTaskSuspend == 1 )
|
|
||||||
{
|
|
||||||
/* Fill in an TaskStatus_t structure with information on
|
|
||||||
* each task in the Suspended state. */
|
|
||||||
uxTask = ( UBaseType_t ) ( uxTask + prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xSuspendedTaskList, eSuspended ) );
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if ( configGENERATE_RUN_TIME_STATS == 1 )
|
|
||||||
{
|
|
||||||
if( pulTotalRunTime != NULL )
|
|
||||||
{
|
|
||||||
#ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
|
|
||||||
portALT_GET_RUN_TIME_COUNTER_VALUE( ( *pulTotalRunTime ) );
|
|
||||||
#else
|
|
||||||
*pulTotalRunTime = ( configRUN_TIME_COUNTER_TYPE ) portGET_RUN_TIME_COUNTER_VALUE();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else /* if ( configGENERATE_RUN_TIME_STATS == 1 ) */
|
|
||||||
{
|
|
||||||
if( pulTotalRunTime != NULL )
|
|
||||||
{
|
|
||||||
*pulTotalRunTime = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* if ( configGENERATE_RUN_TIME_STATS == 1 ) */
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -6344,9 +6381,10 @@ STATIC void prvCheckTasksWaitingTermination( void )
|
|||||||
|
|
||||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||||
|
|
||||||
STATIC UBaseType_t prvListTasksWithinSingleList( TaskStatus_t * pxTaskStatusArray,
|
STATIC UBaseType_t prvForEachTaskInList( List_t * pxList,
|
||||||
List_t * pxList,
|
eTaskState eState,
|
||||||
eTaskState eState )
|
TaskStatusCallbackFunction_t pxCallbackFunction,
|
||||||
|
void * pvCallbackContext )
|
||||||
{
|
{
|
||||||
UBaseType_t uxTask = 0;
|
UBaseType_t uxTask = 0;
|
||||||
const ListItem_t * pxEndMarker = listGET_END_MARKER( pxList );
|
const ListItem_t * pxEndMarker = listGET_END_MARKER( pxList );
|
||||||
@ -6355,10 +6393,7 @@ STATIC void prvCheckTasksWaitingTermination( void )
|
|||||||
|
|
||||||
if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )
|
if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )
|
||||||
{
|
{
|
||||||
/* Populate an TaskStatus_t structure within the
|
/* Hand the callback each task handle referenced from pxList. */
|
||||||
* pxTaskStatusArray array for each task that is referenced from
|
|
||||||
* pxList. See the definition of TaskStatus_t in task.h for the
|
|
||||||
* meaning of each TaskStatus_t structure member. */
|
|
||||||
for( pxIterator = listGET_HEAD_ENTRY( pxList ); pxIterator != pxEndMarker; pxIterator = listGET_NEXT( pxIterator ) )
|
for( pxIterator = listGET_HEAD_ENTRY( pxList ); pxIterator != pxEndMarker; pxIterator = listGET_NEXT( pxIterator ) )
|
||||||
{
|
{
|
||||||
/* MISRA Ref 11.5.3 [Void pointer assignment] */
|
/* MISRA Ref 11.5.3 [Void pointer assignment] */
|
||||||
@ -6366,7 +6401,7 @@ STATIC void prvCheckTasksWaitingTermination( void )
|
|||||||
/* coverity[misra_c_2012_rule_11_5_violation] */
|
/* coverity[misra_c_2012_rule_11_5_violation] */
|
||||||
pxTCB = listGET_LIST_ITEM_OWNER( pxIterator );
|
pxTCB = listGET_LIST_ITEM_OWNER( pxIterator );
|
||||||
|
|
||||||
vTaskGetInfo( ( TaskHandle_t ) pxTCB, &( pxTaskStatusArray[ uxTask ] ), pdTRUE, eState );
|
pxCallbackFunction( ( TaskHandle_t ) pxTCB, eState, pvCallbackContext );
|
||||||
uxTask++;
|
uxTask++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user