[esp32_ble] Skip dropped count check when queue is empty

On Xtensa (dual-core ESP32), even relaxed atomic loads emit a memw
barrier instruction. The dropped_count_ check in get_and_reset_dropped_count()
was executing every loop() iteration even when the queue was empty.

Since drops only occur when the queue is full, and only the main loop
drains the queue, an empty queue guarantees no new drops since the last
reset. Restructure the loop to early-return when pop() returns nullptr,
skipping the unnecessary memw.

Also moves advertising_->loop() before the queue drain so it runs
unconditionally without duplication, and converts while to do/while
since the first element is known non-null after the nullptr check.
This commit is contained in:
J. Nick Koston
2026-04-03 10:21:20 -10:00
parent f8f65c1a7b
commit d341ee8c76
+14 -9
View File
@@ -399,8 +399,17 @@ void ESP32BLE::loop() {
return;
}
#ifdef USE_ESP32_BLE_ADVERTISING
if (this->advertising_ != nullptr) {
this->advertising_->loop();
}
#endif
BLEEvent *ble_event = this->ble_events_.pop();
while (ble_event != nullptr) {
if (ble_event == nullptr)
return;
do {
switch (ble_event->type_) {
#if defined(USE_ESP32_BLE_SERVER) && defined(ESPHOME_ESP32_BLE_GATTS_EVENT_HANDLER_COUNT)
case BLEEvent::GATTS: {
@@ -488,15 +497,11 @@ void ESP32BLE::loop() {
}
// Return the event to the pool
this->ble_event_pool_.release(ble_event);
ble_event = this->ble_events_.pop();
}
#ifdef USE_ESP32_BLE_ADVERTISING
if (this->advertising_ != nullptr) {
this->advertising_->loop();
}
#endif
} while ((ble_event = this->ble_events_.pop()) != nullptr);
// Log dropped events periodically
// Log dropped events - only reachable when events were processed.
// Drops only occur when the queue is full, and only this loop drains it,
// so if pop() returned nullptr above we can skip this check (saves a memw).
uint16_t dropped = this->ble_events_.get_and_reset_dropped_count();
if (dropped > 0) {
ESP_LOGW(TAG, "Dropped %u BLE events due to buffer overflow", dropped);