starnix_core/task/
kernel_threads.rs1use crate::execution::create_kernel_thread;
6use crate::task::dynamic_thread_spawner::DynamicThreadSpawner;
7use crate::task::{CurrentTask, DelayedReleaser, Kernel, Task, ThreadGroup};
8use fragile::Fragile;
9use fuchsia_async as fasync;
10use pin_project::pin_project;
11use scopeguard::ScopeGuard;
12
13use starnix_task_command::TaskCommand;
14
15use starnix_uapi::errors::Errno;
16use starnix_uapi::{errno, error};
17use std::future::Future;
18use std::pin::Pin;
19use std::sync::{Arc, OnceLock, Weak};
20use std::task::{Context, Poll};
21
22pub struct KernelThreads {
26 pub starnix_process: zx::Process,
29
30 ehandle: fasync::EHandle,
35
36 spawner: OnceLock<DynamicThreadSpawner>,
38
39 system_task: OnceLock<SystemTask>,
41
42 kernel: Weak<Kernel>,
44}
45
46impl KernelThreads {
47 pub fn new(kernel: Weak<Kernel>) -> Self {
54 KernelThreads {
55 starnix_process: fuchsia_runtime::process_self()
56 .duplicate_handle(zx::Rights::SAME_RIGHTS)
57 .expect("Failed to duplicate process self"),
58 ehandle: fasync::EHandle::local(),
59 spawner: Default::default(),
60 system_task: Default::default(),
61 kernel,
62 }
63 }
64
65 pub fn init(&self, system_task: CurrentTask) -> Result<(), Errno> {
69 self.system_task.set(SystemTask::new(system_task)).map_err(|_| errno!(EEXIST))?;
70 self.spawner
71 .set(DynamicThreadSpawner::new(2, self.system_task().weak_task(), "kthreadd/init"))
72 .map_err(|_| errno!(EEXIST))?;
73 Ok(())
74 }
75
76 pub fn spawn_future(
83 &self,
84 future: impl AsyncFnOnce() -> () + Send + 'static,
85 name: &'static str,
86 ) {
87 self.ehandle.spawn_detached(WrappedMainFuture::new(
88 self.kernel.clone(),
89 async move { fasync::Task::local(future()).await },
90 name,
91 ));
92 }
93
94 pub fn spawner(&self) -> &DynamicThreadSpawner {
98 self.spawner.get().as_ref().unwrap()
99 }
100
101 pub fn system_task(&self) -> &CurrentTask {
105 self.system_task.get().expect("KernelThreads::init must be called").system_task.get()
106 }
107
108 pub fn system_thread_group(&self) -> Arc<ThreadGroup> {
113 self.system_task
114 .get()
115 .expect("KernelThreads::init must be called")
116 .system_thread_group
117 .upgrade()
118 .expect("System task must be still alive")
119 }
120}
121
122impl Drop for KernelThreads {
123 fn drop(&mut self) {
126 if let Some(system_task) = self.system_task.take() {
127 system_task.system_task.into_inner().release(());
128 }
129 }
130}
131
132pub fn with_new_current_task<F, R>(
135 system_task: &Weak<Task>,
136 task_name: String,
137 f: F,
138) -> Result<R, Errno>
139where
140 F: FnOnce(&CurrentTask) -> R,
141{
142 let current_task = {
143 let Some(system_task) = system_task.upgrade() else {
144 return error!(ESRCH);
145 };
146 create_kernel_thread(&system_task, TaskCommand::new(task_name.as_bytes())).unwrap()
147 };
148 let result = f(¤t_task);
149 current_task.release(());
150
151 DelayedReleaser::finalize();
153
154 Ok(result)
155}
156
157struct SystemTask {
158 system_task: Fragile<CurrentTask>,
161
162 system_thread_group: Weak<ThreadGroup>,
164}
165
166impl SystemTask {
167 fn new(system_task: CurrentTask) -> Self {
168 let system_thread_group = Arc::downgrade(&system_task.thread_group());
169 Self { system_task: system_task.into(), system_thread_group }
170 }
171}
172
173#[pin_project]
176pub(crate) struct WrappedFuture<F, C: Clone> {
177 #[pin]
178 fut: F,
179 cleaner: fn(C),
180 context: ScopeGuard<C, fn(C)>,
181 name: &'static str,
182}
183
184impl<F, C: Clone> WrappedFuture<F, C> {
185 pub(crate) fn new_with_cleaner(context: C, cleaner: fn(C), fut: F, name: &'static str) -> Self {
186 Self { fut, cleaner, context: ScopeGuard::with_strategy(context, cleaner), name }
188 }
189}
190
191impl<F: Future, C: Clone> Future for WrappedFuture<F, C> {
192 type Output = F::Output;
193
194 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
195 let this = self.project();
196 fuchsia_trace::duration!(starnix_logging::CATEGORY_STARNIX, &*this.name);
197 let result = this.fut.poll(cx);
198
199 (this.cleaner)(this.context.clone());
200 result
201 }
202}
203
204type WrappedMainFuture<F> = WrappedFuture<F, Weak<Kernel>>;
205
206impl<F> WrappedMainFuture<F> {
207 fn new(kernel: Weak<Kernel>, fut: F, name: &'static str) -> Self {
208 Self::new_with_cleaner(kernel, trigger_delayed_releaser, fut, name)
209 }
210}
211
212fn trigger_delayed_releaser(kernel: Weak<Kernel>) {
213 if let Some(kernel) = kernel.upgrade() {
214 if let Some(system_task) = kernel.kthreads.system_task.get() {
215 system_task.system_task.get().trigger_delayed_releaser();
216 }
217 }
218}