mikros: Change to using proc_man for CLI arguments

This commit is contained in:
pjht 2024-11-09 21:41:21 -06:00
parent c2dd19bc8f
commit b4bdead6e9
Signed by: pjht
GPG Key ID: 7B5F6AFBEC7EE78E
6 changed files with 47 additions and 42 deletions

View File

@ -11,8 +11,8 @@ pub fn get_initrd() -> &'static [u8] {
} }
#[stable(feature = "mikros", since = "1.80.0")] #[stable(feature = "mikros", since = "1.80.0")]
pub fn new_process(entry_point: u64, space: AddressSpace, args: &[&[u8]]) -> Result<u64, ()> { pub fn new_process(entry_point: u64, space: AddressSpace) -> Result<u64, ()> {
syscalls::new_process(entry_point, space, args) syscalls::new_process(entry_point, space)
} }
#[stable(feature = "mikros", since = "1.80.0")] #[stable(feature = "mikros", since = "1.80.0")]

View File

@ -1,15 +1,23 @@
use crate::ffi::{CStr, OsString}; use super::syscalls;
use crate::sync::atomic::{AtomicPtr, AtomicUsize, Ordering}; use crate::ffi::OsString;
use crate::{fmt, ptr}; use crate::fmt;
use crate::os::mikros::ffi::OsStringExt;
use crate::os::mikros::ipc::rpc;
use crate::sync::OnceLock;
static ARGC: AtomicUsize = AtomicUsize::new(0); static ARGS: OnceLock<Vec<OsString>> = OnceLock::new();
static ARGV: AtomicPtr<*const u8> = AtomicPtr::new(ptr::null_mut());
/// SAFETY: This function must be called either exactly once, pub fn init() {
/// or if called more than once must always be called with the same values ARGS.get_or_init(|| {
pub unsafe fn init(argc: isize, argv: *const *const u8) { if let Some(proc_man_pid) = syscalls::try_get_registered(3) {
ARGC.store(argc as usize, Ordering::Relaxed); let args_raw: Vec<(u32, Vec<u8>)> =
ARGV.store(argv as *mut _, Ordering::Relaxed); postcard::from_bytes(&rpc::send_call(proc_man_pid, 8, 3, &[]).get_return())
.unwrap();
args_raw.into_iter().map(|(_, arg)| OsString::from_vec(arg)).collect::<Vec<_>>()
} else {
Vec::new()
}
});
} }
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
@ -30,30 +38,26 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
impl Iterator for Args { impl Iterator for Args {
type Item = OsString; type Item = OsString;
fn next(&mut self) -> Option<OsString> { fn next(&mut self) -> Option<OsString> {
let argc = ARGC.load(Ordering::Relaxed); let args = ARGS.get().unwrap();
if self.pos == argc { if self.pos == args.len() {
None None
} else { } else {
let argv = ARGV.load(Ordering::Relaxed); let arg = args[self.pos].clone();
let arg = unsafe {
let arg_ptr = argv.add(self.pos).read();
OsString::from_encoded_bytes_unchecked(
CStr::from_ptr(arg_ptr.cast()).to_owned().into_bytes(),
)
};
self.pos += 1; self.pos += 1;
Some(arg) Some(arg)
} }
} }
fn size_hint(&self) -> (usize, Option<usize>) { fn size_hint(&self) -> (usize, Option<usize>) {
let argc = ARGC.load(Ordering::Relaxed); let args = ARGS.get().unwrap();
(argc - self.pos, Some(argc - self.pos)) let remaining = args.len() - self.pos;
(remaining, Some(remaining))
} }
} }
impl ExactSizeIterator for Args { impl ExactSizeIterator for Args {
fn len(&self) -> usize { fn len(&self) -> usize {
ARGC.load(Ordering::Relaxed).into() let args = ARGS.get().unwrap();
args.len()
} }
} }

View File

@ -4,10 +4,10 @@
// SAFETY: must be called only once during runtime initialization. // SAFETY: must be called only once during runtime initialization.
// NOTE: this is not guaranteed to run, for example when Rust code is called externally. // 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) { pub unsafe fn init(_argc: isize, _argv: *const *const u8, _sigpipe: u8) {
rpc::init(); rpc::init();
super::stdio::init(); super::stdio::init();
unsafe { super::args::init(argc, argv) }; super::args::init();
} }
// SAFETY: must be called only once during runtime cleanup. // SAFETY: must be called only once during runtime cleanup.

View File

@ -1,7 +1,7 @@
use super::stdio::{STDERR_FD, STDIN_FD, STDOUT_FD}; use super::stdio::{STDERR_FD, STDIN_FD, STDOUT_FD};
use super::syscalls; use super::syscalls;
pub use crate::ffi::OsString as EnvKey; pub use crate::ffi::OsString as EnvKey;
use crate::ffi::{CString, OsStr, OsString}; use crate::ffi::{OsStr, OsString};
use crate::num::NonZero; use crate::num::NonZero;
use crate::os::mikros::Errno; use crate::os::mikros::Errno;
use crate::os::mikros::ipc::rpc; use crate::os::mikros::ipc::rpc;
@ -128,13 +128,12 @@ pub fn spawn(
let path = Path::new(&self.program); let path = Path::new(&self.program);
let binary = crate::fs::read(path)?; let binary = crate::fs::read(path)?;
let (space, entry) = crate::os::mikros::loader::Loader::load(&binary); let (space, entry) = crate::os::mikros::loader::Loader::load(&binary);
let args_owned = self let args = self
.args .args
.iter() .iter()
.map(|arg| CString::new(arg.clone().into_encoded_bytes()).unwrap()) .map(|arg| (0, arg.clone().into_encoded_bytes()))
.collect::<Vec<CString>>(); .collect::<Vec<(u32, Vec<u8>)>>();
let args = args_owned.iter().map(|arg| arg.to_bytes_with_nul()).collect::<Vec<&[u8]>>(); let pid = super::syscalls::new_process(entry as _, space).unwrap();
let pid = super::syscalls::new_process(entry as _, space, args.as_slice()).unwrap();
if let Some(vfs_pid) = syscalls::try_get_registered(0) { if let Some(vfs_pid) = syscalls::try_get_registered(0) {
let res: Result<(), Errno> = postcard::from_bytes( let res: Result<(), Errno> = postcard::from_bytes(
&rpc::send_call(vfs_pid, 2, 4, &postcard::to_allocvec(&(pid, stdio)).unwrap()) &rpc::send_call(vfs_pid, 2, 4, &postcard::to_allocvec(&(pid, stdio)).unwrap())
@ -143,6 +142,14 @@ pub fn spawn(
.unwrap(); .unwrap();
res?; res?;
}; };
if let Some(proc_man_pid) = syscalls::try_get_registered(3) {
let res: Result<(), Errno> = postcard::from_bytes(
&rpc::send_call(proc_man_pid, 8, 2, &postcard::to_allocvec(&(pid, args)).unwrap())
.get_return(),
)
.unwrap();
res?;
};
syscalls::wake_new(pid).unwrap(); syscalls::wake_new(pid).unwrap();
Ok((Process { pid }, StdioPipes { stdin: None, stdout: None, stderr: None })) Ok((Process { pid }, StdioPipes { stdin: None, stdout: None, stderr: None }))
} }

View File

@ -1,5 +1,5 @@
use crate::arch::asm;
use crate::ffi::{c_char, c_int}; use crate::ffi::{c_char, c_int};
use crate::ptr;
extern "C" { extern "C" {
fn main(argc: c_int, argv: *const *const c_char) -> c_int; fn main(argc: c_int, argv: *const *const c_char) -> c_int;
@ -8,11 +8,8 @@
#[no_mangle] #[no_mangle]
#[allow(unused)] #[allow(unused)]
pub extern "C" fn _start() { pub extern "C" fn _start() {
let argc;
let argv;
unsafe { unsafe {
asm!("int 0x80", in("rax") 19, lateout("rax") argv, lateout("rcx") argc); let code = main(0, ptr::null());
let code = main(argc, argv);
crate::sys::os::exit(code); crate::sys::os::exit(code);
}; };
} }

View File

@ -69,9 +69,8 @@ pub(crate) fn copy_to(
} }
} }
pub fn new_process(entry_point: u64, space: AddressSpace, args: &[&[u8]]) -> Result<u64, ()> { pub fn new_process(entry_point: u64, space: AddressSpace) -> Result<u64, ()> {
let (err, pid) = let (err, pid) = syscall2r2(8, entry_point, space.into_raw());
syscall4r2(8, entry_point, space.into_raw(), args.len() as u64, args.as_ptr() as u64);
if err == 1 { Err(()) } else { Ok(pid) } if err == 1 { Err(()) } else { Ok(pid) }
} }
@ -143,8 +142,6 @@ pub fn wait_for_ipc_message() {
syscall0(18); syscall0(18);
} }
// Syscall 19: Get CLI arguments, used by crt0 startup code to provide argc and argv. Not needed in Rust.
/// ## Safety /// ## Safety
/// ///
/// The caller must ensure that no undefined behavior or memory safety /// The caller must ensure that no undefined behavior or memory safety