Fix remaining direct atomic reads under lock

Replace two more direct item->remove accesses (implicit seq_cst) with
is_item_removed_locked_() in call() and cleanup_(), both under lock.
This commit is contained in:
J. Nick Koston
2026-02-19 23:20:28 -06:00
parent 25b979bbed
commit 7568b64a4a
2 changed files with 8 additions and 4 deletions

View File

@@ -545,7 +545,7 @@ void HOT Scheduler::call(uint32_t now) {
// during the function call and know if we were cancelled.
auto executed_item = this->pop_raw_locked_();
if (executed_item->remove) {
if (this->is_item_removed_locked_(executed_item.get())) {
// We were removed/cancelled in the function call, recycle and continue
this->to_remove_--;
this->recycle_item_main_loop_(std::move(executed_item));
@@ -605,7 +605,7 @@ size_t HOT Scheduler::cleanup_() {
LockGuard guard{this->lock_};
while (!this->items_.empty()) {
auto &item = this->items_[0];
if (!item->remove)
if (!this->is_item_removed_locked_(item.get()))
break;
this->to_remove_--;
this->recycle_item_main_loop_(this->pop_raw_locked_());

View File

@@ -470,8 +470,12 @@ class Scheduler {
// IMPORTANT: Caller must hold the scheduler lock before calling this function.
bool is_item_removed_locked_(SchedulerItem *item) const {
#ifdef ESPHOME_THREAD_MULTI_ATOMICS
// Lock already held - relaxed is sufficient, mutex provides ordering
return item->remove.load(std::memory_order_relaxed);
// Lock already held - relaxed is sufficient, mutex provides ordering.
// Use GCC __atomic_load_n builtin instead of std::atomic::load() because
// GCC for Xtensa emits std::atomic<bool>::load() as an out-of-line
// libstdc++ call, adding function call overhead that exceeds the memw
// barrier savings this optimization aims to eliminate.
return __atomic_load_n(reinterpret_cast<const bool *>(&item->remove), __ATOMIC_RELAXED);
#else
return item->remove;
#endif