From 658a52fb99e47d3d2f08ebf66335774930ad35ac Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 8 Jul 2025 23:29:31 +0200 Subject: executor: do not store task IDs in RAM, we can get it from the pointer every time. --- embassy-executor/src/raw/mod.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'embassy-executor/src/raw/mod.rs') diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index 4b17d4982..bcd4ee432 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs @@ -97,8 +97,6 @@ pub(crate) struct TaskHeader { #[cfg(feature = "trace")] pub(crate) name: Option<&'static str>, #[cfg(feature = "trace")] - pub(crate) id: u32, - #[cfg(feature = "trace")] all_tasks_next: AtomicPtr, } @@ -148,6 +146,12 @@ impl TaskRef { pub(crate) fn as_ptr(self) -> *const TaskHeader { self.ptr.as_ptr() } + + /// Returns the task ID. + /// This can be used in combination with rtos-trace to match task names with IDs + pub fn id(&self) -> u32 { + self.as_ptr() as u32 + } } /// Raw storage in which a task can be spawned. @@ -192,8 +196,6 @@ impl TaskStorage { #[cfg(feature = "trace")] name: None, #[cfg(feature = "trace")] - id: 0, - #[cfg(feature = "trace")] all_tasks_next: AtomicPtr::new(core::ptr::null_mut()), }, future: UninitCell::uninit(), -- cgit From 2ba34ce2178d576f339f0b0dac70ac125f81cc5b Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 8 Jul 2025 23:36:51 +0200 Subject: executor: allow trace and rtos-trace to coexist additively. Before, enabling `trace` would enable embassy-native tracing, and enabling *both* would *disable* embassy-native tracing. --- embassy-executor/src/raw/mod.rs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'embassy-executor/src/raw/mod.rs') diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index bcd4ee432..87328df5a 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs @@ -16,7 +16,7 @@ mod run_queue; #[cfg_attr(not(target_has_atomic = "8"), path = "state_critical_section.rs")] mod state; -#[cfg(feature = "trace")] +#[cfg(feature = "_any_trace")] pub mod trace; pub(crate) mod util; #[cfg_attr(feature = "turbowakers", path = "waker_turbo.rs")] @@ -94,9 +94,9 @@ pub(crate) struct TaskHeader { /// Integrated timer queue storage. This field should not be accessed outside of the timer queue. pub(crate) timer_queue_item: TimerQueueItem, - #[cfg(feature = "trace")] + #[cfg(feature = "_any_trace")] pub(crate) name: Option<&'static str>, - #[cfg(feature = "trace")] + #[cfg(feature = "rtos-trace")] all_tasks_next: AtomicPtr, } @@ -193,9 +193,9 @@ impl TaskStorage { poll_fn: SyncUnsafeCell::new(None), timer_queue_item: TimerQueueItem::new(), - #[cfg(feature = "trace")] + #[cfg(feature = "_any_trace")] name: None, - #[cfg(feature = "trace")] + #[cfg(feature = "rtos-trace")] all_tasks_next: AtomicPtr::new(core::ptr::null_mut()), }, future: UninitCell::uninit(), @@ -231,7 +231,7 @@ impl TaskStorage { let mut cx = Context::from_waker(&waker); match future.poll(&mut cx) { Poll::Ready(_) => { - #[cfg(feature = "trace")] + #[cfg(feature = "_any_trace")] let exec_ptr: *const SyncExecutor = this.raw.executor.load(Ordering::Relaxed); // As the future has finished and this function will not be called @@ -246,7 +246,7 @@ impl TaskStorage { // after we're done with it. this.raw.state.despawn(); - #[cfg(feature = "trace")] + #[cfg(feature = "_any_trace")] trace::task_end(exec_ptr, &p); } Poll::Pending => {} @@ -419,7 +419,7 @@ impl SyncExecutor { /// - `task` must NOT be already enqueued (in this executor or another one). #[inline(always)] unsafe fn enqueue(&self, task: TaskRef, l: state::Token) { - #[cfg(feature = "trace")] + #[cfg(feature = "_any_trace")] trace::task_ready_begin(self, &task); if self.run_queue.enqueue(task, l) { @@ -432,7 +432,7 @@ impl SyncExecutor { .executor .store((self as *const Self).cast_mut(), Ordering::Relaxed); - #[cfg(feature = "trace")] + #[cfg(feature = "_any_trace")] trace::task_new(self, &task); state::locked(|l| { @@ -444,23 +444,23 @@ impl SyncExecutor { /// /// Same as [`Executor::poll`], plus you must only call this on the thread this executor was created. pub(crate) unsafe fn poll(&'static self) { - #[cfg(feature = "trace")] + #[cfg(feature = "_any_trace")] trace::poll_start(self); self.run_queue.dequeue_all(|p| { let task = p.header(); - #[cfg(feature = "trace")] + #[cfg(feature = "_any_trace")] trace::task_exec_begin(self, &p); // Run the task task.poll_fn.get().unwrap_unchecked()(p); - #[cfg(feature = "trace")] + #[cfg(feature = "_any_trace")] trace::task_exec_end(self, &p); }); - #[cfg(feature = "trace")] + #[cfg(feature = "_any_trace")] trace::executor_idle(self) } } -- cgit From da9cdf0c536ec4fa7bdfb649750c44f70ef1cd55 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 9 Jul 2025 01:18:04 +0200 Subject: executor: add "task metadata" concept, make name a task metadata. --- embassy-executor/src/raw/mod.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'embassy-executor/src/raw/mod.rs') diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index 87328df5a..a7e65360d 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs @@ -41,6 +41,7 @@ use self::state::State; use self::util::{SyncUnsafeCell, UninitCell}; pub use self::waker::task_from_waker; use super::SpawnToken; +use crate::Metadata; #[no_mangle] extern "Rust" fn __embassy_time_queue_item_from_waker(waker: &Waker) -> &'static mut TimerQueueItem { @@ -94,8 +95,9 @@ pub(crate) struct TaskHeader { /// Integrated timer queue storage. This field should not be accessed outside of the timer queue. pub(crate) timer_queue_item: TimerQueueItem, - #[cfg(feature = "_any_trace")] - pub(crate) name: Option<&'static str>, + + pub(crate) metadata: Metadata, + #[cfg(feature = "rtos-trace")] all_tasks_next: AtomicPtr, } @@ -127,6 +129,10 @@ impl TaskRef { unsafe { self.ptr.as_ref() } } + pub(crate) fn metadata(self) -> &'static Metadata { + unsafe { &self.ptr.as_ref().metadata } + } + /// Returns a reference to the executor that the task is currently running on. pub unsafe fn executor(self) -> Option<&'static Executor> { let executor = self.header().executor.load(Ordering::Relaxed); @@ -193,8 +199,7 @@ impl TaskStorage { poll_fn: SyncUnsafeCell::new(None), timer_queue_item: TimerQueueItem::new(), - #[cfg(feature = "_any_trace")] - name: None, + metadata: Metadata::new(), #[cfg(feature = "rtos-trace")] all_tasks_next: AtomicPtr::new(core::ptr::null_mut()), }, @@ -281,6 +286,7 @@ impl AvailableTask { fn initialize_impl(self, future: impl FnOnce() -> F) -> SpawnToken { unsafe { + self.task.raw.metadata.reset(); self.task.raw.poll_fn.set(Some(TaskStorage::::poll)); self.task.future.write_in_place(future); -- cgit From 8aec341f28a00012e1771d5c35d2647e11830755 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 9 Jul 2025 01:49:31 +0200 Subject: executor: return error when creating the spawntoken, not when spawning. --- embassy-executor/src/raw/mod.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'embassy-executor/src/raw/mod.rs') diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index a7e65360d..bdaa32951 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs @@ -41,7 +41,7 @@ use self::state::State; use self::util::{SyncUnsafeCell, UninitCell}; pub use self::waker::task_from_waker; use super::SpawnToken; -use crate::Metadata; +use crate::{Metadata, SpawnError}; #[no_mangle] extern "Rust" fn __embassy_time_queue_item_from_waker(waker: &Waker) -> &'static mut TimerQueueItem { @@ -220,11 +220,11 @@ impl TaskStorage { /// /// Once the task has finished running, you may spawn it again. It is allowed to spawn it /// on a different executor. - pub fn spawn(&'static self, future: impl FnOnce() -> F) -> SpawnToken { + pub fn spawn(&'static self, future: impl FnOnce() -> F) -> Result, SpawnError> { let task = AvailableTask::claim(self); match task { - Some(task) => task.initialize(future), - None => SpawnToken::new_failed(), + Some(task) => Ok(task.initialize(future)), + None => Err(SpawnError::Busy), } } @@ -353,10 +353,10 @@ impl TaskPool { } } - fn spawn_impl(&'static self, future: impl FnOnce() -> F) -> SpawnToken { + fn spawn_impl(&'static self, future: impl FnOnce() -> F) -> Result, SpawnError> { match self.pool.iter().find_map(AvailableTask::claim) { - Some(task) => task.initialize_impl::(future), - None => SpawnToken::new_failed(), + Some(task) => Ok(task.initialize_impl::(future)), + None => Err(SpawnError::Busy), } } @@ -367,7 +367,7 @@ impl TaskPool { /// This will loop over the pool and spawn the task in the first storage that /// is currently free. If none is free, a "poisoned" SpawnToken is returned, /// which will cause [`Spawner::spawn()`](super::Spawner::spawn) to return the error. - pub fn spawn(&'static self, future: impl FnOnce() -> F) -> SpawnToken { + pub fn spawn(&'static self, future: impl FnOnce() -> F) -> Result, SpawnError> { self.spawn_impl::(future) } @@ -380,7 +380,7 @@ impl TaskPool { /// SAFETY: `future` must be a closure of the form `move || my_async_fn(args)`, where `my_async_fn` /// is an `async fn`, NOT a hand-written `Future`. #[doc(hidden)] - pub unsafe fn _spawn_async_fn(&'static self, future: FutFn) -> SpawnToken + pub unsafe fn _spawn_async_fn(&'static self, future: FutFn) -> Result, SpawnError> where FutFn: FnOnce() -> F, { -- cgit