From 5ff89903462f3233aea9e25c2fd57690a128a228 Mon Sep 17 00:00:00 2001 From: pjht Date: Sun, 22 Sep 2024 11:53:54 -0500 Subject: [PATCH] mikros: Properly implement stdio --- library/std/src/sys/pal/mikros/common.rs | 1 + library/std/src/sys/pal/mikros/fs.rs | 2 +- library/std/src/sys/pal/mikros/process.rs | 39 +++++++++++-- library/std/src/sys/pal/mikros/stdio.rs | 70 +++++++++++++++++------ 4 files changed, 90 insertions(+), 22 deletions(-) diff --git a/library/std/src/sys/pal/mikros/common.rs b/library/std/src/sys/pal/mikros/common.rs index 963519a48d1..75464a4e0e2 100644 --- a/library/std/src/sys/pal/mikros/common.rs +++ b/library/std/src/sys/pal/mikros/common.rs @@ -5,6 +5,7 @@ // NOTE: this is not guaranteed to run, for example when Rust code is called externally. pub unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) { rpc::init(); + super::stdio::init(); unsafe { super::args::init(argc, argv) }; } diff --git a/library/std/src/sys/pal/mikros/fs.rs b/library/std/src/sys/pal/mikros/fs.rs index 50556ae38d1..b7e7a4be7d6 100644 --- a/library/std/src/sys/pal/mikros/fs.rs +++ b/library/std/src/sys/pal/mikros/fs.rs @@ -38,7 +38,7 @@ fn serialize(&self, serializer: S) -> Result pub struct File { pub(crate) fs_pid: u64, pub(crate) fd: u64, - pos: AtomicUsize, + pub(crate) pos: AtomicUsize, } pub struct FileAttr { diff --git a/library/std/src/sys/pal/mikros/process.rs b/library/std/src/sys/pal/mikros/process.rs index 8c074858cef..7aeaf02c338 100644 --- a/library/std/src/sys/pal/mikros/process.rs +++ b/library/std/src/sys/pal/mikros/process.rs @@ -1,6 +1,9 @@ +use super::stdio::{STDERR_FD, STDIN_FD, STDOUT_FD}; +use super::syscalls; pub use crate::ffi::OsString as EnvKey; use crate::ffi::{CString, OsStr, OsString}; use crate::num::NonZero; +use crate::os::mikros::ipc::rpc; use crate::path::Path; use crate::sys::fs::File; use crate::sys::pipe::AnonPipe; @@ -36,8 +39,8 @@ pub enum Stdio { Inherit, Null, MakePipe, - ParentStdout, - ParentStderr, + //ParentStdout, + //ParentStderr, #[allow(dead_code)] // This variant exists only for the Debug impl InheritFile(File), } @@ -102,6 +105,28 @@ pub fn spawn( _default: Stdio, _needs_stdin: bool, ) -> io::Result<(Process, StdioPipes)> { + let stdin = match self.stdin.take() { + None => None, + Some(Stdio::Null) => None, + Some(Stdio::Inherit) => *STDIN_FD.get().unwrap(), + Some(Stdio::MakePipe) => todo!(), + Some(Stdio::InheritFile(file)) => Some((file.fs_pid, file.fd)), + }; + let stdout = match self.stdout.take() { + None => None, + Some(Stdio::Null) => None, + Some(Stdio::Inherit) => *STDOUT_FD.get().unwrap(), + Some(Stdio::MakePipe) => todo!(), + Some(Stdio::InheritFile(file)) => Some((file.fs_pid, file.fd)), + }; + let stderr = match self.stderr.take() { + None => None, + Some(Stdio::Null) => None, + Some(Stdio::Inherit) => *STDERR_FD.get().unwrap(), + Some(Stdio::MakePipe) => todo!(), + Some(Stdio::InheritFile(file)) => Some((file.fs_pid, file.fd)), + }; + let stdio = [stdin, stdout, stderr]; let path = Path::new(&self.program); let binary = crate::fs::read(path).unwrap(); let (space, entry) = crate::os::mikros::loader::Loader::load(&binary); @@ -111,7 +136,11 @@ pub fn spawn( .map(|arg| CString::new(arg.clone().into_encoded_bytes()).unwrap()) .collect::>(); let args = args_owned.iter().map(|arg| arg.to_bytes_with_nul()).collect::>(); - super::syscalls::new_process(entry as _, space, args.as_slice()).unwrap(); + let pid = super::syscalls::new_process(entry as _, space, args.as_slice()).unwrap(); + if let Some(vfs_pid) = syscalls::try_get_registered(0) { + let _ = &rpc::send_call(vfs_pid, 2, 4, &postcard::to_allocvec(&(pid, stdio)).unwrap()) + .get_return(); + }; Ok((Process { dummy: () }, StdioPipes { stdin: None, stdout: None, stderr: None })) } @@ -128,13 +157,13 @@ fn from(pipe: AnonPipe) -> Stdio { impl From for Stdio { fn from(_: io::Stdout) -> Stdio { - Stdio::ParentStdout + Stdio::Inherit } } impl From for Stdio { fn from(_: io::Stderr) -> Stdio { - Stdio::ParentStderr + Stdio::Inherit } } diff --git a/library/std/src/sys/pal/mikros/stdio.rs b/library/std/src/sys/pal/mikros/stdio.rs index 5a52a9b7fdb..d24f8338cb1 100644 --- a/library/std/src/sys/pal/mikros/stdio.rs +++ b/library/std/src/sys/pal/mikros/stdio.rs @@ -1,5 +1,14 @@ -use crate::arch::asm; +//use crate::arch::asm; +use super::fs::File; +use super::syscalls; use crate::io; +use crate::os::mikros::ipc::rpc; +use crate::sync::atomic::AtomicUsize; +use crate::sync::OnceLock; + +pub(crate) static STDIN_FD: OnceLock> = OnceLock::new(); +pub(crate) static STDOUT_FD: OnceLock> = OnceLock::new(); +pub(crate) static STDERR_FD: OnceLock> = OnceLock::new(); pub struct Stdin; pub struct Stdout; @@ -12,8 +21,13 @@ pub const fn new() -> Stdin { } impl io::Read for Stdin { - fn read(&mut self, _buf: &mut [u8]) -> io::Result { - Ok(0) + fn read(&mut self, buf: &mut [u8]) -> io::Result { + let Some(fd) = *STDIN_FD.get().unwrap() else { + return Ok(0); + }; + let file = File { fs_pid: fd.0, fd: fd.1, pos: AtomicUsize::new(0) }; + let num_bytes = file.read(buf)?; + Ok(num_bytes) } } @@ -25,12 +39,17 @@ pub const fn new() -> Stdout { impl io::Write for Stdout { fn write(&mut self, buf: &[u8]) -> io::Result { - for byte in buf { - unsafe { - asm!("int 0x80", in("rax") 0, in ("rcx") *byte as u64); - }; - } - Ok(buf.len()) + //for byte in buf { + // unsafe { + // asm!("int 0x80", in("rax") 0, in ("rcx") *byte as u64); + // }; + //} + //Ok(buf.len()) + let Some(fd) = *STDOUT_FD.get().unwrap() else { + return Ok(0); + }; + let file = File { fs_pid: fd.0, fd: fd.1, pos: AtomicUsize::new(0) }; + file.write(buf) } fn flush(&mut self) -> io::Result<()> { @@ -46,12 +65,17 @@ pub const fn new() -> Stderr { impl io::Write for Stderr { fn write(&mut self, buf: &[u8]) -> io::Result { - for byte in buf { - unsafe { - asm!("int 0x80", in("rax") 0, in ("rcx") *byte as u64); - }; - } - Ok(buf.len()) + //for byte in buf { + // unsafe { + // asm!("int 0x80", in("rax") 0, in ("rcx") *byte as u64); + // }; + //} + //Ok(buf.len()) + let Some(fd) = *STDERR_FD.get().unwrap() else { + return Ok(0); + }; + let file = File { fs_pid: fd.0, fd: fd.1, pos: AtomicUsize::new(0) }; + file.write(buf) } fn flush(&mut self) -> io::Result<()> { @@ -59,7 +83,7 @@ fn flush(&mut self) -> io::Result<()> { } } -pub const STDIN_BUF_SIZE: usize = 0; +pub const STDIN_BUF_SIZE: usize = 8192; pub fn is_ebadf(_err: &io::Error) -> bool { true @@ -68,3 +92,17 @@ pub fn is_ebadf(_err: &io::Error) -> bool { pub fn panic_output() -> Option { Some(Stderr::new()) } + +pub fn init() { + let Some(vfs_pid) = syscalls::try_get_registered(0) else { + STDIN_FD.get_or_init(|| None); + STDOUT_FD.get_or_init(|| None); + STDERR_FD.get_or_init(|| None); + return; + }; + let stdio: [Option<(u64, u64)>; 3] = + postcard::from_bytes(&rpc::send_call(vfs_pid, 2, 5, &[]).get_return()).unwrap(); + STDIN_FD.get_or_init(|| stdio[0]); + STDOUT_FD.get_or_init(|| stdio[1]); + STDERR_FD.get_or_init(|| stdio[2]); +}