mikros: Properly implement stdio

This commit is contained in:
pjht 2024-09-22 11:53:54 -05:00
parent b3b12eec10
commit 5ff8990346
Signed by: pjht
GPG Key ID: 7B5F6AFBEC7EE78E
4 changed files with 90 additions and 22 deletions

View File

@ -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) };
}

View File

@ -38,7 +38,7 @@ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
pub struct File {
pub(crate) fs_pid: u64,
pub(crate) fd: u64,
pos: AtomicUsize,
pub(crate) pos: AtomicUsize,
}
pub struct FileAttr {

View File

@ -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::<Vec<CString>>();
let args = args_owned.iter().map(|arg| arg.to_bytes_with_nul()).collect::<Vec<&[u8]>>();
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<io::Stdout> for Stdio {
fn from(_: io::Stdout) -> Stdio {
Stdio::ParentStdout
Stdio::Inherit
}
}
impl From<io::Stderr> for Stdio {
fn from(_: io::Stderr) -> Stdio {
Stdio::ParentStderr
Stdio::Inherit
}
}

View File

@ -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<Option<(u64, u64)>> = OnceLock::new();
pub(crate) static STDOUT_FD: OnceLock<Option<(u64, u64)>> = OnceLock::new();
pub(crate) static STDERR_FD: OnceLock<Option<(u64, u64)>> = 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<usize> {
Ok(0)
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
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<usize> {
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<usize> {
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<impl io::Write> {
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]);
}