From 83c9e1b22389a24c7e3ddeda4acaec57e832596a Mon Sep 17 00:00:00 2001 From: Omar Chebib Date: Wed, 4 Aug 2021 10:56:37 +0800 Subject: [PATCH] freertos: take tasks snapshot out of tasks.c source code --- .../private_include/esp_gdbstub_common.h | 1 + components/espcoredump/src/core_dump_common.c | 2 +- .../src/port/riscv/core_dump_port.c | 6 +- components/freertos/CMakeLists.txt | 9 +- components/freertos/component.mk | 4 +- .../freertos/esp_additions/task_snapshot.c | 220 ++++++++++++++++++ .../esp_additions/freertos/task_snapshot.h | 90 +++++++ .../freertos_tasks_c_additions.h | 80 +++++++ .../include/freertos/FreeRTOSConfig.h | 7 +- components/freertos/include/freertos/task.h | 44 +--- components/freertos/linker.lf | 6 +- components/freertos/tasks.c | 195 ---------------- components/freertos/test/CMakeLists.txt | 2 + .../freertos/test/test_tasks_snapshot.c | 2 +- mocks/freertos/CMakeLists.txt | 1 + 15 files changed, 417 insertions(+), 252 deletions(-) create mode 100644 components/freertos/esp_additions/task_snapshot.c create mode 100644 components/freertos/include/esp_additions/freertos/task_snapshot.h create mode 100644 components/freertos/include/esp_additions/freertos_tasks_c_additions.h diff --git a/components/esp_gdbstub/private_include/esp_gdbstub_common.h b/components/esp_gdbstub/private_include/esp_gdbstub_common.h index d9f261c9d2..b74f1e6c09 100644 --- a/components/esp_gdbstub/private_include/esp_gdbstub_common.h +++ b/components/esp_gdbstub/private_include/esp_gdbstub_common.h @@ -25,6 +25,7 @@ #ifdef CONFIG_ESP_GDBSTUB_SUPPORT_TASKS #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#include "freertos/task_snapshot.h" #endif // CONFIG_ESP_GDBSTUB_SUPPORT_TASKS /* Internal error codes used by the routines that parse the incoming gdb packet */ diff --git a/components/espcoredump/src/core_dump_common.c b/components/espcoredump/src/core_dump_common.c index b5cf5bdd34..ca995a6260 100644 --- a/components/espcoredump/src/core_dump_common.c +++ b/components/espcoredump/src/core_dump_common.c @@ -16,7 +16,7 @@ #include "sdkconfig.h" #include "soc/soc_memory_layout.h" #include "freertos/FreeRTOS.h" -#include "freertos/task.h" +#include "freertos/task_snapshot.h" #include "esp_rom_sys.h" #include "esp_core_dump_port.h" #include "esp_core_dump_common.h" diff --git a/components/espcoredump/src/port/riscv/core_dump_port.c b/components/espcoredump/src/port/riscv/core_dump_port.c index 3336cbbc37..3b2a4f63ea 100644 --- a/components/espcoredump/src/port/riscv/core_dump_port.c +++ b/components/espcoredump/src/port/riscv/core_dump_port.c @@ -34,8 +34,8 @@ const static DRAM_ATTR char TAG[] __attribute__((unused)) = "esp_core_dump_port" #define COREDUMP_EM_RISCV 0xF3 #define COREDUMP_INVALID_CAUSE_VALUE 0xFFFF -#define COREDUMP_FAKE_STACK_START 0x20000000 -#define COREDUMP_FAKE_STACK_LIMIT 0x30000000 +#define COREDUMP_FAKE_STACK_START 0x20000000U +#define COREDUMP_FAKE_STACK_LIMIT 0x30000000U #if CONFIG_ESP_COREDUMP_ENABLE @@ -424,7 +424,7 @@ void esp_core_dump_summary_parse_backtrace_info(esp_core_dump_bt_info_t *bt_info /* Check whether the stack is a fake stack created during coredump generation * If its a fake stack, we don't have any actual stack dump */ - if (vaddr >= COREDUMP_FAKE_STACK_START && vaddr < COREDUMP_FAKE_STACK_LIMIT) { + if (vaddr >= (void*) COREDUMP_FAKE_STACK_START && vaddr < (void*) COREDUMP_FAKE_STACK_LIMIT) { bt_info->dump_size = 0; return; } diff --git a/components/freertos/CMakeLists.txt b/components/freertos/CMakeLists.txt index 0c64d68070..95613dafda 100644 --- a/components/freertos/CMakeLists.txt +++ b/components/freertos/CMakeLists.txt @@ -21,7 +21,6 @@ if(CONFIG_IDF_TARGET_ARCH_XTENSA) port/xtensa/include) set(private_include_dirs - include/freertos port/xtensa/include/freertos port/xtensa port/priv_include @@ -37,7 +36,6 @@ elseif(CONFIG_IDF_TARGET_ARCH_RISCV) port/riscv/include) set(private_include_dirs - include/freertos port/riscv/include/freertos port/riscv port/priv_include @@ -46,6 +44,7 @@ elseif(CONFIG_IDF_TARGET_ARCH_RISCV) endif() list(APPEND srcs + "esp_additions/task_snapshot.c" "port/port_common.c" "port/port_systick.c" "croutine.c" @@ -58,6 +57,12 @@ list(APPEND srcs "FreeRTOS-openocd.c" "freertos_v8_compat.c") +list(APPEND include_dirs + "include/esp_additions") + +list(APPEND private_include_dirs + "include/freertos") + if(CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY) list(APPEND srcs "port/xtensa/xtensa_loadstore_handler.S") endif() diff --git a/components/freertos/component.mk b/components/freertos/component.mk index 4225da69a9..e6b3a28dcf 100644 --- a/components/freertos/component.mk +++ b/components/freertos/component.mk @@ -6,9 +6,9 @@ ifdef CONFIG_FREERTOS_DEBUG_OCDAWARE COMPONENT_ADD_LDFLAGS += -Wl,--undefined=uxTopUsedPriority endif -COMPONENT_ADD_INCLUDEDIRS := include port/xtensa/include +COMPONENT_ADD_INCLUDEDIRS := include port/xtensa/include include/esp_additions COMPONENT_PRIV_INCLUDEDIRS := include/freertos port/xtensa/include/freertos port/xtensa port/priv_include . -COMPONENT_SRCDIRS += port port/xtensa +COMPONENT_SRCDIRS += port port/xtensa esp_additions/ ifndef CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY COMPONENT_OBJEXCLUDE := xtensa/xtensa_loadstore_handler.o diff --git a/components/freertos/esp_additions/task_snapshot.c b/components/freertos/esp_additions/task_snapshot.c new file mode 100644 index 0000000000..5fb599bbac --- /dev/null +++ b/components/freertos/esp_additions/task_snapshot.c @@ -0,0 +1,220 @@ +// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "freertos/FreeRTOS.h" +#include "freertos/task_snapshot.h" + +#ifndef DIM +#define DIM(t) (sizeof(t)/ sizeof(*(t))) +#endif + +#if ( configENABLE_TASK_SNAPSHOT == 1 ) + + static void prvTaskGetSnapshot( TaskSnapshot_t *pxTaskSnapshotArray, UBaseType_t *uxTask, void *pxTCB ) + { + if (pxTCB == NULL) { + return; + } + pxTaskSnapshotArray[ *uxTask ].pxTCB = pxTCB; + pxTaskSnapshotArray[ *uxTask ].pxTopOfStack = (StackType_t *) pxTCBGetTopOfStack(pxTCB); + #if( portSTACK_GROWTH < 0 ) + { + pxTaskSnapshotArray[ *uxTask ].pxEndOfStack = pxTCBGetEndOfStack(pxTCB); + } + #else + { + pxTaskSnapshotArray[ *uxTask ].pxEndOfStack = pxTCBGetStartOfStack(pxTCB); + } + #endif + (*uxTask)++; + } + + static void prvTaskGetSnapshotsFromList( TaskSnapshot_t *pxTaskSnapshotArray, UBaseType_t *uxTask, const UBaseType_t uxArraySize, List_t *pxList ) + { + void *pxNextTCB = NULL; + void *pxFirstTCB = NULL; + + if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 ) + { + listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); + do + { + if( *uxTask >= uxArraySize ) { + break; + } + + listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); + prvTaskGetSnapshot( pxTaskSnapshotArray, uxTask, pxNextTCB ); + } while( pxNextTCB != pxFirstTCB ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + UBaseType_t uxTaskGetSnapshotAll( TaskSnapshot_t * const pxTaskSnapshotArray, const UBaseType_t uxArraySize, UBaseType_t * const pxTcbSz ) + { + UBaseType_t uxTask = 0; + UBaseType_t i = 0; + + + *pxTcbSz = pxTCBGetSize(); + /* Fill in an TaskStatus_t structure with information on each + task in the Ready state. */ + i = configMAX_PRIORITIES; + do + { + i--; + prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, pxListGetReadyTask(i) ); + } while( i > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + + /* Fill in an TaskStatus_t structure with information on each + task in the Blocked state. */ + prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, pxGetDelayedTaskList() ); + prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, pxGetOverflowDelayedTaskList() ); + for (i = 0; i < portNUM_PROCESSORS; i++) { + if( uxTask >= uxArraySize ) { + break; + } + prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, pxListGetReadyPendingTask(i) ); + } + + #if( INCLUDE_vTaskDelete == 1 ) + { + prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, pxGetTasksWaitingTermination() ); + } + #endif + + #if ( INCLUDE_vTaskSuspend == 1 ) + { + prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, pxGetSuspendedTaskList() ); + } + #endif + return uxTask; + } + + static void *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 void *prvNextTaskGet( void *pxTCB ) + { + List_t *pxList = listLIST_ITEM_CONTAINER( pxTCBGetStateListItem(pxTCB) ); + ListItem_t *pxListItem = listGET_NEXT( pxTCBGetStateListItem(pxTCB) ); + if( pxListItem != listGET_END_MARKER( pxList ) ) { + return listGET_LIST_ITEM_OWNER( pxListItem ); + } + return NULL; + } + + void vTaskGetSnapshot( TaskHandle_t pxTask, TaskSnapshot_t *pxTaskSnapshot ) + { + configASSERT( portVALID_TCB_MEM(pxTask) ); + configASSERT( pxTaskSnapshot != NULL ); + pxTaskSnapshot->pxTCB = (void*) pxTask; + pxTaskSnapshot->pxTopOfStack = pxTCBGetTopOfStack((void*) pxTask); + pxTaskSnapshot->pxEndOfStack = pxTCBGetEndOfStack((void*) pxTask); + } + + TaskHandle_t pxTaskGetNext( TaskHandle_t pxTask ) + { + void *pxTCB = pxTask; + List_t *pxTaskList = NULL; + UBaseType_t i = configMAX_PRIORITIES; + UBaseType_t bCurTaskListFound = pdFALSE; + List_t *task_lists[] = { + pxGetDelayedTaskList(), + pxGetOverflowDelayedTaskList(), + #if( INCLUDE_vTaskDelete == 1 ) + pxGetTasksWaitingTermination(), + #endif + #if( INCLUDE_vTaskSuspend == 1 ) + pxGetSuspendedTaskList() + #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( pxTCBGetStateListItem(pxTask) ); + } + /* ready tasks lists */ + do + { + i--; + List_t *pxList = pxListGetReadyTask(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 = pxListGetReadyPendingTask(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 < DIM(task_lists); 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 diff --git a/components/freertos/include/esp_additions/freertos/task_snapshot.h b/components/freertos/include/esp_additions/freertos/task_snapshot.h new file mode 100644 index 0000000000..1ad04cce69 --- /dev/null +++ b/components/freertos/include/esp_additions/freertos/task_snapshot.h @@ -0,0 +1,90 @@ +// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#if ( configENABLE_TASK_SNAPSHOT == 1 ) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Check `freertos_tasks_c_additions.h` file for more info + * about these functions declaration. + */ +UBaseType_t pxTCBGetSize ( void ); +ListItem_t* pxTCBGetStateListItem ( void *pxTCB ); +StackType_t* pxTCBGetStartOfStack ( void *pxTCB ); +StackType_t* pxTCBGetTopOfStack ( void *pxTCB ); +StackType_t* pxTCBGetEndOfStack ( void *pxTCB ); +List_t* pxListGetReadyTask ( UBaseType_t idx ); +List_t* pxListGetReadyPendingTask ( UBaseType_t idx ); +List_t* pxGetDelayedTaskList ( void ); +List_t* pxGetOverflowDelayedTaskList ( void ); +List_t* pxGetTasksWaitingTermination ( void ); +List_t* pxGetSuspendedTaskList ( void ); + +/** + * Used with the uxTaskGetSnapshotAll() function to save memory snapshot of each task in the system. + * We need this struct because TCB_t is defined (hidden) in tasks.c. + */ +typedef struct xTASK_SNAPSHOT +{ + void *pxTCB; /*!< Address of task control block. */ + StackType_t *pxTopOfStack; /*!< Points to the location of the last item placed on the tasks stack. */ + StackType_t *pxEndOfStack; /*!< Points to the end of the stack. pxTopOfStack < pxEndOfStack, stack grows hi2lo + pxTopOfStack > pxEndOfStack, stack grows lo2hi*/ +} TaskSnapshot_t; + + +/* + * This function fills array with TaskSnapshot_t structures for every task 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. + * @param pxTcbSz Pointer to store size of TCB. + * @return Number of elements stored in array. + */ +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 ); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/freertos/include/esp_additions/freertos_tasks_c_additions.h b/components/freertos/include/esp_additions/freertos_tasks_c_additions.h new file mode 100644 index 0000000000..464c0b3ffb --- /dev/null +++ b/components/freertos/include/esp_additions/freertos_tasks_c_additions.h @@ -0,0 +1,80 @@ +// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +/** + * This file will be included in `tasks.c` file, thus, it must NOT be included + * by any (other) file. + * The functions below only consist in getters for the static variables in + * `tasks.c` file. + * The only source files that should call these functions are the ones in + * `/additions` directory. + */ + +#if ( configENABLE_TASK_SNAPSHOT == 1 ) + + UBaseType_t pxTCBGetSize ( void ) + { + return sizeof(TCB_t); + } + + ListItem_t* pxTCBGetStateListItem ( void *pxTCB ) + { + return &(((TCB_t*)pxTCB)->xStateListItem); + } + + StackType_t* pxTCBGetStartOfStack ( void *pxTCB ) + { + return (StackType_t*) ((TCB_t*)pxTCB)->pxStack; + } + + StackType_t* pxTCBGetTopOfStack ( void *pxTCB ) + { + return (StackType_t*) ((TCB_t*)pxTCB)->pxTopOfStack; + } + + StackType_t* pxTCBGetEndOfStack ( void *pxTCB ) + { + return (StackType_t*) ((TCB_t*)pxTCB)->pxEndOfStack; + } + + + List_t* pxListGetReadyTask ( UBaseType_t idx ) + { + return &( pxReadyTasksLists[idx] ); + } + + List_t* pxListGetReadyPendingTask ( UBaseType_t idx ) + { + return &( xPendingReadyList[idx] ); + } + + List_t* pxGetDelayedTaskList ( void ) { + return pxDelayedTaskList; + } + + List_t* pxGetOverflowDelayedTaskList ( void ) { + return pxOverflowDelayedTaskList; + } + + List_t* pxGetTasksWaitingTermination ( void ) { + return &xTasksWaitingTermination; + } + + List_t* pxGetSuspendedTaskList ( void ) { + return &xSuspendedTaskList; + } + +#endif diff --git a/components/freertos/include/freertos/FreeRTOSConfig.h b/components/freertos/include/freertos/FreeRTOSConfig.h index 15f97a9676..51a030d523 100644 --- a/components/freertos/include/freertos/FreeRTOSConfig.h +++ b/components/freertos/include/freertos/FreeRTOSConfig.h @@ -277,11 +277,11 @@ extern void vPortCleanUpTCB ( void *pxTCB ); #endif //configUSE_TICKLESS_IDLE -#if CONFIG_ESP_COREDUMP_ENABLE +#if CONFIG_ESP_COREDUMP_ENABLE || CONFIG_ESP_GDBSTUB_SUPPORT_TASKS #define configENABLE_TASK_SNAPSHOT 1 #endif #ifndef configENABLE_TASK_SNAPSHOT -#define configENABLE_TASK_SNAPSHOT 1 +#define configENABLE_TASK_SNAPSHOT 0 #endif #if CONFIG_SYSVIEW_ENABLE @@ -297,4 +297,7 @@ extern void vPortCleanUpTCB ( void *pxTCB ); #define configCHECK_MUTEX_GIVEN_BY_OWNER 0 #endif + +#define configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H 1 + #endif /* FREERTOS_CONFIG_H */ diff --git a/components/freertos/include/freertos/task.h b/components/freertos/include/freertos/task.h index 559945805e..26e71c1f2d 100644 --- a/components/freertos/include/freertos/task.h +++ b/components/freertos/include/freertos/task.h @@ -152,18 +152,6 @@ typedef struct xTASK_STATUS #endif } TaskStatus_t; -/** - * Used with the uxTaskGetSnapshotAll() function to save memory snapshot of each task in the system. - * We need this struct because TCB_t is defined (hidden) in tasks.c. - */ -typedef struct xTASK_SNAPSHOT -{ - void *pxTCB; /*!< Address of task control block. */ - StackType_t *pxTopOfStack; /*!< Points to the location of the last item placed on the tasks stack. */ - StackType_t *pxEndOfStack; /*!< Points to the end of the stack. pxTopOfStack < pxEndOfStack, stack grows hi2lo - pxTopOfStack > pxEndOfStack, stack grows lo2hi*/ -} TaskSnapshot_t; - /** @endcond */ /** @@ -2529,36 +2517,8 @@ TaskHandle_t pvTaskIncrementMutexHeldCount( void ) PRIVILEGED_FUNCTION; */ void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNCTION; -/* - * This function fills array with TaskSnapshot_t structures for every task 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. - * @param pxTcbSz Pointer to store size of TCB. - * @return Number of elements stored in array. - */ -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 ); +/* TODO: IDF-3683 */ +#include "freertos/task_snapshot.h" /** @endcond */ #ifdef __cplusplus diff --git a/components/freertos/linker.lf b/components/freertos/linker.lf index 155436e8f6..23de74c1e7 100644 --- a/components/freertos/linker.lf +++ b/components/freertos/linker.lf @@ -2,13 +2,11 @@ archive: libfreertos.a entries: * (noflash_text) + if ESP_PANIC_HANDLER_IRAM != y: + task_snapshot (default) if FREERTOS_PLACE_FUNCTIONS_INTO_FLASH = y: port: pxPortInitialiseStack (default) port: xPortStartScheduler (default) - if ESP_PANIC_HANDLER_IRAM != y: - tasks: uxTaskGetSnapshotAll (default) - tasks: prvTaskGetSnapshot (default) - tasks: prvTaskGetSnapshotsFromList (default) if IDF_TARGET_ESP32S2 = n && IDF_TARGET_ESP32C3 = n && IDF_TARGET_ESP32H2 = n : port: vPortReleaseTaskMPUSettings (default) tasks: xTaskCreateRestricted (default) diff --git a/components/freertos/tasks.c b/components/freertos/tasks.c index a278734fb8..b6d99836e5 100644 --- a/components/freertos/tasks.c +++ b/components/freertos/tasks.c @@ -5811,201 +5811,6 @@ const TickType_t xConstTickCount = xTickCount; #endif /* INCLUDE_vTaskSuspend */ } -#if ( configENABLE_TASK_SNAPSHOT == 1 ) - static void prvTaskGetSnapshot( TaskSnapshot_t *pxTaskSnapshotArray, UBaseType_t *uxTask, TCB_t *pxTCB ) - { - if (pxTCB == NULL) { - return; - } - pxTaskSnapshotArray[ *uxTask ].pxTCB = pxTCB; - pxTaskSnapshotArray[ *uxTask ].pxTopOfStack = (StackType_t *)pxTCB->pxTopOfStack; - #if( portSTACK_GROWTH < 0 ) - { - pxTaskSnapshotArray[ *uxTask ].pxEndOfStack = pxTCB->pxEndOfStack; - } - #else - { - pxTaskSnapshotArray[ *uxTask ].pxEndOfStack = pxTCB->pxStack; - } - #endif - (*uxTask)++; - } - - static void prvTaskGetSnapshotsFromList( TaskSnapshot_t *pxTaskSnapshotArray, UBaseType_t *uxTask, const UBaseType_t uxArraySize, List_t *pxList ) - { - TCB_t *pxNextTCB, *pxFirstTCB; - - if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 ) - { - listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); - do - { - if( *uxTask >= uxArraySize ) - break; - - listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); - prvTaskGetSnapshot( pxTaskSnapshotArray, uxTask, pxNextTCB ); - } while( pxNextTCB != pxFirstTCB ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - - UBaseType_t uxTaskGetSnapshotAll( TaskSnapshot_t * const pxTaskSnapshotArray, const UBaseType_t uxArraySize, UBaseType_t * const pxTcbSz ) - { - UBaseType_t uxTask = 0, i = 0; - - - *pxTcbSz = sizeof(TCB_t); - /* Fill in an TaskStatus_t structure with information on each - task in the Ready state. */ - i = configMAX_PRIORITIES; - do - { - i--; - prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, &( pxReadyTasksLists[ i ] ) ); - } while( i > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ - - /* Fill in an TaskStatus_t structure with information on each - task in the Blocked state. */ - prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, ( List_t * ) pxDelayedTaskList ); - prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, ( List_t * ) pxOverflowDelayedTaskList ); - for (i = 0; i < portNUM_PROCESSORS; i++) { - if( uxTask >= uxArraySize ) - break; - prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, &( xPendingReadyList[i]) ); - } - - #if( INCLUDE_vTaskDelete == 1 ) - { - prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, &xTasksWaitingTermination ); - } - #endif - - #if ( INCLUDE_vTaskSuspend == 1 ) - { - prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, &xSuspendedTaskList ); - } - #endif - 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, especially where access to file scope functions and data is needed (for example when performing module tests). */ diff --git a/components/freertos/test/CMakeLists.txt b/components/freertos/test/CMakeLists.txt index 12d6eed56c..75c356f830 100644 --- a/components/freertos/test/CMakeLists.txt +++ b/components/freertos/test/CMakeLists.txt @@ -1,3 +1,5 @@ idf_component_register(SRC_DIRS . PRIV_INCLUDE_DIRS . PRIV_REQUIRES cmock test_utils esp_ipc driver) +# Enable task snapshots by setting configENABLE_TASK_SNAPSHOT macro +idf_build_set_property(COMPILE_OPTIONS "-DconfigENABLE_TASK_SNAPSHOT=1" APPEND) diff --git a/components/freertos/test/test_tasks_snapshot.c b/components/freertos/test/test_tasks_snapshot.c index d7648584c8..a24685f3d7 100644 --- a/components/freertos/test/test_tasks_snapshot.c +++ b/components/freertos/test/test_tasks_snapshot.c @@ -5,7 +5,7 @@ #include #include "soc/cpu.h" #include "freertos/FreeRTOS.h" -#include "freertos/task.h" +#include "freertos/task_snapshot.h" #include "unity.h" #include "sdkconfig.h" diff --git a/mocks/freertos/CMakeLists.txt b/mocks/freertos/CMakeLists.txt index 6daa7e539b..0df27f1f66 100644 --- a/mocks/freertos/CMakeLists.txt +++ b/mocks/freertos/CMakeLists.txt @@ -7,6 +7,7 @@ idf_component_get_property(original_freertos_dir freertos COMPONENT_OVERRIDEN_DI set(include_dirs "${original_freertos_dir}/include" "${original_freertos_dir}/include/freertos" # this is due to the way includes are generated in CMock + "${original_freertos_dir}/include/esp_additions" "${original_freertos_dir}/port/linux/include") idf_component_mock(INCLUDE_DIRS ${include_dirs}