Rollup merge of #139711 - thaliaarchi:hermit-args, r=jhpratt
Hermit: Unify `std::env::args` with Unix The only differences between these implementations of `std::env::args` 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. The atomic orderings were established in https://github.com/rust-lang/rust/pull/74006 (cc `@euclio)` for Unix and https://github.com/rust-lang/rust/pull/100579 (cc `@joboet)` for Hermit and, before those, they used mutexes and non-atomic statics. I think the difference in orderings is simply from them being changed at different times. The commented explanation for using acquire/release for Hermit is “to broadcast writes by the OS”. I'm not experienced enough with atomics to accurately judge, but I think acquire/release is stronger than needed. Either way, they should match. Truncating at the first null pointer seems desirable, though I don't know whether it is necessary in practice on Hermit. cc `@mkroening` `@stlankes` for Hermit
This commit is contained in:
commit
5779843eda
3 changed files with 9 additions and 40 deletions
|
@ -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)
|
|
||||||
}
|
|
|
@ -3,15 +3,15 @@
|
||||||
#![forbid(unsafe_op_in_unsafe_fn)]
|
#![forbid(unsafe_op_in_unsafe_fn)]
|
||||||
|
|
||||||
cfg_if::cfg_if! {
|
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;
|
mod unix;
|
||||||
pub use unix::*;
|
pub use unix::*;
|
||||||
} else if #[cfg(target_family = "windows")] {
|
} else if #[cfg(target_family = "windows")] {
|
||||||
mod windows;
|
mod windows;
|
||||||
pub use 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"))] {
|
} else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] {
|
||||||
mod sgx;
|
mod sgx;
|
||||||
pub use sgx::*;
|
pub use sgx::*;
|
||||||
|
|
|
@ -6,6 +6,9 @@
|
||||||
#![allow(dead_code)] // runtime init functions not used during testing
|
#![allow(dead_code)] // runtime init functions not used during testing
|
||||||
|
|
||||||
use crate::ffi::CStr;
|
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;
|
use crate::os::unix::ffi::OsStringExt;
|
||||||
|
|
||||||
#[path = "common.rs"]
|
#[path = "common.rs"]
|
||||||
|
@ -73,6 +76,7 @@ pub fn args() -> Args {
|
||||||
target_os = "illumos",
|
target_os = "illumos",
|
||||||
target_os = "emscripten",
|
target_os = "emscripten",
|
||||||
target_os = "haiku",
|
target_os = "haiku",
|
||||||
|
target_os = "hermit",
|
||||||
target_os = "l4re",
|
target_os = "l4re",
|
||||||
target_os = "fuchsia",
|
target_os = "fuchsia",
|
||||||
target_os = "redox",
|
target_os = "redox",
|
||||||
|
@ -100,7 +104,7 @@ mod imp {
|
||||||
|
|
||||||
unsafe fn really_init(argc: isize, argv: *const *const u8) {
|
unsafe fn really_init(argc: isize, argv: *const *const u8) {
|
||||||
// These don't need to be ordered with each other or other stores,
|
// 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);
|
ARGC.store(argc, Ordering::Relaxed);
|
||||||
ARGV.store(argv as *mut _, Ordering::Relaxed);
|
ARGV.store(argv as *mut _, Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue