Skip to content

Commit d9ddf66

Browse files
DRNadlerrawalexe
authored andcommitted
Add uxTaskCallForEachTask, and refactor uxTaskGetSystemState to use it (take 2).
1 parent 78069a7 commit d9ddf66

2 files changed

Lines changed: 136 additions & 75 deletions

File tree

include/task.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,15 @@ typedef struct xTASK_STATUS
184184
#endif
185185
} TaskStatus_t;
186186

187+
#if ( configUSE_TRACE_FACILITY == 1 )
188+
/* Callback type used by uxTaskCallForEachTask(). The callback receives one
189+
* task handle and state at a time, plus an opaque caller-supplied context
190+
* pointer. The callback may call vTaskGetInfo() if it needs a TaskStatus_t. */
191+
typedef void (* TaskStatusCallbackFunction_t)( TaskHandle_t xTask,
192+
eTaskState eState,
193+
void * pvCallbackContext );
194+
#endif
195+
187196
/* Possible return values for eTaskConfirmSleepModeStatus(). */
188197
typedef enum
189198
{
@@ -2210,6 +2219,32 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION;
22102219
UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray,
22112220
const UBaseType_t uxArraySize,
22122221
configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) PRIVILEGED_FUNCTION;
2222+
/**
2223+
* For each task, call pxCallbackFunction with the task's handle and state,
2224+
* and the provided context.
2225+
*
2226+
* NOTE: This function is intended for debugging use only as it suspends
2227+
* the scheduler for an extended period. The callback runs while the
2228+
* scheduler is suspended, so it must return quickly and must not perform
2229+
* blocking operations.
2230+
*
2231+
* @param pxCallbackFunction Callback to invoke once for each task (passing
2232+
* the task's handle, state, and the pvCallbackContext).
2233+
*
2234+
* @param pvCallbackContext Opaque caller-provided context passed through to
2235+
* each callback invocation.
2236+
*
2237+
* @param pulTotalRunTime If configGENERATE_RUN_TIME_STATS is set to 1 in
2238+
* FreeRTOSConfig.h then *pulTotalRunTime is set to the total run time since
2239+
* boot. pulTotalRunTime can be set to NULL to omit the total run time
2240+
* information.
2241+
*
2242+
* @return The number of TaskStatus_t snapshots provided to the callback.
2243+
*/
2244+
UBaseType_t uxTaskCallForEachTask( TaskStatusCallbackFunction_t pxCallbackFunction,
2245+
void * pvCallbackContext,
2246+
configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) PRIVILEGED_FUNCTION;
2247+
22132248
#endif
22142249

22152250
/**

tasks.c

Lines changed: 101 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -643,22 +643,6 @@ STATIC void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION;
643643
STATIC void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait,
644644
const BaseType_t xCanBlockIndefinitely ) PRIVILEGED_FUNCTION;
645645

646-
/*
647-
* Fills an TaskStatus_t structure with information on each task that is
648-
* referenced from the pxList list (which may be a ready list, a delayed list,
649-
* a suspended list, etc.).
650-
*
651-
* THIS FUNCTION IS INTENDED FOR DEBUGGING ONLY, AND SHOULD NOT BE CALLED FROM
652-
* NORMAL APPLICATION CODE.
653-
*/
654-
#if ( configUSE_TRACE_FACILITY == 1 )
655-
656-
STATIC UBaseType_t prvListTasksWithinSingleList( TaskStatus_t * pxTaskStatusArray,
657-
List_t * pxList,
658-
eTaskState eState ) PRIVILEGED_FUNCTION;
659-
660-
#endif
661-
662646
/*
663647
* Searches pxList for a task with name pcNameToQuery - returning a handle to
664648
* the task if it is found, or NULL if the task is not found.
@@ -3694,9 +3678,9 @@ STATIC BaseType_t prvCreateIdleTasks( void )
36943678
#if ( ( configIDLE_AFFINITY == 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
36953679
{
36963680
xIdleTaskHandles[ xCoreID ]->uxCoreAffinityMask = ( ( UBaseType_t ) 1U << ( UBaseType_t ) xCoreID );
3697-
}
3698-
#endif
36993681
}
3682+
#endif
3683+
}
37003684
#endif /* if ( configNUMBER_OF_CORES == 1 ) */
37013685
}
37023686
}
@@ -4457,11 +4441,100 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery )
44574441

44584442
#if ( configUSE_TRACE_FACILITY == 1 )
44594443

4444+
STATIC UBaseType_t prvForEachTaskInList( List_t * pxList,
4445+
eTaskState eState,
4446+
TaskStatusCallbackFunction_t pxCallbackFunction,
4447+
void * pvCallbackContext );
4448+
4449+
/* for uxTaskGetSystemState callback: write position into TaskStatusArray */
4450+
typedef struct xTASK_STATUS_ARRAY_WRITER_CONTEXT
4451+
{
4452+
TaskStatus_t * pxTaskStatusArray;
4453+
UBaseType_t uxIndex;
4454+
} TaskStatusArrayWriterContext_t;
4455+
4456+
/* callback for uxTaskGetSystemState: write the task status for one task into TaskStatusArray */
4457+
STATIC void prvTaskStatusArrayWriter( TaskHandle_t xTask,
4458+
eTaskState eState,
4459+
void * pvCallbackContext )
4460+
{
4461+
TaskStatusArrayWriterContext_t * pxContext = ( TaskStatusArrayWriterContext_t * ) pvCallbackContext;
4462+
vTaskGetInfo( xTask, &( pxContext->pxTaskStatusArray[ pxContext->uxIndex++ ] ), pdTRUE, eState );
4463+
}
4464+
4465+
STATIC void prvGetTotalRunTime( configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime )
4466+
{
4467+
if( pulTotalRunTime != NULL )
4468+
{
4469+
#if ( configGENERATE_RUN_TIME_STATS == 1 )
4470+
#ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
4471+
portALT_GET_RUN_TIME_COUNTER_VALUE( ( *pulTotalRunTime ) );
4472+
#else
4473+
*pulTotalRunTime = ( configRUN_TIME_COUNTER_TYPE ) portGET_RUN_TIME_COUNTER_VALUE();
4474+
#endif
4475+
#else
4476+
*pulTotalRunTime = 0;
4477+
#endif /* if ( configGENERATE_RUN_TIME_STATS == 1 ) */
4478+
}
4479+
}
4480+
4481+
/* For each task, call the provided callback function (passing the provided context). */
4482+
STATIC UBaseType_t prvCallForEachTask( TaskStatusCallbackFunction_t pxCallbackFunction,
4483+
void * pvCallbackContext )
4484+
{
4485+
UBaseType_t uxTask = 0, uxQueue = configMAX_PRIORITIES;
4486+
4487+
/* Visit each task in the Ready state. */
4488+
do
4489+
{
4490+
uxQueue--;
4491+
uxTask = ( UBaseType_t ) ( uxTask + prvForEachTaskInList( &( pxReadyTasksLists[ uxQueue ] ), eReady, pxCallbackFunction, pvCallbackContext ) );
4492+
} while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY );
4493+
4494+
/* Visit each task in the Blocked state. */
4495+
uxTask = ( UBaseType_t ) ( uxTask + prvForEachTaskInList( ( List_t * ) pxDelayedTaskList, eBlocked, pxCallbackFunction, pvCallbackContext ) );
4496+
uxTask = ( UBaseType_t ) ( uxTask + prvForEachTaskInList( ( List_t * ) pxOverflowDelayedTaskList, eBlocked, pxCallbackFunction, pvCallbackContext ) );
4497+
4498+
#if ( INCLUDE_vTaskDelete == 1 )
4499+
{
4500+
/* Visit each task that has been deleted but not yet cleaned up. */
4501+
uxTask = ( UBaseType_t ) ( uxTask + prvForEachTaskInList( &xTasksWaitingTermination, eDeleted, pxCallbackFunction, pvCallbackContext ) );
4502+
}
4503+
#endif
4504+
4505+
#if ( INCLUDE_vTaskSuspend == 1 )
4506+
{
4507+
/* Visit each task in the Suspended state. */
4508+
uxTask = ( UBaseType_t ) ( uxTask + prvForEachTaskInList( &xSuspendedTaskList, eSuspended, pxCallbackFunction, pvCallbackContext ) );
4509+
}
4510+
#endif
4511+
4512+
return uxTask;
4513+
}
4514+
4515+
UBaseType_t uxTaskCallForEachTask( TaskStatusCallbackFunction_t pxCallbackFunction,
4516+
void * pvCallbackContext,
4517+
configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime )
4518+
{
4519+
UBaseType_t uxTask;
4520+
4521+
configASSERT( pxCallbackFunction != NULL );
4522+
4523+
vTaskSuspendAll();
4524+
{
4525+
uxTask = prvCallForEachTask( pxCallbackFunction, pvCallbackContext );
4526+
prvGetTotalRunTime( pulTotalRunTime );
4527+
}
4528+
( void ) xTaskResumeAll();
4529+
4530+
return uxTask;
4531+
}
4532+
44604533
UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray,
44614534
const UBaseType_t uxArraySize,
44624535
configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime )
44634536
{
4464-
UBaseType_t uxTask = 0, uxQueue = configMAX_PRIORITIES;
4537+
UBaseType_t uxTask = 0;
44654538

44664539
traceENTER_uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, pulTotalRunTime );
44674540

@@ -4470,54 +4543,9 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery )
44704543
/* Is there a space in the array for each task in the system? */
44714544
if( uxArraySize >= uxCurrentNumberOfTasks )
44724545
{
4473-
/* Fill in an TaskStatus_t structure with information on each
4474-
* task in the Ready state. */
4475-
do
4476-
{
4477-
uxQueue--;
4478-
uxTask = ( UBaseType_t ) ( uxTask + prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[ uxQueue ] ), eReady ) );
4479-
} while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY );
4480-
4481-
/* Fill in an TaskStatus_t structure with information on each
4482-
* task in the Blocked state. */
4483-
uxTask = ( UBaseType_t ) ( uxTask + prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxDelayedTaskList, eBlocked ) );
4484-
uxTask = ( UBaseType_t ) ( uxTask + prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxOverflowDelayedTaskList, eBlocked ) );
4485-
4486-
#if ( INCLUDE_vTaskDelete == 1 )
4487-
{
4488-
/* Fill in an TaskStatus_t structure with information on
4489-
* each task that has been deleted but not yet cleaned up. */
4490-
uxTask = ( UBaseType_t ) ( uxTask + prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xTasksWaitingTermination, eDeleted ) );
4491-
}
4492-
#endif
4493-
4494-
#if ( INCLUDE_vTaskSuspend == 1 )
4495-
{
4496-
/* Fill in an TaskStatus_t structure with information on
4497-
* each task in the Suspended state. */
4498-
uxTask = ( UBaseType_t ) ( uxTask + prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xSuspendedTaskList, eSuspended ) );
4499-
}
4500-
#endif
4501-
4502-
#if ( configGENERATE_RUN_TIME_STATS == 1 )
4503-
{
4504-
if( pulTotalRunTime != NULL )
4505-
{
4506-
#ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
4507-
portALT_GET_RUN_TIME_COUNTER_VALUE( ( *pulTotalRunTime ) );
4508-
#else
4509-
*pulTotalRunTime = ( configRUN_TIME_COUNTER_TYPE ) portGET_RUN_TIME_COUNTER_VALUE();
4510-
#endif
4511-
}
4512-
}
4513-
#else /* if ( configGENERATE_RUN_TIME_STATS == 1 ) */
4514-
{
4515-
if( pulTotalRunTime != NULL )
4516-
{
4517-
*pulTotalRunTime = 0;
4518-
}
4519-
}
4520-
#endif /* if ( configGENERATE_RUN_TIME_STATS == 1 ) */
4546+
TaskStatusArrayWriterContext_t xContext = { pxTaskStatusArray, 0 };
4547+
uxTask = prvCallForEachTask( prvTaskStatusArrayWriter, &xContext );
4548+
prvGetTotalRunTime( pulTotalRunTime );
45214549
}
45224550
else
45234551
{
@@ -6344,9 +6372,10 @@ STATIC void prvCheckTasksWaitingTermination( void )
63446372

63456373
#if ( configUSE_TRACE_FACILITY == 1 )
63466374

6347-
STATIC UBaseType_t prvListTasksWithinSingleList( TaskStatus_t * pxTaskStatusArray,
6348-
List_t * pxList,
6349-
eTaskState eState )
6375+
STATIC UBaseType_t prvForEachTaskInList( List_t * pxList,
6376+
eTaskState eState,
6377+
TaskStatusCallbackFunction_t pxCallbackFunction,
6378+
void * pvCallbackContext )
63506379
{
63516380
UBaseType_t uxTask = 0;
63526381
const ListItem_t * pxEndMarker = listGET_END_MARKER( pxList );
@@ -6355,18 +6384,15 @@ STATIC void prvCheckTasksWaitingTermination( void )
63556384

63566385
if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )
63576386
{
6358-
/* Populate an TaskStatus_t structure within the
6359-
* pxTaskStatusArray array for each task that is referenced from
6360-
* pxList. See the definition of TaskStatus_t in task.h for the
6361-
* meaning of each TaskStatus_t structure member. */
6387+
/* Hand the callback each task handle referenced from pxList. */
63626388
for( pxIterator = listGET_HEAD_ENTRY( pxList ); pxIterator != pxEndMarker; pxIterator = listGET_NEXT( pxIterator ) )
63636389
{
63646390
/* MISRA Ref 11.5.3 [Void pointer assignment] */
63656391
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
63666392
/* coverity[misra_c_2012_rule_11_5_violation] */
63676393
pxTCB = listGET_LIST_ITEM_OWNER( pxIterator );
63686394

6369-
vTaskGetInfo( ( TaskHandle_t ) pxTCB, &( pxTaskStatusArray[ uxTask ] ), pdTRUE, eState );
6395+
pxCallbackFunction( ( TaskHandle_t ) pxTCB, eState, pvCallbackContext );
63706396
uxTask++;
63716397
}
63726398
}

0 commit comments

Comments
 (0)