mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 11:10:54 +03:00
fix(freertos): Avoid core switch deadlock on start
With CONFIG_ESP_MAIN_TASK_AFFINITY_NO_AFFINITY=y the main task could switch core between registering the idle hook and the while loop. This would cause a deadlock were the current task was waiting for the idle hook to run on the same core it's busy waiting. Merge https://github.com/espressif/esp-idf/pull/16149
This commit is contained in:
committed by
Konstantin Kondrashov
parent
1ece98b42d
commit
dc5ae69a23
@@ -111,7 +111,7 @@ void esp_startup_start_app_other_cores(void)
|
||||
}
|
||||
|
||||
// Wait for CPU0 to start FreeRTOS before progressing
|
||||
extern volatile unsigned port_xSchedulerRunning[portNUM_PROCESSORS];
|
||||
extern volatile unsigned port_xSchedulerRunning[CONFIG_FREERTOS_NUMBER_OF_CORES];
|
||||
while (port_xSchedulerRunning[0] == 0) {
|
||||
;
|
||||
}
|
||||
@@ -146,27 +146,27 @@ void esp_startup_start_app_other_cores(void)
|
||||
|
||||
static const char* MAIN_TAG = "main_task";
|
||||
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
static volatile bool s_other_cpu_startup_done = false;
|
||||
static bool other_cpu_startup_idle_hook_cb(void)
|
||||
/* This function has to guarantee that all CPUs have finished the FreeRTOS initialization
|
||||
* and the startup stack is not in use.
|
||||
*/
|
||||
static void wait_for_all_cores_ready(void)
|
||||
{
|
||||
s_other_cpu_startup_done = true;
|
||||
return true;
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
extern volatile unsigned port_uxCoreStartupDone[CONFIG_FREERTOS_NUMBER_OF_CORES];
|
||||
bool all_cpus_has_been_started;
|
||||
do {
|
||||
all_cpus_has_been_started = true;
|
||||
for (int cpu = 0; cpu < CONFIG_FREERTOS_NUMBER_OF_CORES; cpu++) {
|
||||
all_cpus_has_been_started &= port_uxCoreStartupDone[cpu] != 0;
|
||||
}
|
||||
} while (!all_cpus_has_been_started);
|
||||
#endif // !CONFIG_FREERTOS_UNICORE
|
||||
}
|
||||
#endif
|
||||
|
||||
static void main_task(void* args)
|
||||
// Reinitialize the startup stack heaps, so it can be used for heap allocation.
|
||||
static void reclaim_startup_stack_memory_for_heap(void)
|
||||
{
|
||||
ESP_LOGI(MAIN_TAG, "Started on CPU%d", (int)xPortGetCoreID());
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
// Wait for FreeRTOS initialization to finish on other core, before replacing its startup stack
|
||||
esp_register_freertos_idle_hook_for_cpu(other_cpu_startup_idle_hook_cb, !xPortGetCoreID());
|
||||
while (!s_other_cpu_startup_done) {
|
||||
;
|
||||
}
|
||||
esp_deregister_freertos_idle_hook_for_cpu(other_cpu_startup_idle_hook_cb, !xPortGetCoreID());
|
||||
#endif
|
||||
|
||||
wait_for_all_cores_ready();
|
||||
// [refactor-todo] check if there is a way to move the following block to esp_system startup
|
||||
heap_caps_enable_nonos_stack_heaps();
|
||||
|
||||
@@ -180,6 +180,13 @@ static void main_task(void* args)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void main_task(void* args)
|
||||
{
|
||||
ESP_LOGI(MAIN_TAG, "Started on CPU%d", (int)xPortGetCoreID());
|
||||
|
||||
reclaim_startup_stack_memory_for_heap();
|
||||
|
||||
// Initialize TWDT if configured to do so
|
||||
#if CONFIG_ESP_TASK_WDT_INIT
|
||||
|
||||
Reference in New Issue
Block a user