mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-01 02:30:52 +03:00
fix(esp_timer): process ISR-dispatch timers in alarm thread on Linux
On real hardware, ESP_TIMER_ISR callbacks run in a hardware interrupt that preempts any FreeRTOS task. On the Linux simulator, there are no real ISRs — the alarm is detected by a native pthread but was only forwarded to the FreeRTOS timer_task via xTaskNotifyGive(). This meant ISR-dispatch callbacks could be starved by higher-priority FreeRTOS tasks, breaking components like the task watchdog that rely on ISR-dispatch timers to detect scheduling starvation. Move ISR-dispatch timer processing into the alarm pthread itself, mirroring the hardware ISR path. The FreeRTOS timer_task is only notified when no ISR-dispatch timer consumed the alarm. This is safe because the Linux FreeRTOS port already handles vPortEnterCritical() calls from non-FreeRTOS threads (bumps nesting counter without blocking on scheduled-task checks).
This commit is contained in:
@@ -551,12 +551,6 @@ static void timer_task(void* arg)
|
||||
while (true) {
|
||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||
// all deferred events are processed at a time
|
||||
#if CONFIG_ESP_TIMER_IMPL_LINUX && CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD
|
||||
esp_timer_impl_try_to_set_next_alarm();
|
||||
if (timer_process_alarm(ESP_TIMER_ISR)) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
timer_process_alarm(ESP_TIMER_TASK);
|
||||
}
|
||||
}
|
||||
@@ -571,7 +565,6 @@ ESP_TIMER_IRAM_ATTR void esp_timer_isr_dispatch_need_yield(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_ESP_TIMER_IMPL_LINUX
|
||||
static void ESP_TIMER_IRAM_ATTR timer_alarm_handler(void* arg)
|
||||
{
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
@@ -589,10 +582,9 @@ static void ESP_TIMER_IRAM_ATTR timer_alarm_handler(void* arg)
|
||||
vTaskNotifyGiveFromISR(s_timer_task, &xHigherPriorityTaskWoken);
|
||||
}
|
||||
if (xHigherPriorityTaskWoken == pdTRUE) {
|
||||
portYIELD_FROM_ISR();
|
||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
||||
}
|
||||
}
|
||||
#endif // !CONFIG_ESP_TIMER_IMPL_LINUX
|
||||
|
||||
static ESP_TIMER_IRAM_ATTR inline bool is_initialized(void)
|
||||
{
|
||||
@@ -646,11 +638,7 @@ esp_err_t esp_timer_init(void)
|
||||
}
|
||||
#endif // CONFIG_ESP_TIMER_ISR_AFFINITY_NO_AFFINITY
|
||||
if (err == ESP_OK) {
|
||||
#ifndef CONFIG_ESP_TIMER_IMPL_LINUX
|
||||
err = esp_timer_impl_init(&timer_alarm_handler);
|
||||
#else
|
||||
err = esp_timer_impl_init(NULL);
|
||||
#endif
|
||||
if (err != ESP_OK) {
|
||||
ESP_EARLY_LOGE(TAG, "ISR init failed");
|
||||
deinit_timer_task();
|
||||
|
||||
Reference in New Issue
Block a user