feat(init): spawn service over IPC with per-client allowance refunded on child death; up to 4 death watchers; spawntest on test image
This commit is contained in:
@@ -10,6 +10,7 @@ pub mod fs;
|
||||
pub mod input;
|
||||
pub mod io;
|
||||
mod rt;
|
||||
pub mod spawn;
|
||||
pub mod start;
|
||||
pub mod syscall;
|
||||
|
||||
|
||||
53
crates/libkos/src/spawn.rs
Normal file
53
crates/libkos/src/spawn.rs
Normal file
@@ -0,0 +1,53 @@
|
||||
//! Running a program through init (protocol: `types::spawn`). Init loads it
|
||||
//! and gives it a log endpoint; the caller hands it any other capabilities
|
||||
//! (`delegate` to the process) and starts it.
|
||||
|
||||
use crate::syscall;
|
||||
use types::address::{EntryPoint, StackPointer};
|
||||
use types::bounded::CapSlot;
|
||||
use types::budget::Limits;
|
||||
use types::spawn::{STACK_TOP, reply, request};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum SpawnError {
|
||||
NotFound,
|
||||
/// More than what is left of this process's spawn allowance.
|
||||
OverAllowance,
|
||||
Failed,
|
||||
}
|
||||
|
||||
/// A loaded program, not yet running.
|
||||
pub struct Spawned {
|
||||
pub process: CapSlot,
|
||||
entry: EntryPoint,
|
||||
log: Option<CapSlot>,
|
||||
}
|
||||
|
||||
pub fn spawn(init: CapSlot, name: &[u8], limits: Limits) -> Result<Spawned, SpawnError> {
|
||||
let words = request(name, limits).ok_or(SpawnError::Failed)?;
|
||||
let reply = syscall::call(init, words, None).map_err(|_| SpawnError::Failed)?;
|
||||
let [tag, entry, log, _] = reply.words();
|
||||
let cap = match reply {
|
||||
syscall::Received::Message { cap, .. } | syscall::Received::Call { cap, .. } => cap,
|
||||
syscall::Received::Signal { .. } => None,
|
||||
};
|
||||
match (tag, cap) {
|
||||
(reply::OK, Some(process)) => Ok(Spawned {
|
||||
process,
|
||||
entry: EntryPoint::from_raw(entry),
|
||||
log: u8::try_from(log).ok().and_then(CapSlot::new),
|
||||
}),
|
||||
(reply::NOT_FOUND, _) => Err(SpawnError::NotFound),
|
||||
(reply::OVER_ALLOWANCE, _) => Err(SpawnError::OverAllowance),
|
||||
_ => Err(SpawnError::Failed),
|
||||
}
|
||||
}
|
||||
|
||||
impl Spawned {
|
||||
/// Runs the program, telling it where its log endpoint is.
|
||||
pub fn start(&self) -> bool {
|
||||
let arg = types::start_arg::encode(None, self.log);
|
||||
let stack = StackPointer::from_raw(STACK_TOP);
|
||||
syscall::spawn_thread_in(self.process, self.entry, stack, arg) != usize::MAX
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user