Merge pull request #4619 from bugadani/perf

[backport] Fix executor perf on ESP32 MCUs
This commit is contained in:
Dario Nieuwenhuis 2025-08-31 22:13:26 +02:00 committed by GitHub
commit 89684d31ff
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 36 additions and 12 deletions

View File

@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
<!-- next-header --> <!-- next-header -->
## Unreleased - ReleaseDate ## Unreleased - ReleaseDate
- Fixed performance regression on some ESP32 MCUs.
## 0.9.0 - 2025-08-26 ## 0.9.0 - 2025-08-26
- Added `extern "Rust" fn __embassy_time_queue_item_from_waker` - Added `extern "Rust" fn __embassy_time_queue_item_from_waker`

View File

@ -12,8 +12,14 @@
mod run_queue; mod run_queue;
#[cfg_attr(all(cortex_m, target_has_atomic = "32"), path = "state_atomics_arm.rs")] #[cfg_attr(all(cortex_m, target_has_atomic = "32"), path = "state_atomics_arm.rs")]
#[cfg_attr(all(not(cortex_m), target_has_atomic = "8"), path = "state_atomics.rs")] #[cfg_attr(
#[cfg_attr(not(target_has_atomic = "8"), path = "state_critical_section.rs")] all(not(cortex_m), any(target_has_atomic = "8", target_has_atomic = "32")),
path = "state_atomics.rs"
)]
#[cfg_attr(
not(any(target_has_atomic = "8", target_has_atomic = "32")),
path = "state_critical_section.rs"
)]
mod state; mod state;
#[cfg(feature = "trace")] #[cfg(feature = "trace")]

View File

@ -1,4 +1,15 @@
use core::sync::atomic::{AtomicU8, Ordering}; // Prefer pointer-width atomic operations, as narrower ones may be slower.
#[cfg(all(target_pointer_width = "32", target_has_atomic = "32"))]
type AtomicState = core::sync::atomic::AtomicU32;
#[cfg(not(all(target_pointer_width = "32", target_has_atomic = "32")))]
type AtomicState = core::sync::atomic::AtomicU8;
#[cfg(all(target_pointer_width = "32", target_has_atomic = "32"))]
type StateBits = u32;
#[cfg(not(all(target_pointer_width = "32", target_has_atomic = "32")))]
type StateBits = u8;
use core::sync::atomic::Ordering;
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub(crate) struct Token(()); pub(crate) struct Token(());
@ -11,18 +22,18 @@ pub(crate) fn locked<R>(f: impl FnOnce(Token) -> R) -> R {
} }
/// Task is spawned (has a future) /// Task is spawned (has a future)
pub(crate) const STATE_SPAWNED: u8 = 1 << 0; pub(crate) const STATE_SPAWNED: StateBits = 1 << 0;
/// Task is in the executor run queue /// Task is in the executor run queue
pub(crate) const STATE_RUN_QUEUED: u8 = 1 << 1; pub(crate) const STATE_RUN_QUEUED: StateBits = 1 << 1;
pub(crate) struct State { pub(crate) struct State {
state: AtomicU8, state: AtomicState,
} }
impl State { impl State {
pub const fn new() -> State { pub const fn new() -> State {
Self { Self {
state: AtomicU8::new(0), state: AtomicState::new(0),
} }
} }

View File

@ -3,13 +3,18 @@ use core::cell::Cell;
pub(crate) use critical_section::{with as locked, CriticalSection as Token}; pub(crate) use critical_section::{with as locked, CriticalSection as Token};
use critical_section::{CriticalSection, Mutex}; use critical_section::{CriticalSection, Mutex};
#[cfg(target_arch = "avr")]
type StateBits = u8;
#[cfg(not(target_arch = "avr"))]
type StateBits = usize;
/// Task is spawned (has a future) /// Task is spawned (has a future)
pub(crate) const STATE_SPAWNED: u8 = 1 << 0; pub(crate) const STATE_SPAWNED: StateBits = 1 << 0;
/// Task is in the executor run queue /// Task is in the executor run queue
pub(crate) const STATE_RUN_QUEUED: u8 = 1 << 1; pub(crate) const STATE_RUN_QUEUED: StateBits = 1 << 1;
pub(crate) struct State { pub(crate) struct State {
state: Mutex<Cell<u8>>, state: Mutex<Cell<StateBits>>,
} }
impl State { impl State {
@ -19,11 +24,11 @@ impl State {
} }
} }
fn update<R>(&self, f: impl FnOnce(&mut u8) -> R) -> R { fn update<R>(&self, f: impl FnOnce(&mut StateBits) -> R) -> R {
critical_section::with(|cs| self.update_with_cs(cs, f)) critical_section::with(|cs| self.update_with_cs(cs, f))
} }
fn update_with_cs<R>(&self, cs: CriticalSection<'_>, f: impl FnOnce(&mut u8) -> R) -> R { fn update_with_cs<R>(&self, cs: CriticalSection<'_>, f: impl FnOnce(&mut StateBits) -> R) -> R {
let s = self.state.borrow(cs); let s = self.state.borrow(cs);
let mut val = s.get(); let mut val = s.get();
let r = f(&mut val); let r = f(&mut val);