change(freertos): Deprecate usage of vPortCleanUpTCB() by applications

Previously, if CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP was enabled, users
would provide a definition for a vPortCleanUpTCB() hook function that is called
right before a task's memory is freed in prvDeleteTCB(). However,
vPortCleanUpTCB() will be reclaimed by ESP-IDF for internal use in v6.0.

This commit introduces the following changes...

Introduced a new CONFIG_FREERTOS_TASK_PRE_DELETION_HOOK option:

- Provides the same pre-deletion hook functionality. But users now define
vTaskPreDeletionHook() instead.
- CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP still exists, but is marked as
deprecated. This is to maintain compatibility with existing applications
that already define vPortCleanUpTCB().
- Removed redundant --wl --wrap workaround with vPortCleanUpTCB()
- Added todo notes to remove support for user defined vPortCleanUpTCB()
completely in v6.0.
- Updated test cases to use new CONFIG_FREERTOS_TASK_PRE_DELETION_HOOK option

Freed up portCLEAN_UP_TCB() to call a new internal vPortTCBPreDeleteHook():

- vPortTCBPreDeleteHook() now replaces the previous "wrapped" implementation
of vPortCleanUpTCB().
- vPortTCBPreDeleteHook() is an internal task pre-delete hook for IDF FreeRTOS
ports to inject some pre-deletion operations.
- Internal pre-delete hook now invokes user provided vTaskPreDeletionHook()
if enabled.
- Relocated vPortTCBPreDeleteHook() to correct section in port.c
This commit is contained in:
Darian Leung
2023-08-22 22:32:44 +08:00
parent 9d8b121ef2
commit 39cf3638ae
15 changed files with 275 additions and 216 deletions

View File

@@ -250,7 +250,4 @@ else()
idf_component_optional_requires(PRIVATE esp_pm) idf_component_optional_requires(PRIVATE esp_pm)
endif() endif()
if(CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP AND CONFIG_FREERTOS_SMP)
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=vPortCleanUpTCB")
endif()
endif() endif()

View File

@@ -143,9 +143,19 @@ void vPortYieldFromISR(void);
static inline BaseType_t __attribute__((always_inline)) xPortGetCoreID( void ); static inline BaseType_t __attribute__((always_inline)) xPortGetCoreID( void );
// ----------------------- TCB Cleanup -------------------------- // --------------------- TCB Cleanup -----------------------
void vPortCleanUpTCB ( void *pxTCB ); /**
* @brief TCB cleanup hook
*
* The portCLEAN_UP_TCB() macro is called in prvDeleteTCB() right before a
* deleted task's memory is freed. We map that macro to this internal function
* so that IDF FreeRTOS ports can inject some task pre-deletion operations.
*
* @note We can't use vPortCleanUpTCB() due to API compatibility issues. See
* CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP. Todo: IDF-8097
*/
void vPortTCBPreDeleteHook( void *pxTCB );
/* ------------------------------------------- FreeRTOS Porting Interface ---------------------------------------------- /* ------------------------------------------- FreeRTOS Porting Interface ----------------------------------------------
* - Contains all the mappings of the macros required by FreeRTOS * - Contains all the mappings of the macros required by FreeRTOS
@@ -218,7 +228,8 @@ extern void vTaskExitCritical( void );
// --------------------- TCB Cleanup ----------------------- // --------------------- TCB Cleanup -----------------------
#define portCLEAN_UP_TCB( pxTCB ) vPortCleanUpTCB( pxTCB ) #define portCLEAN_UP_TCB( pxTCB ) vPortTCBPreDeleteHook( pxTCB )
/* --------------------------------------------- Inline Implementations ------------------------------------------------ /* --------------------------------------------- Inline Implementations ------------------------------------------------
* - Implementation of inline functions of the forward declares * - Implementation of inline functions of the forward declares

View File

@@ -208,6 +208,63 @@ void vPortYieldFromISR( void )
uxSchedulerRunning = 1; uxSchedulerRunning = 1;
xPortSwitchFlag = 1; xPortSwitchFlag = 1;
} }
// ----------------------- System --------------------------
// ------------------- Run Time Stats ----------------------
// --------------------- TCB Cleanup -----------------------
#if ( CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS )
static void vPortTLSPointersDelCb( void *pxTCB )
{
/* Typecast pxTCB to StaticTask_t type to access TCB struct members.
* pvDummy15 corresponds to pvThreadLocalStoragePointers member of the TCB.
*/
StaticTask_t *tcb = ( StaticTask_t * )pxTCB;
/* The TLSP deletion callbacks are stored at an offset of (configNUM_THREAD_LOCAL_STORAGE_POINTERS/2) */
TlsDeleteCallbackFunction_t *pvThreadLocalStoragePointersDelCallback = ( TlsDeleteCallbackFunction_t * )( &( tcb->pvDummy15[ ( configNUM_THREAD_LOCAL_STORAGE_POINTERS / 2 ) ] ) );
/* We need to iterate over half the depth of the pvThreadLocalStoragePointers area
* to access all TLS pointers and their respective TLS deletion callbacks.
*/
for ( int x = 0; x < ( configNUM_THREAD_LOCAL_STORAGE_POINTERS / 2 ); x++ ) {
if ( pvThreadLocalStoragePointersDelCallback[ x ] != NULL ) { //If del cb is set
/* In case the TLSP deletion callback has been overwritten by a TLS pointer, gracefully abort. */
if ( !esp_ptr_executable( pvThreadLocalStoragePointersDelCallback[ x ] ) ) {
ESP_LOGE("FreeRTOS", "Fatal error: TLSP deletion callback at index %d overwritten with non-excutable pointer %p", x, pvThreadLocalStoragePointersDelCallback[ x ]);
abort();
}
pvThreadLocalStoragePointersDelCallback[ x ]( x, tcb->pvDummy15[ x ] ); //Call del cb
}
}
}
#endif /* CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS */
void vPortTCBPreDeleteHook( void *pxTCB )
{
#if ( CONFIG_FREERTOS_TASK_PRE_DELETION_HOOK )
/* Call the user defined task pre-deletion hook */
extern void vTaskPreDeletionHook( void * pxTCB );
vTaskPreDeletionHook( pxTCB );
#endif /* CONFIG_FREERTOS_TASK_PRE_DELETION_HOOK */
#if ( CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP )
/*
* If the user is using the legacy task pre-deletion hook, call it.
* Todo: Will be removed in IDF-8097
*/
#warning "CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP is deprecated. Use CONFIG_FREERTOS_TASK_PRE_DELETION_HOOK instead."
extern void vPortCleanUpTCB( void * pxTCB );
vPortCleanUpTCB( pxTCB );
#endif /* CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP */
#if ( CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS )
/* Call TLS pointers deletion callbacks */
vPortTLSPointersDelCb( pxTCB );
#endif /* CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS */
}
/* ------------------------------------------------ FreeRTOS Portable -------------------------------------------------- /* ------------------------------------------------ FreeRTOS Portable --------------------------------------------------
* - Provides implementation for functions required by FreeRTOS * - Provides implementation for functions required by FreeRTOS
@@ -423,36 +480,6 @@ StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxC
//TODO: IDF-2393 //TODO: IDF-2393
} }
// ------- Thread Local Storage Pointers Deletion Callbacks -------
#if ( CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS )
void vPortTLSPointersDelCb( void *pxTCB )
{
/* Typecast pxTCB to StaticTask_t type to access TCB struct members.
* pvDummy15 corresponds to pvThreadLocalStoragePointers member of the TCB.
*/
StaticTask_t *tcb = ( StaticTask_t * )pxTCB;
/* The TLSP deletion callbacks are stored at an offset of (configNUM_THREAD_LOCAL_STORAGE_POINTERS/2) */
TlsDeleteCallbackFunction_t *pvThreadLocalStoragePointersDelCallback = ( TlsDeleteCallbackFunction_t * )( &( tcb->pvDummy15[ ( configNUM_THREAD_LOCAL_STORAGE_POINTERS / 2 ) ] ) );
/* We need to iterate over half the depth of the pvThreadLocalStoragePointers area
* to access all TLS pointers and their respective TLS deletion callbacks.
*/
for ( int x = 0; x < ( configNUM_THREAD_LOCAL_STORAGE_POINTERS / 2 ); x++ ) {
if ( pvThreadLocalStoragePointersDelCallback[ x ] != NULL ) { //If del cb is set
/* In case the TLSP deletion callback has been overwritten by a TLS pointer, gracefully abort. */
if ( !esp_ptr_executable( pvThreadLocalStoragePointersDelCallback[ x ] ) ) {
ESP_LOGE("FreeRTOS", "Fatal error: TLSP deletion callback at index %d overwritten with non-excutable pointer %p", x, pvThreadLocalStoragePointersDelCallback[ x ]);
abort();
}
pvThreadLocalStoragePointersDelCallback[ x ]( x, tcb->pvDummy15[ x ] ); //Call del cb
}
}
}
#endif // CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS
// ------------------- Hook Functions ---------------------- // ------------------- Hook Functions ----------------------
void __attribute__((weak)) vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName) void __attribute__((weak)) vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName)
@@ -496,26 +523,3 @@ void vApplicationMinimalIdleHook( void )
esp_vApplicationIdleHook(); //Run IDF style hooks esp_vApplicationIdleHook(); //Run IDF style hooks
} }
#endif // CONFIG_FREERTOS_USE_MINIMAL_IDLE_HOOK #endif // CONFIG_FREERTOS_USE_MINIMAL_IDLE_HOOK
/*
* Hook function called during prvDeleteTCB() to cleanup any
* user defined static memory areas in the TCB.
*/
#if CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP
void __real_vPortCleanUpTCB( void *pxTCB );
void __wrap_vPortCleanUpTCB( void *pxTCB )
#else
void vPortCleanUpTCB ( void *pxTCB )
#endif /* CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP */
{
#if ( CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP )
/* Call user defined vPortCleanUpTCB */
__real_vPortCleanUpTCB( pxTCB );
#endif /* CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP */
#if ( CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS )
/* Call TLS pointers deletion callbacks */
vPortTLSPointersDelCb( pxTCB );
#endif /* CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS */
}

View File

@@ -127,9 +127,20 @@ static inline void __attribute__((always_inline)) vPortYieldFromISR( void );
static inline BaseType_t __attribute__((always_inline)) xPortGetCoreID( void ); static inline BaseType_t __attribute__((always_inline)) xPortGetCoreID( void );
// ----------------------- TCB Cleanup -------------------------- // --------------------- TCB Cleanup -----------------------
/**
* @brief TCB cleanup hook
*
* The portCLEAN_UP_TCB() macro is called in prvDeleteTCB() right before a
* deleted task's memory is freed. We map that macro to this internal function
* so that IDF FreeRTOS ports can inject some task pre-deletion operations.
*
* @note We can't use vPortCleanUpTCB() due to API compatibility issues. See
* CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP. Todo: IDF-8097
*/
void vPortTCBPreDeleteHook( void *pxTCB );
void vPortCleanUpTCB ( void *pxTCB );
/* ----------------------------------------- FreeRTOS SMP Porting Interface -------------------------------------------- /* ----------------------------------------- FreeRTOS SMP Porting Interface --------------------------------------------
* - Contains all the mappings of the macros required by FreeRTOS SMP * - Contains all the mappings of the macros required by FreeRTOS SMP
@@ -221,9 +232,9 @@ extern void vTaskExitCritical( void );
#define portALT_GET_RUN_TIME_COUNTER_VALUE(x) ({x = (uint32_t)esp_timer_get_time();}) #define portALT_GET_RUN_TIME_COUNTER_VALUE(x) ({x = (uint32_t)esp_timer_get_time();})
#endif #endif
// ------------------- TCB Cleanup ---------------------- // --------------------- TCB Cleanup -----------------------
#define portCLEAN_UP_TCB( pxTCB ) vPortCleanUpTCB( pxTCB ) #define portCLEAN_UP_TCB( pxTCB ) vPortTCBPreDeleteHook( pxTCB )
/* --------------------------------------------- Inline Implementations ------------------------------------------------ /* --------------------------------------------- Inline Implementations ------------------------------------------------
* - Implementation of inline functions of the forward declares * - Implementation of inline functions of the forward declares

View File

@@ -42,6 +42,14 @@
_Static_assert(portBYTE_ALIGNMENT == 16, "portBYTE_ALIGNMENT must be set to 16"); _Static_assert(portBYTE_ALIGNMENT == 16, "portBYTE_ALIGNMENT must be set to 16");
/**
* @brief Align stack pointer in a downward growing stack
*
* This macro is used to round a stack pointer downwards to the nearest n-byte boundary, where n is a power of 2.
* This macro is generally used when allocating aligned areas on a downward growing stack.
*/
#define STACKPTR_ALIGN_DOWN(n, ptr) ((ptr) & (~((n)-1)))
/* ---------------------------------------------------- Variables ------------------------------------------------------ /* ---------------------------------------------------- Variables ------------------------------------------------------
* - Various variables used to maintain the FreeRTOS port's state. Used from both port.c and various .S files * - Various variables used to maintain the FreeRTOS port's state. Used from both port.c and various .S files
* - Constant offsets are used by assembly to jump to particular TCB members or a stack area (such as the CPSA). We use * - Constant offsets are used by assembly to jump to particular TCB members or a stack area (such as the CPSA). We use
@@ -209,6 +217,90 @@ void vPortReleaseLock( portMUX_TYPE *lock )
// ----------------------- System -------------------------- // ----------------------- System --------------------------
// ------------------- Run Time Stats ----------------------
// --------------------- TCB Cleanup -----------------------
#if ( CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS )
static void vPortTLSPointersDelCb( void *pxTCB )
{
/* Typecast pxTCB to StaticTask_t type to access TCB struct members.
* pvDummy15 corresponds to pvThreadLocalStoragePointers member of the TCB.
*/
StaticTask_t *tcb = ( StaticTask_t * )pxTCB;
/* The TLSP deletion callbacks are stored at an offset of (configNUM_THREAD_LOCAL_STORAGE_POINTERS/2) */
TlsDeleteCallbackFunction_t *pvThreadLocalStoragePointersDelCallback = ( TlsDeleteCallbackFunction_t * )( &( tcb->pvDummy15[ ( configNUM_THREAD_LOCAL_STORAGE_POINTERS / 2 ) ] ) );
/* We need to iterate over half the depth of the pvThreadLocalStoragePointers area
* to access all TLS pointers and their respective TLS deletion callbacks.
*/
for ( int x = 0; x < ( configNUM_THREAD_LOCAL_STORAGE_POINTERS / 2 ); x++ ) {
if ( pvThreadLocalStoragePointersDelCallback[ x ] != NULL ) { //If del cb is set
/* In case the TLSP deletion callback has been overwritten by a TLS pointer, gracefully abort. */
if ( !esp_ptr_executable( pvThreadLocalStoragePointersDelCallback[ x ] ) ) {
// We call EARLY log here as currently portCLEAN_UP_TCB() is called in a critical section
ESP_EARLY_LOGE("FreeRTOS", "Fatal error: TLSP deletion callback at index %d overwritten with non-excutable pointer %p", x, pvThreadLocalStoragePointersDelCallback[ x ]);
abort();
}
pvThreadLocalStoragePointersDelCallback[ x ]( x, tcb->pvDummy15[ x ] ); //Call del cb
}
}
}
#endif /* CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS */
#if ( XCHAL_CP_NUM > 0 && configUSE_CORE_AFFINITY == 1 && configNUM_CORES > 1 )
static void vPortCleanUpCoprocArea( void *pxTCB )
{
UBaseType_t uxCoprocArea;
BaseType_t xTargetCoreID;
/* Get pointer to the task's coprocessor save area from TCB->pxEndOfStack. See uxInitialiseStackCPSA() */
uxCoprocArea = ( UBaseType_t ) ( ( ( StaticTask_t * ) pxTCB )->pxDummy8 ); /* Get TCB_t.pxEndOfStack */
uxCoprocArea = STACKPTR_ALIGN_DOWN(16, uxCoprocArea - XT_CP_SIZE);
/* Extract core ID from the affinity mask */
xTargetCoreID = ( ( StaticTask_t * ) pxTCB )->uxDummy25 ;
xTargetCoreID = ( BaseType_t ) __builtin_ffs( ( int ) xTargetCoreID );
assert( xTargetCoreID >= 1 ); // __builtin_ffs always returns first set index + 1
xTargetCoreID -= 1;
/* If task has live floating point registers somewhere, release them */
void _xt_coproc_release(volatile void *coproc_sa_base, BaseType_t xTargetCoreID);
_xt_coproc_release( (void *)uxCoprocArea, xTargetCoreID );
}
#endif /* ( XCHAL_CP_NUM > 0 && configUSE_CORE_AFFINITY == 1 && configNUM_CORES > 1 ) */
void vPortTCBPreDeleteHook( void *pxTCB )
{
#if ( CONFIG_FREERTOS_TASK_PRE_DELETION_HOOK )
/* Call the user defined task pre-deletion hook */
extern void vTaskPreDeletionHook( void * pxTCB );
vTaskPreDeletionHook( pxTCB );
#endif /* CONFIG_FREERTOS_TASK_PRE_DELETION_HOOK */
#if ( CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP )
/*
* If the user is using the legacy task pre-deletion hook, call it.
* Todo: Will be removed in IDF-8097
*/
#warning "CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP is deprecated. Use CONFIG_FREERTOS_TASK_PRE_DELETION_HOOK instead."
extern void vPortCleanUpTCB( void * pxTCB );
vPortCleanUpTCB( pxTCB );
#endif /* CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP */
#if ( CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS )
/* Call TLS pointers deletion callbacks */
vPortTLSPointersDelCb( pxTCB );
#endif /* CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS */
#if ( XCHAL_CP_NUM > 0 && configUSE_CORE_AFFINITY == 1 && configNUM_CORES > 1 )
/* Cleanup coproc save area */
vPortCleanUpCoprocArea( pxTCB );
#endif /* ( XCHAL_CP_NUM > 0 && configUSE_CORE_AFFINITY == 1 && configNUM_CORES > 1 ) */
}
/* ------------------------------------------------ FreeRTOS Portable -------------------------------------------------- /* ------------------------------------------------ FreeRTOS Portable --------------------------------------------------
* - Provides implementation for functions required by FreeRTOS * - Provides implementation for functions required by FreeRTOS
* - Declared in portable.h * - Declared in portable.h
@@ -269,14 +361,6 @@ static void vPortTaskWrapper(TaskFunction_t pxCode, void *pvParameters)
} }
#endif #endif
/**
* @brief Align stack pointer in a downward growing stack
*
* This macro is used to round a stack pointer downwards to the nearest n-byte boundary, where n is a power of 2.
* This macro is generally used when allocating aligned areas on a downward growing stack.
*/
#define STACKPTR_ALIGN_DOWN(n, ptr) ((ptr) & (~((n)-1)))
#if XCHAL_CP_NUM > 0 #if XCHAL_CP_NUM > 0
/** /**
* @brief Allocate and initialize coprocessor save area on the stack * @brief Allocate and initialize coprocessor save area on the stack
@@ -559,61 +643,6 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
// Return the task's current stack pointer address which should point to the starting interrupt stack frame // Return the task's current stack pointer address which should point to the starting interrupt stack frame
return (StackType_t *)uxStackPointer; return (StackType_t *)uxStackPointer;
} }
// -------------------- Co-Processor -----------------------
#if ( XCHAL_CP_NUM > 0 && configUSE_CORE_AFFINITY == 1 && configNUM_CORES > 1 )
void _xt_coproc_release(volatile void *coproc_sa_base, BaseType_t xTargetCoreID);
void vPortCleanUpCoprocArea( void *pxTCB )
{
UBaseType_t uxCoprocArea;
BaseType_t xTargetCoreID;
/* Get pointer to the task's coprocessor save area from TCB->pxEndOfStack. See uxInitialiseStackCPSA() */
uxCoprocArea = ( UBaseType_t ) ( ( ( StaticTask_t * ) pxTCB )->pxDummy8 ); /* Get TCB_t.pxEndOfStack */
uxCoprocArea = STACKPTR_ALIGN_DOWN(16, uxCoprocArea - XT_CP_SIZE);
/* Extract core ID from the affinity mask */
xTargetCoreID = ( ( StaticTask_t * ) pxTCB )->uxDummy25 ;
xTargetCoreID = ( BaseType_t ) __builtin_ffs( ( int ) xTargetCoreID );
assert( xTargetCoreID >= 1 ); // __builtin_ffs always returns first set index + 1
xTargetCoreID -= 1;
/* If task has live floating point registers somewhere, release them */
_xt_coproc_release( (void *)uxCoprocArea, xTargetCoreID );
}
#endif // ( XCHAL_CP_NUM > 0 && configUSE_CORE_AFFINITY == 1 && configNUM_CORES > 1 )
// ------- Thread Local Storage Pointers Deletion Callbacks -------
#if ( CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS )
void vPortTLSPointersDelCb( void *pxTCB )
{
/* Typecast pxTCB to StaticTask_t type to access TCB struct members.
* pvDummy15 corresponds to pvThreadLocalStoragePointers member of the TCB.
*/
StaticTask_t *tcb = ( StaticTask_t * )pxTCB;
/* The TLSP deletion callbacks are stored at an offset of (configNUM_THREAD_LOCAL_STORAGE_POINTERS/2) */
TlsDeleteCallbackFunction_t *pvThreadLocalStoragePointersDelCallback = ( TlsDeleteCallbackFunction_t * )( &( tcb->pvDummy15[ ( configNUM_THREAD_LOCAL_STORAGE_POINTERS / 2 ) ] ) );
/* We need to iterate over half the depth of the pvThreadLocalStoragePointers area
* to access all TLS pointers and their respective TLS deletion callbacks.
*/
for ( int x = 0; x < ( configNUM_THREAD_LOCAL_STORAGE_POINTERS / 2 ); x++ ) {
if ( pvThreadLocalStoragePointersDelCallback[ x ] != NULL ) { //If del cb is set
/* In case the TLSP deletion callback has been overwritten by a TLS pointer, gracefully abort. */
if ( !esp_ptr_executable( pvThreadLocalStoragePointersDelCallback[ x ] ) ) {
// We call EARLY log here as currently portCLEAN_UP_TCB() is called in a critical section
ESP_EARLY_LOGE("FreeRTOS", "Fatal error: TLSP deletion callback at index %d overwritten with non-excutable pointer %p", x, pvThreadLocalStoragePointersDelCallback[ x ]);
abort();
}
pvThreadLocalStoragePointersDelCallback[ x ]( x, tcb->pvDummy15[ x ] ); //Call del cb
}
}
}
#endif // CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS
// ------------------- Hook Functions ---------------------- // ------------------- Hook Functions ----------------------
@@ -655,31 +684,3 @@ void vApplicationMinimalIdleHook( void )
esp_vApplicationIdleHook(); //Run IDF style hooks esp_vApplicationIdleHook(); //Run IDF style hooks
} }
#endif // CONFIG_FREERTOS_USE_MINIMAL_IDLE_HOOK #endif // CONFIG_FREERTOS_USE_MINIMAL_IDLE_HOOK
/*
* Hook function called during prvDeleteTCB() to cleanup any
* user defined static memory areas in the TCB.
*/
#if CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP
void __real_vPortCleanUpTCB( void *pxTCB );
void __wrap_vPortCleanUpTCB( void *pxTCB )
#else
void vPortCleanUpTCB ( void *pxTCB )
#endif /* CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP */
{
#if ( CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP )
/* Call user defined vPortCleanUpTCB */
__real_vPortCleanUpTCB( pxTCB );
#endif /* CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP */
#if ( CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS )
/* Call TLS pointers deletion callbacks */
vPortTLSPointersDelCb( pxTCB );
#endif /* CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS */
#if ( XCHAL_CP_NUM > 0 && configUSE_CORE_AFFINITY == 1 && configNUM_CORES > 1 )
/* Cleanup coproc save area */
vPortCleanUpCoprocArea( pxTCB );
#endif // ( XCHAL_CP_NUM > 0 && configUSE_CORE_AFFINITY == 1 && configNUM_CORES > 1 )
}

View File

@@ -427,7 +427,19 @@ FORCE_INLINE_ATTR BaseType_t xPortGetCoreID(void)
return (BaseType_t) esp_cpu_get_core_id(); return (BaseType_t) esp_cpu_get_core_id();
} }
// --------------------- TCB Cleanup -----------------------
/**
* @brief TCB cleanup hook
*
* The portCLEAN_UP_TCB() macro is called in prvDeleteTCB() right before a
* deleted task's memory is freed. We map that macro to this internal function
* so that IDF FreeRTOS ports can inject some task pre-deletion operations.
*
* @note We can't use vPortCleanUpTCB() due to API compatibility issues. See
* CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP. Todo: IDF-8097
*/
void vPortTCBPreDeleteHook( void *pxTCB );
/* ------------------------------------------- FreeRTOS Porting Interface ---------------------------------------------- /* ------------------------------------------- FreeRTOS Porting Interface ----------------------------------------------
* - Contains all the mappings of the macros required by FreeRTOS * - Contains all the mappings of the macros required by FreeRTOS
@@ -561,11 +573,7 @@ FORCE_INLINE_ATTR BaseType_t xPortGetCoreID(void)
// --------------------- TCB Cleanup ----------------------- // --------------------- TCB Cleanup -----------------------
#if CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP #define portCLEAN_UP_TCB( pxTCB ) vPortTCBPreDeleteHook( pxTCB )
/* If enabled, users must provide an implementation of vPortCleanUpTCB() */
extern void vPortCleanUpTCB ( void *pxTCB );
#define portCLEAN_UP_TCB( pxTCB ) vPortCleanUpTCB( pxTCB )
#endif /* CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP */
// -------------- Optimized Task Selection ----------------- // -------------- Optimized Task Selection -----------------

View File

@@ -589,7 +589,26 @@ void vPortSetStackWatchpoint(void *pxStackStart)
esp_cpu_set_watchpoint(STACK_WATCH_POINT_NUMBER, (char *)addr, STACK_WATCH_AREA_SIZE, ESP_CPU_WATCHPOINT_STORE); esp_cpu_set_watchpoint(STACK_WATCH_POINT_NUMBER, (char *)addr, STACK_WATCH_AREA_SIZE, ESP_CPU_WATCHPOINT_STORE);
} }
// --------------------- TCB Cleanup -----------------------
void vPortTCBPreDeleteHook( void *pxTCB )
{
#if ( CONFIG_FREERTOS_TASK_PRE_DELETION_HOOK )
/* Call the user defined task pre-deletion hook */
extern void vTaskPreDeletionHook( void * pxTCB );
vTaskPreDeletionHook( pxTCB );
#endif /* CONFIG_FREERTOS_TASK_PRE_DELETION_HOOK */
#if ( CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP )
/*
* If the user is using the legacy task pre-deletion hook, call it.
* Todo: Will be removed in IDF-8097
*/
#warning "CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP is deprecated. Use CONFIG_FREERTOS_TASK_PRE_DELETION_HOOK instead."
extern void vPortCleanUpTCB( void * pxTCB );
vPortCleanUpTCB( pxTCB );
#endif /* CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP */
}
/* ---------------------------------------------- Misc Implementations ------------------------------------------------- /* ---------------------------------------------- Misc Implementations -------------------------------------------------
* *

View File

@@ -4,7 +4,7 @@
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
* *
* SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD * SPDX-FileContributor: 2016-2023 Espressif Systems (Shanghai) CO LTD
*/ */
/* /*
* FreeRTOS Kernel V10.4.3 * FreeRTOS Kernel V10.4.3
@@ -406,6 +406,19 @@ void vPortSetStackWatchpoint( void *pxStackStart );
*/ */
FORCE_INLINE_ATTR BaseType_t xPortGetCoreID(void); FORCE_INLINE_ATTR BaseType_t xPortGetCoreID(void);
// --------------------- TCB Cleanup -----------------------
/**
* @brief TCB cleanup hook
*
* The portCLEAN_UP_TCB() macro is called in prvDeleteTCB() right before a
* deleted task's memory is freed. We map that macro to this internal function
* so that IDF FreeRTOS ports can inject some task pre-deletion operations.
*
* @note We can't use vPortCleanUpTCB() due to API compatibility issues. See
* CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP. Todo: IDF-8097
*/
void vPortTCBPreDeleteHook( void *pxTCB );
/* ------------------------------------------- FreeRTOS Porting Interface ---------------------------------------------- /* ------------------------------------------- FreeRTOS Porting Interface ----------------------------------------------
@@ -525,11 +538,7 @@ extern void _frxt_setup_switch( void ); //Defined in portasm.S
// --------------------- TCB Cleanup ----------------------- // --------------------- TCB Cleanup -----------------------
#if CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP #define portCLEAN_UP_TCB( pxTCB ) vPortTCBPreDeleteHook( pxTCB )
/* If enabled, users must provide an implementation of vPortCleanUpTCB() */
extern void vPortCleanUpTCB ( void *pxTCB );
#define portCLEAN_UP_TCB( pxTCB ) vPortCleanUpTCB( pxTCB )
#endif /* CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP */
// -------------- Optimized Task Selection ----------------- // -------------- Optimized Task Selection -----------------

View File

@@ -4,7 +4,7 @@
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
* *
* SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD * SPDX-FileContributor: 2016-2023 Espressif Systems (Shanghai) CO LTD
*/ */
/* /*
* FreeRTOS Kernel V10.4.3 * FreeRTOS Kernel V10.4.3
@@ -605,6 +605,27 @@ void vPortSetStackWatchpoint( void *pxStackStart )
esp_cpu_set_watchpoint(STACK_WATCH_POINT_NUMBER, (char *)addr, 32, ESP_CPU_WATCHPOINT_STORE); esp_cpu_set_watchpoint(STACK_WATCH_POINT_NUMBER, (char *)addr, 32, ESP_CPU_WATCHPOINT_STORE);
} }
// --------------------- TCB Cleanup -----------------------
void vPortTCBPreDeleteHook( void *pxTCB )
{
#if ( CONFIG_FREERTOS_TASK_PRE_DELETION_HOOK )
/* Call the user defined task pre-deletion hook */
extern void vTaskPreDeletionHook( void * pxTCB );
vTaskPreDeletionHook( pxTCB );
#endif /* CONFIG_FREERTOS_TASK_PRE_DELETION_HOOK */
#if ( CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP )
/*
* If the user is using the legacy task pre-deletion hook, call it.
* Todo: Will be removed in IDF-8097
*/
#warning "CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP is deprecated. Use CONFIG_FREERTOS_TASK_PRE_DELETION_HOOK instead."
extern void vPortCleanUpTCB( void * pxTCB );
vPortCleanUpTCB( pxTCB );
#endif /* CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP */
}
// -------------------- Co-Processor ----------------------- // -------------------- Co-Processor -----------------------
#if XCHAL_CP_NUM > 0 #if XCHAL_CP_NUM > 0

View File

@@ -324,10 +324,28 @@ menu "FreeRTOS"
callbacks. If the user does not wish to use TLSP deletion callbacks then this option could be turned callbacks. If the user does not wish to use TLSP deletion callbacks then this option could be turned
off to save space in the TCB memory. off to save space in the TCB memory.
config FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP config FREERTOS_TASK_PRE_DELETION_HOOK
bool "Enable static task clean up hook" # This option is a replacement for FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP (which is now deprecated). If the
# deprecated option is defined, we hide this option to avoid multiple pre-deletion hooks from running.
bool "Enable task pre-deletion hook"
depends on !FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP
default n default n
help help
Enable this option to make FreeRTOS call a user provided hook function right before it deletes a task
(i.e., frees/releases a dynamically/statically allocated task's memory). This is useful if users want
to know when a task is actually deleted (in case the task's deletion is delegated to the IDLE task).
If this config option is enabled, users must define a ``void vTaskPreDeletionHook( void * pxTCB )``
hook function in their application.
config FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP
# This option is deprecated (replaced by FREERTOS_TASK_PRE_DELETION_HOOK) but still exists to maintain
# compatibility. Todo: Remove by v6.0 (see IDF-8097).
bool "Enable static task clean up hook (DEPRECATED)"
default n
help
THIS OPTION IS DEPRECATED. Use FREERTOS_TASK_PRE_DELETION_HOOK instead.
Enable this option to make FreeRTOS call the static task clean up hook when a task is deleted. Enable this option to make FreeRTOS call the static task clean up hook when a task is deleted.
Note: Users will need to provide a ``void vPortCleanUpTCB ( void *pxTCB )`` callback Note: Users will need to provide a ``void vPortCleanUpTCB ( void *pxTCB )`` callback

View File

@@ -219,7 +219,7 @@ entries:
port:vPortCleanUpCoprocArea (default) port:vPortCleanUpCoprocArea (default)
if FREERTOS_TLSP_DELETION_CALLBACKS = y: if FREERTOS_TLSP_DELETION_CALLBACKS = y:
port:vPortTLSPointersDelCb (default) port:vPortTLSPointersDelCb (default)
port:vPortCleanUpTCB (default) port:vPortTCBPreDeleteHook (default)
# -------------------------------------------------------------------------------------------------------------- # --------------------------------------------------------------------------------------------------------------
# portable/riscv/port.c # portable/riscv/port.c
# - Most functions are called from an ISR context, except for scheduler/task init/deinit functions # - Most functions are called from an ISR context, except for scheduler/task init/deinit functions
@@ -234,4 +234,4 @@ entries:
port:pxPortInitialiseStack (default) port:pxPortInitialiseStack (default)
if FREERTOS_TLSP_DELETION_CALLBACKS = y: if FREERTOS_TLSP_DELETION_CALLBACKS = y:
port:vPortTLSPointersDelCb (default) port:vPortTLSPointersDelCb (default)
port:vPortCleanUpTCB (default) port:vPortTCBPreDeleteHook (default)

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -65,7 +65,7 @@ TEST_CASE("FreeRTOS tick hook", "[freertos]")
#endif // configUSE_TICK_HOOK #endif // configUSE_TICK_HOOK
#endif // CONFIG_FREERTOS_SMP #endif // CONFIG_FREERTOS_SMP
#if CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP #if CONFIG_FREERTOS_TASK_PRE_DELETION_HOOK
static volatile void *deleted_tcb; static volatile void *deleted_tcb;
@@ -74,7 +74,7 @@ static void taskDeletesItself(void *ignored)
vTaskDelete(NULL); vTaskDelete(NULL);
} }
void vPortCleanUpTCB(void *pxTCB) void vTaskPreDeletionHook(void *pxTCB)
{ {
deleted_tcb = pxTCB; deleted_tcb = pxTCB;
} }
@@ -91,4 +91,4 @@ TEST_CASE("static task cleanup hook is called based on config", "[freertos]")
} }
} }
#endif // CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP #endif // CONFIG_FREERTOS_TASK_PRE_DELETION_HOOK

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -105,15 +105,6 @@ TEST_CASE("Test TLSP deletion callbacks", "[freertos]")
//The variables pointed to by Thread Local Storage Pointer //The variables pointed to by Thread Local Storage Pointer
static uint32_t task_storage[portNUM_PROCESSORS][NO_OF_TLSP] = {0}; static uint32_t task_storage[portNUM_PROCESSORS][NO_OF_TLSP] = {0};
/* If static task cleanup is defined, can't set index 0 even if the calling task is not a pthread,
as the cleanup is called for every task.
*/
#if defined(CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP)
static const int skip_index = 0; /*PTHREAD_TLS_INDEX*/
#else
static const int skip_index = -1;
#endif
static void del_cb(int index, void *ptr) static void del_cb(int index, void *ptr)
{ {
*((uint32_t *)ptr) = (TLSP_DEL_BASE << index); //Indicate deletion by setting task storage element to a unique value *((uint32_t *)ptr) = (TLSP_DEL_BASE << index); //Indicate deletion by setting task storage element to a unique value
@@ -123,19 +114,11 @@ static void task_cb(void *arg)
{ {
int core = xPortGetCoreID(); int core = xPortGetCoreID();
for(int i = 0; i < NO_OF_TLSP; i++){ for(int i = 0; i < NO_OF_TLSP; i++){
if (i == skip_index) {
continue;
}
task_storage[core][i] = (TLSP_SET_BASE << i); //Give each element of task_storage a unique number task_storage[core][i] = (TLSP_SET_BASE << i); //Give each element of task_storage a unique number
vTaskSetThreadLocalStoragePointerAndDelCallback(NULL, i, (void *)&task_storage[core][i], del_cb); //Set each TLSP to point to a task storage element vTaskSetThreadLocalStoragePointerAndDelCallback(NULL, i, (void *)&task_storage[core][i], del_cb); //Set each TLSP to point to a task storage element
} }
for(int i = 0; i < NO_OF_TLSP; i++){ for(int i = 0; i < NO_OF_TLSP; i++){
if (i == skip_index) {
continue;
}
uint32_t * tlsp = (uint32_t *)pvTaskGetThreadLocalStoragePointer(NULL, i); uint32_t * tlsp = (uint32_t *)pvTaskGetThreadLocalStoragePointer(NULL, i);
TEST_ASSERT_EQUAL(*tlsp, (TLSP_SET_BASE << i)); //Check if TLSP points to the correct task storage element by checking unique value TEST_ASSERT_EQUAL(*tlsp, (TLSP_SET_BASE << i)); //Check if TLSP points to the correct task storage element by checking unique value
} }
@@ -153,9 +136,6 @@ TEST_CASE("Test FreeRTOS thread local storage pointers and del cb", "[freertos]"
for(int core = 0; core < portNUM_PROCESSORS; core++){ for(int core = 0; core < portNUM_PROCESSORS; core++){
for(int i = 0; i < NO_OF_TLSP; i++){ for(int i = 0; i < NO_OF_TLSP; i++){
if (i == skip_index) {
continue;
}
TEST_ASSERT_EQUAL((TLSP_DEL_BASE << i), task_storage[core][i]); //Check del_cb ran by checking task storage for unique value TEST_ASSERT_EQUAL((TLSP_DEL_BASE << i), task_storage[core][i]); //Check del_cb ran by checking task storage for unique value
} }
} }

View File

@@ -7,7 +7,7 @@ CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL=y
CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=y CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=y
CONFIG_FREERTOS_INTERRUPT_BACKTRACE=n CONFIG_FREERTOS_INTERRUPT_BACKTRACE=n
CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y
CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP=y CONFIG_FREERTOS_TASK_PRE_DELETION_HOOK=y
CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=10 CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=10
CONFIG_FREERTOS_USE_TRACE_FACILITY=y CONFIG_FREERTOS_USE_TRACE_FACILITY=y
CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS=y CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS=y

View File

@@ -103,15 +103,6 @@ TEST_CASE("Test TLSP deletion callbacks", "[freertos]")
//The variables pointed to by Thread Local Storage Pointer //The variables pointed to by Thread Local Storage Pointer
static uint32_t task_storage[portNUM_PROCESSORS][NO_OF_TLSP] = {0}; static uint32_t task_storage[portNUM_PROCESSORS][NO_OF_TLSP] = {0};
/* If static task cleanup is defined, can't set index 0 even if the calling task is not a pthread,
as the cleanup is called for every task.
*/
#if defined(CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP)
static const int skip_index = 0; /*PTHREAD_TLS_INDEX*/
#else
static const int skip_index = -1;
#endif
static void del_cb(int index, void *ptr) static void del_cb(int index, void *ptr)
{ {
*((uint32_t *)ptr) = (TLSP_DEL_BASE << index); //Indicate deletion by setting task storage element to a unique value *((uint32_t *)ptr) = (TLSP_DEL_BASE << index); //Indicate deletion by setting task storage element to a unique value
@@ -121,19 +112,11 @@ static void task_cb(void *arg)
{ {
int core = xPortGetCoreID(); int core = xPortGetCoreID();
for(int i = 0; i < NO_OF_TLSP; i++){ for(int i = 0; i < NO_OF_TLSP; i++){
if (i == skip_index) {
continue;
}
task_storage[core][i] = (TLSP_SET_BASE << i); //Give each element of task_storage a unique number task_storage[core][i] = (TLSP_SET_BASE << i); //Give each element of task_storage a unique number
vTaskSetThreadLocalStoragePointerAndDelCallback(NULL, i, (void *)&task_storage[core][i], del_cb); //Set each TLSP to point to a task storage element vTaskSetThreadLocalStoragePointerAndDelCallback(NULL, i, (void *)&task_storage[core][i], del_cb); //Set each TLSP to point to a task storage element
} }
for(int i = 0; i < NO_OF_TLSP; i++){ for(int i = 0; i < NO_OF_TLSP; i++){
if (i == skip_index) {
continue;
}
uint32_t * tlsp = (uint32_t *)pvTaskGetThreadLocalStoragePointer(NULL, i); uint32_t * tlsp = (uint32_t *)pvTaskGetThreadLocalStoragePointer(NULL, i);
TEST_ASSERT_EQUAL(*tlsp, (TLSP_SET_BASE << i)); //Check if TLSP points to the correct task storage element by checking unique value TEST_ASSERT_EQUAL(*tlsp, (TLSP_SET_BASE << i)); //Check if TLSP points to the correct task storage element by checking unique value
} }
@@ -151,9 +134,6 @@ TEST_CASE("Test FreeRTOS thread local storage pointers and del cb", "[freertos]"
for(int core = 0; core < portNUM_PROCESSORS; core++){ for(int core = 0; core < portNUM_PROCESSORS; core++){
for(int i = 0; i < NO_OF_TLSP; i++){ for(int i = 0; i < NO_OF_TLSP; i++){
if (i == skip_index) {
continue;
}
TEST_ASSERT_EQUAL((TLSP_DEL_BASE << i), task_storage[core][i]); //Check del_cb ran by checking task storage for unique value TEST_ASSERT_EQUAL((TLSP_DEL_BASE << i), task_storage[core][i]); //Check del_cb ran by checking task storage for unique value
} }
} }