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")]
pub fn new_process(entry_point: u64, space: AddressSpace, args: &[&[u8]]) -> Result<u64, ()> {
syscalls::new_process(entry_point, space, args)
pub fn new_process(entry_point: u64, space: AddressSpace) -> Result<u64, ()> {
syscalls::new_process(entry_point, space)
}
#[stable(feature = "mikros", since = "1.80.0")]

View File

@ -1,15 +1,23 @@
use crate::ffi::{CStr, OsString};
use crate::sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
use crate::{fmt, ptr};
use super::syscalls;
use crate::ffi::OsString;
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 ARGV: AtomicPtr<*const u8> = AtomicPtr::new(ptr::null_mut());
static ARGS: OnceLock<Vec<OsString>> = OnceLock::new();
/// SAFETY: This function must be called either exactly once,
/// or if called more than once must always be called with the same values
pub unsafe fn init(argc: isize, argv: *const *const u8) {
ARGC.store(argc as usize, Ordering::Relaxed);
ARGV.store(argv as *mut _, Ordering::Relaxed);
pub fn init() {
ARGS.get_or_init(|| {
if let Some(proc_man_pid) = syscalls::try_get_registered(3) {
let args_raw: Vec<(u32, Vec<u8>)> =
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)]
@ -30,30 +38,26 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
impl Iterator for Args {
type Item = OsString;
fn next(&mut self) -> Option<OsString> {
let argc = ARGC.load(Ordering::Relaxed);
if self.pos == argc {
let args = ARGS.get().unwrap();
if self.pos == args.len() {
None
} else {
let argv = ARGV.load(Ordering::Relaxed);
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(),
)
};
let arg = args[self.pos].clone();
self.pos += 1;
Some(arg)
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let argc = ARGC.load(Ordering::Relaxed);
(argc - self.pos, Some(argc - self.pos))
let args = ARGS.get().unwrap();
let remaining = args.len() - self.pos;
(remaining, Some(remaining))
}
}
impl ExactSizeIterator for Args {
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.
// 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();
super::stdio::init();
unsafe { super::args::init(argc, argv) };
super::args::init();
}
// 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::syscalls;
pub use crate::ffi::OsString as EnvKey;
use crate::ffi::{CString, OsStr, OsString};
use crate::ffi::{OsStr, OsString};
use crate::num::NonZero;
use crate::os::mikros::Errno;
use crate::os::mikros::ipc::rpc;
@ -128,13 +128,12 @@ pub fn spawn(
let path = Path::new(&self.program);
let binary = crate::fs::read(path)?;
let (space, entry) = crate::os::mikros::loader::Loader::load(&binary);
let args_owned = self
let args = self
.args
.iter()
.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]>>();
let pid = super::syscalls::new_process(entry as _, space, args.as_slice()).unwrap();
.map(|arg| (0, arg.clone().into_encoded_bytes()))
.collect::<Vec<(u32, Vec<u8>)>>();
let pid = super::syscalls::new_process(entry as _, space).unwrap();
if let Some(vfs_pid) = syscalls::try_get_registered(0) {
let res: Result<(), Errno> = postcard::from_bytes(
&rpc::send_call(vfs_pid, 2, 4, &postcard::to_allocvec(&(pid, stdio)).unwrap())
@ -143,6 +142,14 @@ pub fn spawn(
.unwrap();
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();
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::ptr;
extern "C" {
fn main(argc: c_int, argv: *const *const c_char) -> c_int;
@ -8,11 +8,8 @@
#[no_mangle]
#[allow(unused)]
pub extern "C" fn _start() {
let argc;
let argv;
unsafe {
asm!("int 0x80", in("rax") 19, lateout("rax") argv, lateout("rcx") argc);
let code = main(argc, argv);
let code = main(0, ptr::null());
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, ()> {
let (err, pid) =
syscall4r2(8, entry_point, space.into_raw(), args.len() as u64, args.as_ptr() as u64);
pub fn new_process(entry_point: u64, space: AddressSpace) -> Result<u64, ()> {
let (err, pid) = syscall2r2(8, entry_point, space.into_raw());
if err == 1 { Err(()) } else { Ok(pid) }
}
@ -143,8 +142,6 @@ pub fn wait_for_ipc_message() {
syscall0(18);
}
// Syscall 19: Get CLI arguments, used by crt0 startup code to provide argc and argv. Not needed in Rust.
/// ## Safety
///
/// The caller must ensure that no undefined behavior or memory safety