From 90f6eeb32785b3701d54fcc3b9f618af76adc00f Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Wed, 3 Jun 2026 17:51:34 +0800 Subject: [PATCH] feat(freertos): introduce thread-safe context management functions --- .../riscv/include/freertos/portmacro.h | 18 +++++++++++ .../FreeRTOS-Kernel-SMP/portable/riscv/port.c | 26 +++++++++++++++- .../xtensa/include/freertos/portmacro.h | 20 ++++++++++++- .../portable/xtensa/port.c | 24 +++++++++++++++ .../freertos/FreeRTOS-Kernel-SMP/tasks.c | 12 +++++++- .../freertos/FreeRTOS-Kernel/idf_changes.md | 4 +++ .../riscv/include/freertos/portmacro.h | 16 ++++++++++ .../FreeRTOS-Kernel/portable/riscv/port.c | 30 +++++++++++++++++++ .../xtensa/include/freertos/portmacro.h | 18 ++++++++++- .../FreeRTOS-Kernel/portable/xtensa/port.c | 23 ++++++++++++++ .../freertos/include/freertos_performance.h | 2 +- docs/en/api-reference/system/freertos_idf.rst | 13 ++++++++ .../api-reference/system/freertos_idf.rst | 13 ++++++++ 13 files changed, 214 insertions(+), 5 deletions(-) diff --git a/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/include/freertos/portmacro.h b/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/include/freertos/portmacro.h index d63062ca520..d0d85db6330 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/include/freertos/portmacro.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/include/freertos/portmacro.h @@ -327,6 +327,24 @@ and vPortExitCritical() from precompiled libraries (.a) thereby failing linking. void vPortEnterCritical(void); void vPortExitCritical(void); +/** + * @brief Claim thread-safe region start + * If claimed, vPortEnterCritical/vPortExitCritical on the current core are no-ops. + * Only can be used in single-core running context with interrupts disabled. + * @note !!! Caller must guarantee thread safety between Claim and Disclaim !!! + */ +void xPortThreadSafeClaim(void); + +/** + * @brief Claim thread-safe region end + * Restores normal port critical behavior + * Only can be used in single-core running context with interrupts disabled. + * @note !!! Caller must guarantee thread safety between Claim and Disclaim !!! + */ +void xPortThreadSafeDisclaim(void); + +extern volatile bool port_xThreadSafeClaimed; + //IDF task critical sections #define portTRY_ENTER_CRITICAL(lock, timeout) ({(void) lock; (void) timeout; vPortEnterCritical(); pdPASS;}) #define portENTER_CRITICAL_IDF(lock) ({(void) lock; vPortEnterCritical();}) diff --git a/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/port.c b/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/port.c index e77a989c3d9..5c37ecd52d3 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/port.c +++ b/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/port.c @@ -1,11 +1,13 @@ /* - * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include "sdkconfig.h" +#include #include +#include "esp_compiler.h" #include "soc/soc_caps.h" #include "soc/periph_defs.h" #include "soc/system_reg.h" @@ -75,6 +77,7 @@ StackType_t *xIsrStackTop = &xIsrStack[0] + (configISR_STACK_SIZE & (~((portPOIN // Variables used for IDF style critical sections. These are orthogonal to FreeRTOS critical sections static UBaseType_t port_uxCriticalNestingIDF = 0; static UBaseType_t port_uxCriticalOldInterruptStateIDF = 0; +volatile bool port_xThreadSafeClaimed = false; /* ------------------------------------------------ IDF Compatibility -------------------------------------------------- * - These need to be defined for IDF to compile @@ -82,8 +85,25 @@ static UBaseType_t port_uxCriticalOldInterruptStateIDF = 0; // ------------------ Critical Sections -------------------- +void xPortThreadSafeClaim(void) +{ + configASSERT(!xPortCanYield()); + configASSERT(!port_xThreadSafeClaimed); + port_xThreadSafeClaimed = true; +} + +void xPortThreadSafeDisclaim(void) +{ + configASSERT(!xPortCanYield()); + configASSERT(port_xThreadSafeClaimed); + port_xThreadSafeClaimed = false; +} + void vPortEnterCritical(void) { + if (unlikely(port_xThreadSafeClaimed)) { + return; + } // Save current interrupt threshold and disable interrupts UBaseType_t old_thresh = ulPortSetInterruptMask(); // Update the IDF critical nesting count @@ -96,6 +116,9 @@ void vPortEnterCritical(void) void vPortExitCritical(void) { + if (unlikely(port_xThreadSafeClaimed)) { + return; + } /* Critical section nesting coung must never be negative */ configASSERT( port_uxCriticalNestingIDF > 0 ); @@ -293,6 +316,7 @@ BaseType_t xPortStartScheduler(void) { uxInterruptNesting = 0; port_uxCriticalNestingIDF = 0; + port_xThreadSafeClaimed = false; uxSchedulerRunning = 0; #if configNUM_CORES > 1 port_uxCoreStartupDone[xPortGetCoreID()] = 0; diff --git a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/portmacro.h b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/portmacro.h index 2c59f7b5737..321f99232cc 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/portmacro.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/include/freertos/portmacro.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -321,6 +321,24 @@ static inline void __attribute__((always_inline)) vPortCPUReleaseMutex(portMUX_T // ------------------ Critical Sections -------------------- +/** + * @brief Claim thread-safe region start + * If claimed, vPortEnterCritical/vPortExitCritical on the current core are no-ops. + * Only can be used in single-core running context with interrupts disabled. + * @note !!! Caller must guarantee thread safety between Claim and Disclaim !!! + */ +void xPortThreadSafeClaim(void); + +/** + * @brief Claim thread-safe region end + * Restores normal port critical behavior + * Only can be used in single-core running context with interrupts disabled. + * @note !!! Caller must guarantee thread safety between Claim and Disclaim !!! + */ +void xPortThreadSafeDisclaim(void); + +extern volatile bool port_xThreadSafeClaimed; + BaseType_t xPortEnterCriticalTimeout(portMUX_TYPE *lock, BaseType_t timeout); static inline void __attribute__((always_inline)) vPortEnterCriticalIDF(portMUX_TYPE *lock) diff --git a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/port.c b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/port.c index d96180c422d..6d3282ae06f 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/port.c +++ b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/port.c @@ -5,8 +5,10 @@ */ #include "sdkconfig.h" +#include #include #include +#include "esp_compiler.h" #include "FreeRTOS.h" #include "task.h" //For vApplicationStackOverflowHook #include "port_systick.h" @@ -102,6 +104,7 @@ Variables used by IDF critical sections only (SMP tracks critical nesting inside */ BaseType_t port_uxCriticalNestingIDF[portNUM_PROCESSORS] = {0}; BaseType_t port_uxCriticalOldInterruptStateIDF[portNUM_PROCESSORS] = {0}; +volatile bool port_xThreadSafeClaimed = false; /* ******************************************************************************* @@ -113,8 +116,25 @@ volatile StackType_t DRAM_ATTR __attribute__((aligned(16))) port_IntStack[portNU /* One flag for each individual CPU. */ volatile uint32_t port_switch_flag[portNUM_PROCESSORS]; +void xPortThreadSafeClaim(void) +{ + configASSERT(!xPortCanYield()); + configASSERT(!port_xThreadSafeClaimed); + port_xThreadSafeClaimed = true; +} + +void xPortThreadSafeDisclaim(void) +{ + configASSERT(!xPortCanYield()); + configASSERT(port_xThreadSafeClaimed); + port_xThreadSafeClaimed = false; +} + BaseType_t xPortEnterCriticalTimeout(portMUX_TYPE *lock, BaseType_t timeout) { + if (unlikely(port_xThreadSafeClaimed)) { + return pdPASS; + } /* Interrupts may already be disabled (if this function is called in nested * manner). However, there's no atomic operation that will allow us to check, * thus we have to disable interrupts again anyways. @@ -143,6 +163,9 @@ BaseType_t xPortEnterCriticalTimeout(portMUX_TYPE *lock, BaseType_t timeout) void vPortExitCriticalIDF(portMUX_TYPE *lock) { + if (unlikely(port_xThreadSafeClaimed)) { + return; + } /* This function may be called in a nested manner. Therefore, we only need * to re-enable interrupts if this is the last call to exit the critical. We * can use the nesting count to determine whether this is the last exit call. @@ -338,6 +361,7 @@ BaseType_t xPortStartScheduler( void ) BaseType_t coreID = xPortGetCoreID(); port_xSchedulerRunning[coreID] = 1; port_uxCoreStartupDone[coreID] = 0; + port_xThreadSafeClaimed = false; #if configNUM_CORES > 1 // Workaround for non-thread safe multi-core OS startup (see IDF-4524) diff --git a/components/freertos/FreeRTOS-Kernel-SMP/tasks.c b/components/freertos/FreeRTOS-Kernel-SMP/tasks.c index 29e1cd988ae..038c5cb4ee7 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/tasks.c +++ b/components/freertos/FreeRTOS-Kernel-SMP/tasks.c @@ -6,7 +6,7 @@ * * SPDX-License-Identifier: MIT * - * SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2023-2026 Espressif Systems (Shanghai) CO LTD * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -6968,6 +6968,11 @@ static void prvResetNextTaskUnblockTime( void ) void vTaskEnterCritical( void ) { + if( port_xThreadSafeClaimed ) + { + return; + } + traceENTER_vTaskEnterCritical(); portDISABLE_INTERRUPTS(); @@ -7095,6 +7100,11 @@ static void prvResetNextTaskUnblockTime( void ) void vTaskExitCritical( void ) { + if( port_xThreadSafeClaimed ) + { + return; + } + traceENTER_vTaskExitCritical(); if( xSchedulerRunning != pdFALSE ) diff --git a/components/freertos/FreeRTOS-Kernel/idf_changes.md b/components/freertos/FreeRTOS-Kernel/idf_changes.md index 0a75fa8cf8a..9a974217cb1 100644 --- a/components/freertos/FreeRTOS-Kernel/idf_changes.md +++ b/components/freertos/FreeRTOS-Kernel/idf_changes.md @@ -142,6 +142,10 @@ The following functions were modified to accommodate SMP behavior: - Queues no longer use queue locks (see `queueUSE_LOCKS`) - Queues now just use critical sections and skips queue locking - Queue functions can now execute within a single critical section block +- New `xPortThreadSafeClaim()` / `xPortThreadSafeDisclaim()` + - While claimed, port-layer vPortEnterCritical/vPortExitCritical on the current core are no-ops + - Claim only with interrupts disabled on the current core; one active claim system-wide; must pair with Disclaim + - Documented in `portmacro.h` and `docs/en/api-reference/system/freertos_idf.rst` ## Single Core Differences diff --git a/components/freertos/FreeRTOS-Kernel/portable/riscv/include/freertos/portmacro.h b/components/freertos/FreeRTOS-Kernel/portable/riscv/include/freertos/portmacro.h index 462fd852e6d..94f5231bc8a 100644 --- a/components/freertos/FreeRTOS-Kernel/portable/riscv/include/freertos/portmacro.h +++ b/components/freertos/FreeRTOS-Kernel/portable/riscv/include/freertos/portmacro.h @@ -230,6 +230,22 @@ void vPortEnterCritical(void); */ void vPortExitCritical(void); +/** + * @brief Claim thread-safe region start + * If claimed, vPortEnterCritical/vPortExitCritical on the current core are no-ops. + * Only can be used in single-core running context with interrupts disabled. + * @note !!! Caller must guarantee thread safety between Claim and Disclaim !!! + */ +void xPortThreadSafeClaim(void); + +/** + * @brief Claim thread-safe region end + * Restores normal port critical behavior + * Only can be used in single-core running context with interrupts disabled. + * @note !!! Caller must guarantee thread safety between Claim and Disclaim !!! + */ +void xPortThreadSafeDisclaim(void); + #if (configNUM_CORES > 1) /** * @brief Enter an SMP critical section with a timeout diff --git a/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c b/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c index 61c02998fb7..cee52c33edc 100644 --- a/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c +++ b/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c @@ -35,6 +35,7 @@ *----------------------------------------------------------------------*/ #include "sdkconfig.h" +#include #include #include "soc/soc_caps.h" #include "soc/periph_defs.h" @@ -48,6 +49,7 @@ #include "esp_private/crosscore_int.h" #include "hal/crosscore_int_ll.h" #include "esp_attr.h" +#include "esp_compiler.h" #include "esp_system.h" #include "esp_intr_alloc.h" #include "esp_log.h" @@ -97,6 +99,7 @@ _Static_assert(offsetof( StaticTask_t, pxDummy8 ) == PORT_OFFSET_PX_END_OF_STACK volatile UBaseType_t port_xSchedulerRunning[portNUM_PROCESSORS] = {0}; // Indicates whether scheduler is running on a per-core basis volatile UBaseType_t port_uxInterruptNesting[portNUM_PROCESSORS] = {0}; // Interrupt nesting level. Increased/decreased in portasm.c volatile UBaseType_t port_uxCriticalNesting[portNUM_PROCESSORS] = {0}; +volatile bool port_xThreadSafeClaimed = false; volatile UBaseType_t port_uxOldInterruptState[portNUM_PROCESSORS] = {0}; volatile UBaseType_t xPortSwitchFlag[portNUM_PROCESSORS] = {0}; volatile UBaseType_t port_uxCoreStartupDone[portNUM_PROCESSORS] = {0}; // Indicates whether the core has completed its startup sequence @@ -156,6 +159,7 @@ BaseType_t xPortStartScheduler(void) BaseType_t coreID = xPortGetCoreID(); port_uxInterruptNesting[coreID] = 0; port_uxCriticalNesting[coreID] = 0; + port_xThreadSafeClaimed = false; port_xSchedulerRunning[coreID] = 0; port_uxCoreStartupDone[coreID] = 0; @@ -525,6 +529,9 @@ void vPortClearInterruptMaskFromISR(UBaseType_t prev_int_level) #if (configNUM_CORES > 1) BaseType_t __attribute__((optimize("-O3"))) xPortEnterCriticalTimeout(portMUX_TYPE *mux, BaseType_t timeout) { + if (unlikely(port_xThreadSafeClaimed)) { + return pdPASS; + } /* Interrupts may already be disabled (if this function is called in nested * manner). However, there's no atomic operation that will allow us to check, * thus we have to disable interrupts again anyways. @@ -552,6 +559,9 @@ BaseType_t __attribute__((optimize("-O3"))) xPortEnterCriticalTimeout(portMUX_TY void __attribute__((optimize("-O3"))) vPortExitCriticalMultiCore(portMUX_TYPE *mux) { + if (unlikely(port_xThreadSafeClaimed)) { + return; + } /* This function may be called in a nested manner. Therefore, we only need * to re-enable interrupts if this is the last call to exit the critical. We * can use the nesting count to determine whether this is the last exit call. @@ -599,12 +609,29 @@ void vPortExitCriticalCompliance(portMUX_TYPE *mux) } #endif /* (configNUM_CORES > 1) */ +void xPortThreadSafeClaim(void) +{ + configASSERT(!xPortCanYield()); + configASSERT(!port_xThreadSafeClaimed); + port_xThreadSafeClaimed = true; +} + +void xPortThreadSafeDisclaim(void) +{ + configASSERT(!xPortCanYield()); + configASSERT(port_xThreadSafeClaimed); + port_xThreadSafeClaimed = false; +} + void vPortEnterCritical(void) { #if (configNUM_CORES > 1) esp_rom_printf("vPortEnterCritical(void) is not supported on multi-core targets. Please use vPortEnterCriticalMultiCore(portMUX_TYPE *mux) instead.\n"); abort(); #endif /* (configNUM_CORES > 1) */ + if (unlikely(port_xThreadSafeClaimed)) { + return; + } BaseType_t state = portSET_INTERRUPT_MASK_FROM_ISR(); port_uxCriticalNesting[0]++; @@ -619,6 +646,9 @@ void vPortExitCritical(void) esp_rom_printf("vPortExitCritical(void) is not supported on multi-core targets. Please use vPortExitCriticalMultiCore(portMUX_TYPE *mux) instead.\n"); abort(); #endif /* (configNUM_CORES > 1) */ + if (unlikely(port_xThreadSafeClaimed)) { + return; + } /* Critical section nesting count must never be negative */ configASSERT( port_uxCriticalNesting[0] > 0 ); diff --git a/components/freertos/FreeRTOS-Kernel/portable/xtensa/include/freertos/portmacro.h b/components/freertos/FreeRTOS-Kernel/portable/xtensa/include/freertos/portmacro.h index 34f387ff25c..9847b325e5a 100644 --- a/components/freertos/FreeRTOS-Kernel/portable/xtensa/include/freertos/portmacro.h +++ b/components/freertos/FreeRTOS-Kernel/portable/xtensa/include/freertos/portmacro.h @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT * - * SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2023-2026 Espressif Systems (Shanghai) CO LTD * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -229,6 +229,22 @@ static inline void __attribute__((always_inline)) vPortEnterCritical(portMUX_TYP */ void vPortExitCritical(portMUX_TYPE *mux); +/** + * @brief Claim thread-safe region start + * If claimed, vPortEnterCritical/vPortExitCritical on the current core are no-ops. + * Only can be used in single-core running context with interrupts disabled. + * @note !!! Caller must guarantee thread safety between Claim and Disclaim !!! + */ +void xPortThreadSafeClaim(void); + +/** + * @brief Claim thread-safe region end + * Restores normal port critical behavior + * Only can be used in single-core running context with interrupts disabled. + * @note !!! Caller must guarantee thread safety between Claim and Disclaim !!! + */ +void xPortThreadSafeDisclaim(void); + /** * @brief FreeRTOS Compliant version of xPortEnterCriticalTimeout() * diff --git a/components/freertos/FreeRTOS-Kernel/portable/xtensa/port.c b/components/freertos/FreeRTOS-Kernel/portable/xtensa/port.c index 558475de231..82ddf41829a 100644 --- a/components/freertos/FreeRTOS-Kernel/portable/xtensa/port.c +++ b/components/freertos/FreeRTOS-Kernel/portable/xtensa/port.c @@ -33,6 +33,7 @@ */ #include "sdkconfig.h" +#include #include #include #include @@ -40,6 +41,7 @@ #include #include "soc/soc_caps.h" #include "esp_attr.h" +#include "esp_compiler.h" #include "esp_private/crosscore_int.h" #include "esp_private/esp_int_wdt.h" #include "esp_system.h" @@ -75,6 +77,7 @@ const DRAM_ATTR uint32_t offset_xCoreID = offsetof(StaticTask_t, xDummyCoreID); volatile unsigned port_xSchedulerRunning[portNUM_PROCESSORS] = {0}; // Indicates whether scheduler is running on a per-core basis unsigned port_interruptNesting[portNUM_PROCESSORS] = {0}; // Interrupt nesting level. Increased/decreased in portasm.c, _frxt_int_enter/_frxt_int_exit BaseType_t port_uxCriticalNesting[portNUM_PROCESSORS] = {0}; +volatile bool port_xThreadSafeClaimed = false; BaseType_t port_uxOldInterruptState[portNUM_PROCESSORS] = {0}; volatile unsigned port_uxCoreStartupDone[portNUM_PROCESSORS] = {0}; // Indicates whether the core has completed its startup sequence @@ -479,8 +482,25 @@ BaseType_t xPortInterruptedFromISRContext(void) // ------------------ Critical Sections -------------------- +void xPortThreadSafeClaim(void) +{ + configASSERT(!xPortCanYield()); + configASSERT(!port_xThreadSafeClaimed); + port_xThreadSafeClaimed = true; +} + +void xPortThreadSafeDisclaim(void) +{ + configASSERT(!xPortCanYield()); + configASSERT(port_xThreadSafeClaimed); + port_xThreadSafeClaimed = false; +} + BaseType_t __attribute__((optimize("-O3"))) xPortEnterCriticalTimeout(portMUX_TYPE *mux, BaseType_t timeout) { + if (unlikely(port_xThreadSafeClaimed)) { + return pdPASS; + } /* Interrupts may already be disabled (if this function is called in nested * manner). However, there's no atomic operation that will allow us to check, * thus we have to disable interrupts again anyways. @@ -508,6 +528,9 @@ BaseType_t __attribute__((optimize("-O3"))) xPortEnterCriticalTimeout(portMUX_TY void __attribute__((optimize("-O3"))) vPortExitCritical(portMUX_TYPE *mux) { + if (unlikely(port_xThreadSafeClaimed)) { + return; + } /* This function may be called in a nested manner. Therefore, we only need * to re-enable interrupts if this is the last call to exit the critical. We * can use the nesting count to determine whether this is the last exit call. diff --git a/components/freertos/test_apps/freertos/include/freertos_performance.h b/components/freertos/test_apps/freertos/include/freertos_performance.h index e133460f382..c281f68a1e2 100644 --- a/components/freertos/test_apps/freertos/include/freertos_performance.h +++ b/components/freertos/test_apps/freertos/include/freertos_performance.h @@ -5,7 +5,7 @@ #pragma once #ifndef IDF_PERFORMANCE_MAX_FREERTOS_SPINLOCK_CYCLES_PER_OP -#define IDF_PERFORMANCE_MAX_FREERTOS_SPINLOCK_CYCLES_PER_OP 215 +#define IDF_PERFORMANCE_MAX_FREERTOS_SPINLOCK_CYCLES_PER_OP 230 #endif #ifndef IDF_PERFORMANCE_MAX_FREERTOS_SPINLOCK_CYCLES_PER_OP_PSRAM #define IDF_PERFORMANCE_MAX_FREERTOS_SPINLOCK_CYCLES_PER_OP_PSRAM 300 diff --git a/docs/en/api-reference/system/freertos_idf.rst b/docs/en/api-reference/system/freertos_idf.rst index f28f8b4f268..10107efa6d9 100644 --- a/docs/en/api-reference/system/freertos_idf.rst +++ b/docs/en/api-reference/system/freertos_idf.rst @@ -382,6 +382,19 @@ In IDF FreeRTOS, the process of a particular core entering and exiting a critica #. The core releases the spinlock by clearing the spinlock's owner value. #. The core re-enables interrupts or interrupt nesting. +Thread-Safe Port Critical Bypass +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``xPortThreadSafeClaim()`` and ``xPortThreadSafeDisclaim()`` (``portmacro.h``) skip port-layer critical enter/exit on the current core. **Thread safety between Claim and Disclaim must be guaranteed by the caller.** + +.. warning:: + + - Caller guarantees thread safety for the Claim–Disclaim window (all cores). + - Claim only with interrupts disabled on the current core; one active claim system-wide; pair with Disclaim on every path. + - ``pdPASS`` from ``xPortEnterCriticalTimeout()`` does not mean ``mux`` was taken. + +Not a substitute for ``taskENTER_CRITICAL(&spinlock)``. + Restrictions and Considerations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/zh_CN/api-reference/system/freertos_idf.rst b/docs/zh_CN/api-reference/system/freertos_idf.rst index 4b0a3e539f0..4ce7c8bfd76 100644 --- a/docs/zh_CN/api-reference/system/freertos_idf.rst +++ b/docs/zh_CN/api-reference/system/freertos_idf.rst @@ -382,6 +382,19 @@ IDF FreeRTOS 中,特定核进入和退出临界区的过程如下: #. 核通过清除自旋锁的所有者值释放自旋锁。 #. 核重新启用中断或中断嵌套。 +线程安全 Port 临界区旁路 +^^^^^^^^^^^^^^^^^^^^^^^^ + +``xPortThreadSafeClaim()`` 与 ``xPortThreadSafeDisclaim()`` (``portmacro.h``) 使当前核上 port 层临界区进入/退出变为 no-op。**Claim 与 Disclaim 之间的线程安全须由调用方保证。** + +.. warning:: + + - 调用方保证 Claim–Disclaim 窗口内的线程安全(含多核)。 + - 仅在当前核已关中断时 Claim;全局至多一个 Claim;所有路径须与 Disclaim 成对。 + - ``xPortEnterCriticalTimeout()`` 返回 ``pdPASS`` 不表示已获取 ``mux``。 + +不能替代 ``taskENTER_CRITICAL(&spinlock)``。 + 限制与注意事项 ^^^^^^^^^^^^^^