Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 34 additions & 2 deletions include/task.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@
* The tskKERNEL_VERSION_MAJOR, tskKERNEL_VERSION_MINOR, tskKERNEL_VERSION_BUILD
* values will reflect the last released version number.
*/
#define tskKERNEL_VERSION_NUMBER "V11.1.0+"
#define tskKERNEL_VERSION_NUMBER "V11.3.0+"
#define tskKERNEL_VERSION_MAJOR 11
#define tskKERNEL_VERSION_MINOR 1
#define tskKERNEL_VERSION_MINOR 3
#define tskKERNEL_VERSION_BUILD 0

/* MPU region parameters passed in ulParameters
Expand Down Expand Up @@ -184,6 +184,14 @@ typedef struct xTASK_STATUS
#endif
} TaskStatus_t;

#if ( configUSE_TRACE_FACILITY == 1 )
/* Callback type used by uxTaskCallForEachTask(). The callback receives one
* populated TaskStatus_t at a time, plus an opaque caller-supplied context
* pointer. */
typedef void (* TaskStatusCallbackFunction_t)( const TaskStatus_t * pxTaskStatus,
void * pvCallbackContext );
#endif

/* Possible return values for eTaskConfirmSleepModeStatus(). */
typedef enum
{
Expand Down Expand Up @@ -2186,6 +2194,30 @@ 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 a filled in TaskStatus_t.
*
* 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.
*
* @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

/**
Expand Down
180 changes: 105 additions & 75 deletions tasks.c
Original file line number Diff line number Diff line change
Expand Up @@ -639,22 +639,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.
Expand Down Expand Up @@ -3690,9 +3674,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 ) */
}
}
Expand Down Expand Up @@ -4453,11 +4437,103 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery )

#if ( configUSE_TRACE_FACILITY == 1 )

static UBaseType_t prvForEachTaskInList( List_t * pxList,
eTaskState eState,
TaskStatusCallbackFunction_t pxCallbackFunction,
void * pvCallbackContext );

typedef struct xTASK_STATUS_ARRAY_WRITER_CONTEXT
{
TaskStatus_t * pxTaskStatusArray;
UBaseType_t uxIndex;
} TaskStatusArrayWriterContext_t;

static void prvTaskStatusArrayWriter( const TaskStatus_t * pxTaskStatus,
void * pvCallbackContext )
{
TaskStatusArrayWriterContext_t * pxContext = ( TaskStatusArrayWriterContext_t * ) pvCallbackContext;

pxContext->pxTaskStatusArray[ pxContext->uxIndex ] = *pxTaskStatus;
pxContext->uxIndex++;
}

static UBaseType_t prvCallForEachTask( TaskStatusCallbackFunction_t pxCallbackFunction,
void * pvCallbackContext,
configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime )
{
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

#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 ) */

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, 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;
TaskStatusArrayWriterContext_t xContext = { pxTaskStatusArray, 0 };

traceENTER_uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, pulTotalRunTime );

Expand All @@ -4466,54 +4542,7 @@ 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 ) */
uxTask = prvCallForEachTask( prvTaskStatusArrayWriter, &xContext, pulTotalRunTime );
}
else
{
Expand Down Expand Up @@ -6338,29 +6367,30 @@ 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 );
ListItem_t * pxIterator;
TCB_t * pxTCB = NULL;
TaskStatus_t xTaskStatusBuffer;

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. */
/* Populate one TaskStatus_t structure for each task referenced
* from pxList, then hand it to the callback. */
for( pxIterator = listGET_HEAD_ENTRY( pxList ); pxIterator != pxEndMarker; pxIterator = listGET_NEXT( pxIterator ) )
{
/* MISRA Ref 11.5.3 [Void pointer assignment] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
pxTCB = listGET_LIST_ITEM_OWNER( pxIterator );

vTaskGetInfo( ( TaskHandle_t ) pxTCB, &( pxTaskStatusArray[ uxTask ] ), pdTRUE, eState );
vTaskGetInfo( ( TaskHandle_t ) pxTCB, &xTaskStatusBuffer, pdTRUE, eState );
pxCallbackFunction( &xTaskStatusBuffer, pvCallbackContext );
uxTask++;
}
}
Expand Down