kernel_manager/
kernels.rs1use crate::{StarnixKernel, generate_kernel_name};
6use anyhow::Error;
7use fidl::endpoints::ServerEnd;
8use frunner::{ComponentControllerMarker, ComponentStartInfo};
9use fuchsia_component::client::connect_to_protocol;
10use fuchsia_sync::Mutex;
11use std::collections::HashMap;
12use std::sync::Arc;
13use vfs::execution_scope::ExecutionScope;
14use {
15 fidl_fuchsia_component as fcomponent, fidl_fuchsia_component_runner as frunner,
16 fidl_fuchsia_power_system as fpower, zx,
17};
18
19const KERNEL_URL: &str = "starnix_kernel#meta/starnix_kernel.cm";
21
22fn create_lease_name(kernel_name: &str) -> String {
24 format!("starnix-kernel-{}", kernel_name)
25}
26
27pub struct Kernels {
29 kernels: Arc<Mutex<HashMap<zx::Koid, StarnixKernel>>>,
30 background_tasks: ExecutionScope,
31}
32
33impl Kernels {
34 pub fn new() -> Self {
36 let kernels = Default::default();
37 Self { kernels, background_tasks: ExecutionScope::new() }
38 }
39
40 pub async fn start(
42 &self,
43 start_info: ComponentStartInfo,
44 controller: ServerEnd<ComponentControllerMarker>,
45 ) -> Result<(), Error> {
46 let realm =
47 connect_to_protocol::<fcomponent::RealmMarker>().expect("Failed to connect to realm.");
48
49 let kernel_name = generate_kernel_name(&start_info)?;
50 let wake_lease = 'out: {
51 let Ok(activity_governor) = connect_to_protocol::<fpower::ActivityGovernorMarker>()
52 else {
53 break 'out None;
54 };
55
56 match activity_governor
57 .take_application_activity_lease(&create_lease_name(&kernel_name))
58 .await
59 {
60 Ok(l) => Some(l),
61 Err(e) => {
62 log::warn!("Failed to acquire application activity lease for kernel: {:?}", e);
63 None
64 }
65 }
66 };
67
68 let (kernel, on_stop) =
69 StarnixKernel::create(realm, KERNEL_URL, start_info, controller).await?;
70 let kernel_job = kernel.job.clone();
71 let kernel_koid = kernel.job.koid()?;
72
73 *kernel.wake_lease.lock() = wake_lease;
74 log::info!("Acquired wake lease for {:?}", kernel_job);
75
76 self.kernels.lock().insert(kernel_koid, kernel);
77
78 let kernels = self.kernels.clone();
79 self.background_tasks.spawn(async move {
80 on_stop.await;
81 _ = kernels.lock().remove(&kernel_koid);
82 });
83
84 Ok(())
85 }
86
87 pub fn all_jobs(&self) -> Vec<Arc<zx::Job>> {
89 self.kernels.lock().iter().map(|(_, k)| Arc::clone(k.job())).collect()
90 }
91
92 pub fn drop_wake_lease(&self, container_job: &zx::Job) -> Result<(), Error> {
94 fuchsia_trace::instant!(
96 "power",
97 "starnix-runner:drop-application-activity-lease",
98 fuchsia_trace::Scope::Process
99 );
100 let job_koid = container_job.koid()?;
102 if let Some(kernel) = self.kernels.lock().get(&job_koid) {
103 kernel.wake_lease.lock().take();
104 log::info!("Dropped wake lease for {:?}", container_job);
105 }
106 Ok(())
107 }
108
109 pub async fn acquire_wake_lease(&self, container_job: &zx::Job) -> Result<(), Error> {
111 fuchsia_trace::duration!("power", "starnix-runner:acquire-application-activity-lease");
113 let job_koid = container_job.koid()?;
115 if let Some(kernel) = self.kernels.lock().get(&job_koid) {
116 let activity_governor = connect_to_protocol::<fpower::ActivityGovernorMarker>()?;
117 let wake_lease = match activity_governor
118 .take_application_activity_lease(&create_lease_name(&kernel.name))
119 .await
120 {
121 Ok(l) => l,
122 Err(e) => {
123 log::warn!("Failed to acquire application activity lease for kernel: {:?}", e);
124 return Ok(());
125 }
126 };
127 *kernel.wake_lease.lock() = Some(wake_lease);
128 log::info!("Acquired wake lease for {:?}", container_job);
129 }
130 Ok(())
131 }
132}
133
134impl Drop for Kernels {
135 fn drop(&mut self) {
136 self.background_tasks.shutdown();
137 }
138}