From 1344103086a3bcfffd75d27939cf2f168010cf0b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 24 Jul 2025 01:04:00 -1000 Subject: [PATCH] [core] Revert #9851 and rename ESPHOME_CORES to ESPHOME_THREAD (#9862) --- esphome/components/esp32/__init__.py | 18 ++----------- esphome/components/esp8266/__init__.py | 4 +-- esphome/components/host/__init__.py | 4 +-- esphome/components/libretiny/__init__.py | 4 +-- esphome/components/nrf52/__init__.py | 4 +-- esphome/components/rp2040/__init__.py | 4 +-- esphome/const.py | 10 ++++---- esphome/core/defines.h | 4 +-- esphome/core/scheduler.cpp | 32 ++++++++++++------------ esphome/core/scheduler.h | 18 ++++++------- 10 files changed, 44 insertions(+), 58 deletions(-) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index e24815741a..5dd2288076 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -31,7 +31,7 @@ from esphome.const import ( KEY_TARGET_FRAMEWORK, KEY_TARGET_PLATFORM, PLATFORM_ESP32, - CoreModel, + ThreadModel, __version__, ) from esphome.core import CORE, HexInt, TimePeriod @@ -98,16 +98,6 @@ ARDUINO_ALLOWED_VARIANTS = [ VARIANT_ESP32S3, ] -# Single-core ESP32 variants -SINGLE_CORE_VARIANTS = frozenset( - [ - VARIANT_ESP32S2, - VARIANT_ESP32C3, - VARIANT_ESP32C6, - VARIANT_ESP32H2, - ] -) - def get_cpu_frequencies(*frequencies): return [str(x) + "MHZ" for x in frequencies] @@ -724,11 +714,7 @@ async def to_code(config): cg.add_define("ESPHOME_BOARD", config[CONF_BOARD]) cg.add_build_flag(f"-DUSE_ESP32_VARIANT_{config[CONF_VARIANT]}") cg.add_define("ESPHOME_VARIANT", VARIANT_FRIENDLY[config[CONF_VARIANT]]) - # Set threading model based on core count - if config[CONF_VARIANT] in SINGLE_CORE_VARIANTS: - cg.add_define(CoreModel.SINGLE) - else: - cg.add_define(CoreModel.MULTI_ATOMICS) + cg.add_define(ThreadModel.MULTI_ATOMICS) cg.add_platformio_option("lib_ldf_mode", "off") cg.add_platformio_option("lib_compat_mode", "strict") diff --git a/esphome/components/esp8266/__init__.py b/esphome/components/esp8266/__init__.py index d08d7121b7..0184c25965 100644 --- a/esphome/components/esp8266/__init__.py +++ b/esphome/components/esp8266/__init__.py @@ -15,7 +15,7 @@ from esphome.const import ( KEY_TARGET_FRAMEWORK, KEY_TARGET_PLATFORM, PLATFORM_ESP8266, - CoreModel, + ThreadModel, ) from esphome.core import CORE, coroutine_with_priority from esphome.helpers import copy_file_if_changed @@ -188,7 +188,7 @@ async def to_code(config): cg.set_cpp_standard("gnu++20") cg.add_define("ESPHOME_BOARD", config[CONF_BOARD]) cg.add_define("ESPHOME_VARIANT", "ESP8266") - cg.add_define(CoreModel.SINGLE) + cg.add_define(ThreadModel.SINGLE) cg.add_platformio_option("extra_scripts", ["post:post_build.py"]) diff --git a/esphome/components/host/__init__.py b/esphome/components/host/__init__.py index 2d77f2f7ab..ba05e497c8 100644 --- a/esphome/components/host/__init__.py +++ b/esphome/components/host/__init__.py @@ -7,7 +7,7 @@ from esphome.const import ( KEY_TARGET_FRAMEWORK, KEY_TARGET_PLATFORM, PLATFORM_HOST, - CoreModel, + ThreadModel, ) from esphome.core import CORE @@ -44,7 +44,7 @@ async def to_code(config): cg.add_define("USE_ESPHOME_HOST_MAC_ADDRESS", config[CONF_MAC_ADDRESS].parts) cg.add_build_flag("-std=gnu++20") cg.add_define("ESPHOME_BOARD", "host") - cg.add_define(CoreModel.MULTI_ATOMICS) + cg.add_define(ThreadModel.MULTI_ATOMICS) cg.add_platformio_option("platform", "platformio/native") cg.add_platformio_option("lib_ldf_mode", "off") cg.add_platformio_option("lib_compat_mode", "strict") diff --git a/esphome/components/libretiny/__init__.py b/esphome/components/libretiny/__init__.py index 7f2a0bc0a5..178660cb40 100644 --- a/esphome/components/libretiny/__init__.py +++ b/esphome/components/libretiny/__init__.py @@ -20,7 +20,7 @@ from esphome.const import ( KEY_FRAMEWORK_VERSION, KEY_TARGET_FRAMEWORK, KEY_TARGET_PLATFORM, - CoreModel, + ThreadModel, __version__, ) from esphome.core import CORE @@ -261,7 +261,7 @@ async def component_to_code(config): cg.add_build_flag(f"-DUSE_LIBRETINY_VARIANT_{config[CONF_FAMILY]}") cg.add_define("ESPHOME_BOARD", config[CONF_BOARD]) cg.add_define("ESPHOME_VARIANT", FAMILY_FRIENDLY[config[CONF_FAMILY]]) - cg.add_define(CoreModel.MULTI_NO_ATOMICS) + cg.add_define(ThreadModel.MULTI_NO_ATOMICS) # force using arduino framework cg.add_platformio_option("framework", "arduino") diff --git a/esphome/components/nrf52/__init__.py b/esphome/components/nrf52/__init__.py index 870c51066c..17807b9e2b 100644 --- a/esphome/components/nrf52/__init__.py +++ b/esphome/components/nrf52/__init__.py @@ -23,7 +23,7 @@ from esphome.const import ( KEY_TARGET_FRAMEWORK, KEY_TARGET_PLATFORM, PLATFORM_NRF52, - CoreModel, + ThreadModel, ) from esphome.core import CORE, EsphomeError, coroutine_with_priority from esphome.storage_json import StorageJSON @@ -110,7 +110,7 @@ async def to_code(config: ConfigType) -> None: cg.add_define("ESPHOME_BOARD", config[CONF_BOARD]) cg.add_define("ESPHOME_VARIANT", "NRF52") # nRF52 processors are single-core - cg.add_define(CoreModel.SINGLE) + cg.add_define(ThreadModel.SINGLE) cg.add_platformio_option(CONF_FRAMEWORK, CORE.data[KEY_CORE][KEY_TARGET_FRAMEWORK]) cg.add_platformio_option( "platform", diff --git a/esphome/components/rp2040/__init__.py b/esphome/components/rp2040/__init__.py index 28c3bbd70c..46eabb5325 100644 --- a/esphome/components/rp2040/__init__.py +++ b/esphome/components/rp2040/__init__.py @@ -16,7 +16,7 @@ from esphome.const import ( KEY_TARGET_FRAMEWORK, KEY_TARGET_PLATFORM, PLATFORM_RP2040, - CoreModel, + ThreadModel, ) from esphome.core import CORE, EsphomeError, coroutine_with_priority from esphome.helpers import copy_file_if_changed, mkdir_p, read_file, write_file @@ -172,7 +172,7 @@ async def to_code(config): cg.set_cpp_standard("gnu++20") cg.add_define("ESPHOME_BOARD", config[CONF_BOARD]) cg.add_define("ESPHOME_VARIANT", "RP2040") - cg.add_define(CoreModel.SINGLE) + cg.add_define(ThreadModel.SINGLE) cg.add_platformio_option("extra_scripts", ["post:post_build.py"]) diff --git a/esphome/const.py b/esphome/const.py index 627b6bac18..7d373ff26c 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -35,12 +35,12 @@ class Framework(StrEnum): ZEPHYR = "zephyr" -class CoreModel(StrEnum): - """Core model identifiers for ESPHome scheduler.""" +class ThreadModel(StrEnum): + """Threading model identifiers for ESPHome scheduler.""" - SINGLE = "ESPHOME_CORES_SINGLE" - MULTI_NO_ATOMICS = "ESPHOME_CORES_MULTI_NO_ATOMICS" - MULTI_ATOMICS = "ESPHOME_CORES_MULTI_ATOMICS" + SINGLE = "ESPHOME_THREAD_SINGLE" + MULTI_NO_ATOMICS = "ESPHOME_THREAD_MULTI_NO_ATOMICS" + MULTI_ATOMICS = "ESPHOME_THREAD_MULTI_ATOMICS" class PlatformFramework(Enum): diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 9355d56084..348f288863 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -15,8 +15,8 @@ #define ESPHOME_VARIANT "ESP32" #define ESPHOME_DEBUG_SCHEDULER -// Default threading model for static analysis (ESP32 is multi-core with atomics) -#define ESPHOME_CORES_MULTI_ATOMICS +// Default threading model for static analysis (ESP32 is multi-threaded with atomics) +#define ESPHOME_THREAD_MULTI_ATOMICS // logger #define ESPHOME_LOG_LEVEL ESPHOME_LOG_LEVEL_VERY_VERBOSE diff --git a/esphome/core/scheduler.cpp b/esphome/core/scheduler.cpp index fc5d43d262..dd80199dc0 100644 --- a/esphome/core/scheduler.cpp +++ b/esphome/core/scheduler.cpp @@ -84,7 +84,7 @@ void HOT Scheduler::set_timer_common_(Component *component, SchedulerItem::Type item->callback = std::move(func); item->remove = false; -#ifndef ESPHOME_CORES_SINGLE +#ifndef ESPHOME_THREAD_SINGLE // Special handling for defer() (delay = 0, type = TIMEOUT) // Single-core platforms don't need thread-safe defer handling if (delay == 0 && type == SchedulerItem::TIMEOUT) { @@ -94,7 +94,7 @@ void HOT Scheduler::set_timer_common_(Component *component, SchedulerItem::Type this->defer_queue_.push_back(std::move(item)); return; } -#endif /* not ESPHOME_CORES_SINGLE */ +#endif /* not ESPHOME_THREAD_SINGLE */ // Get fresh timestamp for new timer/interval - ensures accurate scheduling const auto now = this->millis_64_(millis()); // Fresh millis() call @@ -238,7 +238,7 @@ optional HOT Scheduler::next_schedule_in(uint32_t now) { return item->next_execution_ - now_64; } void HOT Scheduler::call(uint32_t now) { -#ifndef ESPHOME_CORES_SINGLE +#ifndef ESPHOME_THREAD_SINGLE // Process defer queue first to guarantee FIFO execution order for deferred items. // Previously, defer() used the heap which gave undefined order for equal timestamps, // causing race conditions on multi-core systems (ESP32, BK7200). @@ -268,7 +268,7 @@ void HOT Scheduler::call(uint32_t now) { this->execute_item_(item.get(), now); } } -#endif /* not ESPHOME_CORES_SINGLE */ +#endif /* not ESPHOME_THREAD_SINGLE */ // Convert the fresh timestamp from main loop to 64-bit for scheduler operations const auto now_64 = this->millis_64_(now); // 'now' from parameter - fresh from Application::loop() @@ -280,15 +280,15 @@ void HOT Scheduler::call(uint32_t now) { if (now_64 - last_print > 2000) { last_print = now_64; std::vector> old_items; -#ifdef ESPHOME_CORES_MULTI_ATOMICS +#ifdef ESPHOME_THREAD_MULTI_ATOMICS const auto last_dbg = this->last_millis_.load(std::memory_order_relaxed); const auto major_dbg = this->millis_major_.load(std::memory_order_relaxed); ESP_LOGD(TAG, "Items: count=%zu, now=%" PRIu64 " (%" PRIu16 ", %" PRIu32 ")", this->items_.size(), now_64, major_dbg, last_dbg); -#else /* not ESPHOME_CORES_MULTI_ATOMICS */ +#else /* not ESPHOME_THREAD_MULTI_ATOMICS */ ESP_LOGD(TAG, "Items: count=%zu, now=%" PRIu64 " (%" PRIu16 ", %" PRIu32 ")", this->items_.size(), now_64, this->millis_major_, this->last_millis_); -#endif /* else ESPHOME_CORES_MULTI_ATOMICS */ +#endif /* else ESPHOME_THREAD_MULTI_ATOMICS */ // Cleanup before debug output this->cleanup_(); while (!this->items_.empty()) { @@ -473,7 +473,7 @@ bool HOT Scheduler::cancel_item_locked_(Component *component, const char *name_c size_t total_cancelled = 0; // Check all containers for matching items -#ifndef ESPHOME_CORES_SINGLE +#ifndef ESPHOME_THREAD_SINGLE // Only check defer queue for timeouts (intervals never go there) if (type == SchedulerItem::TIMEOUT) { for (auto &item : this->defer_queue_) { @@ -483,7 +483,7 @@ bool HOT Scheduler::cancel_item_locked_(Component *component, const char *name_c } } } -#endif /* not ESPHOME_CORES_SINGLE */ +#endif /* not ESPHOME_THREAD_SINGLE */ // Cancel items in the main heap for (auto &item : this->items_) { @@ -509,9 +509,9 @@ bool HOT Scheduler::cancel_item_locked_(Component *component, const char *name_c uint64_t Scheduler::millis_64_(uint32_t now) { // THREAD SAFETY NOTE: // This function has three implementations, based on the precompiler flags - // - ESPHOME_CORES_SINGLE - Runs on single-core platforms (ESP8266, RP2040, etc.) - // - ESPHOME_CORES_MULTI_NO_ATOMICS - Runs on multi-core platforms without atomics (LibreTiny) - // - ESPHOME_CORES_MULTI_ATOMICS - Runs on multi-core platforms with atomics (ESP32, HOST, etc.) + // - ESPHOME_THREAD_SINGLE - Runs on single-threaded platforms (ESP8266, RP2040, etc.) + // - ESPHOME_THREAD_MULTI_NO_ATOMICS - Runs on multi-threaded platforms without atomics (LibreTiny) + // - ESPHOME_THREAD_MULTI_ATOMICS - Runs on multi-threaded platforms with atomics (ESP32, HOST, etc.) // // Make sure all changes are synchronized if you edit this function. // @@ -520,7 +520,7 @@ uint64_t Scheduler::millis_64_(uint32_t now) { // helps maintain accuracy. // -#ifdef ESPHOME_CORES_SINGLE +#ifdef ESPHOME_THREAD_SINGLE // This is the single core implementation. // // Single-core platforms have no concurrency, so this is a simple implementation @@ -546,7 +546,7 @@ uint64_t Scheduler::millis_64_(uint32_t now) { // Combine major (high 32 bits) and now (low 32 bits) into 64-bit time return now + (static_cast(major) << 32); -#elif defined(ESPHOME_CORES_MULTI_NO_ATOMICS) +#elif defined(ESPHOME_THREAD_MULTI_NO_ATOMICS) // This is the multi core no atomics implementation. // // Without atomics, this implementation uses locks more aggressively: @@ -595,7 +595,7 @@ uint64_t Scheduler::millis_64_(uint32_t now) { // Combine major (high 32 bits) and now (low 32 bits) into 64-bit time return now + (static_cast(major) << 32); -#elif defined(ESPHOME_CORES_MULTI_ATOMICS) +#elif defined(ESPHOME_THREAD_MULTI_ATOMICS) // This is the multi core with atomics implementation. // // Uses atomic operations with acquire/release semantics to ensure coherent @@ -660,7 +660,7 @@ uint64_t Scheduler::millis_64_(uint32_t now) { #else #error \ - "No platform threading model defined. One of ESPHOME_CORES_SINGLE, ESPHOME_CORES_MULTI_NO_ATOMICS, or ESPHOME_CORES_MULTI_ATOMICS must be defined." + "No platform threading model defined. One of ESPHOME_THREAD_SINGLE, ESPHOME_THREAD_MULTI_NO_ATOMICS, or ESPHOME_THREAD_MULTI_ATOMICS must be defined." #endif } diff --git a/esphome/core/scheduler.h b/esphome/core/scheduler.h index c14b7debe4..7bf83f7877 100644 --- a/esphome/core/scheduler.h +++ b/esphome/core/scheduler.h @@ -5,7 +5,7 @@ #include #include #include -#ifdef ESPHOME_CORES_MULTI_ATOMICS +#ifdef ESPHOME_THREAD_MULTI_ATOMICS #include #endif @@ -200,13 +200,13 @@ class Scheduler { Mutex lock_; std::vector> items_; std::vector> to_add_; -#ifndef ESPHOME_CORES_SINGLE +#ifndef ESPHOME_THREAD_SINGLE // Single-core platforms don't need the defer queue and save 40 bytes of RAM std::deque> defer_queue_; // FIFO queue for defer() calls -#endif /* ESPHOME_CORES_SINGLE */ +#endif /* ESPHOME_THREAD_SINGLE */ uint32_t to_remove_{0}; -#ifdef ESPHOME_CORES_MULTI_ATOMICS +#ifdef ESPHOME_THREAD_MULTI_ATOMICS /* * Multi-threaded platforms with atomic support: last_millis_ needs atomic for lock-free updates * @@ -218,10 +218,10 @@ class Scheduler { * it also observes the corresponding increment of `millis_major_`. */ std::atomic last_millis_{0}; -#else /* not ESPHOME_CORES_MULTI_ATOMICS */ +#else /* not ESPHOME_THREAD_MULTI_ATOMICS */ // Platforms without atomic support or single-threaded platforms uint32_t last_millis_{0}; -#endif /* else ESPHOME_CORES_MULTI_ATOMICS */ +#endif /* else ESPHOME_THREAD_MULTI_ATOMICS */ /* * Upper 16 bits of the 64-bit millis counter. Incremented only while holding @@ -229,11 +229,11 @@ class Scheduler { * Ordering relative to `last_millis_` is provided by its release store and the * corresponding acquire loads. */ -#ifdef ESPHOME_CORES_MULTI_ATOMICS +#ifdef ESPHOME_THREAD_MULTI_ATOMICS std::atomic millis_major_{0}; -#else /* not ESPHOME_CORES_MULTI_ATOMICS */ +#else /* not ESPHOME_THREAD_MULTI_ATOMICS */ uint16_t millis_major_{0}; -#endif /* else ESPHOME_CORES_MULTI_ATOMICS */ +#endif /* else ESPHOME_THREAD_MULTI_ATOMICS */ }; } // namespace esphome