Skip to content

Commit

Permalink
Auto merge of #89011 - bjorn3:restructure_rt, r=dtolnay
Browse files Browse the repository at this point in the history
Restructure std::rt

These changes should reduce binary size slightly while at the same slightly improving performance of startup, thread spawning and `std::thread::current()`. I haven't verified if the compiler is able to optimize some of these cases already, but at least for some others the compiler is unable to do these optimizations as they slightly change behavior in cases where program startup would crash anyway by omitting a backtrace and panic location.

I can remove 6f6bb16 if preferred.
  • Loading branch information
bors committed Sep 29, 2021
2 parents 50f9f78 + 37608c7 commit 1149193
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 114 deletions.
12 changes: 6 additions & 6 deletions library/std/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -520,20 +520,20 @@ pub mod task {
pub use alloc::task::*;
}

// Platform-abstraction modules
// The runtime entry point and a few unstable public functions used by the
// compiler
#[macro_use]
mod sys_common;
pub mod rt;

// Platform-abstraction modules
mod sys;
mod sys_common;

pub mod alloc;

// Private support modules
mod panicking;

// The runtime entry point and a few unstable public functions used by the
// compiler
pub mod rt;

#[path = "../../backtrace/src/lib.rs"]
#[allow(dead_code, unused_attributes)]
mod backtrace_rs;
Expand Down
2 changes: 1 addition & 1 deletion library/std/src/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1907,7 +1907,7 @@ impl Child {
/// [platform-specific behavior]: #platform-specific-behavior
#[stable(feature = "rust1", since = "1.0.0")]
pub fn exit(code: i32) -> ! {
crate::sys_common::rt::cleanup();
crate::rt::cleanup();
crate::sys::os::exit(code)
}

Expand Down
88 changes: 85 additions & 3 deletions library/std/src/rt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,93 @@
issue = "none"
)]
#![doc(hidden)]
#![deny(unsafe_op_in_unsafe_fn)]
#![allow(unused_macros)]

use crate::ffi::CString;

// Re-export some of our utilities which are expected by other crates.
pub use crate::panicking::{begin_panic, begin_panic_fmt, panic_count};
pub use core::panicking::panic_display;

use crate::sync::Once;
use crate::sys;
use crate::sys_common::thread_info;
use crate::thread::Thread;

// Prints to the "panic output", depending on the platform this may be:
// - the standard error output
// - some dedicated platform specific output
// - nothing (so this macro is a no-op)
macro_rules! rtprintpanic {
($($t:tt)*) => {
if let Some(mut out) = crate::sys::stdio::panic_output() {
let _ = crate::io::Write::write_fmt(&mut out, format_args!($($t)*));
}
}
}

macro_rules! rtabort {
($($t:tt)*) => {
{
rtprintpanic!("fatal runtime error: {}\n", format_args!($($t)*));
crate::sys::abort_internal();
}
}
}

macro_rules! rtassert {
($e:expr) => {
if !$e {
rtabort!(concat!("assertion failed: ", stringify!($e)));
}
};
}

macro_rules! rtunwrap {
($ok:ident, $e:expr) => {
match $e {
$ok(v) => v,
ref err => {
let err = err.as_ref().map(drop); // map Ok/Some which might not be Debug
rtabort!(concat!("unwrap failed: ", stringify!($e), " = {:?}"), err)
}
}
};
}

// One-time runtime initialization.
// Runs before `main`.
// SAFETY: must be called only once during runtime initialization.
// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
#[cfg_attr(test, allow(dead_code))]
unsafe fn init(argc: isize, argv: *const *const u8) {
unsafe {
sys::init(argc, argv);

let main_guard = sys::thread::guard::init();
// Next, set up the current Thread with the guard information we just
// created. Note that this isn't necessary in general for new threads,
// but we just do this to name the main thread and to give it correct
// info about the stack bounds.
let thread = Thread::new(Some(rtunwrap!(Ok, CString::new("main"))));
thread_info::set(main_guard, thread);
}
}

// One-time runtime cleanup.
// Runs after `main` or at program exit.
// NOTE: this is not guaranteed to run, for example when the program aborts.
pub(crate) fn cleanup() {
static CLEANUP: Once = Once::new();
CLEANUP.call_once(|| unsafe {
// Flush stdout and disable buffering.
crate::io::cleanup();
// SAFETY: Only called once during runtime cleanup.
sys::cleanup();
});
}

// To reduce the generated code of the new `lang_start`, this function is doing
// the real work.
#[cfg(not(test))]
Expand All @@ -26,7 +108,7 @@ fn lang_start_internal(
argc: isize,
argv: *const *const u8,
) -> Result<isize, !> {
use crate::{mem, panic, sys, sys_common};
use crate::{mem, panic};
let rt_abort = move |e| {
mem::forget(e);
rtabort!("initialization or cleanup bug");
Expand All @@ -42,14 +124,14 @@ fn lang_start_internal(
// prevent libstd from accidentally introducing a panic to these functions. Another is from
// user code from `main` or, more nefariously, as described in e.g. issue #86030.
// SAFETY: Only called once during runtime initialization.
panic::catch_unwind(move || unsafe { sys_common::rt::init(argc, argv) }).map_err(rt_abort)?;
panic::catch_unwind(move || unsafe { init(argc, argv) }).map_err(rt_abort)?;
let ret_code = panic::catch_unwind(move || panic::catch_unwind(main).unwrap_or(101) as isize)
.map_err(move |e| {
mem::forget(e);
rtprintpanic!("drop of the panic payload panicked");
sys::abort_internal()
});
panic::catch_unwind(sys_common::rt::cleanup).map_err(rt_abort)?;
panic::catch_unwind(cleanup).map_err(rt_abort)?;
ret_code
}

Expand Down
2 changes: 1 addition & 1 deletion library/std/src/sys/unix/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8) {

unsafe fn reset_sigpipe() {
#[cfg(not(any(target_os = "emscripten", target_os = "fuchsia")))]
assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != libc::SIG_ERR);
rtassert!(signal(libc::SIGPIPE, libc::SIG_IGN) != libc::SIG_ERR);
}
}

Expand Down
2 changes: 0 additions & 2 deletions library/std/src/sys_common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ pub mod memchr;
pub mod mutex;
pub mod process;
pub mod remutex;
#[macro_use]
pub mod rt;
pub mod rwlock;
pub mod thread;
pub mod thread_info;
Expand Down
81 changes: 0 additions & 81 deletions library/std/src/sys_common/rt.rs

This file was deleted.

27 changes: 14 additions & 13 deletions library/std/src/sys_common/thread_info.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#![allow(dead_code)] // stack_guard isn't used right now on all platforms
#![allow(unused_unsafe)] // thread_local with `const {}` triggers this liny

use crate::cell::RefCell;
use crate::sys::thread::guard::Guard;
Expand All @@ -9,20 +10,21 @@ struct ThreadInfo {
thread: Thread,
}

thread_local! { static THREAD_INFO: RefCell<Option<ThreadInfo>> = RefCell::new(None) }
thread_local! { static THREAD_INFO: RefCell<Option<ThreadInfo>> = const { RefCell::new(None) } }

impl ThreadInfo {
fn with<R, F>(f: F) -> Option<R>
where
F: FnOnce(&mut ThreadInfo) -> R,
{
THREAD_INFO
.try_with(move |c| {
if c.borrow().is_none() {
*c.borrow_mut() =
Some(ThreadInfo { stack_guard: None, thread: Thread::new(None) })
}
f(c.borrow_mut().as_mut().unwrap())
.try_with(move |thread_info| {
let mut thread_info = thread_info.borrow_mut();
let thread_info = thread_info.get_or_insert_with(|| ThreadInfo {
stack_guard: None,
thread: Thread::new(None),
});
f(thread_info)
})
.ok()
}
Expand All @@ -37,10 +39,9 @@ pub fn stack_guard() -> Option<Guard> {
}

pub fn set(stack_guard: Option<Guard>, thread: Thread) {
THREAD_INFO.with(|c| assert!(c.borrow().is_none()));
THREAD_INFO.with(move |c| *c.borrow_mut() = Some(ThreadInfo { stack_guard, thread }));
}

pub fn reset_guard(stack_guard: Option<Guard>) {
THREAD_INFO.with(move |c| c.borrow_mut().as_mut().unwrap().stack_guard = stack_guard);
THREAD_INFO.with(move |thread_info| {
let mut thread_info = thread_info.borrow_mut();
rtassert!(thread_info.is_none());
*thread_info = Some(ThreadInfo { stack_guard, thread });
});
}
12 changes: 5 additions & 7 deletions library/std/src/thread/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,9 @@ impl Builder {

let stack_size = stack_size.unwrap_or_else(thread::min_stack);

let my_thread = Thread::new(name);
let my_thread = Thread::new(name.map(|name| {
CString::new(name).expect("thread name may not contain interior null bytes")
}));
let their_thread = my_thread.clone();

let my_packet: Arc<UnsafeCell<Option<Result<T>>>> = Arc::new(UnsafeCell::new(None));
Expand Down Expand Up @@ -1073,12 +1075,8 @@ pub struct Thread {
impl Thread {
// Used only internally to construct a thread object without spawning
// Panics if the name contains nuls.
pub(crate) fn new(name: Option<String>) -> Thread {
let cname =
name.map(|n| CString::new(n).expect("thread name may not contain interior null bytes"));
Thread {
inner: Arc::new(Inner { name: cname, id: ThreadId::new(), parker: Parker::new() }),
}
pub(crate) fn new(name: Option<CString>) -> Thread {
Thread { inner: Arc::new(Inner { name, id: ThreadId::new(), parker: Parker::new() }) }
}

/// Atomically makes the handle's token available if it is not already.
Expand Down

0 comments on commit 1149193

Please sign in to comment.