task/manager/
lifecycle.rs1use super::*;
4use alloc::boxed::Box;
5use core::{
6 future::{Future, poll_fn},
7 ptr::NonNull,
8 task::Poll,
9 time::Duration,
10};
11use embassy_executor::raw::{TaskPool, task_from_waker};
12use embassy_time::Timer;
13
14impl Manager {
15 async fn create_and_run_task<R: 'static, FunctionType, FutureType>(
19 manager: &'static Manager,
20 parent_task_identifier: TaskIdentifier,
21 name: &str,
22 function: FunctionType,
23 spawner: Option<usize>,
24 ) -> Result<(JoinHandle<R>, TaskIdentifier)>
25 where
26 FunctionType: FnOnce(TaskIdentifier) -> FutureType + 'static,
27 FutureType: Future<Output = R> + 'static,
28 {
29 let identifier = manager
30 .register(parent_task_identifier, name)
31 .await
32 .expect("Failed to get new task identifier");
33
34 let pool = Box::new(TaskPool::<_, 1>::new());
35 let pool = Box::leak(pool);
36
37 let (join_handle_parent, join_handle_child) = JoinHandle::new();
38
39 let task = async move || {
40 let manager = manager;
41 let internal_identifier = Manager::get_current_internal_identifier().await;
42
43 manager
44 .set_internal_identifier(identifier, internal_identifier)
45 .await
46 .expect("Failed to register task");
47
48 let result = function(identifier).await;
49
50 join_handle_child.signal(result);
51
52 manager
53 .unregister(identifier)
54 .await
55 .expect("Failed to unregister task");
56 };
57
58 let mut inner = manager.0.write().await;
59
60 let spawner = if let Some(spawner) = spawner {
62 if !inner.spawners.contains_key(&spawner) {
63 return Err(Error::InvalidSpawnerIdentifier);
64 }
65 spawner
66 } else {
67 Manager::select_best_spawner(&inner)?
68 };
69
70 inner
71 .tasks
72 .get_mut(&identifier)
73 .expect("Failed to get task metadata")
74 .spawner_identifier = spawner;
75
76 let token = pool.spawn(task).expect("Failed to spawn task");
77
78 inner
79 .spawners
80 .get(&spawner)
81 .expect("Failed to get spawner")
82 .spawn(token);
83
84 Ok((join_handle_parent, identifier))
85 }
86
87 pub async fn spawn<FunctionType, FutureType, ReturnType>(
89 &'static self,
90 parent_task: TaskIdentifier,
91 name: &str,
92 spawner: Option<usize>,
93 function: FunctionType,
94 ) -> Result<(JoinHandle<ReturnType>, TaskIdentifier)>
95 where
96 FunctionType: FnOnce(TaskIdentifier) -> FutureType + 'static,
97 FutureType: Future<Output = ReturnType> + 'static,
98 ReturnType: 'static,
99 {
100 Self::create_and_run_task(self, parent_task, name, function, spawner).await
102 }
103
104 async fn set_internal_identifier(
109 &self,
110 identifier: TaskIdentifier,
111 internal_identifier: usize,
112 ) -> Result<()> {
113 let mut inner = self.0.write().await;
114
115 let metadata = Self::get_task_mutable(&mut inner, identifier)?;
116
117 metadata.internal_identifier = internal_identifier;
118
119 if let Some(old_identifier) = inner.identifiers.insert(internal_identifier, identifier) {
121 inner.identifiers.remove(&internal_identifier);
123 inner
124 .identifiers
125 .insert(internal_identifier, old_identifier);
126 return Err(Error::InvalidTaskIdentifier);
127 }
128
129 Ok(())
130 }
131
132 pub async fn sleep(duration: Duration) {
134 let nano_seconds = duration.as_nanos();
135
136 Timer::after(embassy_time::Duration::from_nanos(nano_seconds as u64)).await
137 }
138
139 pub async fn get_current_internal_identifier() -> usize {
140 poll_fn(|context| {
141 let task_reference = task_from_waker(context.waker());
142
143 let inner: NonNull<u8> = unsafe { core::mem::transmute(task_reference) };
144
145 let identifier = inner.as_ptr() as usize;
146
147 Poll::Ready(identifier)
148 })
149 .await
150 }
151
152 pub async fn get_current_task_identifier(&self) -> TaskIdentifier {
153 let internal_identifier = Self::get_current_internal_identifier().await;
154
155 {
156 let inner = self.0.read().await;
157 if let Some(identifier) = inner.identifiers.get(&internal_identifier) {
158 return *identifier;
159 }
160 }
161
162 let mut inner = self.0.write().await;
165 if let Some(identifier) = inner.identifiers.get(&internal_identifier) {
166 return *identifier;
167 }
168 let root = Manager::ROOT_TASK_IDENTIFIER;
169 inner.tasks.insert(
170 root,
171 Metadata {
172 internal_identifier,
173 name: "Root".into(),
174 parent: root,
175 user: users::UserIdentifier::ROOT,
176 group: users::GroupIdentifier::ROOT,
177 environment_variables: alloc::vec::Vec::new(),
178 signals: crate::signal::SignalAccumulator::new(),
179 spawner_identifier: 0,
180 },
181 );
182 inner.identifiers.insert(internal_identifier, root);
183
184 root
185 }
186}