1
Fork 0

Hermit: Unify std::env::args with Unix

The only differences between these implementations are that Unix uses
relaxed ordering, but Hermit uses acquire/release, and Unix truncates
`argv` at the first null pointer, but Hermit doesn't. Since Hermit aims
for Unix compatibility, unify it with Unix.
This commit is contained in:
Thalia Archibald 2025-04-12 03:01:00 -07:00
parent 092a284ba0
commit c1f0498e65
3 changed files with 9 additions and 40 deletions

View file

@ -1,35 +0,0 @@
use crate::ffi::{CStr, OsString, c_char};
use crate::os::hermit::ffi::OsStringExt;
use crate::ptr;
use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release};
use crate::sync::atomic::{AtomicIsize, AtomicPtr};
#[path = "common.rs"]
mod common;
pub use common::Args;
static ARGC: AtomicIsize = AtomicIsize::new(0);
static ARGV: AtomicPtr<*const u8> = AtomicPtr::new(ptr::null_mut());
/// One-time global initialization.
pub unsafe fn init(argc: isize, argv: *const *const u8) {
ARGC.store(argc, Relaxed);
// Use release ordering here to broadcast writes by the OS.
ARGV.store(argv as *mut *const u8, Release);
}
/// Returns the command line arguments
pub fn args() -> Args {
// Synchronize with the store above.
let argv = ARGV.load(Acquire);
// If argv has not been initialized yet, do not return any arguments.
let argc = if argv.is_null() { 0 } else { ARGC.load(Relaxed) };
let args: Vec<OsString> = (0..argc)
.map(|i| unsafe {
let cstr = CStr::from_ptr(*argv.offset(i) as *const c_char);
OsStringExt::from_vec(cstr.to_bytes().to_vec())
})
.collect();
Args::new(args)
}

View file

@ -3,15 +3,15 @@
#![forbid(unsafe_op_in_unsafe_fn)]
cfg_if::cfg_if! {
if #[cfg(all(target_family = "unix", not(any(target_os = "espidf", target_os = "vita"))))] {
if #[cfg(any(
all(target_family = "unix", not(any(target_os = "espidf", target_os = "vita"))),
target_os = "hermit",
))] {
mod unix;
pub use unix::*;
} else if #[cfg(target_family = "windows")] {
mod windows;
pub use windows::*;
} else if #[cfg(target_os = "hermit")] {
mod hermit;
pub use hermit::*;
} else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] {
mod sgx;
pub use sgx::*;

View file

@ -6,6 +6,9 @@
#![allow(dead_code)] // runtime init functions not used during testing
use crate::ffi::CStr;
#[cfg(target_os = "hermit")]
use crate::os::hermit::ffi::OsStringExt;
#[cfg(not(target_os = "hermit"))]
use crate::os::unix::ffi::OsStringExt;
#[path = "common.rs"]
@ -73,6 +76,7 @@ pub fn args() -> Args {
target_os = "illumos",
target_os = "emscripten",
target_os = "haiku",
target_os = "hermit",
target_os = "l4re",
target_os = "fuchsia",
target_os = "redox",
@ -100,7 +104,7 @@ mod imp {
unsafe fn really_init(argc: isize, argv: *const *const u8) {
// These don't need to be ordered with each other or other stores,
// because they only hold the unmodified system-provide argv/argc.
// because they only hold the unmodified system-provided argv/argc.
ARGC.store(argc, Ordering::Relaxed);
ARGV.store(argv as *mut _, Ordering::Relaxed);
}