about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-09-29 17:58:08 +0000
committerbors <bors@rust-lang.org>2021-09-29 17:58:08 +0000
commit11491938f80988c7261a1179cf71a25c379c8783 (patch)
treea9d9fa6a784d7eb409400b627ff6ac1aee6722c5
parent50f9f7810c975234ce4730488d32661a76a00428 (diff)
parent37608c7c501b12b634834363827e314f6750946f (diff)
downloadrust-11491938f80988c7261a1179cf71a25c379c8783.tar.gz
rust-11491938f80988c7261a1179cf71a25c379c8783.zip
Auto merge of #89011 - bjorn3:restructure_rt, r=dtolnay
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.
-rw-r--r--library/std/src/lib.rs12
-rw-r--r--library/std/src/process.rs2
-rw-r--r--library/std/src/rt.rs88
-rw-r--r--library/std/src/sys/unix/mod.rs2
-rw-r--r--library/std/src/sys_common/mod.rs2
-rw-r--r--library/std/src/sys_common/rt.rs81
-rw-r--r--library/std/src/sys_common/thread_info.rs27
-rw-r--r--library/std/src/thread/mod.rs12
8 files changed, 112 insertions, 114 deletions
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index f69baba9e73..9e7e92bdc78 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -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;
diff --git a/library/std/src/process.rs b/library/std/src/process.rs
index c9b21fcf9c6..5c68400114d 100644
--- a/library/std/src/process.rs
+++ b/library/std/src/process.rs
@@ -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)
 }
 
diff --git a/library/std/src/rt.rs b/library/std/src/rt.rs
index 893167e3730..4d72aff0116 100644
--- a/library/std/src/rt.rs
+++ b/library/std/src/rt.rs
@@ -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))]
@@ -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");
@@ -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
 }
 
diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs
index f5424e3d282..1c37f4ee498 100644
--- a/library/std/src/sys/unix/mod.rs
+++ b/library/std/src/sys/unix/mod.rs
@@ -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);
     }
 }
 
diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs
index 894440564b7..5a5913ebd79 100644
--- a/library/std/src/sys_common/mod.rs
+++ b/library/std/src/sys_common/mod.rs
@@ -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;
diff --git a/library/std/src/sys_common/rt.rs b/library/std/src/sys_common/rt.rs
deleted file mode 100644
index 02013ecc4ce..00000000000
--- a/library/std/src/sys_common/rt.rs
+++ /dev/null
@@ -1,81 +0,0 @@
-#![deny(unsafe_op_in_unsafe_fn)]
-#![allow(unused_macros)]
-
-use crate::sync::Once;
-use crate::sys;
-use crate::sys_common::thread_info;
-use crate::thread::Thread;
-
-// 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))]
-pub 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("main".to_owned()));
-        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.
-#[cfg_attr(test, allow(dead_code))]
-pub 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();
-    });
-}
-
-// 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)
-            }
-        }
-    };
-}
diff --git a/library/std/src/sys_common/thread_info.rs b/library/std/src/sys_common/thread_info.rs
index f09d16c33e6..38c9e50009a 100644
--- a/library/std/src/sys_common/thread_info.rs
+++ b/library/std/src/sys_common/thread_info.rs
@@ -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;
@@ -9,7 +10,7 @@ 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>
@@ -17,12 +18,13 @@ impl ThreadInfo {
         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()
     }
@@ -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 });
+    });
 }
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index f44df845bf4..9d659102b03 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -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));
@@ -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.