diff --git a/Cargo.lock b/Cargo.lock index 7f3a78c16..b821900ca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -385,7 +385,7 @@ name = "lazy_static" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "spin 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -400,7 +400,7 @@ source = "git+https://github.com/sunriseos/libfat.git#2fc179154b3e7861a93f5f5b4a dependencies = [ "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "spin 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "storage_device 1.0.0 (git+https://github.com/Sunriseos/storage_device.git)", ] @@ -414,7 +414,7 @@ name = "linked_list_allocator" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "spin 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -625,7 +625,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "spin" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -679,7 +679,7 @@ dependencies = [ "futures-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "spin 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "static_assertions 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "sunrise-libuser 0.1.0", "sunrise-libutils 0.1.0", @@ -695,7 +695,7 @@ dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "multiboot2 0.7.1 (git+https://github.com/sunriseos/multiboot2-elf64.git)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "spin 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "static_assertions 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "sunrise-libutils 0.1.0", "xmas-elf 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -742,7 +742,7 @@ dependencies = [ "plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "spin 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "static_assertions 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "sunrise-libkern 0.1.0", "sunrise-libutils 0.1.0", @@ -759,7 +759,7 @@ dependencies = [ "generic-array 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "spin 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "sunrise-libuser 0.1.0", "sunrise-libutils 0.1.0", ] @@ -803,7 +803,7 @@ dependencies = [ "libm 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "linked_list_allocator 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "spin 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "sunrise-libkern 0.1.0", "sunrise-libutils 0.1.0", "swipc-gen 0.1.0", @@ -823,9 +823,11 @@ dependencies = [ name = "sunrise-loader" version = "0.1.0" dependencies = [ + "core-futures-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "futures-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "sunrise-libkern 0.1.0", "sunrise-libuser 0.1.0", "sunrise-libutils 0.1.0", @@ -842,7 +844,7 @@ dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "spin 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "sunrise-libuser 0.1.0", ] @@ -854,7 +856,7 @@ dependencies = [ "hashbrown 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "spin 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "sunrise-libuser 0.1.0", ] @@ -867,7 +869,7 @@ dependencies = [ "futures-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)", "generic-array 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "spin 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "sunrise-libtimezone 0.1.0", "sunrise-libuser 0.1.0", "sunrise-libutils 0.1.0", @@ -880,7 +882,7 @@ dependencies = [ "futures-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)", "hashbrown 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "spin 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "sunrise-libuser 0.1.0", "sunrise-libutils 0.1.0", ] @@ -891,7 +893,7 @@ version = "0.1.0" dependencies = [ "bstr 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "spin 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "sunrise-libuser 0.1.0", ] @@ -1110,7 +1112,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" "checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" "checksum spin 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ceac490aa12c567115b40b7b7fceca03a6c9d53d5defea066123debc83c5dc1f" -"checksum spin 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbdb51a221842709c2dd65b62ad4b78289fc3e706a02c17a26104528b6aa7837" +"checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" "checksum static_assertions 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4f8de36da215253eb5f24020bfaa0646613b48bf7ebe36cdfa37c3b3b33b241" "checksum storage_device 1.0.0 (git+https://github.com/Sunriseos/storage_device.git)" = "" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" diff --git a/ipcdefs/loader.id b/ipcdefs/loader.id index 9478ebf23..59ace6825 100644 --- a/ipcdefs/loader.id +++ b/ipcdefs/loader.id @@ -1,3 +1,4 @@ interface sunrise_libuser::ldr::ILoaderInterface is ldr:shel { - [0] launch_title(array title_name, array args); + [0] launch_title(array title_name, array args) -> u64 pid; + [1] wait(u64 pid) -> u32 exit_status; } \ No newline at end of file diff --git a/libuser/src/error.rs b/libuser/src/error.rs index e569697ee..f1d370e13 100644 --- a/libuser/src/error.rs +++ b/libuser/src/error.rs @@ -48,6 +48,8 @@ pub enum Error { Kernel(KernelError, Backtrace), /// Loader error. Loader(LoaderError, Backtrace), + /// Process Manager error. + Pm(PmError, Backtrace), /// Service Manager error. Sm(SmError, Backtrace), //Vi(ViError, Backtrace), @@ -76,6 +78,7 @@ impl Error { Module::Kernel => Error::Kernel(KernelError::from_description(description), Backtrace::new()), Module::FileSystem => Error::FileSystem(FileSystemError(description), Backtrace::new()), Module::Loader => Error::Loader(LoaderError(description), Backtrace::new()), + Module::Pm => Error::Pm(PmError(description), Backtrace::new()), Module::Sm => Error::Sm(SmError(description), Backtrace::new()), //Module::Vi => Error::Vi(ViError(description), Backtrace::new()), Module::Libuser => Error::Libuser(LibuserError(description), Backtrace::new()), @@ -94,6 +97,7 @@ impl Error { Error::Kernel(err, ..) => err.description() << 9 | Module::Kernel.0, Error::FileSystem(err, ..) => err.0 << 9 | Module::FileSystem.0, Error::Loader(err, ..) => err.0 << 9 | Module::Loader.0, + Error::Pm(err, ..) => err.0 << 9 | Module::Pm.0, Error::Sm(err, ..) => err.0 << 9 | Module::Sm.0, //Error::Vi(err, ..) => err.0 << 9 | Module::Vi.0, Error::Libuser(err, ..) => err.0 << 9 | Module::Libuser.0, @@ -105,6 +109,22 @@ impl Error { } } +enum_with_val! { + #[derive(PartialEq, Eq, Clone, Copy)] + struct Module(u32) { + Kernel = 1, + FileSystem = 2, + Loader = 9, + Pm = 15, + Sm = 21, + Vi = 114, + Time = 116, + Hid = 202, + Libuser = 415, + Ahci = 416, + } +} + impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // TODO: Better Display implementation for libuser::Error @@ -190,21 +210,6 @@ impl From for Error { } } -enum_with_val! { - #[derive(PartialEq, Eq, Clone, Copy)] - struct Module(u32) { - Kernel = 1, - FileSystem = 2, - Loader = 9, - Sm = 21, - Vi = 114, - Time = 116, - Hid = 202, - Libuser = 415, - Ahci = 416, - } -} - enum_with_val! { /// Internal libuser errors. #[derive(PartialEq, Eq, Clone, Copy)] @@ -329,6 +334,21 @@ impl From for Error { } } +enum_with_val! { + /// PM Errors. + #[derive(PartialEq, Eq, Clone, Copy)] + pub struct PmError(u32) { + /// Pid not found + PidNotFound = 1, + } +} + +impl From for Error { + fn from(error: PmError) -> Self { + Error::Pm(error, Backtrace::new()) + } +} + enum_with_val! { /// HID driver errors. #[derive(PartialEq, Eq, Clone, Copy)] diff --git a/libuser/src/types.rs b/libuser/src/types.rs index d6d9b596b..e4ba19dbe 100644 --- a/libuser/src/types.rs +++ b/libuser/src/types.rs @@ -100,7 +100,7 @@ impl<'a> HandleRef<'a> { /// Panics if used from outside the context of a Future spawned on a libuser /// future executor. Please make sure you only call this function from a /// future spawned on a WaitableManager. - fn wait_async<'b>(self, queue: WorkQueue<'b>)-> impl core::future::Future> + Unpin +'b { + pub fn wait_async<'b>(self, queue: WorkQueue<'b>)-> impl core::future::Future> + Unpin +'b { #[allow(missing_docs, clippy::missing_docs_in_private_items)] struct MyFuture<'a> { queue: crate::futures::WorkQueue<'a>, @@ -638,5 +638,5 @@ impl Drop for MappedSharedMemory { /// Each process in Horizon is given a unique, non-reusable PID. It may be used /// to associate capabilities or resources to a particular process. For instance, /// sm might associate a process' service access permissions to its pid. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] pub struct Pid(pub u64); diff --git a/loader/Cargo.toml b/loader/Cargo.toml index cbadf21a9..d5172f293 100644 --- a/loader/Cargo.toml +++ b/loader/Cargo.toml @@ -11,6 +11,8 @@ sunrise-libutils = { path = "../libutils" } log = "0.4" xmas-elf = "0.7.0" futures-preview = { version = "0.3.0-alpha.16", default-features = false, features = ["nightly", "alloc"] } +spin = "0.5.2" +core = { package = "core-futures-tls", version = "0.1.1" } [dependencies.lazy_static] features = ["spin_no_std"] diff --git a/loader/src/main.rs b/loader/src/main.rs index c0126b74c..0cb225e24 100644 --- a/loader/src/main.rs +++ b/loader/src/main.rs @@ -21,6 +21,7 @@ //! - flags/ //! - boot.flag +#![feature(async_await)] #![no_std] #[macro_use] @@ -32,14 +33,16 @@ use core::str; use core::slice; use core::mem::size_of; use alloc::boxed::Box; +use alloc::collections::BTreeMap; use sunrise_libuser::fs::{DirectoryEntry, DirectoryEntryType, FileSystemPath, IFileSystemProxy, IFileSystemServiceProxy}; use sunrise_libuser::{kip_header, capabilities}; use sunrise_libuser::ipc::server::{port_handler}; use sunrise_libuser::futures::{WaitableManager, WorkQueue}; -use sunrise_libuser::error::{Error, LoaderError}; -use sunrise_libuser::ldr::ILoaderInterface; +use sunrise_libuser::error::{Error, LoaderError, PmError}; +use sunrise_libuser::ldr::ILoaderInterfaceAsync; use sunrise_libuser::syscalls::{self, map_process_memory}; +use sunrise_libuser::types::{Pid, Process}; use sunrise_libkern::process::*; use sunrise_libuser::mem::{find_free_address, PAGE_SIZE}; use sunrise_libutils::{align_up, div_ceil}; @@ -47,6 +50,8 @@ use sunrise_libutils::{align_up, div_ceil}; use futures::future::FutureObj; use lazy_static::lazy_static; +use spin::Mutex; + mod elf_loader; /// Max size of an ELF before we issue a warning. Loader needs to keep its @@ -54,8 +59,12 @@ mod elf_loader; /// file bigger than 128MiB. const MAX_ELF_SIZE: u64 = 128 * 1024 * 1024; +lazy_static! { + static ref PROCESSES: Mutex> = Mutex::new(BTreeMap::new()); +} + /// Start the given titleid by loading its content from the provided filesystem. -fn boot(fs: &IFileSystemProxy, titlename: &str, args: &[u8]) -> Result<(), Error> { +fn boot(fs: &IFileSystemProxy, titlename: &str, args: &[u8]) -> Result { info!("Booting titleid {}", titlename); let val = format!("/bin/{}/main", titlename); @@ -174,7 +183,10 @@ fn boot(fs: &IFileSystemProxy, titlename: &str, args: &[u8]) -> Result<(), Error return Err(err) } - Ok(()) + let pid = process.pid()?; + PROCESSES.lock().insert(pid.0, process); + + Ok(pid) } lazy_static! { @@ -188,10 +200,50 @@ lazy_static! { #[derive(Debug, Default)] struct LoaderIface; -impl ILoaderInterface for LoaderIface { - fn launch_title(&mut self, _workqueue: WorkQueue<'static>, title_name: &[u8], args: &[u8]) -> Result<(), Error> { - let title_name = str::from_utf8(title_name).or(Err(LoaderError::ProgramNotFound))?; - boot(&*BOOT_FROM_FS, title_name, args) +impl ILoaderInterfaceAsync for LoaderIface { + fn launch_title(&mut self, _workqueue: WorkQueue<'static>, title_name: &[u8], args: &[u8]) -> FutureObj<'_, Result> { + let res = (|| -> Result { + let title_name = str::from_utf8(title_name).or(Err(LoaderError::ProgramNotFound))?; + let Pid(pid) = boot(&*BOOT_FROM_FS, title_name, args)?; + Ok(pid) + })(); + FutureObj::new(Box::new(async move { + res + })) + } + + fn wait(&mut self, workqueue: WorkQueue<'static>, pid: u64) -> FutureObj<'_, Result> { + FutureObj::new(Box::new(async move { + // Weird logic: we create an as_ref_static process, and then we'll + // relock PROCESSES each time we want a process to reset signal and + // stuff. This kinda sucks. + // + // TODO: Unify Handle/HandleRef behind a single trait. + // BODY: The fact I have to do this makes me think there's really a + // BODY: problem in the handle/handleref design. Maybe there should be a + // BODY: trait unifying Handle/HandleRef, and `Process` and co should be + // BODY: generic on those? That would allow me to call the functions on + // BODY: "borrowed lifetime-erased" handles. + // BODY: + // BODY: This trait could probably be AsRef or Borrow. Ideally the + // BODY: generic types would be an internal implementation details + // BODY: and we'd just expose "Process" and "ProcessBorrowed" types + // BODY: through typedef/newtypes. Needs a lot of thought. + let process_wait = (PROCESSES.lock().get(&pid) + .ok_or(PmError::PidNotFound)?.0).as_ref_static(); + loop { + process_wait.wait_async(workqueue.clone()).await?; + let lock = PROCESSES.lock(); + let process = lock.get(&pid) + .ok_or(PmError::PidNotFound)?; + process.reset_signal()?; + if process.state()? == ProcessState::Exited { + PROCESSES.lock().remove(&pid); + // TODO: Return exit state. + return Ok(0); + } + } + })) } } @@ -286,6 +338,10 @@ capabilities!(CAPABILITIES = Capabilities { sunrise_libuser::syscalls::nr::UnmapProcessMemory, sunrise_libuser::syscalls::nr::SetProcessMemoryPermission, sunrise_libuser::syscalls::nr::StartProcess, + + sunrise_libuser::syscalls::nr::GetProcessInfo, + sunrise_libuser::syscalls::nr::GetProcessId, + sunrise_libuser::syscalls::nr::ResetSignal, ], raw_caps: [sunrise_libuser::caps::ioport(0x60), sunrise_libuser::caps::ioport(0x64), sunrise_libuser::caps::irq_pair(1, 0x3FF)] -}); +}); \ No newline at end of file diff --git a/shell/src/main.rs b/shell/src/main.rs index 12346a3ca..4cb2025be 100644 --- a/shell/src/main.rs +++ b/shell/src/main.rs @@ -255,14 +255,17 @@ fn main() { }, name => { // Try to run it as an external binary. - match loader.launch_title(name.as_bytes(), line.as_bytes()) { + let res = loader.launch_title(name.as_bytes(), line.as_bytes()) + .and_then(|pid| loader.wait(pid)); + + match res { Err(Error::Loader(LoaderError::ProgramNotFound, _)) => { let _ = writeln!(&mut terminal, "Unknown command"); }, Err(err) => { let _ = writeln!(&mut terminal, "Error: {:?}", err); }, - Ok(_) => () + Ok(_exitstatus) => () } } }