From 815951a708f8a3664ea122cbf3e2a3c9faffdb04 Mon Sep 17 00:00:00 2001 From: Dave Nadler Date: Sun, 28 Jun 2026 17:59:28 -0600 Subject: [PATCH 01/16] Add uxTaskCallForEachTask, and refactor uxTaskGetSystemState to use it (take 2). --- include/task.h | 35 ++++++++++ tasks.c | 176 ++++++++++++++++++++++++++++--------------------- 2 files changed, 136 insertions(+), 75 deletions(-) diff --git a/include/task.h b/include/task.h index 2add58b94e..c1a42e436d 100644 --- a/include/task.h +++ b/include/task.h @@ -184,6 +184,15 @@ typedef struct xTASK_STATUS #endif } TaskStatus_t; +#if ( configUSE_TRACE_FACILITY == 1 ) + /* 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 ); +#endif + /* Possible return values for eTaskConfirmSleepModeStatus(). */ typedef enum { @@ -2186,6 +2195,32 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION; UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) PRIVILEGED_FUNCTION; + /** + * 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. + * + * @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 of TaskStatus_t snapshots provided to the callback. + */ + UBaseType_t uxTaskCallForEachTask( TaskStatusCallbackFunction_t pxCallbackFunction, + void * pvCallbackContext, + configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) PRIVILEGED_FUNCTION; + #endif /** diff --git a/tasks.c b/tasks.c index 461271fcff..f3e6f2d43d 100644 --- a/tasks.c +++ b/tasks.c @@ -643,22 +643,6 @@ STATIC void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION; STATIC void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, 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 * the task if it is found, or NULL if the task is not found. @@ -3694,9 +3678,9 @@ STATIC BaseType_t prvCreateIdleTasks( void ) #if ( ( configIDLE_AFFINITY == 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) { xIdleTaskHandles[ xCoreID ]->uxCoreAffinityMask = ( ( UBaseType_t ) 1U << ( UBaseType_t ) xCoreID ); - } - #endif } + #endif + } #endif /* if ( configNUMBER_OF_CORES == 1 ) */ } } @@ -4457,11 +4441,100 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) #if ( configUSE_TRACE_FACILITY == 1 ) + STATIC UBaseType_t prvForEachTaskInList( List_t * pxList, + eTaskState eState, + TaskStatusCallbackFunction_t pxCallbackFunction, + void * pvCallbackContext ); + + /* for uxTaskGetSystemState callback: write position into TaskStatusArray */ + typedef struct xTASK_STATUS_ARRAY_WRITER_CONTEXT + { + TaskStatus_t * pxTaskStatusArray; + UBaseType_t uxIndex; + } TaskStatusArrayWriterContext_t; + + /* callback for uxTaskGetSystemState: write the task status for one task 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). */ + 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 ); + + vTaskSuspendAll(); + { + uxTask = prvCallForEachTask( pxCallbackFunction, pvCallbackContext ); + prvGetTotalRunTime( pulTotalRunTime ); + } + ( void ) xTaskResumeAll(); + + return uxTask; + } + UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) { - UBaseType_t uxTask = 0, uxQueue = configMAX_PRIORITIES; + UBaseType_t uxTask = 0; traceENTER_uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, pulTotalRunTime ); @@ -4470,54 +4543,9 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) /* Is there a space in the array for each task in the system? */ if( uxArraySize >= uxCurrentNumberOfTasks ) { - /* Fill in an TaskStatus_t structure with information on each - * task in the Ready state. */ - do - { - uxQueue--; - 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 ) */ + TaskStatusArrayWriterContext_t xContext = { pxTaskStatusArray, 0 }; + uxTask = prvCallForEachTask( prvTaskStatusArrayWriter, &xContext ); + prvGetTotalRunTime( pulTotalRunTime ); } else { @@ -6344,9 +6372,10 @@ STATIC void prvCheckTasksWaitingTermination( void ) #if ( configUSE_TRACE_FACILITY == 1 ) - STATIC UBaseType_t prvListTasksWithinSingleList( TaskStatus_t * pxTaskStatusArray, - List_t * pxList, - eTaskState eState ) + STATIC UBaseType_t prvForEachTaskInList( List_t * pxList, + eTaskState eState, + TaskStatusCallbackFunction_t pxCallbackFunction, + void * pvCallbackContext ) { UBaseType_t uxTask = 0; const ListItem_t * pxEndMarker = listGET_END_MARKER( pxList ); @@ -6355,10 +6384,7 @@ STATIC void prvCheckTasksWaitingTermination( void ) if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 ) { - /* Populate an TaskStatus_t structure within the - * 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. */ + /* Hand the callback each task handle referenced from pxList. */ for( pxIterator = listGET_HEAD_ENTRY( pxList ); pxIterator != pxEndMarker; pxIterator = listGET_NEXT( pxIterator ) ) { /* MISRA Ref 11.5.3 [Void pointer assignment] */ @@ -6366,7 +6392,7 @@ STATIC void prvCheckTasksWaitingTermination( void ) /* coverity[misra_c_2012_rule_11_5_violation] */ pxTCB = listGET_LIST_ITEM_OWNER( pxIterator ); - vTaskGetInfo( ( TaskHandle_t ) pxTCB, &( pxTaskStatusArray[ uxTask ] ), pdTRUE, eState ); + pxCallbackFunction( ( TaskHandle_t ) pxTCB, eState, pvCallbackContext ); uxTask++; } } From 4df509969a37769da7ba17256ccf1c1e40f79d10 Mon Sep 17 00:00:00 2001 From: Dave Nadler Date: Sun, 28 Jun 2026 21:22:39 -0600 Subject: [PATCH 02/16] Indentation and comment correction only. --- tasks.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasks.c b/tasks.c index f3e6f2d43d..d02e1df17b 100644 --- a/tasks.c +++ b/tasks.c @@ -3678,9 +3678,9 @@ STATIC BaseType_t prvCreateIdleTasks( void ) #if ( ( configIDLE_AFFINITY == 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) { xIdleTaskHandles[ xCoreID ]->uxCoreAffinityMask = ( ( UBaseType_t ) 1U << ( UBaseType_t ) xCoreID ); + } + #endif /* #if ( ( configIDLE_AFFINITY == 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */ } - #endif - } #endif /* if ( configNUMBER_OF_CORES == 1 ) */ } } From f2fa50f7f893ebbac2ca67786f905722e3b68608 Mon Sep 17 00:00:00 2001 From: Dave Nadler Date: Sat, 11 Jul 2026 18:04:27 -0400 Subject: [PATCH 03/16] Apply idiotic crustify formatting patch to satisfy FreeRTOS CI formatting. --- include/task.h | 52 ++++++++++++++++++++++++++------------------------ tasks.c | 9 +++++---- 2 files changed, 32 insertions(+), 29 deletions(-) diff --git a/include/task.h b/include/task.h index c1a42e436d..870d132d72 100644 --- a/include/task.h +++ b/include/task.h @@ -185,9 +185,10 @@ typedef struct xTASK_STATUS } TaskStatus_t; #if ( configUSE_TRACE_FACILITY == 1 ) - /* 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. */ + +/* 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 ); @@ -2195,28 +2196,29 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION; UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) PRIVILEGED_FUNCTION; - /** - * 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. - * - * @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 of TaskStatus_t snapshots provided to the callback. - */ + +/** + * 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. + * + * @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 of TaskStatus_t snapshots provided to the callback. + */ UBaseType_t uxTaskCallForEachTask( TaskStatusCallbackFunction_t pxCallbackFunction, void * pvCallbackContext, configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) PRIVILEGED_FUNCTION; diff --git a/tasks.c b/tasks.c index d02e1df17b..52c4cb495a 100644 --- a/tasks.c +++ b/tasks.c @@ -3679,7 +3679,7 @@ STATIC BaseType_t prvCreateIdleTasks( void ) { xIdleTaskHandles[ xCoreID ]->uxCoreAffinityMask = ( ( UBaseType_t ) 1U << ( UBaseType_t ) xCoreID ); } - #endif /* #if ( ( configIDLE_AFFINITY == 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */ + #endif /* #if ( ( configIDLE_AFFINITY == 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */ } #endif /* if ( configNUMBER_OF_CORES == 1 ) */ } @@ -4446,19 +4446,20 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) TaskStatusCallbackFunction_t pxCallbackFunction, void * pvCallbackContext ); - /* for uxTaskGetSystemState callback: write position into TaskStatusArray */ +/* for uxTaskGetSystemState callback: write position into TaskStatusArray */ typedef struct xTASK_STATUS_ARRAY_WRITER_CONTEXT { TaskStatus_t * pxTaskStatusArray; UBaseType_t uxIndex; } TaskStatusArrayWriterContext_t; - /* callback for uxTaskGetSystemState: write the task status for one task into TaskStatusArray */ +/* callback for uxTaskGetSystemState: write the task status for one task 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 ); } @@ -4478,7 +4479,7 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) } } - /* For each task, call the provided callback function (passing the provided context). */ +/* For each task, call the provided callback function (passing the provided context). */ STATIC UBaseType_t prvCallForEachTask( TaskStatusCallbackFunction_t pxCallbackFunction, void * pvCallbackContext ) { From 74e4c4759d2d03102b7c7873efd28a565588c754 Mon Sep 17 00:00:00 2001 From: Dave Nadler Date: Sat, 11 Jul 2026 18:34:05 -0400 Subject: [PATCH 04/16] move typedef to avoid error introduced by idiotic mock generator in FreeRTOS CI (it lost the typedef) --- include/task.h | 14 +++----------- tasks.c | 11 +++++++++-- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/include/task.h b/include/task.h index 870d132d72..6395a6ef30 100644 --- a/include/task.h +++ b/include/task.h @@ -184,16 +184,6 @@ typedef struct xTASK_STATUS #endif } TaskStatus_t; -#if ( configUSE_TRACE_FACILITY == 1 ) - -/* 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 ); -#endif - /* Possible return values for eTaskConfirmSleepModeStatus(). */ typedef enum { @@ -2219,7 +2209,9 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION; * * @return The number of TaskStatus_t snapshots provided to the callback. */ - UBaseType_t uxTaskCallForEachTask( TaskStatusCallbackFunction_t pxCallbackFunction, + UBaseType_t uxTaskCallForEachTask( void (* pxCallbackFunction)( TaskHandle_t xTask, + eTaskState eState, + * pvCallbackContext ), void * pvCallbackContext, configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) PRIVILEGED_FUNCTION; diff --git a/tasks.c b/tasks.c index 52c4cb495a..f3bacf0a32 100644 --- a/tasks.c +++ b/tasks.c @@ -4441,19 +4441,26 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) #if ( configUSE_TRACE_FACILITY == 1 ) +/* 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 ); + STATIC UBaseType_t prvForEachTaskInList( List_t * pxList, eTaskState eState, TaskStatusCallbackFunction_t pxCallbackFunction, void * pvCallbackContext ); -/* for uxTaskGetSystemState callback: write position into TaskStatusArray */ +/* 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 the task status for one task into TaskStatusArray */ +/* callback for uxTaskGetSystemState: write one task's status into TaskStatusArray */ STATIC void prvTaskStatusArrayWriter( TaskHandle_t xTask, eTaskState eState, void * pvCallbackContext ) From 4d346cbd4edcaf3f179300bc6c91003789d8eaf3 Mon Sep 17 00:00:00 2001 From: Dave Nadler Date: Thu, 16 Jul 2026 11:57:40 -0400 Subject: [PATCH 05/16] Correct missing 'void' introduced in formatting 'correction' --- include/task.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/task.h b/include/task.h index 6395a6ef30..d2b1c6ffb8 100644 --- a/include/task.h +++ b/include/task.h @@ -2211,7 +2211,7 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION; */ UBaseType_t uxTaskCallForEachTask( void (* pxCallbackFunction)( TaskHandle_t xTask, eTaskState eState, - * pvCallbackContext ), + void * pvCallbackContext ), void * pvCallbackContext, configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) PRIVILEGED_FUNCTION; From 0cc9a68bd29fea87b264803020092563c258d58a Mon Sep 17 00:00:00 2001 From: Dave Nadler Date: Thu, 16 Jul 2026 15:25:14 -0400 Subject: [PATCH 06/16] Replace readable initializer with ancient C89-compatible equivalent --- tasks.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tasks.c b/tasks.c index f3bacf0a32..d7d09dcc3d 100644 --- a/tasks.c +++ b/tasks.c @@ -4551,7 +4551,9 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) /* Is there a space in the array for each task in the system? */ if( uxArraySize >= uxCurrentNumberOfTasks ) { - TaskStatusArrayWriterContext_t xContext = { pxTaskStatusArray, 0 }; + TaskStatusArrayWriterContext_t xContext; /* Nope, not in ancient C89: = { pxTaskStatusArray, 0 }; */ + xContext.pxTaskStatusArray = pxTaskStatusArray; + xContext.uxIndex = 0; uxTask = prvCallForEachTask( prvTaskStatusArrayWriter, &xContext ); prvGetTotalRunTime( pulTotalRunTime ); } From d9ddf6602d231d9f7c56ab151d82a435f3060220 Mon Sep 17 00:00:00 2001 From: Dave Nadler Date: Sun, 28 Jun 2026 17:59:28 -0600 Subject: [PATCH 07/16] Add uxTaskCallForEachTask, and refactor uxTaskGetSystemState to use it (take 2). --- include/task.h | 35 ++++++++++ tasks.c | 176 ++++++++++++++++++++++++++++--------------------- 2 files changed, 136 insertions(+), 75 deletions(-) diff --git a/include/task.h b/include/task.h index 5353dc6945..cd09134cef 100644 --- a/include/task.h +++ b/include/task.h @@ -184,6 +184,15 @@ typedef struct xTASK_STATUS #endif } TaskStatus_t; +#if ( configUSE_TRACE_FACILITY == 1 ) + /* 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 ); +#endif + /* Possible return values for eTaskConfirmSleepModeStatus(). */ typedef enum { @@ -2210,6 +2219,32 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION; UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) PRIVILEGED_FUNCTION; + /** + * 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. + * + * @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 of TaskStatus_t snapshots provided to the callback. + */ + UBaseType_t uxTaskCallForEachTask( TaskStatusCallbackFunction_t pxCallbackFunction, + void * pvCallbackContext, + configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) PRIVILEGED_FUNCTION; + #endif /** diff --git a/tasks.c b/tasks.c index 3c97d3c2f2..9f43ce287a 100644 --- a/tasks.c +++ b/tasks.c @@ -643,22 +643,6 @@ STATIC void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION; STATIC void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, 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 * the task if it is found, or NULL if the task is not found. @@ -3694,9 +3678,9 @@ STATIC BaseType_t prvCreateIdleTasks( void ) #if ( ( configIDLE_AFFINITY == 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) { xIdleTaskHandles[ xCoreID ]->uxCoreAffinityMask = ( ( UBaseType_t ) 1U << ( UBaseType_t ) xCoreID ); - } - #endif } + #endif + } #endif /* if ( configNUMBER_OF_CORES == 1 ) */ } } @@ -4457,11 +4441,100 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) #if ( configUSE_TRACE_FACILITY == 1 ) + STATIC UBaseType_t prvForEachTaskInList( List_t * pxList, + eTaskState eState, + TaskStatusCallbackFunction_t pxCallbackFunction, + void * pvCallbackContext ); + + /* for uxTaskGetSystemState callback: write position into TaskStatusArray */ + typedef struct xTASK_STATUS_ARRAY_WRITER_CONTEXT + { + TaskStatus_t * pxTaskStatusArray; + UBaseType_t uxIndex; + } TaskStatusArrayWriterContext_t; + + /* callback for uxTaskGetSystemState: write the task status for one task 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). */ + 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 ); + + vTaskSuspendAll(); + { + uxTask = prvCallForEachTask( pxCallbackFunction, pvCallbackContext ); + prvGetTotalRunTime( pulTotalRunTime ); + } + ( void ) xTaskResumeAll(); + + return uxTask; + } + UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) { - UBaseType_t uxTask = 0, uxQueue = configMAX_PRIORITIES; + UBaseType_t uxTask = 0; traceENTER_uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, pulTotalRunTime ); @@ -4470,54 +4543,9 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) /* Is there a space in the array for each task in the system? */ if( uxArraySize >= uxCurrentNumberOfTasks ) { - /* Fill in an TaskStatus_t structure with information on each - * task in the Ready state. */ - do - { - uxQueue--; - 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 ) */ + TaskStatusArrayWriterContext_t xContext = { pxTaskStatusArray, 0 }; + uxTask = prvCallForEachTask( prvTaskStatusArrayWriter, &xContext ); + prvGetTotalRunTime( pulTotalRunTime ); } else { @@ -6344,9 +6372,10 @@ STATIC void prvCheckTasksWaitingTermination( void ) #if ( configUSE_TRACE_FACILITY == 1 ) - STATIC UBaseType_t prvListTasksWithinSingleList( TaskStatus_t * pxTaskStatusArray, - List_t * pxList, - eTaskState eState ) + STATIC UBaseType_t prvForEachTaskInList( List_t * pxList, + eTaskState eState, + TaskStatusCallbackFunction_t pxCallbackFunction, + void * pvCallbackContext ) { UBaseType_t uxTask = 0; const ListItem_t * pxEndMarker = listGET_END_MARKER( pxList ); @@ -6355,10 +6384,7 @@ STATIC void prvCheckTasksWaitingTermination( void ) if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 ) { - /* Populate an TaskStatus_t structure within the - * 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. */ + /* Hand the callback each task handle referenced from pxList. */ for( pxIterator = listGET_HEAD_ENTRY( pxList ); pxIterator != pxEndMarker; pxIterator = listGET_NEXT( pxIterator ) ) { /* MISRA Ref 11.5.3 [Void pointer assignment] */ @@ -6366,7 +6392,7 @@ STATIC void prvCheckTasksWaitingTermination( void ) /* coverity[misra_c_2012_rule_11_5_violation] */ pxTCB = listGET_LIST_ITEM_OWNER( pxIterator ); - vTaskGetInfo( ( TaskHandle_t ) pxTCB, &( pxTaskStatusArray[ uxTask ] ), pdTRUE, eState ); + pxCallbackFunction( ( TaskHandle_t ) pxTCB, eState, pvCallbackContext ); uxTask++; } } From 6dacdfb163014939a8b668316bb79dabd946ff31 Mon Sep 17 00:00:00 2001 From: Dave Nadler Date: Sun, 28 Jun 2026 21:22:39 -0600 Subject: [PATCH 08/16] Indentation and comment correction only. --- tasks.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasks.c b/tasks.c index 9f43ce287a..5e2739cf40 100644 --- a/tasks.c +++ b/tasks.c @@ -3678,9 +3678,9 @@ STATIC BaseType_t prvCreateIdleTasks( void ) #if ( ( configIDLE_AFFINITY == 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) { xIdleTaskHandles[ xCoreID ]->uxCoreAffinityMask = ( ( UBaseType_t ) 1U << ( UBaseType_t ) xCoreID ); + } + #endif /* #if ( ( configIDLE_AFFINITY == 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */ } - #endif - } #endif /* if ( configNUMBER_OF_CORES == 1 ) */ } } From 7472f1dfba983e6cd7163c60c6d3d5fee027d892 Mon Sep 17 00:00:00 2001 From: Dave Nadler Date: Sat, 11 Jul 2026 18:04:27 -0400 Subject: [PATCH 09/16] Apply idiotic crustify formatting patch to satisfy FreeRTOS CI formatting. --- include/task.h | 52 ++++++++++++++++++++++++++------------------------ tasks.c | 9 +++++---- 2 files changed, 32 insertions(+), 29 deletions(-) diff --git a/include/task.h b/include/task.h index cd09134cef..5ffbf6f895 100644 --- a/include/task.h +++ b/include/task.h @@ -185,9 +185,10 @@ typedef struct xTASK_STATUS } TaskStatus_t; #if ( configUSE_TRACE_FACILITY == 1 ) - /* 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. */ + +/* 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 ); @@ -2219,28 +2220,29 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION; UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) PRIVILEGED_FUNCTION; - /** - * 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. - * - * @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 of TaskStatus_t snapshots provided to the callback. - */ + +/** + * 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. + * + * @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 of TaskStatus_t snapshots provided to the callback. + */ UBaseType_t uxTaskCallForEachTask( TaskStatusCallbackFunction_t pxCallbackFunction, void * pvCallbackContext, configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) PRIVILEGED_FUNCTION; diff --git a/tasks.c b/tasks.c index 5e2739cf40..c8892f578d 100644 --- a/tasks.c +++ b/tasks.c @@ -3679,7 +3679,7 @@ STATIC BaseType_t prvCreateIdleTasks( void ) { xIdleTaskHandles[ xCoreID ]->uxCoreAffinityMask = ( ( UBaseType_t ) 1U << ( UBaseType_t ) xCoreID ); } - #endif /* #if ( ( configIDLE_AFFINITY == 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */ + #endif /* #if ( ( configIDLE_AFFINITY == 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */ } #endif /* if ( configNUMBER_OF_CORES == 1 ) */ } @@ -4446,19 +4446,20 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) TaskStatusCallbackFunction_t pxCallbackFunction, void * pvCallbackContext ); - /* for uxTaskGetSystemState callback: write position into TaskStatusArray */ +/* for uxTaskGetSystemState callback: write position into TaskStatusArray */ typedef struct xTASK_STATUS_ARRAY_WRITER_CONTEXT { TaskStatus_t * pxTaskStatusArray; UBaseType_t uxIndex; } TaskStatusArrayWriterContext_t; - /* callback for uxTaskGetSystemState: write the task status for one task into TaskStatusArray */ +/* callback for uxTaskGetSystemState: write the task status for one task 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 ); } @@ -4478,7 +4479,7 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) } } - /* For each task, call the provided callback function (passing the provided context). */ +/* For each task, call the provided callback function (passing the provided context). */ STATIC UBaseType_t prvCallForEachTask( TaskStatusCallbackFunction_t pxCallbackFunction, void * pvCallbackContext ) { From 3ac9afbff5990c60f5fe10cffe15fe600d7e6658 Mon Sep 17 00:00:00 2001 From: Dave Nadler Date: Sat, 11 Jul 2026 18:34:05 -0400 Subject: [PATCH 10/16] move typedef to avoid error introduced by idiotic mock generator in FreeRTOS CI (it lost the typedef) --- include/task.h | 14 +++----------- tasks.c | 11 +++++++++-- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/include/task.h b/include/task.h index 5ffbf6f895..3b9a141a07 100644 --- a/include/task.h +++ b/include/task.h @@ -184,16 +184,6 @@ typedef struct xTASK_STATUS #endif } TaskStatus_t; -#if ( configUSE_TRACE_FACILITY == 1 ) - -/* 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 ); -#endif - /* Possible return values for eTaskConfirmSleepModeStatus(). */ typedef enum { @@ -2243,7 +2233,9 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION; * * @return The number of TaskStatus_t snapshots provided to the callback. */ - UBaseType_t uxTaskCallForEachTask( TaskStatusCallbackFunction_t pxCallbackFunction, + UBaseType_t uxTaskCallForEachTask( void (* pxCallbackFunction)( TaskHandle_t xTask, + eTaskState eState, + * pvCallbackContext ), void * pvCallbackContext, configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) PRIVILEGED_FUNCTION; diff --git a/tasks.c b/tasks.c index c8892f578d..27e101efb5 100644 --- a/tasks.c +++ b/tasks.c @@ -4441,19 +4441,26 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) #if ( configUSE_TRACE_FACILITY == 1 ) +/* 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 ); + STATIC UBaseType_t prvForEachTaskInList( List_t * pxList, eTaskState eState, TaskStatusCallbackFunction_t pxCallbackFunction, void * pvCallbackContext ); -/* for uxTaskGetSystemState callback: write position into TaskStatusArray */ +/* 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 the task status for one task into TaskStatusArray */ +/* callback for uxTaskGetSystemState: write one task's status into TaskStatusArray */ STATIC void prvTaskStatusArrayWriter( TaskHandle_t xTask, eTaskState eState, void * pvCallbackContext ) From a729cd9434de9a1ca66dc020bbd57e6b8e10bcad Mon Sep 17 00:00:00 2001 From: Dave Nadler Date: Thu, 16 Jul 2026 15:25:14 -0400 Subject: [PATCH 11/16] Replace readable initializer with ancient C89-compatible equivalent --- tasks.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tasks.c b/tasks.c index 27e101efb5..ba041b2def 100644 --- a/tasks.c +++ b/tasks.c @@ -4551,7 +4551,9 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) /* Is there a space in the array for each task in the system? */ if( uxArraySize >= uxCurrentNumberOfTasks ) { - TaskStatusArrayWriterContext_t xContext = { pxTaskStatusArray, 0 }; + TaskStatusArrayWriterContext_t xContext; /* Nope, not in ancient C89: = { pxTaskStatusArray, 0 }; */ + xContext.pxTaskStatusArray = pxTaskStatusArray; + xContext.uxIndex = 0; uxTask = prvCallForEachTask( prvTaskStatusArrayWriter, &xContext ); prvGetTotalRunTime( pulTotalRunTime ); } From f942603dce451d41971093e1b1b7859d8e918d24 Mon Sep 17 00:00:00 2001 From: Dave Nadler Date: Thu, 16 Jul 2026 11:57:40 -0400 Subject: [PATCH 12/16] Correct missing 'void' introduced in formatting 'correction' --- include/task.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/task.h b/include/task.h index 3b9a141a07..8320133350 100644 --- a/include/task.h +++ b/include/task.h @@ -2235,7 +2235,7 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION; */ UBaseType_t uxTaskCallForEachTask( void (* pxCallbackFunction)( TaskHandle_t xTask, eTaskState eState, - * pvCallbackContext ), + void * pvCallbackContext ), void * pvCallbackContext, configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) PRIVILEGED_FUNCTION; From 40a8545f20feaaeae7f18bd4a08c06d6f3282b14 Mon Sep 17 00:00:00 2001 From: Dave Nadler Date: Thu, 16 Jul 2026 15:25:14 -0400 Subject: [PATCH 13/16] Replace readable initializer with ancient C89-compatible equivalent --- tasks.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tasks.c b/tasks.c index 27e101efb5..62d4cc40a6 100644 --- a/tasks.c +++ b/tasks.c @@ -4551,7 +4551,9 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) /* Is there a space in the array for each task in the system? */ if( uxArraySize >= uxCurrentNumberOfTasks ) { - TaskStatusArrayWriterContext_t xContext = { pxTaskStatusArray, 0 }; + TaskStatusArrayWriterContext_t xContext; + xContext.pxTaskStatusArray = pxTaskStatusArray; + xContext.uxIndex = 0; uxTask = prvCallForEachTask( prvTaskStatusArrayWriter, &xContext ); prvGetTotalRunTime( pulTotalRunTime ); } From afcd5625cc90145dc4ad9facb1bcca923ec0dd6a Mon Sep 17 00:00:00 2001 From: Anubhav Rawal Date: Fri, 17 Jul 2026 13:06:13 -0700 Subject: [PATCH 14/16] Fix uncrustify formatting for uxTaskCallForEachTask declaration --- include/task.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/task.h b/include/task.h index 8320133350..3f46a85ae9 100644 --- a/include/task.h +++ b/include/task.h @@ -2233,13 +2233,13 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION; * * @return The number of TaskStatus_t snapshots provided to the callback. */ - UBaseType_t uxTaskCallForEachTask( void (* pxCallbackFunction)( TaskHandle_t xTask, - eTaskState eState, - void * pvCallbackContext ), + UBaseType_t uxTaskCallForEachTask( void ( * pxCallbackFunction )( TaskHandle_t xTask, + eTaskState eState, + void * pvCallbackContext ), void * pvCallbackContext, configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) PRIVILEGED_FUNCTION; -#endif +#endif /* if ( configUSE_TRACE_FACILITY == 1 ) */ /** * task. h From 87f887a6d01ad917ecf156e38f672f3bd9511943 Mon Sep 17 00:00:00 2001 From: Dave Nadler Date: Fri, 17 Jul 2026 16:57:32 -0400 Subject: [PATCH 15/16] Update erroneous comment in task.h (uxTaskCallForEachTask documentation). --- include/task.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/task.h b/include/task.h index 8320133350..2bcc82af72 100644 --- a/include/task.h +++ b/include/task.h @@ -2231,7 +2231,7 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION; * boot. pulTotalRunTime can be set to NULL to omit the total run time * information. * - * @return The number of TaskStatus_t snapshots provided to the callback. + * @return The number tasks provided to the callback. */ UBaseType_t uxTaskCallForEachTask( void (* pxCallbackFunction)( TaskHandle_t xTask, eTaskState eState, From 397367ae77e377e3732cb1ed6fd01ec381ea1ad1 Mon Sep 17 00:00:00 2001 From: Dave Nadler Date: Fri, 17 Jul 2026 17:44:00 -0400 Subject: [PATCH 16/16] task.h/tasks.c updates per Anubhav Rawal (AWS) suggestions. --- include/task.h | 14 +++++++++++--- tasks.c | 9 ++------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/include/task.h b/include/task.h index 5ba8e980a9..1da4081fed 100644 --- a/include/task.h +++ b/include/task.h @@ -2211,6 +2211,13 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION; const UBaseType_t uxArraySize, configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) PRIVILEGED_FUNCTION; +/* 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 ); + /** * For each task, call pxCallbackFunction with the task's handle and state, * and the provided context. @@ -2219,6 +2226,9 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION; * 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). @@ -2233,9 +2243,7 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION; * * @return The number tasks provided to the callback. */ - UBaseType_t uxTaskCallForEachTask( void ( * pxCallbackFunction )( TaskHandle_t xTask, - eTaskState eState, - void * pvCallbackContext ), + UBaseType_t uxTaskCallForEachTask( TaskStatusCallbackFunction_t pxCallbackFunction, void * pvCallbackContext, configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) PRIVILEGED_FUNCTION; diff --git a/tasks.c b/tasks.c index 62d4cc40a6..e5fe8083fe 100644 --- a/tasks.c +++ b/tasks.c @@ -4441,13 +4441,6 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) #if ( configUSE_TRACE_FACILITY == 1 ) -/* 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 ); - STATIC UBaseType_t prvForEachTaskInList( List_t * pxList, eTaskState eState, TaskStatusCallbackFunction_t pxCallbackFunction, @@ -4487,6 +4480,7 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) } /* 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 ) { @@ -4527,6 +4521,7 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) UBaseType_t uxTask; configASSERT( pxCallbackFunction != NULL ); + if( pxCallbackFunction == NULL ) return 0; vTaskSuspendAll(); {