Преглед на файлове

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
Darian Leung преди 2 години
родител
ревизия
39cf3638ae

+ 0 - 3
components/freertos/CMakeLists.txt

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

+ 14 - 3
components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/include/freertos/portmacro.h

@@ -143,9 +143,19 @@ void vPortYieldFromISR(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 ----------------------------------------------
  * - Contains all the mappings of the macros required by FreeRTOS
@@ -218,7 +228,8 @@ extern void vTaskExitCritical( void );
 
 // --------------------- TCB Cleanup -----------------------
 
-#define portCLEAN_UP_TCB( pxTCB )                   vPortCleanUpTCB( pxTCB )
+#define portCLEAN_UP_TCB( pxTCB )                   vPortTCBPreDeleteHook( pxTCB )
+
 
 /* --------------------------------------------- Inline Implementations ------------------------------------------------
  * - Implementation of inline functions of the forward declares

+ 57 - 53
components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/port.c

@@ -208,6 +208,63 @@ void vPortYieldFromISR( void )
     uxSchedulerRunning = 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 --------------------------------------------------
  * - Provides implementation for functions required by FreeRTOS
@@ -423,36 +480,6 @@ StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxC
     //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 ----------------------
 
 void __attribute__((weak)) vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName)
@@ -496,26 +523,3 @@ void vApplicationMinimalIdleHook( void )
     esp_vApplicationIdleHook(); //Run IDF style hooks
 }
 #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 */
-}

+ 15 - 4
components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/portmacro.h

@@ -127,9 +127,20 @@ static inline void __attribute__((always_inline)) vPortYieldFromISR( 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 --------------------------------------------
  * - 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();})
 #endif
 
-// ------------------- TCB Cleanup ----------------------
+// --------------------- TCB Cleanup -----------------------
 
-#define portCLEAN_UP_TCB( pxTCB )                   vPortCleanUpTCB( pxTCB )
+#define portCLEAN_UP_TCB( pxTCB )                   vPortTCBPreDeleteHook( pxTCB )
 
 /* --------------------------------------------- Inline Implementations ------------------------------------------------
  * - Implementation of inline functions of the forward declares

+ 92 - 91
components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/port.c

@@ -42,6 +42,14 @@
 
 _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 ------------------------------------------------------
  * - 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
@@ -209,6 +217,90 @@ void vPortReleaseLock( portMUX_TYPE *lock )
 
 // ----------------------- 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 --------------------------------------------------
  * - Provides implementation for functions required by FreeRTOS
  * - Declared in portable.h
@@ -269,14 +361,6 @@ static void vPortTaskWrapper(TaskFunction_t pxCode, void *pvParameters)
 }
 #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
 /**
  * @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 (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 ----------------------
 
@@ -655,31 +684,3 @@ void vApplicationMinimalIdleHook( void )
     esp_vApplicationIdleHook(); //Run IDF style hooks
 }
 #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 )
-}

+ 13 - 5
components/freertos/FreeRTOS-Kernel/portable/riscv/include/freertos/portmacro.h

@@ -427,7 +427,19 @@ FORCE_INLINE_ATTR BaseType_t xPortGetCoreID(void)
     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 ----------------------------------------------
  * - Contains all the mappings of the macros required by FreeRTOS
@@ -561,11 +573,7 @@ FORCE_INLINE_ATTR BaseType_t xPortGetCoreID(void)
 
 // --------------------- TCB Cleanup -----------------------
 
-#if CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP
-/* 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 */
+#define portCLEAN_UP_TCB( pxTCB ) vPortTCBPreDeleteHook( pxTCB )
 
 // -------------- Optimized Task Selection -----------------
 

+ 19 - 0
components/freertos/FreeRTOS-Kernel/portable/riscv/port.c

@@ -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);
 }
 
+// --------------------- 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 -------------------------------------------------
  *

+ 15 - 6
components/freertos/FreeRTOS-Kernel/portable/xtensa/include/freertos/portmacro.h

@@ -4,7 +4,7 @@
  *
  * 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
@@ -406,6 +406,19 @@ void vPortSetStackWatchpoint( void *pxStackStart );
  */
 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 ----------------------------------------------
@@ -525,11 +538,7 @@ extern void _frxt_setup_switch( void );     //Defined in portasm.S
 
 // --------------------- TCB Cleanup -----------------------
 
-#if CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP
-/* 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 */
+#define portCLEAN_UP_TCB( pxTCB ) vPortTCBPreDeleteHook( pxTCB )
 
 // -------------- Optimized Task Selection -----------------
 

+ 22 - 1
components/freertos/FreeRTOS-Kernel/portable/xtensa/port.c

@@ -4,7 +4,7 @@
  *
  * 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
@@ -605,6 +605,27 @@ void vPortSetStackWatchpoint( void *pxStackStart )
     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 -----------------------
 
 #if XCHAL_CP_NUM > 0

+ 19 - 1
components/freertos/Kconfig

@@ -324,10 +324,28 @@ menu "FreeRTOS"
                 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.
 
+        config FREERTOS_TASK_PRE_DELETION_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
+            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
-            bool "Enable static task clean up hook"
+            # 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.
 
                 Note: Users will need to provide a ``void vPortCleanUpTCB ( void *pxTCB )`` callback

+ 2 - 2
components/freertos/linker_smp.lf

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

+ 4 - 4
components/freertos/test_apps/freertos/kernel/tasks/test_freertos_hooks.c

@@ -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
  */
@@ -65,7 +65,7 @@ TEST_CASE("FreeRTOS tick hook", "[freertos]")
 #endif // configUSE_TICK_HOOK
 #endif // CONFIG_FREERTOS_SMP
 
-#if CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP
+#if CONFIG_FREERTOS_TASK_PRE_DELETION_HOOK
 
 static volatile void *deleted_tcb;
 
@@ -74,7 +74,7 @@ static void taskDeletesItself(void *ignored)
     vTaskDelete(NULL);
 }
 
-void vPortCleanUpTCB(void *pxTCB)
+void vTaskPreDeletionHook(void *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

+ 1 - 21
components/freertos/test_apps/freertos/port/test_tlsp_del_cb.c

@@ -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
  */
@@ -105,15 +105,6 @@ TEST_CASE("Test TLSP deletion callbacks", "[freertos]")
 //The variables pointed to by Thread Local Storage Pointer
 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)
 {
     *((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();
     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
         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++){
-        if (i == skip_index) {
-            continue;
-        }
-
         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
     }
@@ -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 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
         }
     }

+ 1 - 1
components/freertos/test_apps/freertos/sdkconfig.ci.freertos_options

@@ -7,7 +7,7 @@ CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL=y
 CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=y
 CONFIG_FREERTOS_INTERRUPT_BACKTRACE=n
 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_USE_TRACE_FACILITY=y
 CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS=y

+ 0 - 20
tools/test_apps/linux_compatible/linux_freertos/components/kernel_tests/port/test_tlsp_del_cb.c

@@ -103,15 +103,6 @@ TEST_CASE("Test TLSP deletion callbacks", "[freertos]")
 //The variables pointed to by Thread Local Storage Pointer
 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)
 {
     *((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();
     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
         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++){
-        if (i == skip_index) {
-            continue;
-        }
-
         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
     }
@@ -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 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
         }
     }