aboutsummaryrefslogtreecommitdiff
path: root/embassy-executor/src/spawner.rs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-executor/src/spawner.rs')
-rw-r--r--embassy-executor/src/spawner.rs117
1 files changed, 14 insertions, 103 deletions
diff --git a/embassy-executor/src/spawner.rs b/embassy-executor/src/spawner.rs
index 2909d19a0..83d896b76 100644
--- a/embassy-executor/src/spawner.rs
+++ b/embassy-executor/src/spawner.rs
@@ -5,8 +5,7 @@ use core::sync::atomic::Ordering;
5use core::task::Poll; 5use core::task::Poll;
6 6
7use super::raw; 7use super::raw;
8#[cfg(feature = "trace")] 8use crate::Metadata;
9use crate::raw::trace::TaskRefTrace;
10 9
11/// Token to spawn a newly-created task in an executor. 10/// Token to spawn a newly-created task in an executor.
12/// 11///
@@ -24,33 +23,28 @@ use crate::raw::trace::TaskRefTrace;
24/// Once you've invoked a task function and obtained a SpawnToken, you *must* spawn it. 23/// Once you've invoked a task function and obtained a SpawnToken, you *must* spawn it.
25#[must_use = "Calling a task function does nothing on its own. You must spawn the returned SpawnToken, typically with Spawner::spawn()"] 24#[must_use = "Calling a task function does nothing on its own. You must spawn the returned SpawnToken, typically with Spawner::spawn()"]
26pub struct SpawnToken<S> { 25pub struct SpawnToken<S> {
27 pub(crate) raw_task: Option<raw::TaskRef>, 26 pub(crate) raw_task: raw::TaskRef,
28 phantom: PhantomData<*mut S>, 27 phantom: PhantomData<*mut S>,
29} 28}
30 29
31impl<S> SpawnToken<S> { 30impl<S> SpawnToken<S> {
32 pub(crate) unsafe fn new(raw_task: raw::TaskRef) -> Self { 31 pub(crate) unsafe fn new(raw_task: raw::TaskRef) -> Self {
33 Self { 32 Self {
34 raw_task: Some(raw_task), 33 raw_task,
35 phantom: PhantomData, 34 phantom: PhantomData,
36 } 35 }
37 } 36 }
38 37
39 /// Returns the task id if available, otherwise 0 38 /// Returns the task ID.
40 /// This can be used in combination with rtos-trace to match task names with id's 39 /// This can be used in combination with rtos-trace to match task names with IDs
41 pub fn id(&self) -> u32 { 40 pub fn id(&self) -> u32 {
42 match self.raw_task { 41 self.raw_task.id()
43 None => 0,
44 Some(t) => t.as_ptr() as u32,
45 }
46 } 42 }
47 43
48 /// Return a SpawnToken that represents a failed spawn. 44 /// Get the metadata for this task. You can use this to set metadata fields
49 pub fn new_failed() -> Self { 45 /// prior to spawning it.
50 Self { 46 pub fn metadata(&self) -> &Metadata {
51 raw_task: None, 47 self.raw_task.metadata()
52 phantom: PhantomData,
53 }
54 } 48 }
55} 49}
56 50
@@ -159,30 +153,10 @@ impl Spawner {
159 /// Spawn a task into an executor. 153 /// Spawn a task into an executor.
160 /// 154 ///
161 /// You obtain the `token` by calling a task function (i.e. one marked with `#[embassy_executor::task]`). 155 /// You obtain the `token` by calling a task function (i.e. one marked with `#[embassy_executor::task]`).
162 pub fn spawn<S>(&self, token: SpawnToken<S>) -> Result<(), SpawnError> { 156 pub fn spawn<S>(&self, token: SpawnToken<S>) {
163 let task = token.raw_task; 157 let task = token.raw_task;
164 mem::forget(token); 158 mem::forget(token);
165 159 unsafe { self.executor.spawn(task) }
166 match task {
167 Some(task) => {
168 unsafe { self.executor.spawn(task) };
169 Ok(())
170 }
171 None => Err(SpawnError::Busy),
172 }
173 }
174
175 // Used by the `embassy_executor_macros::main!` macro to throw an error when spawn
176 // fails. This is here to allow conditional use of `defmt::unwrap!`
177 // without introducing a `defmt` feature in the `embassy_executor_macros` package,
178 // which would require use of `-Z namespaced-features`.
179 /// Spawn a task into an executor, panicking on failure.
180 ///
181 /// # Panics
182 ///
183 /// Panics if the spawning fails.
184 pub fn must_spawn<S>(&self, token: SpawnToken<S>) {
185 unwrap!(self.spawn(token));
186 } 160 }
187 161
188 /// Convert this Spawner to a SendSpawner. This allows you to send the 162 /// Convert this Spawner to a SendSpawner. This allows you to send the
@@ -198,53 +172,6 @@ impl Spawner {
198 } 172 }
199} 173}
200 174
201/// Extension trait adding tracing capabilities to the Spawner
202///
203/// This trait provides an additional method to spawn tasks with an associated name,
204/// which can be useful for debugging and tracing purposes.
205pub trait SpawnerTraceExt {
206 /// Spawns a new task with a specified name.
207 ///
208 /// # Arguments
209 /// * `name` - Static string name to associate with the task
210 /// * `token` - Token representing the task to spawn
211 ///
212 /// # Returns
213 /// Result indicating whether the spawn was successful
214 fn spawn_named<S>(&self, name: &'static str, token: SpawnToken<S>) -> Result<(), SpawnError>;
215}
216
217/// Implementation of the SpawnerTraceExt trait for Spawner when trace is enabled
218#[cfg(feature = "trace")]
219impl SpawnerTraceExt for Spawner {
220 fn spawn_named<S>(&self, name: &'static str, token: SpawnToken<S>) -> Result<(), SpawnError> {
221 let task = token.raw_task;
222 core::mem::forget(token);
223
224 match task {
225 Some(task) => {
226 // Set the name and ID when trace is enabled
227 task.set_name(Some(name));
228 let task_id = task.as_ptr() as u32;
229 task.set_id(task_id);
230
231 unsafe { self.executor.spawn(task) };
232 Ok(())
233 }
234 None => Err(SpawnError::Busy),
235 }
236 }
237}
238
239/// Implementation of the SpawnerTraceExt trait for Spawner when trace is disabled
240#[cfg(not(feature = "trace"))]
241impl SpawnerTraceExt for Spawner {
242 fn spawn_named<S>(&self, _name: &'static str, token: SpawnToken<S>) -> Result<(), SpawnError> {
243 // When trace is disabled, just forward to regular spawn and ignore the name
244 self.spawn(token)
245 }
246}
247
248/// Handle to spawn tasks into an executor from any thread. 175/// Handle to spawn tasks into an executor from any thread.
249/// 176///
250/// This Spawner can be used from any thread (it is Send), but it can 177/// This Spawner can be used from any thread (it is Send), but it can
@@ -287,25 +214,9 @@ impl SendSpawner {
287 /// Spawn a task into an executor. 214 /// Spawn a task into an executor.
288 /// 215 ///
289 /// You obtain the `token` by calling a task function (i.e. one marked with `#[embassy_executor::task]`). 216 /// You obtain the `token` by calling a task function (i.e. one marked with `#[embassy_executor::task]`).
290 pub fn spawn<S: Send>(&self, token: SpawnToken<S>) -> Result<(), SpawnError> { 217 pub fn spawn<S: Send>(&self, token: SpawnToken<S>) {
291 let header = token.raw_task; 218 let header = token.raw_task;
292 mem::forget(token); 219 mem::forget(token);
293 220 unsafe { self.executor.spawn(header) }
294 match header {
295 Some(header) => {
296 unsafe { self.executor.spawn(header) };
297 Ok(())
298 }
299 None => Err(SpawnError::Busy),
300 }
301 }
302
303 /// Spawn a task into an executor, panicking on failure.
304 ///
305 /// # Panics
306 ///
307 /// Panics if the spawning fails.
308 pub fn must_spawn<S: Send>(&self, token: SpawnToken<S>) {
309 unwrap!(self.spawn(token));
310 } 221 }
311} 222}