diff --git a/esphome/components/wifi/wifi_component_esp_idf.cpp b/esphome/components/wifi/wifi_component_esp_idf.cpp index d8b3db9667..cc8af38f75 100644 --- a/esphome/components/wifi/wifi_component_esp_idf.cpp +++ b/esphome/components/wifi/wifi_component_esp_idf.cpp @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -48,7 +49,10 @@ static const char *const TAG = "wifi_esp32"; static EventGroupHandle_t s_wifi_event_group; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) static QueueHandle_t s_event_queue; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) -static esp_netif_t *s_sta_netif = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) +// Fast-path counter to skip xQueueReceive kernel call when queue is empty. +// Incremented from event handler (ISR-safe context), read from main loop. +static std::atomic s_event_count{0}; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) +static esp_netif_t *s_sta_netif = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) #ifdef USE_WIFI_AP static esp_netif_t *s_ap_netif = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) #endif // USE_WIFI_AP @@ -138,6 +142,8 @@ void event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, voi // don't block, we may miss events but the core can handle that if (xQueueSend(s_event_queue, &to_send, 0L) != pdPASS) { delete to_send; // NOLINT(cppcoreguidelines-owning-memory) + } else { + s_event_count.fetch_add(1, std::memory_order_release); } } @@ -724,12 +730,18 @@ const char *get_disconnect_reason_str(uint8_t reason) { } void WiFiComponent::wifi_loop_() { + // Fast path: skip xQueueReceive kernel call when no events are pending. + // The atomic load is much cheaper than entering the FreeRTOS kernel. + if (s_event_count.load(std::memory_order_acquire) == 0) + return; + while (true) { IDFWiFiEvent *data; if (xQueueReceive(s_event_queue, &data, 0L) != pdTRUE) { // no event ready break; } + s_event_count.fetch_sub(1, std::memory_order_relaxed); // process event wifi_process_event_(data);