1
Fork 0

Remove an unnecessary Mutex around argument initialization.

In the command-line argument initialization code, remove the Mutex
around the `ARGV` and `ARGC` variables, and simply check whether
ARGV is non-null before dereferencing it. This way, if either of
ARGV or ARGC is not initialized, we'll get an empty argument list.

This allows simple cdylibs to avoid having
`pthread_mutex_lock`/`pthread_mutex_unlock` appear in their symbol
tables if they don't otherwise use threads.
This commit is contained in:
Dan Gohman 2021-07-17 12:33:31 -07:00
parent 46010c4618
commit 9bb11ba511

View file

@ -77,16 +77,10 @@ mod imp {
use crate::ptr;
use crate::sync::atomic::{AtomicIsize, AtomicPtr, Ordering};
use crate::sys_common::mutex::StaticMutex;
static ARGC: AtomicIsize = AtomicIsize::new(0);
static ARGV: AtomicPtr<*const u8> = AtomicPtr::new(ptr::null_mut());
// We never call `ENV_LOCK.init()`, so it is UB to attempt to
// acquire this mutex reentrantly!
static LOCK: StaticMutex = StaticMutex::new();
unsafe fn really_init(argc: isize, argv: *const *const u8) {
let _guard = LOCK.lock();
ARGC.store(argc, Ordering::Relaxed);
ARGV.store(argv as *mut _, Ordering::Relaxed);
}
@ -128,9 +122,14 @@ mod imp {
fn clone() -> Vec<OsString> {
unsafe {
let _guard = LOCK.lock();
let argc = ARGC.load(Ordering::Relaxed);
// Load ARGC and ARGV without a lock. If the store to either ARGV or
// ARGC isn't visible yet, we'll return an empty argument list.
let argv = ARGV.load(Ordering::Relaxed);
let argc = if argv.is_null() {
0
} else {
ARGC.load(Ordering::Relaxed)
};
(0..argc)
.map(|i| {
let cstr = CStr::from_ptr(*argv.offset(i) as *const libc::c_char);