about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-01-24 21:23:11 +0000
committerbors <bors@rust-lang.org>2019-01-24 21:23:11 +0000
commit278067d34d1535a840cf9c99bcb8b538bf5b109a (patch)
tree7d3bd558b1a01bef4485dba03117107a7e132635 /src/libstd
parent01f8e25b15f4ab157c8e7c9c56054df7595ec0e1 (diff)
parent5fa1016f93d77e43c3ed69b1155308616095cfcb (diff)
downloadrust-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.rs2
-rw-r--r--src/libstd/os/fortanix_sgx/mod.rs2
-rw-r--r--src/libstd/sys/sgx/ext/ffi.rs109
-rw-r--r--src/libstd/sys/sgx/ext/mod.rs1
-rw-r--r--src/libstd/sys/sgx/rwlock.rs15
-rw-r--r--src/libstd/sys/windows/time.rs118
-rw-r--r--src/libstd/time.rs9
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();