From 568840707cd5f98a1970a44d632b833439d5312e Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Fri, 30 Sep 2016 20:13:58 +0000 Subject: [PATCH 01/10] std: Move elf TLS to sys::fast_thread_local --- src/libstd/sys/unix/fast_thread_local.rs | 167 +++++++++++++++++++++++ src/libstd/sys/unix/mod.rs | 1 + src/libstd/thread/local.rs | 163 +--------------------- src/libstd/thread/mod.rs | 2 +- src/tools/tidy/src/pal.rs | 1 - 5 files changed, 171 insertions(+), 163 deletions(-) create mode 100644 src/libstd/sys/unix/fast_thread_local.rs diff --git a/src/libstd/sys/unix/fast_thread_local.rs b/src/libstd/sys/unix/fast_thread_local.rs new file mode 100644 index 0000000000000..0c625e7add9d0 --- /dev/null +++ b/src/libstd/sys/unix/fast_thread_local.rs @@ -0,0 +1,167 @@ +// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![cfg(target_thread_local)] +#![unstable(feature = "thread_local_internals", issue = "0")] + +use cell::{Cell, UnsafeCell}; +use intrinsics; +use ptr; + +pub struct Key { + inner: UnsafeCell>, + + // Metadata to keep track of the state of the destructor. Remember that + // these variables are thread-local, not global. + dtor_registered: Cell, + dtor_running: Cell, +} + +unsafe impl ::marker::Sync for Key { } + +impl Key { + pub const fn new() -> Key { + Key { + inner: UnsafeCell::new(None), + dtor_registered: Cell::new(false), + dtor_running: Cell::new(false) + } + } + + pub fn get(&'static self) -> Option<&'static UnsafeCell>> { + unsafe { + if intrinsics::needs_drop::() && self.dtor_running.get() { + return None + } + self.register_dtor(); + } + Some(&self.inner) + } + + unsafe fn register_dtor(&self) { + if !intrinsics::needs_drop::() || self.dtor_registered.get() { + return + } + + register_dtor(self as *const _ as *mut u8, + destroy_value::); + self.dtor_registered.set(true); + } +} + +#[cfg(any(target_os = "linux", target_os = "fuchsia"))] +unsafe fn register_dtor_fallback(t: *mut u8, dtor: unsafe extern fn(*mut u8)) { + // The fallback implementation uses a vanilla OS-based TLS key to track + // the list of destructors that need to be run for this thread. The key + // then has its own destructor which runs all the other destructors. + // + // The destructor for DTORS is a little special in that it has a `while` + // loop to continuously drain the list of registered destructors. It + // *should* be the case that this loop always terminates because we + // provide the guarantee that a TLS key cannot be set after it is + // flagged for destruction. + use sys_common::thread_local as os; + + static DTORS: os::StaticKey = os::StaticKey::new(Some(run_dtors)); + type List = Vec<(*mut u8, unsafe extern fn(*mut u8))>; + if DTORS.get().is_null() { + let v: Box = box Vec::new(); + DTORS.set(Box::into_raw(v) as *mut u8); + } + let list: &mut List = &mut *(DTORS.get() as *mut List); + list.push((t, dtor)); + + unsafe extern fn run_dtors(mut ptr: *mut u8) { + while !ptr.is_null() { + let list: Box = Box::from_raw(ptr as *mut List); + for &(ptr, dtor) in list.iter() { + dtor(ptr); + } + ptr = DTORS.get(); + DTORS.set(ptr::null_mut()); + } + } +} + +// Since what appears to be glibc 2.18 this symbol has been shipped which +// GCC and clang both use to invoke destructors in thread_local globals, so +// let's do the same! +// +// Note, however, that we run on lots older linuxes, as well as cross +// compiling from a newer linux to an older linux, so we also have a +// fallback implementation to use as well. +// +// Due to rust-lang/rust#18804, make sure this is not generic! +#[cfg(target_os = "linux")] +unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) { + use mem; + use libc; + + extern { + #[linkage = "extern_weak"] + static __dso_handle: *mut u8; + #[linkage = "extern_weak"] + static __cxa_thread_atexit_impl: *const libc::c_void; + } + if !__cxa_thread_atexit_impl.is_null() { + type F = unsafe extern fn(dtor: unsafe extern fn(*mut u8), + arg: *mut u8, + dso_handle: *mut u8) -> libc::c_int; + mem::transmute::<*const libc::c_void, F>(__cxa_thread_atexit_impl) + (dtor, t, &__dso_handle as *const _ as *mut _); + return + } + register_dtor_fallback(t, dtor); +} + +// OSX's analog of the above linux function is this _tlv_atexit function. +// The disassembly of thread_local globals in C++ (at least produced by +// clang) will have this show up in the output. +#[cfg(target_os = "macos")] +unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) { + extern { + fn _tlv_atexit(dtor: unsafe extern fn(*mut u8), + arg: *mut u8); + } + _tlv_atexit(dtor, t); +} + +// Just use the thread_local fallback implementation, at least until there's +// a more direct implementation. +#[cfg(target_os = "fuchsia")] +unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) { + register_dtor_fallback(t, dtor); +} + +pub unsafe extern fn destroy_value(ptr: *mut u8) { + let ptr = ptr as *mut Key; + // Right before we run the user destructor be sure to flag the + // destructor as running for this thread so calls to `get` will return + // `None`. + (*ptr).dtor_running.set(true); + + // The OSX implementation of TLS apparently had an odd aspect to it + // where the pointer we have may be overwritten while this destructor + // is running. Specifically if a TLS destructor re-accesses TLS it may + // trigger a re-initialization of all TLS variables, paving over at + // least some destroyed ones with initial values. + // + // This means that if we drop a TLS value in place on OSX that we could + // revert the value to its original state halfway through the + // destructor, which would be bad! + // + // Hence, we use `ptr::read` on OSX (to move to a "safe" location) + // instead of drop_in_place. + if cfg!(target_os = "macos") { + ptr::read((*ptr).inner.get()); + } else { + ptr::drop_in_place((*ptr).inner.get()); + } +} diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs index 66bc9d4a4915f..0e28426b32f20 100644 --- a/src/libstd/sys/unix/mod.rs +++ b/src/libstd/sys/unix/mod.rs @@ -38,6 +38,7 @@ pub mod backtrace; pub mod condvar; pub mod env; pub mod ext; +pub mod fast_thread_local; pub mod fd; pub mod fs; pub mod memchr; diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index 54d3f7930456c..f74dd5924951c 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -166,8 +166,8 @@ macro_rules! __thread_local_inner { { #[thread_local] #[cfg(target_thread_local)] - static __KEY: $crate::thread::__ElfLocalKeyInner<$t> = - $crate::thread::__ElfLocalKeyInner::new(); + static __KEY: $crate::thread::__FastLocalKeyInner<$t> = + $crate::thread::__FastLocalKeyInner::new(); #[cfg(not(target_thread_local))] static __KEY: $crate::thread::__OsLocalKeyInner<$t> = @@ -310,165 +310,6 @@ impl LocalKey { } } -#[cfg(target_thread_local)] -#[doc(hidden)] -pub mod elf { - use cell::{Cell, UnsafeCell}; - use intrinsics; - use ptr; - - pub struct Key { - inner: UnsafeCell>, - - // Metadata to keep track of the state of the destructor. Remember that - // these variables are thread-local, not global. - dtor_registered: Cell, - dtor_running: Cell, - } - - unsafe impl ::marker::Sync for Key { } - - impl Key { - pub const fn new() -> Key { - Key { - inner: UnsafeCell::new(None), - dtor_registered: Cell::new(false), - dtor_running: Cell::new(false) - } - } - - pub fn get(&'static self) -> Option<&'static UnsafeCell>> { - unsafe { - if intrinsics::needs_drop::() && self.dtor_running.get() { - return None - } - self.register_dtor(); - } - Some(&self.inner) - } - - unsafe fn register_dtor(&self) { - if !intrinsics::needs_drop::() || self.dtor_registered.get() { - return - } - - register_dtor(self as *const _ as *mut u8, - destroy_value::); - self.dtor_registered.set(true); - } - } - - #[cfg(any(target_os = "linux", target_os = "fuchsia"))] - unsafe fn register_dtor_fallback(t: *mut u8, dtor: unsafe extern fn(*mut u8)) { - // The fallback implementation uses a vanilla OS-based TLS key to track - // the list of destructors that need to be run for this thread. The key - // then has its own destructor which runs all the other destructors. - // - // The destructor for DTORS is a little special in that it has a `while` - // loop to continuously drain the list of registered destructors. It - // *should* be the case that this loop always terminates because we - // provide the guarantee that a TLS key cannot be set after it is - // flagged for destruction. - use sys_common::thread_local as os; - - static DTORS: os::StaticKey = os::StaticKey::new(Some(run_dtors)); - type List = Vec<(*mut u8, unsafe extern fn(*mut u8))>; - if DTORS.get().is_null() { - let v: Box = box Vec::new(); - DTORS.set(Box::into_raw(v) as *mut u8); - } - let list: &mut List = &mut *(DTORS.get() as *mut List); - list.push((t, dtor)); - - unsafe extern fn run_dtors(mut ptr: *mut u8) { - while !ptr.is_null() { - let list: Box = Box::from_raw(ptr as *mut List); - for &(ptr, dtor) in list.iter() { - dtor(ptr); - } - ptr = DTORS.get(); - DTORS.set(ptr::null_mut()); - } - } - } - - // Since what appears to be glibc 2.18 this symbol has been shipped which - // GCC and clang both use to invoke destructors in thread_local globals, so - // let's do the same! - // - // Note, however, that we run on lots older linuxes, as well as cross - // compiling from a newer linux to an older linux, so we also have a - // fallback implementation to use as well. - // - // Due to rust-lang/rust#18804, make sure this is not generic! - #[cfg(target_os = "linux")] - unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) { - use mem; - use libc; - - extern { - #[linkage = "extern_weak"] - static __dso_handle: *mut u8; - #[linkage = "extern_weak"] - static __cxa_thread_atexit_impl: *const libc::c_void; - } - if !__cxa_thread_atexit_impl.is_null() { - type F = unsafe extern fn(dtor: unsafe extern fn(*mut u8), - arg: *mut u8, - dso_handle: *mut u8) -> libc::c_int; - mem::transmute::<*const libc::c_void, F>(__cxa_thread_atexit_impl) - (dtor, t, &__dso_handle as *const _ as *mut _); - return - } - register_dtor_fallback(t, dtor); - } - - // OSX's analog of the above linux function is this _tlv_atexit function. - // The disassembly of thread_local globals in C++ (at least produced by - // clang) will have this show up in the output. - #[cfg(target_os = "macos")] - unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) { - extern { - fn _tlv_atexit(dtor: unsafe extern fn(*mut u8), - arg: *mut u8); - } - _tlv_atexit(dtor, t); - } - - // Just use the thread_local fallback implementation, at least until there's - // a more direct implementation. - #[cfg(target_os = "fuchsia")] - unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) { - register_dtor_fallback(t, dtor); - } - - pub unsafe extern fn destroy_value(ptr: *mut u8) { - let ptr = ptr as *mut Key; - // Right before we run the user destructor be sure to flag the - // destructor as running for this thread so calls to `get` will return - // `None`. - (*ptr).dtor_running.set(true); - - // The OSX implementation of TLS apparently had an odd aspect to it - // where the pointer we have may be overwritten while this destructor - // is running. Specifically if a TLS destructor re-accesses TLS it may - // trigger a re-initialization of all TLS variables, paving over at - // least some destroyed ones with initial values. - // - // This means that if we drop a TLS value in place on OSX that we could - // revert the value to its original state halfway through the - // destructor, which would be bad! - // - // Hence, we use `ptr::read` on OSX (to move to a "safe" location) - // instead of drop_in_place. - if cfg!(target_os = "macos") { - ptr::read((*ptr).inner.get()); - } else { - ptr::drop_in_place((*ptr).inner.get()); - } - } -} - #[doc(hidden)] pub mod os { use cell::{Cell, UnsafeCell}; diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 150482e4af458..4c3980b3c7b34 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -183,7 +183,7 @@ pub use self::local::{LocalKey, LocalKeyState}; #[unstable(feature = "libstd_thread_internals", issue = "0")] #[cfg(target_thread_local)] -#[doc(hidden)] pub use self::local::elf::Key as __ElfLocalKeyInner; +#[doc(hidden)] pub use sys::fast_thread_local::Key as __FastLocalKeyInner; #[unstable(feature = "libstd_thread_internals", issue = "0")] #[doc(hidden)] pub use self::local::os::Key as __OsLocalKeyInner; diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs index 1d04e8fc8eb79..80a2d22691b8b 100644 --- a/src/tools/tidy/src/pal.rs +++ b/src/tools/tidy/src/pal.rs @@ -69,7 +69,6 @@ const EXCEPTION_PATHS: &'static [&'static str] = &[ "src/libstd/io/stdio.rs", "src/libstd/num/f32.rs", "src/libstd/num/f64.rs", - "src/libstd/thread/local.rs", "src/libstd/sys/common/mod.rs", "src/libstd/sys/common/net.rs", "src/libstd/sys/common/util.rs", From 8b2600dbf9a02a19acc92db5d980986cad2ea38d Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Tue, 4 Oct 2016 18:00:27 +0000 Subject: [PATCH 02/10] Document reasoning for supporting both fast and OS TLS in the same bin --- src/libstd/thread/mod.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 4c3980b3c7b34..255cd2a9bc0f1 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -181,6 +181,15 @@ use time::Duration; #[stable(feature = "rust1", since = "1.0.0")] pub use self::local::{LocalKey, LocalKeyState}; +// The types used by the thread_local! macro to access TLS keys. Note that there +// are two types, the "OS" type and the "fast" type. The OS thread local key +// type is accessed via platform-specific API calls and is slow, while the fast +// key type is accessed via code generated via LLVM, where TLS keys are set up +// by the elf linker. Note that the OS TLS type is always available: on macOS +// the standard library is compiled with support for older platform versions +// where fast TLS was not available; end-user code is compiled with fast TLS +// where available, but both are needed. + #[unstable(feature = "libstd_thread_internals", issue = "0")] #[cfg(target_thread_local)] #[doc(hidden)] pub use sys::fast_thread_local::Key as __FastLocalKeyInner; From 6d54cd4b2cd864fbd6f2f8d036903f88b6ea79b4 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Fri, 30 Sep 2016 21:01:53 +0000 Subject: [PATCH 03/10] std: Move a plattform-specific constant to sys::stdio --- src/libstd/io/mod.rs | 2 +- src/libstd/io/stdio.rs | 10 +--------- src/libstd/sys/common/io.rs | 2 ++ src/libstd/sys/unix/stdio.rs | 1 + src/libstd/sys/windows/stdio.rs | 5 +++++ src/tools/tidy/src/pal.rs | 1 - 6 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 37c3f70d54dda..193f396c0d4ab 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -289,7 +289,7 @@ mod lazy; mod util; mod stdio; -const DEFAULT_BUF_SIZE: usize = 8 * 1024; +const DEFAULT_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE; // A few methods below (read_to_string, read_line) will append data into a // `String` buffer, but we need to be pretty careful when doing this. The diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index c24ee8ff303c8..1777b79ea1b59 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -214,15 +214,7 @@ pub fn stdin() -> Stdin { _ => Maybe::Fake }; - // The default buffer capacity is 64k, but apparently windows - // doesn't like 64k reads on stdin. See #13304 for details, but the - // idea is that on windows we use a slightly smaller buffer that's - // been seen to be acceptable. - Arc::new(Mutex::new(if cfg!(windows) { - BufReader::with_capacity(8 * 1024, stdin) - } else { - BufReader::new(stdin) - })) + Arc::new(Mutex::new(BufReader::with_capacity(stdio::STDIN_BUF_SIZE, stdin))) } } diff --git a/src/libstd/sys/common/io.rs b/src/libstd/sys/common/io.rs index 0483725dd83bc..23daeeb5187b7 100644 --- a/src/libstd/sys/common/io.rs +++ b/src/libstd/sys/common/io.rs @@ -12,6 +12,8 @@ use io::ErrorKind; use io::Read; use slice::from_raw_parts_mut; +pub const DEFAULT_BUF_SIZE: usize = 8 * 1024; + // Provides read_to_end functionality over an uninitialized buffer. // This function is unsafe because it calls the underlying // read function with a slice into uninitialized memory. The default diff --git a/src/libstd/sys/unix/stdio.rs b/src/libstd/sys/unix/stdio.rs index 947ba2cc75232..273341b1918d1 100644 --- a/src/libstd/sys/unix/stdio.rs +++ b/src/libstd/sys/unix/stdio.rs @@ -67,3 +67,4 @@ impl io::Write for Stderr { } pub const EBADF_ERR: i32 = ::libc::EBADF as i32; +pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE; diff --git a/src/libstd/sys/windows/stdio.rs b/src/libstd/sys/windows/stdio.rs index 5f097d2631d95..72788776dedd6 100644 --- a/src/libstd/sys/windows/stdio.rs +++ b/src/libstd/sys/windows/stdio.rs @@ -207,3 +207,8 @@ fn invalid_encoding() -> io::Error { } pub const EBADF_ERR: i32 = ::sys::c::ERROR_INVALID_HANDLE as i32; +// The default buffer capacity is 64k, but apparently windows +// doesn't like 64k reads on stdin. See #13304 for details, but the +// idea is that on windows we use a slightly smaller buffer that's +// been seen to be acceptable. +pub const STDIN_BUF_SIZE: usize = 8 * 1024; diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs index 80a2d22691b8b..6ce5f7ee7fe27 100644 --- a/src/tools/tidy/src/pal.rs +++ b/src/tools/tidy/src/pal.rs @@ -66,7 +66,6 @@ const EXCEPTION_PATHS: &'static [&'static str] = &[ "src/libstd/lib.rs", // This could probably be done within the sys directory "src/libstd/rtdeps.rs", // Until rustbuild replaces make "src/libstd/path.rs", - "src/libstd/io/stdio.rs", "src/libstd/num/f32.rs", "src/libstd/num/f64.rs", "src/libstd/sys/common/mod.rs", From 219c018894b31fec7059ca89bb1ab0606068aeaf Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Fri, 30 Sep 2016 22:11:46 +0000 Subject: [PATCH 04/10] std: Move platform-specific code out of libstd/lib.rs --- src/libstd/lib.rs | 5 +---- src/libstd/sys/mod.rs | 19 +++++++++++++++++++ src/libstd/sys/windows/mod.rs | 6 +++--- src/tools/tidy/src/pal.rs | 6 +++--- 4 files changed, 26 insertions(+), 10 deletions(-) create mode 100644 src/libstd/sys/mod.rs diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index e470690b7c6b8..1d6c2403c2fe6 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -458,10 +458,7 @@ mod memchr; #[macro_use] #[path = "sys/common/mod.rs"] mod sys_common; -#[cfg(unix)] -#[path = "sys/unix/mod.rs"] mod sys; -#[cfg(windows)] -#[path = "sys/windows/mod.rs"] mod sys; +mod sys; pub mod rt; mod panicking; diff --git a/src/libstd/sys/mod.rs b/src/libstd/sys/mod.rs new file mode 100644 index 0000000000000..f7e1a0a075a85 --- /dev/null +++ b/src/libstd/sys/mod.rs @@ -0,0 +1,19 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub use self::imp::*; + +#[cfg(unix)] +#[path = "unix/mod.rs"] +mod imp; + +#[cfg(windows)] +#[path = "windows/mod.rs"] +mod imp; diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index 9cd6e6ca1761d..0610a0245ea68 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -179,7 +179,7 @@ pub fn truncate_utf16_at_nul<'a>(v: &'a [u16]) -> &'a [u16] { } } -trait IsZero { +pub trait IsZero { fn is_zero(&self) -> bool; } @@ -193,7 +193,7 @@ macro_rules! impl_is_zero { impl_is_zero! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize } -fn cvt(i: I) -> io::Result { +pub fn cvt(i: I) -> io::Result { if i.is_zero() { Err(io::Error::last_os_error()) } else { @@ -201,7 +201,7 @@ fn cvt(i: I) -> io::Result { } } -fn dur2timeout(dur: Duration) -> c::DWORD { +pub fn dur2timeout(dur: Duration) -> c::DWORD { // Note that a duration is a (u64, u32) (seconds, nanoseconds) pair, and the // timeouts in windows APIs are typically u32 milliseconds. To translate, we // have two pieces to take care of: diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs index 6ce5f7ee7fe27..5caa7f8af440d 100644 --- a/src/tools/tidy/src/pal.rs +++ b/src/tools/tidy/src/pal.rs @@ -57,13 +57,13 @@ const EXCEPTION_PATHS: &'static [&'static str] = &[ "src/libpanic_abort", "src/libpanic_unwind", "src/libunwind", - "src/libstd/sys/unix", // This is where platform-specific code for std should live - "src/libstd/sys/windows", // Ditto + "src/libstd/sys/unix", // This is where platform-specific code for unix + "src/libstd/sys/windows", // Ditto for windows + "src/libstd/sys/mod.rs", // This file chooses the platform "src/libstd/os", // Platform-specific public interfaces "src/rtstartup", // Not sure what to do about this. magic stuff for mingw // temporary exceptions - "src/libstd/lib.rs", // This could probably be done within the sys directory "src/libstd/rtdeps.rs", // Until rustbuild replaces make "src/libstd/path.rs", "src/libstd/num/f32.rs", From f3a709dc52bb3e617ccb016a8b20a741c23da77d Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Fri, 30 Sep 2016 23:07:04 +0000 Subject: [PATCH 05/10] std: Move platform-specific out of sys_common::util --- src/libstd/sys/common/util.rs | 28 +--------------------------- src/libstd/sys/unix/mod.rs | 11 +++++++++++ src/libstd/sys/windows/mod.rs | 14 ++++++++++++++ src/tools/tidy/src/pal.rs | 1 - 4 files changed, 26 insertions(+), 28 deletions(-) diff --git a/src/libstd/sys/common/util.rs b/src/libstd/sys/common/util.rs index b5d0357633875..daa0c15920b66 100644 --- a/src/libstd/sys/common/util.rs +++ b/src/libstd/sys/common/util.rs @@ -33,32 +33,6 @@ pub fn dumb_print(args: fmt::Arguments) { let _ = Stderr::new().map(|mut stderr| stderr.write_fmt(args)); } -// On Unix-like platforms, libc::abort will unregister signal handlers -// including the SIGABRT handler, preventing the abort from being blocked, and -// fclose streams, with the side effect of flushing them so libc bufferred -// output will be printed. Additionally the shell will generally print a more -// understandable error message like "Abort trap" rather than "Illegal -// instruction" that intrinsics::abort would cause, as intrinsics::abort is -// implemented as an illegal instruction. -#[cfg(unix)] -unsafe fn abort_internal() -> ! { - ::libc::abort() -} - -// On Windows, use the processor-specific __fastfail mechanism. In Windows 8 -// and later, this will terminate the process immediately without running any -// in-process exception handlers. In earlier versions of Windows, this -// sequence of instructions will be treated as an access violation, -// terminating the process but without necessarily bypassing all exception -// handlers. -// -// https://msdn.microsoft.com/en-us/library/dn774154.aspx -#[cfg(all(windows, any(target_arch = "x86", target_arch = "x86_64")))] -unsafe fn abort_internal() -> ! { - asm!("int $$0x29" :: "{ecx}"(7) ::: volatile); // 7 is FAST_FAIL_FATAL_APP_EXIT - ::intrinsics::unreachable(); -} - // Other platforms should use the appropriate platform-specific mechanism for // aborting the process. If no platform-specific mechanism is available, // ::intrinsics::abort() may be used instead. The above implementations cover @@ -66,7 +40,7 @@ unsafe fn abort_internal() -> ! { pub fn abort(args: fmt::Arguments) -> ! { dumb_print(format_args!("fatal runtime error: {}\n", args)); - unsafe { abort_internal(); } + unsafe { ::sys::abort_internal(); } } #[allow(dead_code)] // stack overflow detection not enabled on all platforms diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs index 0e28426b32f20..fd7dc17cccd8c 100644 --- a/src/libstd/sys/unix/mod.rs +++ b/src/libstd/sys/unix/mod.rs @@ -163,3 +163,14 @@ pub fn cvt_r(mut f: F) -> io::Result } } } + +// On Unix-like platforms, libc::abort will unregister signal handlers +// including the SIGABRT handler, preventing the abort from being blocked, and +// fclose streams, with the side effect of flushing them so libc bufferred +// output will be printed. Additionally the shell will generally print a more +// understandable error message like "Abort trap" rather than "Illegal +// instruction" that intrinsics::abort would cause, as intrinsics::abort is +// implemented as an illegal instruction. +pub unsafe fn abort_internal() -> ! { + ::libc::abort() +} diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index 0610a0245ea68..defc41c5f46a3 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -221,3 +221,17 @@ pub fn dur2timeout(dur: Duration) -> c::DWORD { } }).unwrap_or(c::INFINITE) } + +// On Windows, use the processor-specific __fastfail mechanism. In Windows 8 +// and later, this will terminate the process immediately without running any +// in-process exception handlers. In earlier versions of Windows, this +// sequence of instructions will be treated as an access violation, +// terminating the process but without necessarily bypassing all exception +// handlers. +// +// https://msdn.microsoft.com/en-us/library/dn774154.aspx +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +pub unsafe fn abort_internal() -> ! { + asm!("int $$0x29" :: "{ecx}"(7) ::: volatile); // 7 is FAST_FAIL_FATAL_APP_EXIT + ::intrinsics::unreachable(); +} diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs index 5caa7f8af440d..68b0c819c5a8b 100644 --- a/src/tools/tidy/src/pal.rs +++ b/src/tools/tidy/src/pal.rs @@ -70,7 +70,6 @@ const EXCEPTION_PATHS: &'static [&'static str] = &[ "src/libstd/num/f64.rs", "src/libstd/sys/common/mod.rs", "src/libstd/sys/common/net.rs", - "src/libstd/sys/common/util.rs", "src/libterm", // Not sure how to make this crate portable, but test needs it "src/libtest", // Probably should defer to unstable std::sys APIs From ca30691813836e1c6896e5ba5d4397eb717e7270 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Fri, 30 Sep 2016 23:26:44 +0000 Subject: [PATCH 06/10] std: Move sys_common to libstd/sys_common Make the directory structure reflect the module structure. I've always found the existing structure confusing. --- src/libstd/lib.rs | 3 +-- src/libstd/{sys/common => sys_common}/at_exit_imp.rs | 0 src/libstd/{sys/common => sys_common}/backtrace.rs | 0 src/libstd/{sys/common => sys_common}/condvar.rs | 0 .../{sys/common => sys_common}/gnu/libbacktrace.rs | 0 src/libstd/{sys/common => sys_common}/gnu/mod.rs | 0 src/libstd/{sys/common => sys_common}/io.rs | 0 src/libstd/{sys/common => sys_common}/memchr.rs | 0 src/libstd/{sys/common => sys_common}/mod.rs | 0 src/libstd/{sys/common => sys_common}/mutex.rs | 0 src/libstd/{sys/common => sys_common}/net.rs | 0 src/libstd/{sys/common => sys_common}/poison.rs | 0 src/libstd/{sys/common => sys_common}/remutex.rs | 0 src/libstd/{sys/common => sys_common}/rwlock.rs | 0 src/libstd/{sys/common => sys_common}/thread.rs | 0 src/libstd/{sys/common => sys_common}/thread_info.rs | 0 src/libstd/{sys/common => sys_common}/thread_local.rs | 0 src/libstd/{sys/common => sys_common}/util.rs | 0 src/libstd/{sys/common => sys_common}/wtf8.rs | 0 src/tools/tidy/src/pal.rs | 9 ++++----- 20 files changed, 5 insertions(+), 7 deletions(-) rename src/libstd/{sys/common => sys_common}/at_exit_imp.rs (100%) rename src/libstd/{sys/common => sys_common}/backtrace.rs (100%) rename src/libstd/{sys/common => sys_common}/condvar.rs (100%) rename src/libstd/{sys/common => sys_common}/gnu/libbacktrace.rs (100%) rename src/libstd/{sys/common => sys_common}/gnu/mod.rs (100%) rename src/libstd/{sys/common => sys_common}/io.rs (100%) rename src/libstd/{sys/common => sys_common}/memchr.rs (100%) rename src/libstd/{sys/common => sys_common}/mod.rs (100%) rename src/libstd/{sys/common => sys_common}/mutex.rs (100%) rename src/libstd/{sys/common => sys_common}/net.rs (100%) rename src/libstd/{sys/common => sys_common}/poison.rs (100%) rename src/libstd/{sys/common => sys_common}/remutex.rs (100%) rename src/libstd/{sys/common => sys_common}/rwlock.rs (100%) rename src/libstd/{sys/common => sys_common}/thread.rs (100%) rename src/libstd/{sys/common => sys_common}/thread_info.rs (100%) rename src/libstd/{sys/common => sys_common}/thread_local.rs (100%) rename src/libstd/{sys/common => sys_common}/util.rs (100%) rename src/libstd/{sys/common => sys_common}/wtf8.rs (100%) diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 1d6c2403c2fe6..3eb8288109097 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -456,8 +456,7 @@ pub mod time; mod memchr; #[macro_use] -#[path = "sys/common/mod.rs"] mod sys_common; - +mod sys_common; mod sys; pub mod rt; diff --git a/src/libstd/sys/common/at_exit_imp.rs b/src/libstd/sys_common/at_exit_imp.rs similarity index 100% rename from src/libstd/sys/common/at_exit_imp.rs rename to src/libstd/sys_common/at_exit_imp.rs diff --git a/src/libstd/sys/common/backtrace.rs b/src/libstd/sys_common/backtrace.rs similarity index 100% rename from src/libstd/sys/common/backtrace.rs rename to src/libstd/sys_common/backtrace.rs diff --git a/src/libstd/sys/common/condvar.rs b/src/libstd/sys_common/condvar.rs similarity index 100% rename from src/libstd/sys/common/condvar.rs rename to src/libstd/sys_common/condvar.rs diff --git a/src/libstd/sys/common/gnu/libbacktrace.rs b/src/libstd/sys_common/gnu/libbacktrace.rs similarity index 100% rename from src/libstd/sys/common/gnu/libbacktrace.rs rename to src/libstd/sys_common/gnu/libbacktrace.rs diff --git a/src/libstd/sys/common/gnu/mod.rs b/src/libstd/sys_common/gnu/mod.rs similarity index 100% rename from src/libstd/sys/common/gnu/mod.rs rename to src/libstd/sys_common/gnu/mod.rs diff --git a/src/libstd/sys/common/io.rs b/src/libstd/sys_common/io.rs similarity index 100% rename from src/libstd/sys/common/io.rs rename to src/libstd/sys_common/io.rs diff --git a/src/libstd/sys/common/memchr.rs b/src/libstd/sys_common/memchr.rs similarity index 100% rename from src/libstd/sys/common/memchr.rs rename to src/libstd/sys_common/memchr.rs diff --git a/src/libstd/sys/common/mod.rs b/src/libstd/sys_common/mod.rs similarity index 100% rename from src/libstd/sys/common/mod.rs rename to src/libstd/sys_common/mod.rs diff --git a/src/libstd/sys/common/mutex.rs b/src/libstd/sys_common/mutex.rs similarity index 100% rename from src/libstd/sys/common/mutex.rs rename to src/libstd/sys_common/mutex.rs diff --git a/src/libstd/sys/common/net.rs b/src/libstd/sys_common/net.rs similarity index 100% rename from src/libstd/sys/common/net.rs rename to src/libstd/sys_common/net.rs diff --git a/src/libstd/sys/common/poison.rs b/src/libstd/sys_common/poison.rs similarity index 100% rename from src/libstd/sys/common/poison.rs rename to src/libstd/sys_common/poison.rs diff --git a/src/libstd/sys/common/remutex.rs b/src/libstd/sys_common/remutex.rs similarity index 100% rename from src/libstd/sys/common/remutex.rs rename to src/libstd/sys_common/remutex.rs diff --git a/src/libstd/sys/common/rwlock.rs b/src/libstd/sys_common/rwlock.rs similarity index 100% rename from src/libstd/sys/common/rwlock.rs rename to src/libstd/sys_common/rwlock.rs diff --git a/src/libstd/sys/common/thread.rs b/src/libstd/sys_common/thread.rs similarity index 100% rename from src/libstd/sys/common/thread.rs rename to src/libstd/sys_common/thread.rs diff --git a/src/libstd/sys/common/thread_info.rs b/src/libstd/sys_common/thread_info.rs similarity index 100% rename from src/libstd/sys/common/thread_info.rs rename to src/libstd/sys_common/thread_info.rs diff --git a/src/libstd/sys/common/thread_local.rs b/src/libstd/sys_common/thread_local.rs similarity index 100% rename from src/libstd/sys/common/thread_local.rs rename to src/libstd/sys_common/thread_local.rs diff --git a/src/libstd/sys/common/util.rs b/src/libstd/sys_common/util.rs similarity index 100% rename from src/libstd/sys/common/util.rs rename to src/libstd/sys_common/util.rs diff --git a/src/libstd/sys/common/wtf8.rs b/src/libstd/sys_common/wtf8.rs similarity index 100% rename from src/libstd/sys/common/wtf8.rs rename to src/libstd/sys_common/wtf8.rs diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs index 68b0c819c5a8b..72970bbe6e3c1 100644 --- a/src/tools/tidy/src/pal.rs +++ b/src/tools/tidy/src/pal.rs @@ -57,9 +57,8 @@ const EXCEPTION_PATHS: &'static [&'static str] = &[ "src/libpanic_abort", "src/libpanic_unwind", "src/libunwind", - "src/libstd/sys/unix", // This is where platform-specific code for unix - "src/libstd/sys/windows", // Ditto for windows - "src/libstd/sys/mod.rs", // This file chooses the platform + "src/libstd/sys/", // Platform-specific code for std lives here. + // This has the trailing slash so that sys_common is not excepted. "src/libstd/os", // Platform-specific public interfaces "src/rtstartup", // Not sure what to do about this. magic stuff for mingw @@ -68,8 +67,8 @@ const EXCEPTION_PATHS: &'static [&'static str] = &[ "src/libstd/path.rs", "src/libstd/num/f32.rs", "src/libstd/num/f64.rs", - "src/libstd/sys/common/mod.rs", - "src/libstd/sys/common/net.rs", + "src/libstd/sys_common/mod.rs", + "src/libstd/sys_common/net.rs", "src/libterm", // Not sure how to make this crate portable, but test needs it "src/libtest", // Probably should defer to unstable std::sys APIs From ee71dc54765c161c51b2a8d860f9ebf95c6d7e12 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Fri, 30 Sep 2016 23:56:28 +0000 Subject: [PATCH 07/10] Document sys_common and sys --- src/libstd/sys/mod.rs | 22 ++++++++++++++++++++++ src/libstd/sys_common/mod.rs | 14 ++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/src/libstd/sys/mod.rs b/src/libstd/sys/mod.rs index f7e1a0a075a85..84f41a1c535c7 100644 --- a/src/libstd/sys/mod.rs +++ b/src/libstd/sys/mod.rs @@ -8,6 +8,28 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//! Platform-dependent platform abstraction +//! +//! The `std::sys` module is the abstracted interface through which +//! `std` talks to the underlying operating system. It has different +//! implementations for different operating system families, today +//! just Unix and Windows. +//! +//! The centralization of platform-specific code in this module is +//! enforced by the "platform abstraction layer" tidy script in +//! `tools/tidy/pal.rs`. +//! +//! This module is closely related to the platform-independent system +//! integration code in `std::sys_common`. See that module's +//! documentation for details. +//! +//! In the future it would be desirable for the indepedent +//! implementations of this module to be extracted to their own crates +//! that `std` can link to, thus enabling their implementation +//! out-of-tree via crate replacement. Though due to the complex +//! inter-dependencies within `std` that will be a challenging goal to +//! achieve. + pub use self::imp::*; #[cfg(unix)] diff --git a/src/libstd/sys_common/mod.rs b/src/libstd/sys_common/mod.rs index 2845f895f1869..ac2b27844dc57 100644 --- a/src/libstd/sys_common/mod.rs +++ b/src/libstd/sys_common/mod.rs @@ -8,6 +8,20 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//! Platform-independent platform abstraction +//! +//! This is the platform-independent portion of the standard libraries +//! platform abstraction layer, whereas `std::sys` is the +//! platform-specific portion. +//! +//! The relationship between `std::sys_common`, `std::sys` and the +//! rest of `std` is complex, with dependencies going in all +//! directions: `std` depending on `sys_common`, `sys_common` +//! depending on `sys`, and `sys` depending on `sys_common` and `std`. +//! Ideally `sys_common` would be split into two and the dependencies +//! between them all would form a dag, facilitating the extraction of +//! `std::sys` from the standard library. + #![allow(missing_docs)] use sync::Once; From 8f5bb1f7c05f92986dcf612d81d9c20312dca2fc Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Fri, 30 Sep 2016 23:59:06 +0000 Subject: [PATCH 08/10] std: Remove unused test feature --- src/libstd/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 3eb8288109097..d203f80e5e831 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -248,7 +248,6 @@ #![feature(link_args)] #![feature(linkage)] #![feature(macro_reexport)] -#![cfg_attr(test, feature(map_values_mut))] #![feature(needs_panic_runtime)] #![feature(num_bits_bytes)] #![feature(old_wrapping)] From c2518845752e2c7e7bb3682c29a62ae97cfa18ed Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sat, 1 Oct 2016 01:38:29 +0000 Subject: [PATCH 09/10] Clean up and add more comments to libstd/lib.rs --- src/libstd/lib.rs | 133 +++++++++++++++++------------------ src/libstd/sys_common/mod.rs | 16 ++--- 2 files changed, 70 insertions(+), 79 deletions(-) diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index d203f80e5e831..6f9aa6d1e082e 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -210,8 +210,27 @@ test(no_crate_inject, attr(deny(warnings))), test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))))] +// Don't link to std. We are std. +#![no_std] + +#![deny(missing_docs)] + +// Tell the compiler to link to either panic_abort or panic_unwind #![needs_panic_runtime] +// Always use alloc_system during stage0 since jemalloc might be unavailable or +// disabled (Issue #30592) +#![cfg_attr(stage0, feature(alloc_system))] + +// Turn warnings into errors, but only after stage0, where it can be useful for +// code to emit warnings during language transitions +#![cfg_attr(not(stage0), deny(warnings))] + +// std may use features in a platform-specific way +#![allow(unused_features)] + +// std is implemented with unstable features, many of which are internal +// compiler details that will never be stable #![feature(alloc)] #![feature(allow_internal_unstable)] #![feature(asm)] @@ -283,21 +302,13 @@ #![feature(zero_one)] #![cfg_attr(test, feature(update_panic_count))] -// Issue# 30592: Systematically use alloc_system during stage0 since jemalloc -// might be unavailable or disabled -#![cfg_attr(stage0, feature(alloc_system))] - -// Don't link to std. We are std. -#![no_std] - -#![deny(missing_docs)] -#![allow(unused_features)] // std may use features in a platform-specific way -#![cfg_attr(not(stage0), deny(warnings))] - +// Explicitly import the prelude. The compiler uses this same unstable attribute +// to import the prelude implicitly when building crates that depend on std. #[prelude_import] #[allow(unused)] use prelude::v1::*; +// Access to Bencher, etc. #[cfg(test)] extern crate test; // We want to reexport a few macros from core but libcore has already been @@ -325,11 +336,22 @@ extern crate alloc_system; // compiler-rt intrinsics extern crate compiler_builtins; -// Make std testable by not duplicating lang items and other globals. See #2912 +// During testing, this crate is not actually the "real" std library, but rather +// it links to the real std library, which was compiled from this same source +// code. So any lang items std defines are conditionally excluded (or else they +// wolud generate duplicate lang item errors), and any globals it defines are +// _not_ the globals used by "real" std. So this import, defined only during +// testing gives test-std access to real-std lang items and globals. See #2912 #[cfg(test)] extern crate std as realstd; -// NB: These reexports are in the order they should be listed in rustdoc +// The standard macros that are not built-in to the compiler. +#[macro_use] +mod macros; + +// The Rust prelude +pub mod prelude; +// Public module declarations and reexports #[stable(feature = "rust1", since = "1.0.0")] pub use core::any; #[stable(feature = "rust1", since = "1.0.0")] @@ -362,48 +384,6 @@ pub use core::raw; pub use core::result; #[stable(feature = "rust1", since = "1.0.0")] pub use core::option; - -pub mod error; - -#[stable(feature = "rust1", since = "1.0.0")] -pub use alloc::boxed; -#[stable(feature = "rust1", since = "1.0.0")] -pub use alloc::rc; - -#[stable(feature = "rust1", since = "1.0.0")] -pub use core_collections::borrow; -#[stable(feature = "rust1", since = "1.0.0")] -pub use core_collections::fmt; -#[stable(feature = "rust1", since = "1.0.0")] -pub use core_collections::slice; -#[stable(feature = "rust1", since = "1.0.0")] -pub use core_collections::str; -#[stable(feature = "rust1", since = "1.0.0")] -pub use core_collections::string; -#[stable(feature = "rust1", since = "1.0.0")] -pub use core_collections::vec; - -#[stable(feature = "rust1", since = "1.0.0")] -pub use rustc_unicode::char; - -/* Exported macros */ - -#[macro_use] -mod macros; - -mod rtdeps; - -/* The Prelude. */ - -pub mod prelude; - - -/* Primitive types */ - -// NB: slice and str are primitive types too, but their module docs + primitive -// doc pages are inlined from the public re-exports of core_collections::{slice, -// str} above. - #[stable(feature = "rust1", since = "1.0.0")] pub use core::isize; #[stable(feature = "rust1", since = "1.0.0")] @@ -414,7 +394,6 @@ pub use core::i16; pub use core::i32; #[stable(feature = "rust1", since = "1.0.0")] pub use core::i64; - #[stable(feature = "rust1", since = "1.0.0")] pub use core::usize; #[stable(feature = "rust1", since = "1.0.0")] @@ -425,42 +404,62 @@ pub use core::u16; pub use core::u32; #[stable(feature = "rust1", since = "1.0.0")] pub use core::u64; +#[stable(feature = "rust1", since = "1.0.0")] +pub use alloc::boxed; +#[stable(feature = "rust1", since = "1.0.0")] +pub use alloc::rc; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core_collections::borrow; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core_collections::fmt; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core_collections::slice; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core_collections::str; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core_collections::string; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core_collections::vec; +#[stable(feature = "rust1", since = "1.0.0")] +pub use rustc_unicode::char; #[path = "num/f32.rs"] pub mod f32; #[path = "num/f64.rs"] pub mod f64; -pub mod ascii; - -/* Common traits */ - -pub mod num; - -/* Runtime and platform support */ - #[macro_use] pub mod thread; - +pub mod ascii; pub mod collections; pub mod env; +pub mod error; pub mod ffi; pub mod fs; pub mod io; pub mod net; +pub mod num; pub mod os; pub mod panic; pub mod path; pub mod process; pub mod sync; pub mod time; -mod memchr; +// Platform-abstraction modules #[macro_use] mod sys_common; mod sys; -pub mod rt; +// Private support modules mod panicking; mod rand; +mod memchr; + +// This module just defines per-platform native library dependencies +mod rtdeps; + +// The runtime entry point and a few unstable public functions used by the +// compiler +pub mod rt; // Some external utilities of the standard library rely on randomness (aka // rustc_back::TempDir and tests) and need a way to get at the OS rng we've got diff --git a/src/libstd/sys_common/mod.rs b/src/libstd/sys_common/mod.rs index ac2b27844dc57..1dd9b73e262c8 100644 --- a/src/libstd/sys_common/mod.rs +++ b/src/libstd/sys_common/mod.rs @@ -27,18 +27,6 @@ use sync::Once; use sys; -macro_rules! rtabort { - ($($t:tt)*) => (::sys_common::util::abort(format_args!($($t)*))) -} - -macro_rules! rtassert { - ($e:expr) => ({ - if !$e { - rtabort!(concat!("assertion failed: ", stringify!($e))) - } - }) -} - pub mod at_exit_imp; #[cfg(any(not(cargobuild), feature = "backtrace"))] pub mod backtrace; @@ -101,6 +89,10 @@ pub fn at_exit(f: F) -> Result<(), ()> { if at_exit_imp::push(Box::new(f)) {Ok(())} else {Err(())} } +macro_rules! rtabort { + ($($t:tt)*) => (::sys_common::util::abort(format_args!($($t)*))) +} + /// One-time runtime cleanup. pub fn cleanup() { static CLEANUP: Once = Once::new(); From 6135cbc9e2b9a7e62ae274cf57e9921f60f6ec73 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sat, 1 Oct 2016 23:07:17 +0000 Subject: [PATCH 10/10] std: Flatten the num directory to reflect the module layout This makes it dissimilar to how core is structured on disk, but more predictable on its own. --- src/libstd/{num => }/f32.rs | 0 src/libstd/{num => }/f64.rs | 0 src/libstd/lib.rs | 4 ++-- src/libstd/{num/mod.rs => num.rs} | 0 src/tools/tidy/src/pal.rs | 4 ++-- 5 files changed, 4 insertions(+), 4 deletions(-) rename src/libstd/{num => }/f32.rs (100%) rename src/libstd/{num => }/f64.rs (100%) rename src/libstd/{num/mod.rs => num.rs} (100%) diff --git a/src/libstd/num/f32.rs b/src/libstd/f32.rs similarity index 100% rename from src/libstd/num/f32.rs rename to src/libstd/f32.rs diff --git a/src/libstd/num/f64.rs b/src/libstd/f64.rs similarity index 100% rename from src/libstd/num/f64.rs rename to src/libstd/f64.rs diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 6f9aa6d1e082e..8d973fc1ade47 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -423,8 +423,8 @@ pub use core_collections::vec; #[stable(feature = "rust1", since = "1.0.0")] pub use rustc_unicode::char; -#[path = "num/f32.rs"] pub mod f32; -#[path = "num/f64.rs"] pub mod f64; +pub mod f32; +pub mod f64; #[macro_use] pub mod thread; diff --git a/src/libstd/num/mod.rs b/src/libstd/num.rs similarity index 100% rename from src/libstd/num/mod.rs rename to src/libstd/num.rs diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs index 72970bbe6e3c1..a5e4e5a4c2672 100644 --- a/src/tools/tidy/src/pal.rs +++ b/src/tools/tidy/src/pal.rs @@ -65,8 +65,8 @@ const EXCEPTION_PATHS: &'static [&'static str] = &[ // temporary exceptions "src/libstd/rtdeps.rs", // Until rustbuild replaces make "src/libstd/path.rs", - "src/libstd/num/f32.rs", - "src/libstd/num/f64.rs", + "src/libstd/f32.rs", + "src/libstd/f64.rs", "src/libstd/sys_common/mod.rs", "src/libstd/sys_common/net.rs", "src/libterm", // Not sure how to make this crate portable, but test needs it