aboutsummaryrefslogtreecommitdiff
path: root/embassy-executor/src/raw/mod.rs
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2025-08-29 12:04:29 +0000
committerGitHub <[email protected]>2025-08-29 12:04:29 +0000
commitf86cf87f2f20f723e2ba2fe7d83908a2b3bac2d1 (patch)
tree57f9200ed729746ef5f077af6c79863c37e824ae /embassy-executor/src/raw/mod.rs
parentdf10e8a6bc407544d29c234ed00bdec3e9caf837 (diff)
parente2c34ac735888d25d57d3ea07e8915c2e112048c (diff)
Merge pull request #4606 from diondokter/taskmeta-update-2
Taskmeta update
Diffstat (limited to 'embassy-executor/src/raw/mod.rs')
-rw-r--r--embassy-executor/src/raw/mod.rs62
1 files changed, 35 insertions, 27 deletions
diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs
index 4b17d4982..bdaa32951 100644
--- a/embassy-executor/src/raw/mod.rs
+++ b/embassy-executor/src/raw/mod.rs
@@ -16,7 +16,7 @@ mod run_queue;
16#[cfg_attr(not(target_has_atomic = "8"), path = "state_critical_section.rs")] 16#[cfg_attr(not(target_has_atomic = "8"), path = "state_critical_section.rs")]
17mod state; 17mod state;
18 18
19#[cfg(feature = "trace")] 19#[cfg(feature = "_any_trace")]
20pub mod trace; 20pub mod trace;
21pub(crate) mod util; 21pub(crate) mod util;
22#[cfg_attr(feature = "turbowakers", path = "waker_turbo.rs")] 22#[cfg_attr(feature = "turbowakers", path = "waker_turbo.rs")]
@@ -41,6 +41,7 @@ use self::state::State;
41use self::util::{SyncUnsafeCell, UninitCell}; 41use self::util::{SyncUnsafeCell, UninitCell};
42pub use self::waker::task_from_waker; 42pub use self::waker::task_from_waker;
43use super::SpawnToken; 43use super::SpawnToken;
44use crate::{Metadata, SpawnError};
44 45
45#[no_mangle] 46#[no_mangle]
46extern "Rust" fn __embassy_time_queue_item_from_waker(waker: &Waker) -> &'static mut TimerQueueItem { 47extern "Rust" fn __embassy_time_queue_item_from_waker(waker: &Waker) -> &'static mut TimerQueueItem {
@@ -94,11 +95,10 @@ pub(crate) struct TaskHeader {
94 95
95 /// Integrated timer queue storage. This field should not be accessed outside of the timer queue. 96 /// Integrated timer queue storage. This field should not be accessed outside of the timer queue.
96 pub(crate) timer_queue_item: TimerQueueItem, 97 pub(crate) timer_queue_item: TimerQueueItem,
97 #[cfg(feature = "trace")] 98
98 pub(crate) name: Option<&'static str>, 99 pub(crate) metadata: Metadata,
99 #[cfg(feature = "trace")] 100
100 pub(crate) id: u32, 101 #[cfg(feature = "rtos-trace")]
101 #[cfg(feature = "trace")]
102 all_tasks_next: AtomicPtr<TaskHeader>, 102 all_tasks_next: AtomicPtr<TaskHeader>,
103} 103}
104 104
@@ -129,6 +129,10 @@ impl TaskRef {
129 unsafe { self.ptr.as_ref() } 129 unsafe { self.ptr.as_ref() }
130 } 130 }
131 131
132 pub(crate) fn metadata(self) -> &'static Metadata {
133 unsafe { &self.ptr.as_ref().metadata }
134 }
135
132 /// Returns a reference to the executor that the task is currently running on. 136 /// Returns a reference to the executor that the task is currently running on.
133 pub unsafe fn executor(self) -> Option<&'static Executor> { 137 pub unsafe fn executor(self) -> Option<&'static Executor> {
134 let executor = self.header().executor.load(Ordering::Relaxed); 138 let executor = self.header().executor.load(Ordering::Relaxed);
@@ -148,6 +152,12 @@ impl TaskRef {
148 pub(crate) fn as_ptr(self) -> *const TaskHeader { 152 pub(crate) fn as_ptr(self) -> *const TaskHeader {
149 self.ptr.as_ptr() 153 self.ptr.as_ptr()
150 } 154 }
155
156 /// Returns the task ID.
157 /// This can be used in combination with rtos-trace to match task names with IDs
158 pub fn id(&self) -> u32 {
159 self.as_ptr() as u32
160 }
151} 161}
152 162
153/// Raw storage in which a task can be spawned. 163/// Raw storage in which a task can be spawned.
@@ -189,11 +199,8 @@ impl<F: Future + 'static> TaskStorage<F> {
189 poll_fn: SyncUnsafeCell::new(None), 199 poll_fn: SyncUnsafeCell::new(None),
190 200
191 timer_queue_item: TimerQueueItem::new(), 201 timer_queue_item: TimerQueueItem::new(),
192 #[cfg(feature = "trace")] 202 metadata: Metadata::new(),
193 name: None, 203 #[cfg(feature = "rtos-trace")]
194 #[cfg(feature = "trace")]
195 id: 0,
196 #[cfg(feature = "trace")]
197 all_tasks_next: AtomicPtr::new(core::ptr::null_mut()), 204 all_tasks_next: AtomicPtr::new(core::ptr::null_mut()),
198 }, 205 },
199 future: UninitCell::uninit(), 206 future: UninitCell::uninit(),
@@ -213,11 +220,11 @@ impl<F: Future + 'static> TaskStorage<F> {
213 /// 220 ///
214 /// Once the task has finished running, you may spawn it again. It is allowed to spawn it 221 /// Once the task has finished running, you may spawn it again. It is allowed to spawn it
215 /// on a different executor. 222 /// on a different executor.
216 pub fn spawn(&'static self, future: impl FnOnce() -> F) -> SpawnToken<impl Sized> { 223 pub fn spawn(&'static self, future: impl FnOnce() -> F) -> Result<SpawnToken<impl Sized>, SpawnError> {
217 let task = AvailableTask::claim(self); 224 let task = AvailableTask::claim(self);
218 match task { 225 match task {
219 Some(task) => task.initialize(future), 226 Some(task) => Ok(task.initialize(future)),
220 None => SpawnToken::new_failed(), 227 None => Err(SpawnError::Busy),
221 } 228 }
222 } 229 }
223 230
@@ -229,7 +236,7 @@ impl<F: Future + 'static> TaskStorage<F> {
229 let mut cx = Context::from_waker(&waker); 236 let mut cx = Context::from_waker(&waker);
230 match future.poll(&mut cx) { 237 match future.poll(&mut cx) {
231 Poll::Ready(_) => { 238 Poll::Ready(_) => {
232 #[cfg(feature = "trace")] 239 #[cfg(feature = "_any_trace")]
233 let exec_ptr: *const SyncExecutor = this.raw.executor.load(Ordering::Relaxed); 240 let exec_ptr: *const SyncExecutor = this.raw.executor.load(Ordering::Relaxed);
234 241
235 // As the future has finished and this function will not be called 242 // As the future has finished and this function will not be called
@@ -244,7 +251,7 @@ impl<F: Future + 'static> TaskStorage<F> {
244 // after we're done with it. 251 // after we're done with it.
245 this.raw.state.despawn(); 252 this.raw.state.despawn();
246 253
247 #[cfg(feature = "trace")] 254 #[cfg(feature = "_any_trace")]
248 trace::task_end(exec_ptr, &p); 255 trace::task_end(exec_ptr, &p);
249 } 256 }
250 Poll::Pending => {} 257 Poll::Pending => {}
@@ -279,6 +286,7 @@ impl<F: Future + 'static> AvailableTask<F> {
279 286
280 fn initialize_impl<S>(self, future: impl FnOnce() -> F) -> SpawnToken<S> { 287 fn initialize_impl<S>(self, future: impl FnOnce() -> F) -> SpawnToken<S> {
281 unsafe { 288 unsafe {
289 self.task.raw.metadata.reset();
282 self.task.raw.poll_fn.set(Some(TaskStorage::<F>::poll)); 290 self.task.raw.poll_fn.set(Some(TaskStorage::<F>::poll));
283 self.task.future.write_in_place(future); 291 self.task.future.write_in_place(future);
284 292
@@ -345,10 +353,10 @@ impl<F: Future + 'static, const N: usize> TaskPool<F, N> {
345 } 353 }
346 } 354 }
347 355
348 fn spawn_impl<T>(&'static self, future: impl FnOnce() -> F) -> SpawnToken<T> { 356 fn spawn_impl<T>(&'static self, future: impl FnOnce() -> F) -> Result<SpawnToken<T>, SpawnError> {
349 match self.pool.iter().find_map(AvailableTask::claim) { 357 match self.pool.iter().find_map(AvailableTask::claim) {
350 Some(task) => task.initialize_impl::<T>(future), 358 Some(task) => Ok(task.initialize_impl::<T>(future)),
351 None => SpawnToken::new_failed(), 359 None => Err(SpawnError::Busy),
352 } 360 }
353 } 361 }
354 362
@@ -359,7 +367,7 @@ impl<F: Future + 'static, const N: usize> TaskPool<F, N> {
359 /// This will loop over the pool and spawn the task in the first storage that 367 /// This will loop over the pool and spawn the task in the first storage that
360 /// is currently free. If none is free, a "poisoned" SpawnToken is returned, 368 /// is currently free. If none is free, a "poisoned" SpawnToken is returned,
361 /// which will cause [`Spawner::spawn()`](super::Spawner::spawn) to return the error. 369 /// which will cause [`Spawner::spawn()`](super::Spawner::spawn) to return the error.
362 pub fn spawn(&'static self, future: impl FnOnce() -> F) -> SpawnToken<impl Sized> { 370 pub fn spawn(&'static self, future: impl FnOnce() -> F) -> Result<SpawnToken<impl Sized>, SpawnError> {
363 self.spawn_impl::<F>(future) 371 self.spawn_impl::<F>(future)
364 } 372 }
365 373
@@ -372,7 +380,7 @@ impl<F: Future + 'static, const N: usize> TaskPool<F, N> {
372 /// SAFETY: `future` must be a closure of the form `move || my_async_fn(args)`, where `my_async_fn` 380 /// SAFETY: `future` must be a closure of the form `move || my_async_fn(args)`, where `my_async_fn`
373 /// is an `async fn`, NOT a hand-written `Future`. 381 /// is an `async fn`, NOT a hand-written `Future`.
374 #[doc(hidden)] 382 #[doc(hidden)]
375 pub unsafe fn _spawn_async_fn<FutFn>(&'static self, future: FutFn) -> SpawnToken<impl Sized> 383 pub unsafe fn _spawn_async_fn<FutFn>(&'static self, future: FutFn) -> Result<SpawnToken<impl Sized>, SpawnError>
376 where 384 where
377 FutFn: FnOnce() -> F, 385 FutFn: FnOnce() -> F,
378 { 386 {
@@ -417,7 +425,7 @@ impl SyncExecutor {
417 /// - `task` must NOT be already enqueued (in this executor or another one). 425 /// - `task` must NOT be already enqueued (in this executor or another one).
418 #[inline(always)] 426 #[inline(always)]
419 unsafe fn enqueue(&self, task: TaskRef, l: state::Token) { 427 unsafe fn enqueue(&self, task: TaskRef, l: state::Token) {
420 #[cfg(feature = "trace")] 428 #[cfg(feature = "_any_trace")]
421 trace::task_ready_begin(self, &task); 429 trace::task_ready_begin(self, &task);
422 430
423 if self.run_queue.enqueue(task, l) { 431 if self.run_queue.enqueue(task, l) {
@@ -430,7 +438,7 @@ impl SyncExecutor {
430 .executor 438 .executor
431 .store((self as *const Self).cast_mut(), Ordering::Relaxed); 439 .store((self as *const Self).cast_mut(), Ordering::Relaxed);
432 440
433 #[cfg(feature = "trace")] 441 #[cfg(feature = "_any_trace")]
434 trace::task_new(self, &task); 442 trace::task_new(self, &task);
435 443
436 state::locked(|l| { 444 state::locked(|l| {
@@ -442,23 +450,23 @@ impl SyncExecutor {
442 /// 450 ///
443 /// Same as [`Executor::poll`], plus you must only call this on the thread this executor was created. 451 /// Same as [`Executor::poll`], plus you must only call this on the thread this executor was created.
444 pub(crate) unsafe fn poll(&'static self) { 452 pub(crate) unsafe fn poll(&'static self) {
445 #[cfg(feature = "trace")] 453 #[cfg(feature = "_any_trace")]
446 trace::poll_start(self); 454 trace::poll_start(self);
447 455
448 self.run_queue.dequeue_all(|p| { 456 self.run_queue.dequeue_all(|p| {
449 let task = p.header(); 457 let task = p.header();
450 458
451 #[cfg(feature = "trace")] 459 #[cfg(feature = "_any_trace")]
452 trace::task_exec_begin(self, &p); 460 trace::task_exec_begin(self, &p);
453 461
454 // Run the task 462 // Run the task
455 task.poll_fn.get().unwrap_unchecked()(p); 463 task.poll_fn.get().unwrap_unchecked()(p);
456 464
457 #[cfg(feature = "trace")] 465 #[cfg(feature = "_any_trace")]
458 trace::task_exec_end(self, &p); 466 trace::task_exec_end(self, &p);
459 }); 467 });
460 468
461 #[cfg(feature = "trace")] 469 #[cfg(feature = "_any_trace")]
462 trace::executor_idle(self) 470 trace::executor_idle(self)
463 } 471 }
464} 472}