diff options
Diffstat (limited to 'src/libstd')
25 files changed, 429 insertions, 141 deletions
diff --git a/src/libstd/alloc.rs b/src/libstd/alloc.rs index 537f56a8da7..8b6e5680c2d 100644 --- a/src/libstd/alloc.rs +++ b/src/libstd/alloc.rs @@ -95,11 +95,11 @@ pub use alloc_crate::alloc::*; /// /// ```rust /// use std::alloc::{System, GlobalAlloc, Layout}; -/// use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering::SeqCst}; +/// use std::sync::atomic::{AtomicUsize, Ordering::SeqCst}; /// /// struct Counter; /// -/// static ALLOCATED: AtomicUsize = ATOMIC_USIZE_INIT; +/// static ALLOCATED: AtomicUsize = AtomicUsize::new(0); /// /// unsafe impl GlobalAlloc for Counter { /// unsafe fn alloc(&self, layout: Layout) -> *mut u8 { diff --git a/src/libstd/error.rs b/src/libstd/error.rs index 2f9efb3f0fb..50415d9aeb9 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -197,9 +197,7 @@ pub trait Error: Debug + Display { /// Get the `TypeId` of `self` #[doc(hidden)] - #[unstable(feature = "error_type_id", - reason = "unclear whether to commit to this public implementation detail", - issue = "27745")] + #[stable(feature = "error_type_id", since = "1.34.0")] fn type_id(&self) -> TypeId where Self: 'static { TypeId::of::<Self>() } diff --git a/src/libstd/future.rs b/src/libstd/future.rs index a7b9895177f..d1203be3cf0 100644 --- a/src/libstd/future.rs +++ b/src/libstd/future.rs @@ -11,7 +11,7 @@ use core::ops::{Drop, Generator, GeneratorState}; #[doc(inline)] pub use core::future::*; -/// Wrap a future in a generator. +/// Wrap a generator in a future. /// /// This function returns a `GenFuture` underneath, but hides it in `impl Trait` to give /// better error messages (`impl Future` rather than `GenFuture<[closure.....]>`). @@ -33,7 +33,9 @@ impl<T: Generator<Yield = ()>> !Unpin for GenFuture<T> {} impl<T: Generator<Yield = ()>> Future for GenFuture<T> { type Output = T::Return; fn poll(self: Pin<&mut Self>, lw: &LocalWaker) -> Poll<Self::Output> { - set_task_waker(lw, || match unsafe { Pin::get_unchecked_mut(self).0.resume() } { + // Safe because we're !Unpin + !Drop mapping to a ?Unpin value + let gen = unsafe { Pin::map_unchecked_mut(self, |s| &mut s.0) }; + set_task_waker(lw, || match gen.resume() { GeneratorState::Yielded(()) => Poll::Pending, GeneratorState::Complete(x) => Poll::Ready(x), }) diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 83db3f347a7..244caf28ec7 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -7,11 +7,9 @@ //! primitives](#primitives), [standard macros](#macros), [I/O] and //! [multithreading], among [many other things][other]. //! -//! `std` is available to all Rust crates by default, just as if each one -//! contained an `extern crate std;` import at the [crate root]. Therefore the +//! `std` is available to all Rust crates by default. Therefore the //! standard library can be accessed in [`use`] statements through the path -//! `std`, as in [`use std::env`], or in expressions through the absolute path -//! `::std`, as in [`::std::env::args`]. +//! `std`, as in [`use std::env`]. //! //! # How to read this documentation //! @@ -157,7 +155,6 @@ //! [TCP]: net/struct.TcpStream.html //! [The Rust Prelude]: prelude/index.html //! [UDP]: net/struct.UdpSocket.html -//! [`::std::env::args`]: env/fn.args.html //! [`Arc`]: sync/struct.Arc.html //! [owned slice]: boxed/index.html //! [`Cell`]: cell/struct.Cell.html @@ -191,7 +188,6 @@ //! [`thread`]: thread/index.html //! [`use std::env`]: env/index.html //! [`use`]: ../book/ch07-02-modules-and-use-to-control-scope-and-privacy.html#the-use-keyword-to-bring-paths-into-a-scope -//! [crate root]: ../book/ch07-01-packages-and-crates-for-making-libraries-and-executables.html //! [crates.io]: https://crates.io //! [deref-coercions]: ../book/ch15-02-deref.html#implicit-deref-coercions-with-functions-and-methods //! [files]: fs/struct.File.html @@ -238,12 +234,9 @@ #![feature(c_variadic)] #![feature(cfg_target_has_atomic)] #![feature(cfg_target_thread_local)] -#![cfg_attr(stage0, feature(cfg_target_vendor))] #![feature(char_error_internals)] #![feature(compiler_builtins_lib)] #![feature(concat_idents)] -#![cfg_attr(stage0, feature(const_int_ops))] -#![cfg_attr(stage0, feature(const_ip))] #![feature(const_raw_ptr_deref)] #![feature(const_cstr_unchecked)] #![feature(core_intrinsics)] @@ -365,6 +358,9 @@ pub mod prelude; // Public module declarations and re-exports #[stable(feature = "rust1", since = "1.0.0")] pub use core::any; +#[stable(feature = "simd_arch", since = "1.27.0")] +#[doc(no_inline)] +pub use core::arch; #[stable(feature = "rust1", since = "1.0.0")] pub use core::cell; #[stable(feature = "rust1", since = "1.0.0")] @@ -496,29 +492,22 @@ mod memchr; // compiler pub mod rt; -// Pull in the `stdsimd` crate directly into libstd. This is the same as -// libcore's arch/simd modules where the source of truth here is in a different -// repository, but we pull things in here manually to get it into libstd. +// Pull in the `std_detect` crate directly into libstd. The contents of +// `std_detect` are in a different repository: rust-lang-nursery/stdsimd. // -// Note that the #[cfg] here is intended to do two things. First it allows us to -// change the rustc implementation of intrinsics in stage0 by not compiling simd -// intrinsics in stage0. Next it doesn't compile anything in test mode as -// stdsimd has tons of its own tests which we don't want to run. -#[path = "../stdsimd/stdsimd/mod.rs"] +// `std_detect` depends on libstd, but the contents of this module are +// set up in such a way that directly pulling it here works such that the +// crate uses the this crate as its libstd. +#[path = "../stdsimd/crates/std_detect/src/mod.rs"] #[allow(missing_debug_implementations, missing_docs, dead_code)] #[unstable(feature = "stdsimd", issue = "48556")] #[cfg(not(test))] -mod stdsimd; - -// A "fake" module needed by the `stdsimd` module to compile, not actually -// exported though. -mod coresimd { - pub use core::arch; -} +mod std_detect; -#[stable(feature = "simd_arch", since = "1.27.0")] +#[doc(hidden)] +#[unstable(feature = "stdsimd", issue = "48556")] #[cfg(not(test))] -pub use stdsimd::arch; +pub use std_detect::detect; // Include a number of private modules that exist solely to provide // the rustdoc documentation for primitive types. Using `include!` diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index f98113e0896..f45cd8b8c10 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -328,7 +328,6 @@ impl Ipv4Addr { /// let addr = Ipv4Addr::new(127, 0, 0, 1); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(stage0, rustc_const_unstable(feature = "const_ip"))] pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr { Ipv4Addr { inner: c::in_addr { diff --git a/src/libstd/os/fortanix_sgx/mod.rs b/src/libstd/os/fortanix_sgx/mod.rs index 47c7b5dcbe6..bd6f4b4465b 100644 --- a/src/libstd/os/fortanix_sgx/mod.rs +++ b/src/libstd/os/fortanix_sgx/mod.rs @@ -16,31 +16,16 @@ pub mod usercalls { /// Primitives for allocating memory in userspace as well as copying data /// to and from user memory. pub mod alloc { - pub use sys::abi::usercalls::alloc; + pub use sys::abi::usercalls::alloc::*; } /// Lowest-level interfaces to usercalls and usercall ABI type definitions. pub mod raw { - use sys::abi::usercalls::raw::invoke_with_usercalls; - pub use sys::abi::usercalls::raw::do_usercall; + pub use sys::abi::usercalls::raw::{do_usercall, Usercalls as UsercallNrs}; pub use sys::abi::usercalls::raw::{accept_stream, alloc, async_queues, bind_stream, close, connect_stream, exit, flush, free, insecure_time, launch_thread, read, read_alloc, send, wait, write}; - macro_rules! define_usercallnrs { - ($(fn $f:ident($($n:ident: $t:ty),*) $(-> $r:ty)*; )*) => { - /// Usercall numbers as per the ABI. - #[repr(C)] - #[unstable(feature = "sgx_platform", issue = "56975")] - #[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)] - #[allow(missing_docs)] - pub enum UsercallNrs { - $($f,)* - } - }; - } - invoke_with_usercalls!(define_usercallnrs); - // fortanix-sgx-abi re-exports pub use sys::abi::usercalls::raw::{ByteBuffer, FifoDescriptor, Return, Usercall}; pub use sys::abi::usercalls::raw::Error; @@ -56,4 +41,4 @@ pub mod mem { pub use sys::abi::mem::*; } -pub use sys::ext::{io, arch}; +pub use sys::ext::{io, arch, ffi}; diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index 856bb260424..59829db23cb 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -450,9 +450,7 @@ impl<'a, T: ?Sized> Drop for MutexGuard<'a, T> { #[stable(feature = "std_debug", since = "1.16.0")] impl<'a, T: ?Sized + fmt::Debug> fmt::Debug for MutexGuard<'a, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("MutexGuard") - .field("lock", &self.__lock) - .finish() + fmt::Debug::fmt(&**self, f) } } diff --git a/src/libstd/sys/mod.rs b/src/libstd/sys/mod.rs index f398a2a6225..99ef74179c2 100644 --- a/src/libstd/sys/mod.rs +++ b/src/libstd/sys/mod.rs @@ -54,6 +54,7 @@ cfg_if! { cfg_if! { if #[cfg(any(unix, target_os = "redox"))] { // On unix we'll document what's already available + #[stable(feature = "rust1", since = "1.0.0")] pub use self::ext as unix_ext; } else if #[cfg(any(target_os = "cloudabi", target_arch = "wasm32", @@ -77,6 +78,7 @@ cfg_if! { if #[cfg(windows)] { // On windows we'll just be documenting what's already available #[allow(missing_docs)] + #[stable(feature = "rust1", since = "1.0.0")] pub use self::ext as windows_ext; } else if #[cfg(any(target_os = "cloudabi", target_arch = "wasm32", diff --git a/src/libstd/sys/redox/thread_local.rs b/src/libstd/sys/redox/thread_local.rs index a1c4b10e450..a1929b94165 100644 --- a/src/libstd/sys/redox/thread_local.rs +++ b/src/libstd/sys/redox/thread_local.rs @@ -2,13 +2,13 @@ use collections::BTreeMap; use ptr; -use sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; +use sync::atomic::{AtomicUsize, Ordering}; pub type Key = usize; type Dtor = unsafe extern fn(*mut u8); -static NEXT_KEY: AtomicUsize = ATOMIC_USIZE_INIT; +static NEXT_KEY: AtomicUsize = AtomicUsize::new(0); static mut KEYS: *mut BTreeMap<Key, Option<Dtor>> = ptr::null_mut(); diff --git a/src/libstd/sys/sgx/abi/entry.S b/src/libstd/sys/sgx/abi/entry.S index ac7f95d4eae..9b46c2180d9 100644 --- a/src/libstd/sys/sgx/abi/entry.S +++ b/src/libstd/sys/sgx/abi/entry.S @@ -66,7 +66,7 @@ IMAGE_BASE: globvar EH_FRM_HDR_SIZE 8 .Lreentry_panic_msg: - .asciz "Re-entered panicked enclave!" + .asciz "Re-entered aborted enclave!" .Lreentry_panic_msg_end: .Lusercall_panic_msg: @@ -80,7 +80,7 @@ IMAGE_BASE: .org .+48 /* reserved bits */ .data -.Lpanicked: +.Laborted: .byte 0 /* TCS local storage section */ @@ -134,6 +134,9 @@ sgx_entry: jz .Lskip_debug_init mov %r10,%gs:tcsls_debug_panic_buf_ptr .Lskip_debug_init: +/* check for abort */ + bt $0,.Laborted(%rip) + jc .Lreentry_panic /* check if returning from usercall */ mov %gs:tcsls_last_rsp,%r11 test %r11,%r11 @@ -164,9 +167,6 @@ sgx_entry: mov %r14,%r8 mov %r15,%r9 .Lskip_init: -/* check for panic */ - bt $0,.Lpanicked(%rip) - jc .Lreentry_panic /* call into main entry point */ load_tcsls_flag_secondary_bool cx /* RCX = entry() argument: secondary: bool */ call entry /* RDI, RSI, RDX, R8, R9 passed in from userspace */ @@ -237,18 +237,18 @@ sgx_entry: stmxcsr (%rsp) .endm -.global panic_exit -panic_exit: +.global usercall_exit +usercall_exit: /* save registers in DEBUG mode, so that debugger can reconstruct the stack */ testb $0xff,DEBUG(%rip) jz .Lskip_save_registers push_callee_saved_registers movq %rsp,%gs:tcsls_panic_last_rsp .Lskip_save_registers: -/* set panicked bit */ - movb $1,.Lpanicked(%rip) +/* set aborted bit */ + movb $1,.Laborted(%rip) /* call usercall exit(true) */ - mov $1,%esi /* RSI = usercall() argument: panic = true */ + /* NOP: mov %rsi,%rsi */ /* RSI = usercall() argument: panic */ xor %rdx,%rdx /* RDX cleared */ movq $usercall_nr_exit,%rdi /* RDI = usercall exit */ jmp .Lexit diff --git a/src/libstd/sys/sgx/abi/panic.rs b/src/libstd/sys/sgx/abi/panic.rs index 5ace7fb3368..d23fa9a9ec6 100644 --- a/src/libstd/sys/sgx/abi/panic.rs +++ b/src/libstd/sys/sgx/abi/panic.rs @@ -1,12 +1,18 @@ +use super::usercalls::alloc::UserRef; +use cmp; use io::{self, Write}; -use slice::from_raw_parts_mut; +use mem; extern "C" { fn take_debug_panic_buf_ptr() -> *mut u8; static DEBUG: u8; } -pub(crate) struct SgxPanicOutput(Option<&'static mut [u8]>); +pub(crate) struct SgxPanicOutput(Option<&'static mut UserRef<[u8]>>); + +fn empty_user_slice() -> &'static mut UserRef<[u8]> { + unsafe { UserRef::from_raw_parts_mut(1 as *mut u8, 0) } +} impl SgxPanicOutput { pub(crate) fn new() -> Option<Self> { @@ -17,32 +23,36 @@ impl SgxPanicOutput { } } - fn init(&mut self) -> &mut &'static mut [u8] { + fn init(&mut self) -> &mut &'static mut UserRef<[u8]> { self.0.get_or_insert_with(|| unsafe { let ptr = take_debug_panic_buf_ptr(); if ptr.is_null() { - &mut [] + empty_user_slice() } else { - from_raw_parts_mut(ptr, 1024) + UserRef::from_raw_parts_mut(ptr, 1024) } }) } } impl Write for SgxPanicOutput { - fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - self.init().write(buf) + fn write(&mut self, src: &[u8]) -> io::Result<usize> { + let dst = mem::replace(self.init(), empty_user_slice()); + let written = cmp::min(src.len(), dst.len()); + dst[..written].copy_from_enclave(&src[..written]); + self.0 = Some(&mut dst[written..]); + Ok(written) } fn flush(&mut self) -> io::Result<()> { - self.init().flush() + Ok(()) } } #[no_mangle] pub extern "C" fn panic_msg(msg: &str) -> ! { let _ = SgxPanicOutput::new().map(|mut out| out.write(msg.as_bytes())); - unsafe { panic_exit(); } + unsafe { usercall_exit(true); } } -extern "C" { pub fn panic_exit() -> !; } +extern "C" { pub fn usercall_exit(panic: bool) -> !; } diff --git a/src/libstd/sys/sgx/abi/tls.rs b/src/libstd/sys/sgx/abi/tls.rs index aba93db915f..b8e09d58deb 100644 --- a/src/libstd/sys/sgx/abi/tls.rs +++ b/src/libstd/sys/sgx/abi/tls.rs @@ -1,4 +1,4 @@ -use sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; +use sync::atomic::{AtomicUsize, Ordering}; use ptr; use mem; use cell::Cell; @@ -15,7 +15,40 @@ macro_rules! dup { ((* $($exp:tt)*) $($val:tt)*) => (dup!( ($($exp)*) $($val)* $($val)* )); (() $($val:tt)*) => ([$($val),*]) } -static TLS_DESTRUCTOR: [AtomicUsize; TLS_KEYS] = dup!((* * * * * * *) ATOMIC_USIZE_INIT); +static TLS_DESTRUCTOR: [AtomicUsize; TLS_KEYS] = [ + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), + AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), +]; extern "C" { fn get_tls_ptr() -> *const u8; @@ -119,7 +152,7 @@ impl Tls { } mod sync_bitset { - use sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; + use sync::atomic::{AtomicUsize, Ordering}; use iter::{Enumerate, Peekable}; use slice::Iter; use super::{TLS_KEYS_BITSET_SIZE, USIZE_BITS}; @@ -128,7 +161,7 @@ mod sync_bitset { pub(super) struct SyncBitset([AtomicUsize; TLS_KEYS_BITSET_SIZE]); pub(super) const SYNC_BITSET_INIT: SyncBitset = - SyncBitset([ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT]); + SyncBitset([AtomicUsize::new(0), AtomicUsize::new(0)]); impl SyncBitset { pub fn get(&self, index: usize) -> bool { diff --git a/src/libstd/sys/sgx/abi/usercalls/alloc.rs b/src/libstd/sys/sgx/abi/usercalls/alloc.rs index 8d0013a235a..2efbaa9b148 100644 --- a/src/libstd/sys/sgx/abi/usercalls/alloc.rs +++ b/src/libstd/sys/sgx/abi/usercalls/alloc.rs @@ -537,7 +537,12 @@ impl UserRef<super::raw::ByteBuffer> { pub fn copy_user_buffer(&self) -> Vec<u8> { unsafe { let buf = self.to_enclave(); - User::from_raw_parts(buf.data as _, buf.len).to_enclave() + if buf.len > 0 { + User::from_raw_parts(buf.data as _, buf.len).to_enclave() + } else { + // Mustn't look at `data` or call `free` if `len` is `0`. + Vec::with_capacity(0) + } } } } diff --git a/src/libstd/sys/sgx/abi/usercalls/mod.rs b/src/libstd/sys/sgx/abi/usercalls/mod.rs index 58903761ebe..bae044b906b 100644 --- a/src/libstd/sys/sgx/abi/usercalls/mod.rs +++ b/src/libstd/sys/sgx/abi/usercalls/mod.rs @@ -22,7 +22,8 @@ pub fn read(fd: Fd, buf: &mut [u8]) -> IoResult<usize> { #[unstable(feature = "sgx_platform", issue = "56975")] pub fn read_alloc(fd: Fd) -> IoResult<Vec<u8>> { unsafe { - let mut userbuf = alloc::User::<ByteBuffer>::uninitialized(); + let userbuf = ByteBuffer { data: ::ptr::null_mut(), len: 0 }; + let mut userbuf = alloc::User::new_from_enclave(&userbuf); raw::read_alloc(fd, userbuf.as_raw_mut_ptr()).from_sgx_result()?; Ok(userbuf.copy_user_buffer()) } @@ -119,7 +120,7 @@ pub unsafe fn launch_thread() -> IoResult<()> { /// Usercall `exit`. See the ABI documentation for more information. #[unstable(feature = "sgx_platform", issue = "56975")] pub fn exit(panic: bool) -> ! { - unsafe { raw::exit(panic) } + unsafe { super::panic::usercall_exit(panic) } } /// Usercall `wait`. See the ABI documentation for more information. diff --git a/src/libstd/sys/sgx/abi/usercalls/raw.rs b/src/libstd/sys/sgx/abi/usercalls/raw.rs index 27aca7c0903..27f780ca224 100644 --- a/src/libstd/sys/sgx/abi/usercalls/raw.rs +++ b/src/libstd/sys/sgx/abi/usercalls/raw.rs @@ -41,10 +41,15 @@ trait ReturnValue { macro_rules! define_usercalls { // Using `$r:tt` because `$r:ty` doesn't match ! in `clobber_diverging` ($(fn $f:ident($($n:ident: $t:ty),*) $(-> $r:tt)*; )*) => { - #[repr(C)] - #[allow(non_camel_case_types)] - enum Usercalls { - __enclave_usercalls_invalid, + /// Usercall numbers as per the ABI. + #[repr(u64)] + #[unstable(feature = "sgx_platform", issue = "56975")] + #[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)] + #[allow(missing_docs, non_camel_case_types)] + #[non_exhaustive] + pub enum Usercalls { + #[doc(hidden)] + __enclave_usercalls_invalid = 0, $($f,)* } diff --git a/src/libstd/sys/sgx/ext/ffi.rs b/src/libstd/sys/sgx/ext/ffi.rs new file mode 100644 index 00000000000..7b0ffea49ae --- /dev/null +++ b/src/libstd/sys/sgx/ext/ffi.rs @@ -0,0 +1,109 @@ +//! SGX-specific extension to the primitives in the `std::ffi` module + +#![unstable(feature = "sgx_platform", issue = "56975")] + +use ffi::{OsStr, OsString}; +use mem; +use sys::os_str::Buf; +use sys_common::{FromInner, IntoInner, AsInner}; + +/// SGX-specific extensions to [`OsString`]. +/// +/// [`OsString`]: ../../../../std/ffi/struct.OsString.html +#[unstable(feature = "sgx_platform", issue = "56975")] +pub trait OsStringExt { + /// Creates an [`OsString`] from a byte vector. + /// + /// # Examples + /// + /// ``` + /// use std::ffi::OsString; + /// use std::os::unix::ffi::OsStringExt; + /// + /// let bytes = b"foo".to_vec(); + /// let os_string = OsString::from_vec(bytes); + /// assert_eq!(os_string.to_str(), Some("foo")); + /// ``` + /// + /// [`OsString`]: ../../../ffi/struct.OsString.html + #[unstable(feature = "sgx_platform", issue = "56975")] + fn from_vec(vec: Vec<u8>) -> Self; + + /// Yields the underlying byte vector of this [`OsString`]. + /// + /// # Examples + /// + /// ``` + /// use std::ffi::OsString; + /// use std::os::unix::ffi::OsStringExt; + /// + /// let mut os_string = OsString::new(); + /// os_string.push("foo"); + /// let bytes = os_string.into_vec(); + /// assert_eq!(bytes, b"foo"); + /// ``` + /// + /// [`OsString`]: ../../../ffi/struct.OsString.html + #[unstable(feature = "sgx_platform", issue = "56975")] + fn into_vec(self) -> Vec<u8>; +} + +#[unstable(feature = "sgx_platform", issue = "56975")] +impl OsStringExt for OsString { + fn from_vec(vec: Vec<u8>) -> OsString { + FromInner::from_inner(Buf { inner: vec }) + } + fn into_vec(self) -> Vec<u8> { + self.into_inner().inner + } +} + +/// SGX-specific extensions to [`OsStr`]. +/// +/// [`OsStr`]: ../../../../std/ffi/struct.OsStr.html +#[unstable(feature = "sgx_platform", issue = "56975")] +pub trait OsStrExt { + #[unstable(feature = "sgx_platform", issue = "56975")] + /// Creates an [`OsStr`] from a byte slice. + /// + /// # Examples + /// + /// ``` + /// use std::ffi::OsStr; + /// use std::os::unix::ffi::OsStrExt; + /// + /// let bytes = b"foo"; + /// let os_str = OsStr::from_bytes(bytes); + /// assert_eq!(os_str.to_str(), Some("foo")); + /// ``` + /// + /// [`OsStr`]: ../../../ffi/struct.OsStr.html + fn from_bytes(slice: &[u8]) -> &Self; + + /// Gets the underlying byte view of the [`OsStr`] slice. + /// + /// # Examples + /// + /// ``` + /// use std::ffi::OsStr; + /// use std::os::unix::ffi::OsStrExt; + /// + /// let mut os_str = OsStr::new("foo"); + /// let bytes = os_str.as_bytes(); + /// assert_eq!(bytes, b"foo"); + /// ``` + /// + /// [`OsStr`]: ../../../ffi/struct.OsStr.html + #[unstable(feature = "sgx_platform", issue = "56975")] + fn as_bytes(&self) -> &[u8]; +} + +#[unstable(feature = "sgx_platform", issue = "56975")] +impl OsStrExt for OsStr { + fn from_bytes(slice: &[u8]) -> &OsStr { + unsafe { mem::transmute(slice) } + } + fn as_bytes(&self) -> &[u8] { + &self.as_inner().inner + } +} diff --git a/src/libstd/sys/sgx/ext/mod.rs b/src/libstd/sys/sgx/ext/mod.rs index 5489f6f5694..51b2659da83 100644 --- a/src/libstd/sys/sgx/ext/mod.rs +++ b/src/libstd/sys/sgx/ext/mod.rs @@ -2,3 +2,4 @@ pub mod arch; pub mod io; +pub mod ffi; diff --git a/src/libstd/sys/sgx/mod.rs b/src/libstd/sys/sgx/mod.rs index 7f8550490a1..f2593c35bed 100644 --- a/src/libstd/sys/sgx/mod.rs +++ b/src/libstd/sys/sgx/mod.rs @@ -125,7 +125,7 @@ pub unsafe fn strlen(mut s: *const c_char) -> usize { } pub unsafe fn abort_internal() -> ! { - abi::panic::panic_exit() + abi::panic::usercall_exit(true) } pub fn hashmap_random_keys() -> (u64, u64) { diff --git a/src/libstd/sys/sgx/rwlock.rs b/src/libstd/sys/sgx/rwlock.rs index 47874158ed9..33163a556c1 100644 --- a/src/libstd/sys/sgx/rwlock.rs +++ b/src/libstd/sys/sgx/rwlock.rs @@ -1,3 +1,4 @@ +use alloc::{self, Layout}; use num::NonZeroUsize; use slice; use str; @@ -18,9 +19,6 @@ unsafe fn rw_lock_size_assert(r: RWLock) { mem::transmute::<RWLock, [u8; 128]>(r); } -//unsafe impl Send for RWLock {} -//unsafe impl Sync for RWLock {} // FIXME - impl RWLock { pub const fn new() -> RWLock { RWLock { @@ -147,6 +145,7 @@ impl RWLock { self.__write_unlock(rguard, wguard); } + // only used by __rust_rwlock_unlock below #[inline] unsafe fn unlock(&self) { let rguard = self.readers.lock(); @@ -164,6 +163,7 @@ impl RWLock { const EINVAL: i32 = 22; +// used by libunwind port #[no_mangle] pub unsafe extern "C" fn __rust_rwlock_rdlock(p: *mut RWLock) -> i32 { if p.is_null() { @@ -190,6 +190,8 @@ pub unsafe extern "C" fn __rust_rwlock_unlock(p: *mut RWLock) -> i32 { return 0; } +// the following functions are also used by the libunwind port. They're +// included here to make sure parallel codegen and LTO don't mess things up. #[no_mangle] pub unsafe extern "C" fn __rust_print_err(m: *mut u8, s: i32) { if s < 0 { @@ -206,6 +208,16 @@ pub unsafe extern "C" fn __rust_abort() { ::sys::abort_internal(); } +#[no_mangle] +pub unsafe extern "C" fn __rust_c_alloc(size: usize, align: usize) -> *mut u8 { + alloc::alloc(Layout::from_size_align_unchecked(size, align)) +} + +#[no_mangle] +pub unsafe extern "C" fn __rust_c_dealloc(ptr: *mut u8, size: usize, align: usize) { + alloc::dealloc(ptr, Layout::from_size_align_unchecked(size, align)) +} + #[cfg(test)] mod tests { diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs index 91793a0d5ec..a746d982c6c 100644 --- a/src/libstd/sys/unix/pipe.rs +++ b/src/libstd/sys/unix/pipe.rs @@ -1,7 +1,7 @@ use io; use libc::{self, c_int}; use mem; -use sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering}; +use sync::atomic::{AtomicBool, Ordering}; use sys::fd::FileDesc; use sys::{cvt, cvt_r}; @@ -13,7 +13,7 @@ pub struct AnonPipe(FileDesc); pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> { syscall! { fn pipe2(fds: *mut c_int, flags: c_int) -> c_int } - static INVALID: AtomicBool = ATOMIC_BOOL_INIT; + static INVALID: AtomicBool = AtomicBool::new(false); let mut fds = [0; 2]; diff --git a/src/libstd/sys/windows/pipe.rs b/src/libstd/sys/windows/pipe.rs index 2b1dbe310ee..0d9195a5c97 100644 --- a/src/libstd/sys/windows/pipe.rs +++ b/src/libstd/sys/windows/pipe.rs @@ -7,7 +7,7 @@ use path::Path; use ptr; use slice; use sync::atomic::Ordering::SeqCst; -use sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT}; +use sync::atomic::AtomicUsize; use sys::c; use sys::fs::{File, OpenOptions}; use sys::handle::Handle; @@ -148,7 +148,7 @@ pub fn anon_pipe(ours_readable: bool) -> io::Result<Pipes> { } fn random_number() -> usize { - static N: AtomicUsize = ATOMIC_USIZE_INIT; + static N: AtomicUsize = AtomicUsize::new(0); loop { if N.load(SeqCst) != 0 { return N.fetch_add(1, SeqCst) diff --git a/src/libstd/sys/windows/time.rs b/src/libstd/sys/windows/time.rs index 8e8e9195cf4..8a8159af2f1 100644 --- a/src/libstd/sys/windows/time.rs +++ b/src/libstd/sys/windows/time.rs @@ -1,10 +1,7 @@ use cmp::Ordering; use fmt; use mem; -use sync::Once; use sys::c; -use sys::cvt; -use sys_common::mul_div_u64; use time::Duration; use convert::TryInto; use core::hash::{Hash, Hasher}; @@ -14,7 +11,9 @@ const INTERVALS_PER_SEC: u64 = NANOS_PER_SEC / 100; #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)] pub struct Instant { - t: c::LARGE_INTEGER, + // This duration is relative to an arbitrary microsecond epoch + // from the winapi QueryPerformanceCounter function. + t: Duration, } #[derive(Copy, Clone)] @@ -33,11 +32,12 @@ pub const UNIX_EPOCH: SystemTime = SystemTime { impl Instant { pub fn now() -> Instant { - let mut t = Instant { t: 0 }; - cvt(unsafe { - c::QueryPerformanceCounter(&mut t.t) - }).unwrap(); - t + // High precision timing on windows operates in "Performance Counter" + // units, as returned by the WINAPI QueryPerformanceCounter function. + // These relate to seconds by a factor of QueryPerformanceFrequency. + // In order to keep unit conversions out of normal interval math, we + // measure in QPC units and immediately convert to nanoseconds. + perf_counter::PerformanceCounterInstant::now().into() } pub fn actually_monotonic() -> bool { @@ -45,47 +45,31 @@ impl Instant { } pub const fn zero() -> Instant { - Instant { t: 0 } + Instant { t: Duration::from_secs(0) } } pub fn sub_instant(&self, other: &Instant) -> Duration { - // Values which are +- 1 need to be considered as basically the same - // units in time due to various measurement oddities, according to - // Windows [1] - // - // [1]: - // https://msdn.microsoft.com/en-us/library/windows/desktop - // /dn553408%28v=vs.85%29.aspx#guidance - if other.t > self.t && other.t - self.t == 1 { + // On windows there's a threshold below which we consider two timestamps + // equivalent due to measurement error. For more details + doc link, + // check the docs on epsilon. + let epsilon = + perf_counter::PerformanceCounterInstant::epsilon(); + if other.t > self.t && other.t - self.t <= epsilon { return Duration::new(0, 0) } - let diff = (self.t as u64).checked_sub(other.t as u64) - .expect("specified instant was later than \ - self"); - let nanos = mul_div_u64(diff, NANOS_PER_SEC, frequency() as u64); - Duration::new(nanos / NANOS_PER_SEC, (nanos % NANOS_PER_SEC) as u32) + self.t.checked_sub(other.t) + .expect("specified instant was later than self") } pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> { - let freq = frequency() as u64; - let t = other.as_secs() - .checked_mul(freq)? - .checked_add(mul_div_u64(other.subsec_nanos() as u64, freq, NANOS_PER_SEC))? - .checked_add(self.t as u64)?; Some(Instant { - t: t as c::LARGE_INTEGER, + t: self.t.checked_add(*other)? }) } pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> { - let freq = frequency() as u64; - let t = other.as_secs().checked_mul(freq).and_then(|i| { - (self.t as u64).checked_sub(i) - }).and_then(|i| { - i.checked_sub(mul_div_u64(other.subsec_nanos() as u64, freq, NANOS_PER_SEC)) - })?; Some(Instant { - t: t as c::LARGE_INTEGER, + t: self.t.checked_sub(*other)? }) } } @@ -186,14 +170,60 @@ fn intervals2dur(intervals: u64) -> Duration { ((intervals % INTERVALS_PER_SEC) * 100) as u32) } -fn frequency() -> c::LARGE_INTEGER { - static mut FREQUENCY: c::LARGE_INTEGER = 0; - static ONCE: Once = Once::new(); +mod perf_counter { + use super::{NANOS_PER_SEC}; + use sync::Once; + use sys_common::mul_div_u64; + use sys::c; + use sys::cvt; + use time::Duration; + + pub struct PerformanceCounterInstant { + ts: c::LARGE_INTEGER + } + impl PerformanceCounterInstant { + pub fn now() -> Self { + Self { + ts: query() + } + } - unsafe { - ONCE.call_once(|| { - cvt(c::QueryPerformanceFrequency(&mut FREQUENCY)).unwrap(); - }); - FREQUENCY + // Per microsoft docs, the margin of error for cross-thread time comparisons + // using QueryPerformanceCounter is 1 "tick" -- defined as 1/frequency(). + // Reference: https://docs.microsoft.com/en-us/windows/desktop/SysInfo + // /acquiring-high-resolution-time-stamps + pub fn epsilon() -> Duration { + let epsilon = NANOS_PER_SEC / (frequency() as u64); + Duration::from_nanos(epsilon) + } + } + impl From<PerformanceCounterInstant> for super::Instant { + fn from(other: PerformanceCounterInstant) -> Self { + let freq = frequency() as u64; + let instant_nsec = mul_div_u64(other.ts as u64, NANOS_PER_SEC, freq); + Self { + t: Duration::from_nanos(instant_nsec) + } + } + } + + fn frequency() -> c::LARGE_INTEGER { + static mut FREQUENCY: c::LARGE_INTEGER = 0; + static ONCE: Once = Once::new(); + + unsafe { + ONCE.call_once(|| { + cvt(c::QueryPerformanceFrequency(&mut FREQUENCY)).unwrap(); + }); + FREQUENCY + } + } + + fn query() -> c::LARGE_INTEGER { + let mut qpc_value: c::LARGE_INTEGER = 0; + cvt(unsafe { + c::QueryPerformanceCounter(&mut qpc_value) + }).unwrap(); + qpc_value } } diff --git a/src/libstd/tests/run-time-detect.rs b/src/libstd/tests/run-time-detect.rs new file mode 100644 index 00000000000..eacce1e5682 --- /dev/null +++ b/src/libstd/tests/run-time-detect.rs @@ -0,0 +1,100 @@ +//! These tests just check that the macros are available in libstd. + +#![cfg_attr( + any( + all(target_arch = "arm", any(target_os = "linux", target_os = "android")), + all(target_arch = "aarch64", any(target_os = "linux", target_os = "android")), + all(target_arch = "powerpc", target_os = "linux"), + all(target_arch = "powerpc64", target_os = "linux"), + ), + feature(stdsimd) +)] + +#[test] +#[cfg(all(target_arch = "arm", + any(target_os = "linux", target_os = "android")))] +fn arm_linux() { + println!("neon: {}", is_arm_feature_detected!("neon")); + println!("pmull: {}", is_arm_feature_detected!("pmull")); +} + +#[test] +#[cfg(all( + target_arch = "aarch64", + any(target_os = "linux", target_os = "android") +))] +fn aarch64_linux() { + println!("fp: {}", is_aarch64_feature_detected!("fp")); + println!("fp16: {}", is_aarch64_feature_detected!("fp16")); + println!("neon: {}", is_aarch64_feature_detected!("neon")); + println!("asimd: {}", is_aarch64_feature_detected!("asimd")); + println!("sve: {}", is_aarch64_feature_detected!("sve")); + println!("crc: {}", is_aarch64_feature_detected!("crc")); + println!("crypto: {}", is_aarch64_feature_detected!("crypto")); + println!("lse: {}", is_aarch64_feature_detected!("lse")); + println!("rdm: {}", is_aarch64_feature_detected!("rdm")); + println!("rcpc: {}", is_aarch64_feature_detected!("rcpc")); + println!("dotprod: {}", is_aarch64_feature_detected!("dotprod")); +} + +#[test] +#[cfg(all(target_arch = "powerpc", target_os = "linux"))] +fn powerpc_linux() { + println!("altivec: {}", is_powerpc_feature_detected!("altivec")); + println!("vsx: {}", is_powerpc_feature_detected!("vsx")); + println!("power8: {}", is_powerpc_feature_detected!("power8")); +} + +#[test] +#[cfg(all(target_arch = "powerpc64", target_os = "linux"))] +fn powerpc64_linux() { + println!("altivec: {}", is_powerpc64_feature_detected!("altivec")); + println!("vsx: {}", is_powerpc64_feature_detected!("vsx")); + println!("power8: {}", is_powerpc64_feature_detected!("power8")); +} + +#[test] +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +fn x86_all() { + println!("aes: {:?}", is_x86_feature_detected!("aes")); + println!("pcmulqdq: {:?}", is_x86_feature_detected!("pclmulqdq")); + println!("rdrand: {:?}", is_x86_feature_detected!("rdrand")); + println!("rdseed: {:?}", is_x86_feature_detected!("rdseed")); + println!("tsc: {:?}", is_x86_feature_detected!("tsc")); + println!("mmx: {:?}", is_x86_feature_detected!("mmx")); + println!("sse: {:?}", is_x86_feature_detected!("sse")); + println!("sse2: {:?}", is_x86_feature_detected!("sse2")); + println!("sse3: {:?}", is_x86_feature_detected!("sse3")); + println!("ssse3: {:?}", is_x86_feature_detected!("ssse3")); + println!("sse4.1: {:?}", is_x86_feature_detected!("sse4.1")); + println!("sse4.2: {:?}", is_x86_feature_detected!("sse4.2")); + println!("sse4a: {:?}", is_x86_feature_detected!("sse4a")); + println!("sha: {:?}", is_x86_feature_detected!("sha")); + println!("avx: {:?}", is_x86_feature_detected!("avx")); + println!("avx2: {:?}", is_x86_feature_detected!("avx2")); + println!("avx512f {:?}", is_x86_feature_detected!("avx512f")); + println!("avx512cd {:?}", is_x86_feature_detected!("avx512cd")); + println!("avx512er {:?}", is_x86_feature_detected!("avx512er")); + println!("avx512pf {:?}", is_x86_feature_detected!("avx512pf")); + println!("avx512bw {:?}", is_x86_feature_detected!("avx512bw")); + println!("avx512dq {:?}", is_x86_feature_detected!("avx512dq")); + println!("avx512vl {:?}", is_x86_feature_detected!("avx512vl")); + println!("avx512_ifma {:?}", is_x86_feature_detected!("avx512ifma")); + println!("avx512_vbmi {:?}", is_x86_feature_detected!("avx512vbmi")); + println!( + "avx512_vpopcntdq {:?}", + is_x86_feature_detected!("avx512vpopcntdq") + ); + println!("fma: {:?}", is_x86_feature_detected!("fma")); + println!("bmi1: {:?}", is_x86_feature_detected!("bmi1")); + println!("bmi2: {:?}", is_x86_feature_detected!("bmi2")); + println!("abm: {:?}", is_x86_feature_detected!("abm")); + println!("lzcnt: {:?}", is_x86_feature_detected!("lzcnt")); + println!("tbm: {:?}", is_x86_feature_detected!("tbm")); + println!("popcnt: {:?}", is_x86_feature_detected!("popcnt")); + println!("fxsr: {:?}", is_x86_feature_detected!("fxsr")); + println!("xsave: {:?}", is_x86_feature_detected!("xsave")); + println!("xsaveopt: {:?}", is_x86_feature_detected!("xsaveopt")); + println!("xsaves: {:?}", is_x86_feature_detected!("xsaves")); + println!("xsavec: {:?}", is_x86_feature_detected!("xsavec")); +} diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index a55b32c08a3..eb8e0c1c8ac 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -607,7 +607,7 @@ impl Builder { pub fn spawn<F, T>(f: F) -> JoinHandle<T> where F: FnOnce() -> T, F: Send + 'static, T: Send + 'static { - Builder::new().spawn(f).unwrap() + Builder::new().spawn(f).expect("failed to spawn thread") } /// Gets a handle to the thread that invokes it. diff --git a/src/libstd/time.rs b/src/libstd/time.rs index 507ea395c6c..23924559fcc 100644 --- a/src/libstd/time.rs +++ b/src/libstd/time.rs @@ -611,6 +611,15 @@ mod tests { } #[test] + fn instant_math_is_associative() { + let now = Instant::now(); + let offset = Duration::from_millis(5); + // Changing the order of instant math shouldn't change the results, + // especially when the expression reduces to X + identity. + assert_eq!((now + offset) - now, (now - now) + offset); + } + + #[test] #[should_panic] fn instant_duration_panic() { let a = Instant::now(); |
