Merge branch 'bugfix/freertos_smp_disable_interrupt_usage' into 'master'

FreeRTOS: Replace portSET_INTERRUPT_MASK_FROM_ISR() call for SMP

Closes IDF-5062 and IDF-5066

See merge request espressif/esp-idf!18301
This commit is contained in:
Ivan Grokhotkov 2022-06-01 00:18:26 +08:00
commit 0c10b937f5
5 changed files with 55 additions and 1 deletions

View File

@ -62,13 +62,21 @@ esp_err_t esp_apptrace_lock_take(esp_apptrace_lock_t *lock, esp_apptrace_tmo_t *
while (1) {
//Todo: Replace the current locking mechanism and int_state with portTRY_ENTER_CRITICAL() instead.
// do not overwrite lock->int_state before we actually acquired the mux
#if CONFIG_FREERTOS_SMP
unsigned int_state = portDISABLE_INTERRUPTS();
#else
unsigned int_state = portSET_INTERRUPT_MASK_FROM_ISR();
#endif
bool success = spinlock_acquire(&lock->mux, 0);
if (success) {
lock->int_state = int_state;
return ESP_OK;
}
#if CONFIG_FREERTOS_SMP
portRESTORE_INTERRUPTS(int_state);
#else
portCLEAR_INTERRUPT_MASK_FROM_ISR(int_state);
#endif
// we can be preempted from this place till the next call (above) to portSET_INTERRUPT_MASK_FROM_ISR()
res = esp_apptrace_tmo_check(tmo);
if (res != ESP_OK) {
@ -85,7 +93,11 @@ esp_err_t esp_apptrace_lock_give(esp_apptrace_lock_t *lock)
// after call to the following func we can not be sure that lock->int_state
// is not overwritten by other CPU who has acquired the mux just after we released it. See esp_apptrace_lock_take().
spinlock_release(&lock->mux);
#if CONFIG_FREERTOS_SMP
portRESTORE_INTERRUPTS(int_state);
#else
portCLEAR_INTERRUPT_MASK_FROM_ISR(int_state);
#endif
return ESP_OK;
}

View File

@ -789,7 +789,11 @@ void esp_pm_impl_init(void)
void esp_pm_impl_idle_hook(void)
{
int core_id = xPortGetCoreID();
#if CONFIG_FREERTOS_SMP
uint32_t state = portDISABLE_INTERRUPTS();
#else
uint32_t state = portSET_INTERRUPT_MASK_FROM_ISR();
#endif
if (!s_core_idle[core_id]
#ifdef CONFIG_FREERTOS_USE_TICKLESS_IDLE
&& !periph_should_skip_light_sleep()
@ -798,7 +802,11 @@ void esp_pm_impl_idle_hook(void)
esp_pm_lock_release(s_rtos_lock_handle[core_id]);
s_core_idle[core_id] = true;
}
#if CONFIG_FREERTOS_SMP
portRESTORE_INTERRUPTS(state);
#else
portCLEAR_INTERRUPT_MASK_FROM_ISR(state);
#endif
ESP_PM_TRACE_ENTER(IDLE, core_id);
}
@ -809,7 +817,11 @@ void IRAM_ATTR esp_pm_impl_isr_hook(void)
/* Prevent higher level interrupts (than the one this function was called from)
* from happening in this section, since they will also call into esp_pm_impl_isr_hook.
*/
#if CONFIG_FREERTOS_SMP
uint32_t state = portDISABLE_INTERRUPTS();
#else
uint32_t state = portSET_INTERRUPT_MASK_FROM_ISR();
#endif
#if defined(CONFIG_FREERTOS_SYSTICK_USES_CCOUNT) && (portNUM_PROCESSORS == 2)
if (s_need_update_ccompare[core_id]) {
update_ccompare();
@ -820,7 +832,11 @@ void IRAM_ATTR esp_pm_impl_isr_hook(void)
#else
leave_idle();
#endif // CONFIG_FREERTOS_SYSTICK_USES_CCOUNT && portNUM_PROCESSORS == 2
#if CONFIG_FREERTOS_SMP
portRESTORE_INTERRUPTS(state);
#else
portCLEAR_INTERRUPT_MASK_FROM_ISR(state);
#endif
ESP_PM_TRACE_EXIT(ISR_HOOK, core_id);
}

View File

@ -108,7 +108,11 @@ void esp_ipc_isr_waiting_for_finish_cmd(void* finish_cmd);
void IRAM_ATTR esp_ipc_isr_stall_other_cpu(void)
{
if (s_stall_state == STALL_STATE_RUNNING) {
#if CONFIG_FREERTOS_SMP
BaseType_t intLvl = portDISABLE_INTERRUPTS();
#else
BaseType_t intLvl = portSET_INTERRUPT_MASK_FROM_ISR();
#endif
const uint32_t cpu_id = xPortGetCoreID();
if (s_count_of_nested_calls[cpu_id]++ == 0) {
IPC_ISR_ENTER_CRITICAL();
@ -119,7 +123,11 @@ void IRAM_ATTR esp_ipc_isr_stall_other_cpu(void)
}
/* Interrupts are already disabled by the parent, we're nested here. */
#if CONFIG_FREERTOS_SMP
portRESTORE_INTERRUPTS(intLvl);
#else
portCLEAR_INTERRUPT_MASK_FROM_ISR(intLvl);
#endif
}
}
@ -130,7 +138,11 @@ void IRAM_ATTR esp_ipc_isr_release_other_cpu(void)
if (--s_count_of_nested_calls[cpu_id] == 0) {
esp_ipc_isr_finish_cmd = 1;
IPC_ISR_EXIT_CRITICAL();
#if CONFIG_FREERTOS_SMP
portRESTORE_INTERRUPTS(s_stored_interrupt_level);
#else
portCLEAR_INTERRUPT_MASK_FROM_ISR(s_stored_interrupt_level);
#endif
} else if (s_count_of_nested_calls[cpu_id] < 0) {
assert(0);
}

View File

@ -181,7 +181,11 @@ TEST_CASE_MULTIPLE_STAGES("reset reason ESP_RST_SW after restart from APP CPU",
static void do_int_wdt(void)
{
setup_values();
#if CONFIG_FREERTOS_SMP
BaseType_t prev_level = portDISABLE_INTERRUPTS();
#else
BaseType_t prev_level = portSET_INTERRUPT_MASK_FROM_ISR();
#endif
(void) prev_level;
while(1);
}

View File

@ -39,6 +39,16 @@
// Single core SoC: atomics can be implemented using portSET_INTERRUPT_MASK_FROM_ISR
// and portCLEAR_INTERRUPT_MASK_FROM_ISR, which disables and enables interrupts.
#if CONFIG_FREERTOS_SMP
#define _ATOMIC_ENTER_CRITICAL() ({ \
unsigned state = portDISABLE_INTERRUPTS(); \
state; \
})
#define _ATOMIC_EXIT_CRITICAL(state) do { \
portRESTORE_INTERRUPTS(state); \
} while (0)
#else // CONFIG_FREERTOS_SMP
#define _ATOMIC_ENTER_CRITICAL() ({ \
unsigned state = portSET_INTERRUPT_MASK_FROM_ISR(); \
state; \
@ -47,7 +57,7 @@
#define _ATOMIC_EXIT_CRITICAL(state) do { \
portCLEAR_INTERRUPT_MASK_FROM_ISR(state); \
} while (0)
#endif
#else // SOC_CPU_CORES_NUM
_Static_assert(HAS_ATOMICS_32, "32-bit atomics should be supported if SOC_CPU_CORES_NUM > 1");