diff options
| author | bors <bors@rust-lang.org> | 2019-01-24 21:23:11 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2019-01-24 21:23:11 +0000 |
| commit | 278067d34d1535a840cf9c99bcb8b538bf5b109a (patch) | |
| tree | 7d3bd558b1a01bef4485dba03117107a7e132635 /src/libstd | |
| parent | 01f8e25b15f4ab157c8e7c9c56054df7595ec0e1 (diff) | |
| parent | 5fa1016f93d77e43c3ed69b1155308616095cfcb (diff) | |
| download | rust-278067d34d1535a840cf9c99bcb8b538bf5b109a.tar.gz rust-278067d34d1535a840cf9c99bcb8b538bf5b109a.zip | |
Auto merge of #57879 - Centril:rollup, r=Centril
Rollup of 9 pull requests Successful merges: - #57380 (Fix Instant/Duration math precision & associativity on Windows) - #57606 (Get rid of the fake stack frame for reading from constants) - #57803 (Several changes to libunwind for SGX target) - #57846 (rustdoc: fix ICE from loading proc-macro stubs) - #57860 (Add os::fortanix_sgx::ffi module) - #57861 (Don't export table by default in wasm) - #57863 (Add suggestion for incorrect field syntax.) - #57867 (Fix std::future::from_generator documentation) - #57873 (Stabilize no_panic_pow) Failed merges: r? @ghost
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/future.rs | 2 | ||||
| -rw-r--r-- | src/libstd/os/fortanix_sgx/mod.rs | 2 | ||||
| -rw-r--r-- | src/libstd/sys/sgx/ext/ffi.rs | 109 | ||||
| -rw-r--r-- | src/libstd/sys/sgx/ext/mod.rs | 1 | ||||
| -rw-r--r-- | src/libstd/sys/sgx/rwlock.rs | 15 | ||||
| -rw-r--r-- | src/libstd/sys/windows/time.rs | 118 | ||||
| -rw-r--r-- | src/libstd/time.rs | 9 |
7 files changed, 210 insertions, 46 deletions
diff --git a/src/libstd/future.rs b/src/libstd/future.rs index a7b9895177f..22900c3067b 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.....]>`). diff --git a/src/libstd/os/fortanix_sgx/mod.rs b/src/libstd/os/fortanix_sgx/mod.rs index 47c7b5dcbe6..810965fc1b8 100644 --- a/src/libstd/os/fortanix_sgx/mod.rs +++ b/src/libstd/os/fortanix_sgx/mod.rs @@ -56,4 +56,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/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/rwlock.rs b/src/libstd/sys/sgx/rwlock.rs index 47874158ed9..43ceae7d33b 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; @@ -147,6 +148,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 +166,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 +193,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 +211,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/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/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(); |
