From ae1cc5f49b6dc18d8a2ef02dfa631d9faa6aadf2 Mon Sep 17 00:00:00 2001 From: Alexey Gerenkov Date: Mon, 4 May 2020 22:34:39 +0300 Subject: [PATCH] freertos: Adds snapshot API to walk over tasks lists --- components/freertos/include/freertos/task.h | 22 +++- components/freertos/tasks.c | 112 ++++++++++++++++++++ 2 files changed, 133 insertions(+), 1 deletion(-) diff --git a/components/freertos/include/freertos/task.h b/components/freertos/include/freertos/task.h index 0012cc600b..469383707c 100644 --- a/components/freertos/include/freertos/task.h +++ b/components/freertos/include/freertos/task.h @@ -2529,7 +2529,7 @@ void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNC /* * This function fills array with TaskSnapshot_t structures for every task in the system. - * Used by core dump facility to get snapshots of all tasks in the system. + * Used by panic handling code to get snapshots of all tasks in the system. * Only available when configENABLE_TASK_SNAPSHOT is set to 1. * @param pxTaskSnapshotArray Pointer to array of TaskSnapshot_t structures to store tasks snapshot data. * @param uxArraySize Size of tasks snapshots array. @@ -2538,6 +2538,26 @@ void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNC */ UBaseType_t uxTaskGetSnapshotAll( TaskSnapshot_t * const pxTaskSnapshotArray, const UBaseType_t uxArraySize, UBaseType_t * const pxTcbSz ); +/* + * This function iterates over all tasks in the system. + * Used by panic handling code to iterate over tasks in the system. + * Only available when configENABLE_TASK_SNAPSHOT is set to 1. + * @note This function should not be used while FreeRTOS is running (as it doesn't acquire any locks). + * @param pxTask task handle. + * @return Handle for the next task. If pxTask is NULL, returns hadnle for the first task. + */ +TaskHandle_t pxTaskGetNext( TaskHandle_t pxTask ); + +/* + * This function fills TaskSnapshot_t structure for specified task. + * Used by panic handling code to get snapshot of a task. + * Only available when configENABLE_TASK_SNAPSHOT is set to 1. + * @note This function should not be used while FreeRTOS is running (as it doesn't acquire any locks). + * @param pxTask task handle. + * @param pxTaskSnapshot address of TaskSnapshot_t structure to fill. + */ +void vTaskGetSnapshot( TaskHandle_t pxTask, TaskSnapshot_t *pxTaskSnapshot ); + /** @endcond */ #ifdef __cplusplus } diff --git a/components/freertos/tasks.c b/components/freertos/tasks.c index 4799e0e328..7476014f2a 100644 --- a/components/freertos/tasks.c +++ b/components/freertos/tasks.c @@ -5877,6 +5877,118 @@ const TickType_t xConstTickCount = xTickCount; return uxTask; } + static TCB_t *prvFirstTaskGet( List_t *pxList ) + { + ListItem_t *pxListItem = listGET_HEAD_ENTRY( pxList ); + if( pxListItem != listGET_END_MARKER( pxList ) ) { + return listGET_LIST_ITEM_OWNER( pxListItem ); + } + return NULL; + } + + static TCB_t *prvNextTaskGet( TCB_t *pxTCB ) + { + List_t *pxList = listLIST_ITEM_CONTAINER( &( pxTCB->xStateListItem ) ); + ListItem_t *pxListItem = listGET_NEXT( &( pxTCB->xStateListItem ) ); + if( pxListItem != listGET_END_MARKER( pxList ) ) { + return listGET_LIST_ITEM_OWNER( pxListItem ); + } + return NULL; + } + + inline void vTaskGetSnapshot( TaskHandle_t pxTask, TaskSnapshot_t *pxTaskSnapshot ) + { + configASSERT( portVALID_TCB_MEM(pxTask) ); + configASSERT( pxTaskSnapshot != NULL ); + pxTaskSnapshot->pxTCB = (TCB_t *)pxTask; + pxTaskSnapshot->pxTopOfStack = (StackType_t *)((TCB_t *)pxTask)->pxTopOfStack; + pxTaskSnapshot->pxEndOfStack = ((TCB_t *)pxTask)->pxEndOfStack; + } + + TaskHandle_t pxTaskGetNext( TaskHandle_t pxTask ) + { + TCB_t *pxTCB = pxTask; + List_t *pxTaskList = NULL; + UBaseType_t i = configMAX_PRIORITIES; + UBaseType_t bCurTaskListFound = pdFALSE; + List_t *task_lists[] = { + pxDelayedTaskList, + pxOverflowDelayedTaskList, + #if( INCLUDE_vTaskDelete == 1 ) + &xTasksWaitingTermination, + #endif + #if( INCLUDE_vTaskSuspend == 1 ) + &xSuspendedTaskList + #endif + }; + + if( pxTask != NULL && !portVALID_TCB_MEM(pxTask) ) { + return NULL; + } + + if( pxTCB != NULL ) { + pxTCB = prvNextTaskGet( pxTCB ); + if( pxTCB != NULL ) { + // take care not to return garbage + return portVALID_TCB_MEM(pxTCB) ? pxTCB : NULL; + } + pxTaskList = listLIST_ITEM_CONTAINER( &( ((TCB_t *)pxTask)->xStateListItem ) ); + } + /* ready tasks lists */ + do + { + i--; + List_t *pxList = &( pxReadyTasksLists[ i ] ); + if( bCurTaskListFound == pdFALSE && pxTaskList != NULL ) { + /* need to find list the current task item from */ + if( pxTaskList == pxList ) { + bCurTaskListFound = pdTRUE; + } + continue; /* go to the next 'ready list' */ + } + pxTCB = prvFirstTaskGet( pxList ); + if( pxTCB != NULL ) { + // take care not to return garbage + return portVALID_TCB_MEM(pxTCB) ? pxTCB : NULL; + } + } + while( i > tskIDLE_PRIORITY ); + /* pending ready tasks lists */ + for (i = 0; i < portNUM_PROCESSORS; i++) { + List_t *pxList = &( xPendingReadyList[ i ] ); + if( bCurTaskListFound == pdFALSE && pxTaskList != NULL ) { + /* need to find list the current task item from */ + if( pxTaskList == pxList ) { + bCurTaskListFound = pdTRUE; + } + continue; /* go to the next 'ready list' */ + } + pxTCB = prvFirstTaskGet( pxList ); + if( pxTCB != NULL ) { + // take care not to return garbage + return portVALID_TCB_MEM(pxTCB) ? pxTCB : NULL; + } + } + /* other tasks lists */ + for (i = 0; i < sizeof(task_lists)/sizeof(task_lists[0]); i++) { + List_t *pxList = task_lists[ i ]; + if( bCurTaskListFound == pdFALSE && pxTaskList != NULL ) { + /* need to find list the current task item from */ + if( pxTaskList == pxList ) { + bCurTaskListFound = pdTRUE; + } + continue; /* go to the next 'ready list' */ + } + pxTCB = prvFirstTaskGet( pxList ); + if( pxTCB != NULL ) { + // take care not to return garbage + return portVALID_TCB_MEM(pxTCB) ? pxTCB : NULL; + } + } + + return NULL; + } + #endif /* Code below here allows additional code to be inserted into this source file,