libstd: remove some mutable statics in sys::unix
This commit is contained in:
parent
f844ea1e56
commit
792f2dedd7
3 changed files with 33 additions and 26 deletions
|
@ -78,19 +78,20 @@ mod imp {
|
||||||
use crate::marker::PhantomData;
|
use crate::marker::PhantomData;
|
||||||
use crate::os::unix::prelude::*;
|
use crate::os::unix::prelude::*;
|
||||||
use crate::ptr;
|
use crate::ptr;
|
||||||
|
use crate::sync::atomic::{AtomicIsize, AtomicPtr, Ordering};
|
||||||
|
|
||||||
use crate::sys_common::mutex::Mutex;
|
use crate::sys_common::mutex::Mutex;
|
||||||
|
|
||||||
static mut ARGC: isize = 0;
|
static ARGC: AtomicIsize = AtomicIsize::new(0);
|
||||||
static mut ARGV: *const *const u8 = ptr::null();
|
static ARGV: AtomicPtr<*const u8> = AtomicPtr::new(ptr::null_mut());
|
||||||
// We never call `ENV_LOCK.init()`, so it is UB to attempt to
|
// We never call `ENV_LOCK.init()`, so it is UB to attempt to
|
||||||
// acquire this mutex reentrantly!
|
// acquire this mutex reentrantly!
|
||||||
static LOCK: Mutex = Mutex::new();
|
static LOCK: Mutex = Mutex::new();
|
||||||
|
|
||||||
unsafe fn really_init(argc: isize, argv: *const *const u8) {
|
unsafe fn really_init(argc: isize, argv: *const *const u8) {
|
||||||
let _guard = LOCK.lock();
|
let _guard = LOCK.lock();
|
||||||
ARGC = argc;
|
ARGC.store(argc, Ordering::Relaxed);
|
||||||
ARGV = argv;
|
ARGV.store(argv as *mut _, Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -126,8 +127,8 @@ mod imp {
|
||||||
|
|
||||||
pub unsafe fn cleanup() {
|
pub unsafe fn cleanup() {
|
||||||
let _guard = LOCK.lock();
|
let _guard = LOCK.lock();
|
||||||
ARGC = 0;
|
ARGC.store(0, Ordering::Relaxed);
|
||||||
ARGV = ptr::null();
|
ARGV.store(ptr::null_mut(), Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn args() -> Args {
|
pub fn args() -> Args {
|
||||||
|
@ -137,9 +138,11 @@ mod imp {
|
||||||
fn clone() -> Vec<OsString> {
|
fn clone() -> Vec<OsString> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let _guard = LOCK.lock();
|
let _guard = LOCK.lock();
|
||||||
(0..ARGC)
|
let argc = ARGC.load(Ordering::Relaxed);
|
||||||
|
let argv = ARGV.load(Ordering::Relaxed);
|
||||||
|
(0..argc)
|
||||||
.map(|i| {
|
.map(|i| {
|
||||||
let cstr = CStr::from_ptr(*ARGV.offset(i) as *const libc::c_char);
|
let cstr = CStr::from_ptr(*argv.offset(i) as *const libc::c_char);
|
||||||
OsStringExt::from_vec(cstr.to_bytes().to_vec())
|
OsStringExt::from_vec(cstr.to_bytes().to_vec())
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
|
|
|
@ -48,6 +48,7 @@ mod imp {
|
||||||
use libc::{sigaltstack, SIGSTKSZ, SS_DISABLE};
|
use libc::{sigaltstack, SIGSTKSZ, SS_DISABLE};
|
||||||
use libc::{MAP_ANON, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE, SIGSEGV};
|
use libc::{MAP_ANON, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE, SIGSEGV};
|
||||||
|
|
||||||
|
use crate::sync::atomic::{AtomicBool, AtomicPtr, Ordering};
|
||||||
use crate::sys::unix::os::page_size;
|
use crate::sys::unix::os::page_size;
|
||||||
use crate::sys_common::thread_info;
|
use crate::sys_common::thread_info;
|
||||||
|
|
||||||
|
@ -113,8 +114,8 @@ mod imp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static mut MAIN_ALTSTACK: *mut libc::c_void = ptr::null_mut();
|
static MAIN_ALTSTACK: AtomicPtr<libc::c_void> = AtomicPtr::new(ptr::null_mut());
|
||||||
static mut NEED_ALTSTACK: bool = false;
|
static NEED_ALTSTACK: AtomicBool = AtomicBool::new(false);
|
||||||
|
|
||||||
pub unsafe fn init() {
|
pub unsafe fn init() {
|
||||||
let mut action: sigaction = mem::zeroed();
|
let mut action: sigaction = mem::zeroed();
|
||||||
|
@ -125,17 +126,17 @@ mod imp {
|
||||||
action.sa_flags = SA_SIGINFO | SA_ONSTACK;
|
action.sa_flags = SA_SIGINFO | SA_ONSTACK;
|
||||||
action.sa_sigaction = signal_handler as sighandler_t;
|
action.sa_sigaction = signal_handler as sighandler_t;
|
||||||
sigaction(signal, &action, ptr::null_mut());
|
sigaction(signal, &action, ptr::null_mut());
|
||||||
NEED_ALTSTACK = true;
|
NEED_ALTSTACK.store(true, Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let handler = make_handler();
|
let handler = make_handler();
|
||||||
MAIN_ALTSTACK = handler._data;
|
MAIN_ALTSTACK.store(handler._data, Ordering::Relaxed);
|
||||||
mem::forget(handler);
|
mem::forget(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn cleanup() {
|
pub unsafe fn cleanup() {
|
||||||
Handler { _data: MAIN_ALTSTACK };
|
Handler { _data: MAIN_ALTSTACK.load(Ordering::Relaxed) };
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn get_stackp() -> *mut libc::c_void {
|
unsafe fn get_stackp() -> *mut libc::c_void {
|
||||||
|
@ -176,7 +177,7 @@ mod imp {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn make_handler() -> Handler {
|
pub unsafe fn make_handler() -> Handler {
|
||||||
if !NEED_ALTSTACK {
|
if !NEED_ALTSTACK.load(Ordering::Relaxed) {
|
||||||
return Handler::null();
|
return Handler::null();
|
||||||
}
|
}
|
||||||
let mut stack = mem::zeroed();
|
let mut stack = mem::zeroed();
|
||||||
|
|
|
@ -246,10 +246,11 @@ pub mod guard {
|
||||||
use libc::{MAP_ANON, MAP_FAILED, MAP_FIXED, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE};
|
use libc::{MAP_ANON, MAP_FAILED, MAP_FIXED, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE};
|
||||||
|
|
||||||
use crate::ops::Range;
|
use crate::ops::Range;
|
||||||
|
use crate::sync::atomic::{AtomicUsize, Ordering};
|
||||||
use crate::sys::os;
|
use crate::sys::os;
|
||||||
|
|
||||||
// This is initialized in init() and only read from after
|
// This is initialized in init() and only read from after
|
||||||
static mut PAGE_SIZE: usize = 0;
|
static PAGE_SIZE: AtomicUsize = AtomicUsize::new(0);
|
||||||
|
|
||||||
pub type Guard = Range<usize>;
|
pub type Guard = Range<usize>;
|
||||||
|
|
||||||
|
@ -275,7 +276,7 @@ pub mod guard {
|
||||||
|
|
||||||
let stackaddr = if libc::pthread_main_np() == 1 {
|
let stackaddr = if libc::pthread_main_np() == 1 {
|
||||||
// main thread
|
// main thread
|
||||||
current_stack.ss_sp as usize - current_stack.ss_size + PAGE_SIZE
|
current_stack.ss_sp as usize - current_stack.ss_size + PAGE_SIZE.load(Ordering::Relaxed)
|
||||||
} else {
|
} else {
|
||||||
// new thread
|
// new thread
|
||||||
current_stack.ss_sp as usize - current_stack.ss_size
|
current_stack.ss_sp as usize - current_stack.ss_size
|
||||||
|
@ -310,7 +311,8 @@ pub mod guard {
|
||||||
|
|
||||||
// Precondition: PAGE_SIZE is initialized.
|
// Precondition: PAGE_SIZE is initialized.
|
||||||
unsafe fn get_stack_start_aligned() -> Option<*mut libc::c_void> {
|
unsafe fn get_stack_start_aligned() -> Option<*mut libc::c_void> {
|
||||||
assert!(PAGE_SIZE != 0);
|
let page_size = PAGE_SIZE.load(Ordering::Relaxed);
|
||||||
|
assert!(page_size != 0);
|
||||||
let stackaddr = get_stack_start()?;
|
let stackaddr = get_stack_start()?;
|
||||||
|
|
||||||
// Ensure stackaddr is page aligned! A parent process might
|
// Ensure stackaddr is page aligned! A parent process might
|
||||||
|
@ -319,16 +321,17 @@ pub mod guard {
|
||||||
// stackaddr < stackaddr + stacksize, so if stackaddr is not
|
// stackaddr < stackaddr + stacksize, so if stackaddr is not
|
||||||
// page-aligned, calculate the fix such that stackaddr <
|
// page-aligned, calculate the fix such that stackaddr <
|
||||||
// new_page_aligned_stackaddr < stackaddr + stacksize
|
// new_page_aligned_stackaddr < stackaddr + stacksize
|
||||||
let remainder = (stackaddr as usize) % PAGE_SIZE;
|
let remainder = (stackaddr as usize) % page_size;
|
||||||
Some(if remainder == 0 {
|
Some(if remainder == 0 {
|
||||||
stackaddr
|
stackaddr
|
||||||
} else {
|
} else {
|
||||||
((stackaddr as usize) + PAGE_SIZE - remainder) as *mut libc::c_void
|
((stackaddr as usize) + page_size - remainder) as *mut libc::c_void
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn init() -> Option<Guard> {
|
pub unsafe fn init() -> Option<Guard> {
|
||||||
PAGE_SIZE = os::page_size();
|
let page_size = os::page_size();
|
||||||
|
PAGE_SIZE.store(page_size, Ordering::Relaxed);
|
||||||
|
|
||||||
let stackaddr = get_stack_start_aligned()?;
|
let stackaddr = get_stack_start_aligned()?;
|
||||||
|
|
||||||
|
@ -344,7 +347,7 @@ pub mod guard {
|
||||||
// faulting, so our handler can report "stack overflow", and
|
// faulting, so our handler can report "stack overflow", and
|
||||||
// trust that the kernel's own stack guard will work.
|
// trust that the kernel's own stack guard will work.
|
||||||
let stackaddr = stackaddr as usize;
|
let stackaddr = stackaddr as usize;
|
||||||
Some(stackaddr - PAGE_SIZE..stackaddr)
|
Some(stackaddr - page_size..stackaddr)
|
||||||
} else {
|
} else {
|
||||||
// Reallocate the last page of the stack.
|
// Reallocate the last page of the stack.
|
||||||
// This ensures SIGBUS will be raised on
|
// This ensures SIGBUS will be raised on
|
||||||
|
@ -356,7 +359,7 @@ pub mod guard {
|
||||||
// no permissions at all. See issue #50313.
|
// no permissions at all. See issue #50313.
|
||||||
let result = mmap(
|
let result = mmap(
|
||||||
stackaddr,
|
stackaddr,
|
||||||
PAGE_SIZE,
|
page_size,
|
||||||
PROT_READ | PROT_WRITE,
|
PROT_READ | PROT_WRITE,
|
||||||
MAP_PRIVATE | MAP_ANON | MAP_FIXED,
|
MAP_PRIVATE | MAP_ANON | MAP_FIXED,
|
||||||
-1,
|
-1,
|
||||||
|
@ -366,7 +369,7 @@ pub mod guard {
|
||||||
panic!("failed to allocate a guard page");
|
panic!("failed to allocate a guard page");
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = mprotect(stackaddr, PAGE_SIZE, PROT_NONE);
|
let result = mprotect(stackaddr, page_size, PROT_NONE);
|
||||||
if result != 0 {
|
if result != 0 {
|
||||||
panic!("failed to protect the guard page");
|
panic!("failed to protect the guard page");
|
||||||
}
|
}
|
||||||
|
@ -374,14 +377,14 @@ pub mod guard {
|
||||||
let guardaddr = stackaddr as usize;
|
let guardaddr = stackaddr as usize;
|
||||||
let offset = if cfg!(target_os = "freebsd") { 2 } else { 1 };
|
let offset = if cfg!(target_os = "freebsd") { 2 } else { 1 };
|
||||||
|
|
||||||
Some(guardaddr..guardaddr + offset * PAGE_SIZE)
|
Some(guardaddr..guardaddr + offset * page_size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(target_os = "macos", target_os = "openbsd", target_os = "solaris"))]
|
#[cfg(any(target_os = "macos", target_os = "openbsd", target_os = "solaris"))]
|
||||||
pub unsafe fn current() -> Option<Guard> {
|
pub unsafe fn current() -> Option<Guard> {
|
||||||
let stackaddr = get_stack_start()? as usize;
|
let stackaddr = get_stack_start()? as usize;
|
||||||
Some(stackaddr - PAGE_SIZE..stackaddr)
|
Some(stackaddr - PAGE_SIZE.load(Ordering::Relaxed)..stackaddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
|
@ -413,7 +416,7 @@ pub mod guard {
|
||||||
ret = if cfg!(target_os = "freebsd") {
|
ret = if cfg!(target_os = "freebsd") {
|
||||||
// FIXME does freebsd really fault *below* the guard addr?
|
// FIXME does freebsd really fault *below* the guard addr?
|
||||||
let guardaddr = stackaddr - guardsize;
|
let guardaddr = stackaddr - guardsize;
|
||||||
Some(guardaddr - PAGE_SIZE..guardaddr)
|
Some(guardaddr - PAGE_SIZE.load(Ordering::Relaxed)..guardaddr)
|
||||||
} else if cfg!(target_os = "netbsd") {
|
} else if cfg!(target_os = "netbsd") {
|
||||||
Some(stackaddr - guardsize..stackaddr)
|
Some(stackaddr - guardsize..stackaddr)
|
||||||
} else if cfg!(all(target_os = "linux", target_env = "gnu")) {
|
} else if cfg!(all(target_os = "linux", target_env = "gnu")) {
|
||||||
|
|
Loading…
Reference in a new issue