feat(freertos): speed up SMP critical section enter and exit

The critical section port already disables interrupts and reads the core id for
the whole section, but spinlock_acquire()/spinlock_release() then disabled
interrupts again to the same level and re-read the core id register.

Add spinlock_acquire_impl()/spinlock_release_impl(), which take a caller-supplied
owner id and skip interrupt management, and reuse them from
spinlock_acquire()/spinlock_release() to avoid duplicated code. The Xtensa and
RISC-V ports now read the core id once and call the impl variants, removing one
core id read and one interrupt mask/restore per critical section enter and exit.

Closes https://github.com/espressif/esp-idf/issues/18908
This commit is contained in:
Sudeep Mohanty
2026-08-04 16:18:03 +02:00
parent cc6cc219f8
commit 9ab3da0da8
5 changed files with 232 additions and 92 deletions

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -25,25 +25,6 @@ extern "C" {
*
* ------------------------------------------------------------------------------------------------------------------ */
FORCE_INLINE_ATTR __attribute__((pure)) uint32_t xt_utils_get_core_id(void)
{
/*
Note: We depend on SOC_CPU_CORES_NUM instead of XCHAL_HAVE_PRID as some single Xtensa targets (such as ESP32-S2) have
the PRID register even though they are single core.
*/
#if SOC_CPU_CORES_NUM > 1
// Read and extract bit 13 of special register PRID
uint32_t id;
asm volatile (
"rsr.prid %0\n"
"extui %0,%0,13,1"
:"=r"(id));
return id;
#else
return 0;
#endif // SOC_CPU_CORES_NUM > 1
}
FORCE_INLINE_ATTR __attribute__((pure)) uint32_t xt_utils_get_raw_core_id(void)
{
#if XCHAL_HAVE_PRID
@@ -58,6 +39,34 @@ FORCE_INLINE_ATTR __attribute__((pure)) uint32_t xt_utils_get_raw_core_id(void)
#endif // XCHAL_HAVE_PRID
}
FORCE_INLINE_ATTR __attribute__((pure)) uint32_t xt_utils_get_core_id_from_raw(uint32_t raw_core_id)
{
/*
Note: We depend on SOC_CPU_CORES_NUM instead of XCHAL_HAVE_PRID as some single Xtensa targets (such as ESP32-S2) have
the PRID register even though they are single core.
*/
#if SOC_CPU_CORES_NUM > 1
// Extract bit 13 of the PRID register value
uint32_t id;
asm volatile (
"extui %0,%1,13,1"
:"=r"(id):"r"(raw_core_id));
return id;
#else
(void)raw_core_id;
return 0;
#endif // SOC_CPU_CORES_NUM > 1
}
FORCE_INLINE_ATTR __attribute__((pure)) uint32_t xt_utils_get_core_id(void)
{
#if SOC_CPU_CORES_NUM > 1
return xt_utils_get_core_id_from_raw(xt_utils_get_raw_core_id());
#else
return 0;
#endif // SOC_CPU_CORES_NUM > 1
}
FORCE_INLINE_ATTR void *xt_utils_get_sp(void)
{
void *sp;