From 276af456fe3ab38c7569b52f6dac1ec152dae4fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20F=C3=A4rnstrand?= Date: Fri, 14 Dec 2018 23:47:15 +0100 Subject: [PATCH 01/14] Trying to force the code to work as submodule of libstd --- core/src/lib.rs | 1 + core/src/parking_lot.rs | 22 ++++++++++++++++++---- core/src/spinwait.rs | 2 +- core/src/word_lock.rs | 4 ++-- lock_api/src/lib.rs | 3 ++- lock_api/src/mutex.rs | 2 ++ lock_api/src/remutex.rs | 6 ++++-- lock_api/src/rwlock.rs | 6 ++++++ src/condvar.rs | 6 +++--- src/mutex.rs | 2 +- src/once.rs | 2 +- src/raw_mutex.rs | 2 +- src/raw_rwlock.rs | 6 +++--- src/remutex.rs | 2 +- src/rwlock.rs | 2 +- 15 files changed, 47 insertions(+), 21 deletions(-) diff --git a/core/src/lib.rs b/core/src/lib.rs index 1d599a31..ff9dc550 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -56,6 +56,7 @@ feature(thread_local, checked_duration_since) )] +#[cfg(not(feature = "i-am-libstd"))] use cfg_if::cfg_if; cfg_if! { diff --git a/core/src/parking_lot.rs b/core/src/parking_lot.rs index 5779c318..2477fecd 100644 --- a/core/src/parking_lot.rs +++ b/core/src/parking_lot.rs @@ -5,15 +5,17 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. -use crate::thread_parker::ThreadParker; -use crate::util::UncheckedOptionExt; -use crate::word_lock::WordLock; +use super::thread_parker::ThreadParker; +use super::util::UncheckedOptionExt; +use super::word_lock::WordLock; use core::{ cell::{Cell, UnsafeCell}, ptr, sync::atomic::{AtomicPtr, AtomicUsize, Ordering}, }; +#[cfg(not(feature = "i-am-libstd"))] use rand::{rngs::SmallRng, FromEntropy, Rng}; +#[cfg(not(feature = "i-am-libstd"))] use smallvec::SmallVec; use std::time::{Duration, Instant}; @@ -85,6 +87,7 @@ struct FairTimeout { timeout: Instant, // Random number generator for calculating the next timeout + #[cfg(not(feature = "i-am-libstd"))] rng: SmallRng, } @@ -93,6 +96,7 @@ impl FairTimeout { fn new(timeout: Instant) -> FairTimeout { FairTimeout { timeout, + #[cfg(not(feature = "i-am-libstd"))] rng: SmallRng::from_entropy(), } } @@ -102,7 +106,11 @@ impl FairTimeout { fn should_timeout(&mut self) -> bool { let now = Instant::now(); if now > self.timeout { - self.timeout = now + Duration::new(0, self.rng.gen_range(0, 1000000)); + #[cfg(not(feature = "i-am-libstd"))] + let ns_offset = self.rng.gen_range(0, 1000000); + #[cfg(feature = "i-am-libstd")] + let ns_offset = 500000; + self.timeout = now + Duration::new(0, ns_offset); true } else { false @@ -767,7 +775,10 @@ pub unsafe fn unpark_all(key: usize, unpark_token: UnparkToken) -> usize { let mut link = &bucket.queue_head; let mut current = bucket.queue_head.get(); let mut previous = ptr::null(); + #[cfg(not(feature = "i-am-libstd"))] let mut threads = SmallVec::<[_; 8]>::new(); + #[cfg(feature = "i-am-libstd")] + let mut threads = Vec::new(); while !current.is_null() { if (*current).key.load(Ordering::Relaxed) == key { // Remove the thread from the queue @@ -978,7 +989,10 @@ where let mut link = &bucket.queue_head; let mut current = bucket.queue_head.get(); let mut previous = ptr::null(); + #[cfg(not(feature = "i-am-libstd"))] let mut threads = SmallVec::<[_; 8]>::new(); + #[cfg(feature = "i-am-libstd")] + let mut threads = Vec::new(); let mut result = UnparkResult::default(); while !current.is_null() { if (*current).key.load(Ordering::Relaxed) == key { diff --git a/core/src/spinwait.rs b/core/src/spinwait.rs index ad0327a3..d77cc2f8 100644 --- a/core/src/spinwait.rs +++ b/core/src/spinwait.rs @@ -5,7 +5,7 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. -use crate::thread_parker; +use super::thread_parker; use std::sync::atomic::spin_loop_hint; // Wastes some CPU time for the given number of iterations, diff --git a/core/src/word_lock.rs b/core/src/word_lock.rs index a6a10e83..257bd3c3 100644 --- a/core/src/word_lock.rs +++ b/core/src/word_lock.rs @@ -5,8 +5,8 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. -use crate::spinwait::SpinWait; -use crate::thread_parker::ThreadParker; +use super::spinwait::SpinWait; +use super::thread_parker::ThreadParker; use core::{ cell::Cell, mem, ptr, diff --git a/lock_api/src/lib.rs b/lock_api/src/lib.rs index d388d8a3..cb237f69 100644 --- a/lock_api/src/lib.rs +++ b/lock_api/src/lib.rs @@ -83,11 +83,12 @@ //! - `nightly`: Enables nightly-only features. At the moment the only such //! feature is `const fn` constructors for lock types. -#![no_std] +#![cfg_attr(not(feature = "i-am-libstd"), no_std)] #![warn(missing_docs)] #![warn(rust_2018_idioms)] #![cfg_attr(feature = "nightly", feature(const_fn))] +#[cfg(not(feature = "i-am-libstd"))] #[macro_use] extern crate scopeguard; diff --git a/lock_api/src/mutex.rs b/lock_api/src/mutex.rs index 12fb3689..df6b4888 100644 --- a/lock_api/src/mutex.rs +++ b/lock_api/src/mutex.rs @@ -392,6 +392,7 @@ impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> MutexGuard<'a, R, T> { /// /// This is safe because `&mut` guarantees that there exist no other /// references to the data protected by the mutex. + #[cfg(not(feature = "i-am-libstd"))] #[inline] pub fn unlocked(s: &mut Self, f: F) -> U where @@ -428,6 +429,7 @@ impl<'a, R: RawMutexFair + 'a, T: ?Sized + 'a> MutexGuard<'a, R, T> { /// /// This is safe because `&mut` guarantees that there exist no other /// references to the data protected by the mutex. + #[cfg(not(feature = "i-am-libstd"))] #[inline] pub fn unlocked_fair(s: &mut Self, f: F) -> U where diff --git a/lock_api/src/remutex.rs b/lock_api/src/remutex.rs index fe419210..ed75284a 100644 --- a/lock_api/src/remutex.rs +++ b/lock_api/src/remutex.rs @@ -5,8 +5,8 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. -use crate::mutex::{RawMutex, RawMutexFair, RawMutexTimed}; -use crate::GuardNoSend; +use super::mutex::{RawMutex, RawMutexFair, RawMutexTimed}; +use super::GuardNoSend; use core::cell::{Cell, UnsafeCell}; use core::fmt; use core::marker::PhantomData; @@ -467,6 +467,7 @@ impl<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: ?Sized + 'a> ReentrantMutexGu /// /// This is safe because `&mut` guarantees that there exist no other /// references to the data protected by the mutex. + #[cfg(not(feature = "i-am-libstd"))] #[inline] pub fn unlocked(s: &mut Self, f: F) -> U where @@ -505,6 +506,7 @@ impl<'a, R: RawMutexFair + 'a, G: GetThreadId + 'a, T: ?Sized + 'a> /// /// This is safe because `&mut` guarantees that there exist no other /// references to the data protected by the mutex. + #[cfg(not(feature = "i-am-libstd"))] #[inline] pub fn unlocked_fair(s: &mut Self, f: F) -> U where diff --git a/lock_api/src/rwlock.rs b/lock_api/src/rwlock.rs index 900b1d00..31e1e39b 100644 --- a/lock_api/src/rwlock.rs +++ b/lock_api/src/rwlock.rs @@ -796,6 +796,7 @@ impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> RwLockReadGuard<'a, R, T> { /// /// This is safe because `&mut` guarantees that there exist no other /// references to the data protected by the `RwLock`. + #[cfg(not(feature = "i-am-libstd"))] #[inline] pub fn unlocked(s: &mut Self, f: F) -> U where @@ -832,6 +833,7 @@ impl<'a, R: RawRwLockFair + 'a, T: ?Sized + 'a> RwLockReadGuard<'a, R, T> { /// /// This is safe because `&mut` guarantees that there exist no other /// references to the data protected by the `RwLock`. + #[cfg(not(feature = "i-am-libstd"))] #[inline] pub fn unlocked_fair(s: &mut Self, f: F) -> U where @@ -955,6 +957,7 @@ impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> RwLockWriteGuard<'a, R, T> { /// /// This is safe because `&mut` guarantees that there exist no other /// references to the data protected by the `RwLock`. + #[cfg(not(feature = "i-am-libstd"))] #[inline] pub fn unlocked(s: &mut Self, f: F) -> U where @@ -1027,6 +1030,7 @@ impl<'a, R: RawRwLockFair + 'a, T: ?Sized + 'a> RwLockWriteGuard<'a, R, T> { /// /// This is safe because `&mut` guarantees that there exist no other /// references to the data protected by the `RwLock`. + #[cfg(not(feature = "i-am-libstd"))] #[inline] pub fn unlocked_fair(s: &mut Self, f: F) -> U where @@ -1110,6 +1114,7 @@ impl<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + 'a> RwLockUpgradableReadGuard<'a, /// /// This is safe because `&mut` guarantees that there exist no other /// references to the data protected by the `RwLock`. + #[cfg(not(feature = "i-am-libstd"))] #[inline] pub fn unlocked(s: &mut Self, f: F) -> U where @@ -1174,6 +1179,7 @@ impl<'a, R: RawRwLockUpgradeFair + 'a, T: ?Sized + 'a> RwLockUpgradableReadGuard /// /// This is safe because `&mut` guarantees that there exist no other /// references to the data protected by the `RwLock`. + #[cfg(not(feature = "i-am-libstd"))] #[inline] pub fn unlocked_fair(s: &mut Self, f: F) -> U where diff --git a/src/condvar.rs b/src/condvar.rs index 59979671..efdf294c 100644 --- a/src/condvar.rs +++ b/src/condvar.rs @@ -5,9 +5,9 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. -use crate::mutex::MutexGuard; -use crate::raw_mutex::{RawMutex, TOKEN_HANDOFF, TOKEN_NORMAL}; -use crate::{deadlock, util}; +use super::mutex::MutexGuard; +use super::raw_mutex::{RawMutex, TOKEN_HANDOFF, TOKEN_NORMAL}; +use super::{deadlock, util}; use core::{ fmt, ptr, sync::atomic::{AtomicPtr, Ordering}, diff --git a/src/mutex.rs b/src/mutex.rs index 4f88e583..1d9c7ee2 100644 --- a/src/mutex.rs +++ b/src/mutex.rs @@ -5,7 +5,7 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. -use crate::raw_mutex::RawMutex; +use super::raw_mutex::RawMutex; use lock_api; /// A mutual exclusion primitive useful for protecting shared data diff --git a/src/once.rs b/src/once.rs index e205e653..224607f8 100644 --- a/src/once.rs +++ b/src/once.rs @@ -5,7 +5,7 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. -use crate::util::UncheckedOptionExt; +use super::util::UncheckedOptionExt; #[cfg(has_sized_atomics)] use core::sync::atomic::AtomicU8; #[cfg(not(has_sized_atomics))] diff --git a/src/raw_mutex.rs b/src/raw_mutex.rs index be6eedb4..8baa511c 100644 --- a/src/raw_mutex.rs +++ b/src/raw_mutex.rs @@ -5,7 +5,7 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. -use crate::{deadlock, util}; +use super::{deadlock, util}; #[cfg(has_sized_atomics)] use core::sync::atomic::AtomicU8; #[cfg(not(has_sized_atomics))] diff --git a/src/raw_rwlock.rs b/src/raw_rwlock.rs index ccfe4616..5ca672c1 100644 --- a/src/raw_rwlock.rs +++ b/src/raw_rwlock.rs @@ -5,9 +5,9 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. -use crate::elision::{have_elision, AtomicElisionExt}; -use crate::raw_mutex::{TOKEN_HANDOFF, TOKEN_NORMAL}; -use crate::util; +use super::elision::{have_elision, AtomicElisionExt}; +use super::raw_mutex::{TOKEN_HANDOFF, TOKEN_NORMAL}; +use super::{deadlock, util}; use core::{ cell::Cell, sync::atomic::{AtomicUsize, Ordering}, diff --git a/src/remutex.rs b/src/remutex.rs index c655a99a..9e51cdfb 100644 --- a/src/remutex.rs +++ b/src/remutex.rs @@ -5,7 +5,7 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. -use crate::raw_mutex::RawMutex; +use super::raw_mutex::RawMutex; use lock_api::{self, GetThreadId}; /// Implementation of the `GetThreadId` trait for `lock_api::ReentrantMutex`. diff --git a/src/rwlock.rs b/src/rwlock.rs index fbfb39f2..0d3c77fa 100644 --- a/src/rwlock.rs +++ b/src/rwlock.rs @@ -5,7 +5,7 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. -use crate::raw_rwlock::RawRwLock; +use super::raw_rwlock::RawRwLock; use lock_api; /// A reader-writer lock From 5d8c51641d16f4b968f860e5ed003d9cbb3da1f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20F=C3=A4rnstrand?= Date: Mon, 17 Dec 2018 19:51:22 +0100 Subject: [PATCH 02/14] Remove tests when inside libstd --- src/condvar.rs | 2 +- src/deadlock.rs | 2 +- src/mutex.rs | 2 +- src/once.rs | 2 +- src/remutex.rs | 2 +- src/rwlock.rs | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/condvar.rs b/src/condvar.rs index efdf294c..57332ce6 100644 --- a/src/condvar.rs +++ b/src/condvar.rs @@ -408,7 +408,7 @@ impl fmt::Debug for Condvar { } } -#[cfg(test)] +#[cfg(all(test, not(feature = "i-am-libstd")))] mod tests { use crate::{Condvar, Mutex, MutexGuard}; use std::sync::mpsc::channel; diff --git a/src/deadlock.rs b/src/deadlock.rs index 810edf1f..b68e0166 100644 --- a/src/deadlock.rs +++ b/src/deadlock.rs @@ -37,7 +37,7 @@ pub use parking_lot_core::deadlock::check_deadlock; pub(crate) use parking_lot_core::deadlock::{acquire_resource, release_resource}; -#[cfg(test)] +#[cfg(all(test, not(feature = "i-am-libstd")))] #[cfg(feature = "deadlock_detection")] mod tests { use crate::{Mutex, ReentrantMutex, RwLock}; diff --git a/src/mutex.rs b/src/mutex.rs index 1d9c7ee2..65c3427f 100644 --- a/src/mutex.rs +++ b/src/mutex.rs @@ -103,7 +103,7 @@ pub type MutexGuard<'a, T> = lock_api::MutexGuard<'a, RawMutex, T>; /// thread. pub type MappedMutexGuard<'a, T> = lock_api::MappedMutexGuard<'a, RawMutex, T>; -#[cfg(test)] +#[cfg(all(test, not(feature = "i-am-libstd")))] mod tests { use crate::{Condvar, Mutex}; use std::sync::atomic::{AtomicUsize, Ordering}; diff --git a/src/once.rs b/src/once.rs index 224607f8..6c084c36 100644 --- a/src/once.rs +++ b/src/once.rs @@ -340,7 +340,7 @@ impl fmt::Debug for Once { } } -#[cfg(test)] +#[cfg(all(test, not(feature = "i-am-libstd")))] mod tests { use crate::Once; use std::panic; diff --git a/src/remutex.rs b/src/remutex.rs index 9e51cdfb..9f9ea9f8 100644 --- a/src/remutex.rs +++ b/src/remutex.rs @@ -52,7 +52,7 @@ pub type ReentrantMutexGuard<'a, T> = lock_api::ReentrantMutexGuard<'a, RawMutex pub type MappedReentrantMutexGuard<'a, T> = lock_api::MappedReentrantMutexGuard<'a, RawMutex, RawThreadId, T>; -#[cfg(test)] +#[cfg(all(test, not(feature = "i-am-libstd")))] mod tests { use crate::ReentrantMutex; use std::cell::RefCell; diff --git a/src/rwlock.rs b/src/rwlock.rs index 0d3c77fa..f3949065 100644 --- a/src/rwlock.rs +++ b/src/rwlock.rs @@ -118,7 +118,7 @@ pub type MappedRwLockWriteGuard<'a, T> = lock_api::MappedRwLockWriteGuard<'a, Ra /// dropped. pub type RwLockUpgradableReadGuard<'a, T> = lock_api::RwLockUpgradableReadGuard<'a, RawRwLock, T>; -#[cfg(test)] +#[cfg(all(test, not(feature = "i-am-libstd")))] mod tests { use crate::{RwLock, RwLockUpgradableReadGuard, RwLockWriteGuard}; use rand::Rng; From 84682397269a7c11af88790c003830f200e85137 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20F=C3=A4rnstrand?= Date: Thu, 14 Feb 2019 22:00:33 +0100 Subject: [PATCH 03/14] Replace scopeguard dependency with local implementation --- lock_api/Cargo.toml | 1 - lock_api/src/lib.rs | 14 +++++----- lock_api/src/scopeguard.rs | 55 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 8 deletions(-) create mode 100644 lock_api/src/scopeguard.rs diff --git a/lock_api/Cargo.toml b/lock_api/Cargo.toml index 161104bc..650c98c0 100644 --- a/lock_api/Cargo.toml +++ b/lock_api/Cargo.toml @@ -10,7 +10,6 @@ categories = ["concurrency", "no-std"] edition = "2018" [dependencies] -scopeguard = { version = "1.0", default-features = false } owning_ref = { version = "0.4", optional = true } # Optional dependency for supporting serde. Optional crates automatically diff --git a/lock_api/src/lib.rs b/lock_api/src/lib.rs index cb237f69..f3bc839b 100644 --- a/lock_api/src/lib.rs +++ b/lock_api/src/lib.rs @@ -88,21 +88,21 @@ #![warn(rust_2018_idioms)] #![cfg_attr(feature = "nightly", feature(const_fn))] -#[cfg(not(feature = "i-am-libstd"))] -#[macro_use] -extern crate scopeguard; - /// Marker type which indicates that the Guard type for a lock is `Send`. pub struct GuardSend(()); /// Marker type which indicates that the Guard type for a lock is not `Send`. pub struct GuardNoSend(*mut ()); +#[cfg(not(feature = "i-am-libstd"))] +#[macro_use] +mod scopeguard; + mod mutex; -pub use crate::mutex::*; +pub use self::mutex::*; mod remutex; -pub use crate::remutex::*; +pub use self::remutex::*; mod rwlock; -pub use crate::rwlock::*; +pub use self::rwlock::*; diff --git a/lock_api/src/scopeguard.rs b/lock_api/src/scopeguard.rs new file mode 100644 index 00000000..3cd8ce1d --- /dev/null +++ b/lock_api/src/scopeguard.rs @@ -0,0 +1,55 @@ +// Extracted from the scopeguard crate +use core::ops::{Deref, DerefMut}; + +macro_rules! defer { + ($e:expr) => { + let _guard = $crate::scopeguard::guard((), |&mut ()| $e); + }; +} + +pub struct ScopeGuard +where + F: FnMut(&mut T), +{ + dropfn: F, + value: T, +} + +#[inline] +pub fn guard(value: T, dropfn: F) -> ScopeGuard +where + F: FnMut(&mut T), +{ + ScopeGuard { dropfn, value } +} + +impl Deref for ScopeGuard +where + F: FnMut(&mut T), +{ + type Target = T; + #[inline] + fn deref(&self) -> &T { + &self.value + } +} + +impl DerefMut for ScopeGuard +where + F: FnMut(&mut T), +{ + #[inline] + fn deref_mut(&mut self) -> &mut T { + &mut self.value + } +} + +impl Drop for ScopeGuard +where + F: FnMut(&mut T), +{ + #[inline] + fn drop(&mut self) { + (self.dropfn)(&mut self.value) + } +} From c60e6ba8f172b1010ace5b696172762eff72d731 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20F=C3=A4rnstrand?= Date: Thu, 21 Feb 2019 20:45:21 +0100 Subject: [PATCH 04/14] Import Windows C bindings from sys::c in libstd --- core/src/thread_parker/windows/keyed_event.rs | 7 +++++++ core/src/thread_parker/windows/mod.rs | 6 +++++- core/src/thread_parker/windows/waitaddress.rs | 6 ++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/core/src/thread_parker/windows/keyed_event.rs b/core/src/thread_parker/windows/keyed_event.rs index 71b55f0f..791ff290 100644 --- a/core/src/thread_parker/windows/keyed_event.rs +++ b/core/src/thread_parker/windows/keyed_event.rs @@ -10,6 +10,13 @@ use std::{ sync::atomic::{AtomicUsize, Ordering}, time::Instant, }; +#[cfg(feature = "i-am-libstd")] +use sys::c::{ + CloseHandle, GetModuleHandleA, GetProcAddress, ACCESS_MASK, BOOLEAN, GENERIC_READ, + GENERIC_WRITE, HANDLE, LARGE_INTEGER, LPCSTR, LPHANDLE as PHANDLE, LPVOID as PVOID, NTSTATUS, + PLARGE_INTEGER, STATUS_SUCCESS, STATUS_TIMEOUT, TRUE, ULONG, +}; +#[cfg(not(feature = "i-am-libstd"))] use winapi::{ shared::{ minwindef::{TRUE, ULONG}, diff --git a/core/src/thread_parker/windows/mod.rs b/core/src/thread_parker/windows/mod.rs index 32f51c2d..03120a8b 100644 --- a/core/src/thread_parker/windows/mod.rs +++ b/core/src/thread_parker/windows/mod.rs @@ -164,6 +164,10 @@ impl UnparkHandle { // Yields the rest of the current timeslice to the OS #[inline] pub fn thread_yield() { + #[cfg(feature = "i-am-libstd")] + use sys::c::DWORD; + #[cfg(not(feature = "i-am-libstd"))] + use winapi::shared::minwindef::DWORD; // Note that this is manually defined here rather than using the definition // through `winapi`. The `winapi` definition comes from the `synchapi` // header which enables the "synchronization.lib" library. It turns out, @@ -178,7 +182,7 @@ pub fn thread_yield() { // libraries, but that'll probably take a lot longer than patching this here // and avoiding the `synchapi` feature entirely. extern "system" { - fn Sleep(a: winapi::shared::minwindef::DWORD); + fn Sleep(a: DWORD); } unsafe { // We don't use SwitchToThread here because it doesn't consider all diff --git a/core/src/thread_parker/windows/waitaddress.rs b/core/src/thread_parker/windows/waitaddress.rs index 0ec78040..89c77a24 100644 --- a/core/src/thread_parker/windows/waitaddress.rs +++ b/core/src/thread_parker/windows/waitaddress.rs @@ -10,6 +10,12 @@ use core::{ sync::atomic::{AtomicUsize, Ordering}, }; use std::time::Instant; +#[cfg(feature = "i-am-libstd")] +use sys::c::{ + GetLastError, GetModuleHandleA, GetProcAddress, BOOL, DWORD, ERROR_TIMEOUT, FALSE, INFINITE, + LPCSTR, LPVOID as PVOID, SIZE_T, TRUE, +}; +#[cfg(not(feature = "i-am-libstd"))] use winapi::{ shared::{ basetsd::SIZE_T, From 69ba9df2440cd94d01eae072df3e369a4b1b74e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20F=C3=A4rnstrand?= Date: Thu, 21 Feb 2019 21:37:38 +0100 Subject: [PATCH 05/14] Fix libstd difference to LARGE_INTEGER --- core/src/thread_parker/windows/keyed_event.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/src/thread_parker/windows/keyed_event.rs b/core/src/thread_parker/windows/keyed_event.rs index 791ff290..8cec87c3 100644 --- a/core/src/thread_parker/windows/keyed_event.rs +++ b/core/src/thread_parker/windows/keyed_event.rs @@ -146,6 +146,9 @@ impl KeyedEvent { // NT uses a timeout in units of 100ns. We use a negative value to // indicate a relative timeout based on a monotonic clock. + #[cfg(feature = "i-am-libstd")] + let mut nt_timeout: LARGE_INTEGER; + #[cfg(not(feature = "i-am-libstd"))] let mut nt_timeout: LARGE_INTEGER = mem::zeroed(); let diff = timeout - now; let value = (diff.as_secs() as i64) @@ -153,6 +156,9 @@ impl KeyedEvent { .and_then(|x| x.checked_sub((diff.subsec_nanos() as i64 + 99) / 100)); match value { + #[cfg(feature = "i-am-libstd")] + Some(x) => nt_timeout = x, + #[cfg(not(feature = "i-am-libstd"))] Some(x) => *nt_timeout.QuadPart_mut() = x, None => { // Timeout overflowed, just sleep indefinitely From 93b506366ae06af9332bb0169690fb443faed129 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20F=C3=A4rnstrand?= Date: Fri, 22 Feb 2019 23:08:45 +0100 Subject: [PATCH 06/14] Disable doctests when in libstd --- lock_api/src/lib.rs | 5 +++++ src/condvar.rs | 10 ++++++++++ src/mutex.rs | 5 +++++ src/once.rs | 10 ++++++++++ src/rwlock.rs | 5 +++++ 5 files changed, 35 insertions(+) diff --git a/lock_api/src/lib.rs b/lock_api/src/lib.rs index f3bc839b..0a73c596 100644 --- a/lock_api/src/lib.rs +++ b/lock_api/src/lib.rs @@ -27,6 +27,8 @@ //! # Example //! //! ``` +//! # #[cfg(not(feature = "i-am-libstd"))] +//! # fn main() { //! use lock_api::{RawMutex, Mutex, GuardSend}; //! use std::sync::atomic::{AtomicBool, Ordering}; //! @@ -58,6 +60,9 @@ //! // 3. Export the wrappers. This are the types that your users will actually use. //! pub type Spinlock = lock_api::Mutex; //! pub type SpinlockGuard<'a, T> = lock_api::MutexGuard<'a, RawSpinlock, T>; +//! # } +//! # #[cfg(feature = "i-am-libstd")] +//! # fn main() {} //! ``` //! //! # Extension traits diff --git a/src/condvar.rs b/src/condvar.rs index 57332ce6..f132b2f0 100644 --- a/src/condvar.rs +++ b/src/condvar.rs @@ -60,6 +60,8 @@ impl WaitTimeoutResult { /// # Examples /// /// ``` +/// # #[cfg(not(feature = "i-am-libstd"))] +/// # fn main() { /// use parking_lot::{Mutex, Condvar}; /// use std::sync::Arc; /// use std::thread; @@ -81,6 +83,9 @@ impl WaitTimeoutResult { /// while !*started { /// cvar.wait(&mut started); /// } +/// # } +/// # #[cfg(feature = "i-am-libstd")] +/// # fn main() {} /// ``` pub struct Condvar { state: AtomicPtr, @@ -109,6 +114,8 @@ impl Condvar { /// # Examples /// /// ``` + /// # #[cfg(not(feature = "i-am-libstd"))] + /// # fn main() { /// use parking_lot::Condvar; /// /// let condvar = Condvar::new(); @@ -118,6 +125,9 @@ impl Condvar { /// if !condvar.notify_one() { /// println!("Nobody was listening for this."); /// } + /// # } + /// # #[cfg(feature = "i-am-libstd")] + /// # fn main() {} /// ``` #[inline] pub fn notify_one(&self) -> bool { diff --git a/src/mutex.rs b/src/mutex.rs index 65c3427f..49d0b322 100644 --- a/src/mutex.rs +++ b/src/mutex.rs @@ -53,6 +53,8 @@ use lock_api; /// # Examples /// /// ``` +/// # #[cfg(not(feature = "i-am-libstd"))] +/// # fn main() { /// use std::sync::Arc; /// use parking_lot::Mutex; /// use std::thread; @@ -84,6 +86,9 @@ use lock_api; /// } /// /// rx.recv().unwrap(); +/// # } +/// # #[cfg(feature = "i-am-libstd")] +/// # fn main() {} /// ``` pub type Mutex = lock_api::Mutex; diff --git a/src/once.rs b/src/once.rs index 6c084c36..7e072f0d 100644 --- a/src/once.rs +++ b/src/once.rs @@ -81,6 +81,8 @@ impl OnceState { /// # Examples /// /// ``` +/// # #[cfg(not(feature = "i-am-libstd"))] +/// # fn main() { /// use parking_lot::Once; /// /// static START: Once = Once::new(); @@ -88,6 +90,9 @@ impl OnceState { /// START.call_once(|| { /// // run initialization here /// }); +/// # } +/// # #[cfg(feature = "i-am-libstd")] +/// # fn main() {} /// ``` pub struct Once(AtomicU8); @@ -130,6 +135,8 @@ impl Once { /// # Examples /// /// ``` + /// # #[cfg(not(feature = "i-am-libstd"))] + /// # fn main() { /// use parking_lot::Once; /// /// static mut VAL: usize = 0; @@ -154,6 +161,9 @@ impl Once { /// // ... /// # 2 /// } + /// # } + /// # #[cfg(feature = "i-am-libstd")] + /// # fn main() {} /// ``` /// /// # Panics diff --git a/src/rwlock.rs b/src/rwlock.rs index f3949065..17f8bede 100644 --- a/src/rwlock.rs +++ b/src/rwlock.rs @@ -67,6 +67,8 @@ use lock_api; /// # Examples /// /// ``` +/// # #[cfg(not(feature = "i-am-libstd"))] +/// # fn main() { /// use parking_lot::RwLock; /// /// let lock = RwLock::new(5); @@ -85,6 +87,9 @@ use lock_api; /// *w += 1; /// assert_eq!(*w, 6); /// } // write lock is dropped here +/// # } +/// # #[cfg(feature = "i-am-libstd")] +/// # fn main() {} /// ``` pub type RwLock = lock_api::RwLock; From 494bb433d52e67b09b23f4e5463ace6cffbd83b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20F=C3=A4rnstrand?= Date: Wed, 27 Mar 2019 13:12:17 +0100 Subject: [PATCH 07/14] Activate more "nightly" features when in libstd --- core/src/lib.rs | 8 ++++---- src/once.rs | 8 ++++---- src/raw_mutex.rs | 8 ++++---- src/util.rs | 4 ++-- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/core/src/lib.rs b/core/src/lib.rs index ff9dc550..ed517941 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -60,7 +60,7 @@ use cfg_if::cfg_if; cfg_if! { - if #[cfg(all(has_sized_atomics, target_os = "linux"))] { + if #[cfg(all(any(has_sized_atomics, feature = "i-am-libstd"), target_os = "linux"))] { #[path = "thread_parker/linux.rs"] mod thread_parker; } else if #[cfg(unix)] { @@ -69,20 +69,20 @@ cfg_if! { } else if #[cfg(windows)] { #[path = "thread_parker/windows/mod.rs"] mod thread_parker; - } else if #[cfg(all(has_sized_atomics, target_os = "redox"))] { + } else if #[cfg(all(any(has_sized_atomics, feature = "i-am-libstd"), target_os = "redox"))] { #[path = "thread_parker/redox.rs"] mod thread_parker; } else if #[cfg(all(target_env = "sgx", target_vendor = "fortanix"))] { #[path = "thread_parker/sgx.rs"] mod thread_parker; } else if #[cfg(all( - feature = "nightly", + any(feature = "nightly", feature = "i-am-libstd"), target_arch = "wasm32", target_feature = "atomics" ))] { #[path = "thread_parker/wasm.rs"] mod thread_parker; - } else if #[cfg(all(feature = "nightly", target_os = "cloudabi"))] { + } else if #[cfg(all(any(feature = "nightly", feature = "i-am-libstd"), target_os = "cloudabi"))] { #[path = "thread_parker/cloudabi.rs"] mod thread_parker; } else { diff --git a/src/once.rs b/src/once.rs index 7e072f0d..b52d92ff 100644 --- a/src/once.rs +++ b/src/once.rs @@ -6,9 +6,9 @@ // copied, modified, or distributed except according to those terms. use super::util::UncheckedOptionExt; -#[cfg(has_sized_atomics)] +#[cfg(any(has_sized_atomics, feature = "i-am-libstd"))] use core::sync::atomic::AtomicU8; -#[cfg(not(has_sized_atomics))] +#[cfg(not(any(has_sized_atomics, feature = "i-am-libstd")))] use core::sync::atomic::AtomicUsize as AtomicU8; use core::{ fmt, mem, @@ -16,9 +16,9 @@ use core::{ }; use parking_lot_core::{self, SpinWait, DEFAULT_PARK_TOKEN, DEFAULT_UNPARK_TOKEN}; -#[cfg(has_sized_atomics)] +#[cfg(any(has_sized_atomics, feature = "i-am-libstd"))] type U8 = u8; -#[cfg(not(has_sized_atomics))] +#[cfg(not(any(has_sized_atomics, feature = "i-am-libstd")))] type U8 = usize; const DONE_BIT: U8 = 1; diff --git a/src/raw_mutex.rs b/src/raw_mutex.rs index 8baa511c..d021eb9b 100644 --- a/src/raw_mutex.rs +++ b/src/raw_mutex.rs @@ -6,18 +6,18 @@ // copied, modified, or distributed except according to those terms. use super::{deadlock, util}; -#[cfg(has_sized_atomics)] +#[cfg(any(has_sized_atomics, feature = "i-am-libstd"))] use core::sync::atomic::AtomicU8; -#[cfg(not(has_sized_atomics))] +#[cfg(not(any(has_sized_atomics, feature = "i-am-libstd")))] use core::sync::atomic::AtomicUsize as AtomicU8; use core::{sync::atomic::Ordering, time::Duration}; use lock_api::{GuardNoSend, RawMutex as RawMutexTrait, RawMutexFair, RawMutexTimed}; use parking_lot_core::{self, ParkResult, SpinWait, UnparkResult, UnparkToken, DEFAULT_PARK_TOKEN}; use std::time::Instant; -#[cfg(has_sized_atomics)] +#[cfg(any(has_sized_atomics, feature = "i-am-libstd"))] type U8 = u8; -#[cfg(not(has_sized_atomics))] +#[cfg(not(any(has_sized_atomics, feature = "i-am-libstd")))] type U8 = usize; // UnparkToken used to indicate that that the target thread should attempt to diff --git a/src/util.rs b/src/util.rs index 159af7f0..65f3c2d2 100644 --- a/src/util.rs +++ b/src/util.rs @@ -35,9 +35,9 @@ unsafe fn unreachable() -> ! { #[inline] pub fn to_deadline(timeout: Duration) -> Option { - #[cfg(has_checked_instant)] + #[cfg(any(has_checked_instant, feature = "i-am-libstd"))] let deadline = Instant::now().checked_add(timeout); - #[cfg(not(has_checked_instant))] + #[cfg(not(any(has_checked_instant, feature = "i-am-libstd")))] let deadline = Some(Instant::now() + timeout); deadline From a9b06bb08e386850f74f78db4f90827391a2211e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20F=C3=A4rnstrand?= Date: Fri, 1 Mar 2019 21:10:54 +0100 Subject: [PATCH 08/14] Make most use statements relative --- core/src/lib.rs | 7 +++++++ core/src/parking_lot.rs | 2 +- core/src/spinwait.rs | 2 +- core/src/thread_parker/cloudabi.rs | 3 ++- core/src/thread_parker/generic.rs | 2 +- core/src/thread_parker/linux.rs | 2 +- core/src/thread_parker/redox.rs | 2 +- core/src/thread_parker/sgx.rs | 4 ++-- core/src/thread_parker/unix.rs | 8 ++++---- core/src/thread_parker/wasm.rs | 3 ++- core/src/thread_parker/windows/keyed_event.rs | 12 ++++++------ core/src/thread_parker/windows/mod.rs | 4 ++-- core/src/thread_parker/windows/waitaddress.rs | 12 ++++++------ src/condvar.rs | 6 +++--- src/deadlock.rs | 4 ++-- src/elision.rs | 2 +- src/lib.rs | 11 +++++++++++ src/mutex.rs | 2 +- src/once.rs | 2 +- src/raw_mutex.rs | 8 +++++--- src/raw_rwlock.rs | 18 +++++++++--------- src/remutex.rs | 5 +++-- src/rwlock.rs | 2 +- src/util.rs | 2 +- 24 files changed, 74 insertions(+), 51 deletions(-) diff --git a/core/src/lib.rs b/core/src/lib.rs index ed517941..f7cca0de 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -59,6 +59,13 @@ #[cfg(not(feature = "i-am-libstd"))] use cfg_if::cfg_if; +mod libstd { + #[cfg(feature = "i-am-libstd")] + pub use crate::*; + #[cfg(not(feature = "i-am-libstd"))] + pub use std::*; +} + cfg_if! { if #[cfg(all(any(has_sized_atomics, feature = "i-am-libstd"), target_os = "linux"))] { #[path = "thread_parker/linux.rs"] diff --git a/core/src/parking_lot.rs b/core/src/parking_lot.rs index 2477fecd..10b43f6d 100644 --- a/core/src/parking_lot.rs +++ b/core/src/parking_lot.rs @@ -5,6 +5,7 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. +use super::libstd::time::{Duration, Instant}; use super::thread_parker::ThreadParker; use super::util::UncheckedOptionExt; use super::word_lock::WordLock; @@ -17,7 +18,6 @@ use core::{ use rand::{rngs::SmallRng, FromEntropy, Rng}; #[cfg(not(feature = "i-am-libstd"))] use smallvec::SmallVec; -use std::time::{Duration, Instant}; static NUM_THREADS: AtomicUsize = AtomicUsize::new(0); static HASHTABLE: AtomicPtr = AtomicPtr::new(ptr::null_mut()); diff --git a/core/src/spinwait.rs b/core/src/spinwait.rs index d77cc2f8..fa29fdb4 100644 --- a/core/src/spinwait.rs +++ b/core/src/spinwait.rs @@ -6,7 +6,7 @@ // copied, modified, or distributed except according to those terms. use super::thread_parker; -use std::sync::atomic::spin_loop_hint; +use core::sync::atomic::spin_loop_hint; // Wastes some CPU time for the given number of iterations, // using a hint to indicate to the CPU that we are spinning. diff --git a/core/src/thread_parker/cloudabi.rs b/core/src/thread_parker/cloudabi.rs index d6d51438..a3322377 100644 --- a/core/src/thread_parker/cloudabi.rs +++ b/core/src/thread_parker/cloudabi.rs @@ -10,8 +10,9 @@ use core::{ cell::Cell, mem, sync::atomic::{AtomicU32, Ordering}, + convert::TryFrom, }; -use std::{convert::TryFrom, thread, time::Instant}; +use super::libstd::{thread, time::Instant}; extern "C" { #[thread_local] diff --git a/core/src/thread_parker/generic.rs b/core/src/thread_parker/generic.rs index bcfc86df..602131c8 100644 --- a/core/src/thread_parker/generic.rs +++ b/core/src/thread_parker/generic.rs @@ -8,8 +8,8 @@ //! A simple spin lock based thread parker. Used on platforms without better //! parking facilities available. +use super::libstd::{thread, time::Instant}; use core::sync::atomic::{spin_loop_hint, AtomicBool, Ordering}; -use std::{thread, time::Instant}; // Helper type for putting a thread to sleep until some other thread wakes it up pub struct ThreadParker { diff --git a/core/src/thread_parker/linux.rs b/core/src/thread_parker/linux.rs index 319d04ea..6017b534 100644 --- a/core/src/thread_parker/linux.rs +++ b/core/src/thread_parker/linux.rs @@ -5,12 +5,12 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. +use super::libstd::{thread, time::Instant}; use core::{ ptr, sync::atomic::{AtomicI32, Ordering}, }; use libc; -use std::{thread, time::Instant}; const FUTEX_WAIT: i32 = 0; const FUTEX_WAKE: i32 = 1; diff --git a/core/src/thread_parker/redox.rs b/core/src/thread_parker/redox.rs index 1c631a1f..42304d49 100644 --- a/core/src/thread_parker/redox.rs +++ b/core/src/thread_parker/redox.rs @@ -9,7 +9,7 @@ use core::{ ptr, sync::atomic::{AtomicI32, Ordering}, }; -use std::{thread, time::Instant}; +use super::libstd::{thread, time::Instant}; use syscall::{ call::futex, data::TimeSpec, diff --git a/core/src/thread_parker/sgx.rs b/core/src/thread_parker/sgx.rs index c5ef6cbe..ed511ce2 100644 --- a/core/src/thread_parker/sgx.rs +++ b/core/src/thread_parker/sgx.rs @@ -5,8 +5,7 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. -use core::sync::atomic::{AtomicBool, Ordering}; -use std::{ +use super::libstd::{ io, os::fortanix_sgx::{ thread::current as current_tcs, @@ -18,6 +17,7 @@ use std::{ thread, time::Instant, }; +use core::sync::atomic::{AtomicBool, Ordering}; // Helper type for putting a thread to sleep until some other thread wakes it up pub struct ThreadParker { diff --git a/core/src/thread_parker/unix.rs b/core/src/thread_parker/unix.rs index 8712ebdf..49d1ad10 100644 --- a/core/src/thread_parker/unix.rs +++ b/core/src/thread_parker/unix.rs @@ -5,6 +5,10 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. +use super::libstd::{ + thread, + time::{Duration, Instant}, +}; #[cfg(any(target_os = "macos", target_os = "ios"))] use core::ptr; use core::{ @@ -12,10 +16,6 @@ use core::{ mem, }; use libc; -use std::{ - thread, - time::{Duration, Instant}, -}; // x32 Linux uses a non-standard type for tv_nsec in timespec. // See https://sourceware.org/bugzilla/show_bug.cgi?id=16437 diff --git a/core/src/thread_parker/wasm.rs b/core/src/thread_parker/wasm.rs index 7a9f7abf..cab7d2b3 100644 --- a/core/src/thread_parker/wasm.rs +++ b/core/src/thread_parker/wasm.rs @@ -8,8 +8,9 @@ use core::{ arch::wasm32, sync::atomic::{AtomicI32, Ordering}, + convert::TryFrom, }; -use std::{convert::TryFrom, thread, time::Instant}; +use super::libstd::{thread, time::Instant}; // Helper type for putting a thread to sleep until some other thread wakes it up pub struct ThreadParker { diff --git a/core/src/thread_parker/windows/keyed_event.rs b/core/src/thread_parker/windows/keyed_event.rs index 8cec87c3..1f2bcace 100644 --- a/core/src/thread_parker/windows/keyed_event.rs +++ b/core/src/thread_parker/windows/keyed_event.rs @@ -5,17 +5,17 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. -use core::{mem, ptr}; -use std::{ - sync::atomic::{AtomicUsize, Ordering}, - time::Instant, -}; +use super::super::libstd::time::Instant; #[cfg(feature = "i-am-libstd")] -use sys::c::{ +use crate::sys::c::{ CloseHandle, GetModuleHandleA, GetProcAddress, ACCESS_MASK, BOOLEAN, GENERIC_READ, GENERIC_WRITE, HANDLE, LARGE_INTEGER, LPCSTR, LPHANDLE as PHANDLE, LPVOID as PVOID, NTSTATUS, PLARGE_INTEGER, STATUS_SUCCESS, STATUS_TIMEOUT, TRUE, ULONG, }; +use core::{ + mem, ptr, + sync::atomic::{AtomicUsize, Ordering}, +}; #[cfg(not(feature = "i-am-libstd"))] use winapi::{ shared::{ diff --git a/core/src/thread_parker/windows/mod.rs b/core/src/thread_parker/windows/mod.rs index 03120a8b..57f40777 100644 --- a/core/src/thread_parker/windows/mod.rs +++ b/core/src/thread_parker/windows/mod.rs @@ -5,11 +5,11 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. +use super::libstd::time::Instant; use core::{ ptr, sync::atomic::{AtomicPtr, AtomicUsize, Ordering}, }; -use std::time::Instant; mod keyed_event; mod waitaddress; @@ -165,7 +165,7 @@ impl UnparkHandle { #[inline] pub fn thread_yield() { #[cfg(feature = "i-am-libstd")] - use sys::c::DWORD; + use crate::sys::c::DWORD; #[cfg(not(feature = "i-am-libstd"))] use winapi::shared::minwindef::DWORD; // Note that this is manually defined here rather than using the definition diff --git a/core/src/thread_parker/windows/waitaddress.rs b/core/src/thread_parker/windows/waitaddress.rs index 89c77a24..e77f55b8 100644 --- a/core/src/thread_parker/windows/waitaddress.rs +++ b/core/src/thread_parker/windows/waitaddress.rs @@ -5,16 +5,16 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. -use core::{ - mem, - sync::atomic::{AtomicUsize, Ordering}, -}; -use std::time::Instant; +use super::super::libstd::time::Instant; #[cfg(feature = "i-am-libstd")] -use sys::c::{ +use crate::sys::c::{ GetLastError, GetModuleHandleA, GetProcAddress, BOOL, DWORD, ERROR_TIMEOUT, FALSE, INFINITE, LPCSTR, LPVOID as PVOID, SIZE_T, TRUE, }; +use core::{ + mem, + sync::atomic::{AtomicUsize, Ordering}, +}; #[cfg(not(feature = "i-am-libstd"))] use winapi::{ shared::{ diff --git a/src/condvar.rs b/src/condvar.rs index f132b2f0..b9122f42 100644 --- a/src/condvar.rs +++ b/src/condvar.rs @@ -5,16 +5,16 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. +use super::libstd::time::{Duration, Instant}; +use super::lock_api::RawMutex as RawMutexTrait; use super::mutex::MutexGuard; +use super::parking_lot_core::{self, ParkResult, RequeueOp, UnparkResult, DEFAULT_PARK_TOKEN}; use super::raw_mutex::{RawMutex, TOKEN_HANDOFF, TOKEN_NORMAL}; use super::{deadlock, util}; use core::{ fmt, ptr, sync::atomic::{AtomicPtr, Ordering}, }; -use lock_api::RawMutex as RawMutexTrait; -use parking_lot_core::{self, ParkResult, RequeueOp, UnparkResult, DEFAULT_PARK_TOKEN}; -use std::time::{Duration, Instant}; /// A type indicating whether a timed wait on a condition variable returned /// due to a time out or not. diff --git a/src/deadlock.rs b/src/deadlock.rs index b68e0166..182a22a1 100644 --- a/src/deadlock.rs +++ b/src/deadlock.rs @@ -34,8 +34,8 @@ //! ``` #[cfg(feature = "deadlock_detection")] -pub use parking_lot_core::deadlock::check_deadlock; -pub(crate) use parking_lot_core::deadlock::{acquire_resource, release_resource}; +pub use super::parking_lot_core::deadlock::check_deadlock; +pub(crate) use super::parking_lot_core::deadlock::{acquire_resource, release_resource}; #[cfg(all(test, not(feature = "i-am-libstd")))] #[cfg(feature = "deadlock_detection")] diff --git a/src/elision.rs b/src/elision.rs index 74ff5ffc..e8816c4e 100644 --- a/src/elision.rs +++ b/src/elision.rs @@ -5,7 +5,7 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. -use std::sync::atomic::AtomicUsize; +use core::sync::atomic::AtomicUsize; // Extension trait to add lock elision primitives to atomic types pub trait AtomicElisionExt { diff --git a/src/lib.rs b/src/lib.rs index 5e652897..71da8340 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,6 +13,17 @@ #![warn(rust_2018_idioms)] #![cfg_attr(feature = "nightly", feature(asm))] +mod libstd { + #[cfg(feature = "i-am-libstd")] + pub use crate::*; + #[cfg(not(feature = "i-am-libstd"))] + pub use std::*; +} +#[cfg(feature = "i-am-libstd")] +use crate::{lock_api, parking_lot_core}; +#[cfg(not(feature = "i-am-libstd"))] +use {lock_api, parking_lot_core}; + mod condvar; mod elision; mod mutex; diff --git a/src/mutex.rs b/src/mutex.rs index 49d0b322..8ca01f19 100644 --- a/src/mutex.rs +++ b/src/mutex.rs @@ -5,8 +5,8 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. +use super::lock_api; use super::raw_mutex::RawMutex; -use lock_api; /// A mutual exclusion primitive useful for protecting shared data /// diff --git a/src/once.rs b/src/once.rs index b52d92ff..3b34089f 100644 --- a/src/once.rs +++ b/src/once.rs @@ -5,6 +5,7 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. +use super::parking_lot_core::{self, SpinWait, DEFAULT_PARK_TOKEN, DEFAULT_UNPARK_TOKEN}; use super::util::UncheckedOptionExt; #[cfg(any(has_sized_atomics, feature = "i-am-libstd"))] use core::sync::atomic::AtomicU8; @@ -14,7 +15,6 @@ use core::{ fmt, mem, sync::atomic::{fence, Ordering}, }; -use parking_lot_core::{self, SpinWait, DEFAULT_PARK_TOKEN, DEFAULT_UNPARK_TOKEN}; #[cfg(any(has_sized_atomics, feature = "i-am-libstd"))] type U8 = u8; diff --git a/src/raw_mutex.rs b/src/raw_mutex.rs index d021eb9b..8bf784b1 100644 --- a/src/raw_mutex.rs +++ b/src/raw_mutex.rs @@ -5,15 +5,17 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. +use super::libstd::time::Instant; +use super::lock_api::{GuardNoSend, RawMutex as RawMutexTrait, RawMutexFair, RawMutexTimed}; +use super::parking_lot_core::{ + self, ParkResult, SpinWait, UnparkResult, UnparkToken, DEFAULT_PARK_TOKEN, +}; use super::{deadlock, util}; #[cfg(any(has_sized_atomics, feature = "i-am-libstd"))] use core::sync::atomic::AtomicU8; #[cfg(not(any(has_sized_atomics, feature = "i-am-libstd")))] use core::sync::atomic::AtomicUsize as AtomicU8; use core::{sync::atomic::Ordering, time::Duration}; -use lock_api::{GuardNoSend, RawMutex as RawMutexTrait, RawMutexFair, RawMutexTimed}; -use parking_lot_core::{self, ParkResult, SpinWait, UnparkResult, UnparkToken, DEFAULT_PARK_TOKEN}; -use std::time::Instant; #[cfg(any(has_sized_atomics, feature = "i-am-libstd"))] type U8 = u8; diff --git a/src/raw_rwlock.rs b/src/raw_rwlock.rs index 5ca672c1..ef7a9819 100644 --- a/src/raw_rwlock.rs +++ b/src/raw_rwlock.rs @@ -6,21 +6,21 @@ // copied, modified, or distributed except according to those terms. use super::elision::{have_elision, AtomicElisionExt}; +use super::libstd::time::{Duration, Instant}; +use super::lock_api::{ + GuardNoSend, RawRwLock as RawRwLockTrait, RawRwLockDowngrade, RawRwLockFair, + RawRwLockRecursive, RawRwLockRecursiveTimed, RawRwLockTimed, RawRwLockUpgrade, + RawRwLockUpgradeDowngrade, RawRwLockUpgradeFair, RawRwLockUpgradeTimed, +}; +use super::parking_lot_core::{ + self, FilterOp, ParkResult, ParkToken, SpinWait, UnparkResult, UnparkToken, +}; use super::raw_mutex::{TOKEN_HANDOFF, TOKEN_NORMAL}; use super::{deadlock, util}; use core::{ cell::Cell, sync::atomic::{AtomicUsize, Ordering}, }; -use lock_api::{ - GuardNoSend, RawRwLock as RawRwLockTrait, RawRwLockDowngrade, RawRwLockFair, - RawRwLockRecursive, RawRwLockRecursiveTimed, RawRwLockTimed, RawRwLockUpgrade, - RawRwLockUpgradeDowngrade, RawRwLockUpgradeFair, RawRwLockUpgradeTimed, -}; -use parking_lot_core::{ - self, deadlock, FilterOp, ParkResult, ParkToken, SpinWait, UnparkResult, UnparkToken, -}; -use std::time::{Duration, Instant}; // This reader-writer lock implementation is based on Boost's upgrade_mutex: // https://github.com/boostorg/thread/blob/fc08c1fe2840baeeee143440fba31ef9e9a813c8/include/boost/thread/v2/shared_mutex.hpp#L432 diff --git a/src/remutex.rs b/src/remutex.rs index 9f9ea9f8..7f0ed1b2 100644 --- a/src/remutex.rs +++ b/src/remutex.rs @@ -5,8 +5,9 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. +use super::lock_api::{self, GetThreadId}; use super::raw_mutex::RawMutex; -use lock_api::{self, GetThreadId}; +use core::mem; /// Implementation of the `GetThreadId` trait for `lock_api::ReentrantMutex`. pub struct RawThreadId; @@ -17,7 +18,7 @@ unsafe impl GetThreadId for RawThreadId { fn nonzero_thread_id(&self) -> usize { // The address of a thread-local variable is guaranteed to be unique to the // current thread, and is also guaranteed to be non-zero. - thread_local!(static KEY: u8 = unsafe { ::std::mem::uninitialized() }); + thread_local!(static KEY: u8 = unsafe { mem::uninitialized() }); KEY.with(|x| x as *const _ as usize) } } diff --git a/src/rwlock.rs b/src/rwlock.rs index 17f8bede..33a7d897 100644 --- a/src/rwlock.rs +++ b/src/rwlock.rs @@ -5,8 +5,8 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. +use super::lock_api; use super::raw_rwlock::RawRwLock; -use lock_api; /// A reader-writer lock /// diff --git a/src/util.rs b/src/util.rs index 65f3c2d2..6a55f19e 100644 --- a/src/util.rs +++ b/src/util.rs @@ -5,7 +5,7 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. -use std::time::{Duration, Instant}; +use super::libstd::time::{Duration, Instant}; // Option::unchecked_unwrap pub trait UncheckedOptionExt { From f968e745c19ae444fafeaf3db56e1204c9d597f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20F=C3=A4rnstrand?= Date: Wed, 20 Mar 2019 01:05:48 +0100 Subject: [PATCH 09/14] Only activate feature gates when not in libstd --- core/src/lib.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/core/src/lib.rs b/core/src/lib.rs index f7cca0de..ae0bb6b8 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -40,11 +40,16 @@ #![warn(missing_docs)] #![warn(rust_2018_idioms)] #![cfg_attr( - all(target_env = "sgx", target_vendor = "fortanix"), + all( + not(feature = "i-am-libstd"), + target_env = "sgx", + target_vendor = "fortanix" + ), feature(sgx_platform) )] #![cfg_attr( all( + not(feature = "i-am-libstd"), feature = "nightly", target_arch = "wasm32", target_feature = "atomics" From 6015c144dbdfdf7adda030fde5faaa80666c1744 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20F=C3=A4rnstrand?= Date: Wed, 27 Mar 2019 13:19:49 +0100 Subject: [PATCH 10/14] Disable generic spin lock based thread parker in libstd --- core/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/src/lib.rs b/core/src/lib.rs index ae0bb6b8..1e9f5b85 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -97,6 +97,8 @@ cfg_if! { } else if #[cfg(all(any(feature = "nightly", feature = "i-am-libstd"), target_os = "cloudabi"))] { #[path = "thread_parker/cloudabi.rs"] mod thread_parker; + } else if #[cfg(all(feature = "i-am-libstd", not(target_arch = "wasm32")))] { + compile_error!("Not allowed to fall back to generic spin lock based thread parker"); } else { #[path = "thread_parker/generic.rs"] mod thread_parker; From cd5fa712eedf426cc4a24ea5806f36f11647400a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20F=C3=A4rnstrand?= Date: Mon, 1 Apr 2019 00:38:50 +0200 Subject: [PATCH 11/14] Fix cloudabi abi import in libstd --- core/src/thread_parker/cloudabi.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/src/thread_parker/cloudabi.rs b/core/src/thread_parker/cloudabi.rs index a3322377..53a4d8c0 100644 --- a/core/src/thread_parker/cloudabi.rs +++ b/core/src/thread_parker/cloudabi.rs @@ -5,7 +5,10 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. +#[cfg(not(feature = "i-am-libstd"))] use cloudabi as abi; +#[cfg(feature = "i-am-libstd")] +use crate::sys::abi; use core::{ cell::Cell, mem, From 00112a13e4e5b56e4fd95fe798d51402b7af9de4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20F=C3=A4rnstrand?= Date: Tue, 2 Apr 2019 10:23:45 +0200 Subject: [PATCH 12/14] Abort process on syscall error in SGX --- core/src/thread_parker/sgx.rs | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/core/src/thread_parker/sgx.rs b/core/src/thread_parker/sgx.rs index ed511ce2..3c0e0b81 100644 --- a/core/src/thread_parker/sgx.rs +++ b/core/src/thread_parker/sgx.rs @@ -19,6 +19,15 @@ use super::libstd::{ }; use core::sync::atomic::{AtomicBool, Ordering}; +macro_rules! abort { + ($($t:tt)*) => {{ + #[cfg(not(feature = "i-am-libstd"))] + std::process::abort(); + #[cfg(feature = "i-am-libstd")] + rtabort!($($t)*); + }} +} + // Helper type for putting a thread to sleep until some other thread wakes it up pub struct ThreadParker { parked: AtomicBool, @@ -55,7 +64,10 @@ impl ThreadParker { pub fn park(&self) { while self.parked.load(Ordering::Acquire) { let result = usercalls::wait(EV_UNPARK, WAIT_INDEFINITE); - debug_assert_eq!(result.expect("wait returned error") & EV_UNPARK, EV_UNPARK); + match result.map(|eventset| eventset & EV_UNPARK) { + Ok(EV_UNPARK) => {} + _ => abort!("usercall wait returned an invalid value"), + } } } @@ -65,7 +77,7 @@ impl ThreadParker { #[inline] pub fn park_until(&self, _timeout: Instant) -> bool { // FIXME: https://github.com/fortanix/rust-sgx/issues/31 - panic!("timeout not supported in SGX"); + abort!("timeout not supported in SGX"); } // Locks the parker to prevent the target thread from exiting. This is @@ -90,13 +102,11 @@ impl UnparkHandle { #[inline] pub fn unpark(self) { let result = usercalls::send(EV_UNPARK, Some(self.0)); - if cfg!(debug_assertions) { - if let Err(error) = result { - // `InvalidInput` may be returned if the thread we send to has - // already been unparked and exited. - if error.kind() != io::ErrorKind::InvalidInput { - panic!("send returned an unexpected error: {:?}", error); - } + if let Err(error) = result { + // `InvalidInput` may be returned if the thread we send to has + // already been unparked and exited. + if error.kind() != io::ErrorKind::InvalidInput { + abort!("send returned an unexpected error: {:?}", error); } } } From b8fa13aec5f20f342d3b09eecba29bb6f6dbe7c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20F=C3=A4rnstrand?= Date: Fri, 5 Apr 2019 23:25:09 +0200 Subject: [PATCH 13/14] Make sure NUM_THREADS+HASHTABLE only have one instance --- core/src/parking_lot.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/core/src/parking_lot.rs b/core/src/parking_lot.rs index 10b43f6d..87906c1e 100644 --- a/core/src/parking_lot.rs +++ b/core/src/parking_lot.rs @@ -19,7 +19,26 @@ use rand::{rngs::SmallRng, FromEntropy, Rng}; #[cfg(not(feature = "i-am-libstd"))] use smallvec::SmallVec; +// When compiling the tests of std, there are basically two copies of std: +// one normal one, and one with cfg(test). This means that during testing of +// std there will be two instances of NUM_THREADS and HASHTABLE unless we make +// sure both versions of std link to the same instance. It's usually not a +// problem that different locks are based on different HASHTABLEs. Except if +// the two locks both think they guard a global resource. Such as the mutexes +// around the stdio file descriptors. +// Here we use #[linkage] and #[export_name] to make both versions point to +// the same instance. +#[cfg_attr(all(test, feature = "i-am-libstd"), linkage = "available_externally")] +#[cfg_attr( + feature = "i-am-libstd", + export_name = "_ZN3std16parking_lot_core11parking_lot11NUM_THREADSE" +)] static NUM_THREADS: AtomicUsize = AtomicUsize::new(0); +#[cfg_attr(all(test, feature = "i-am-libstd"), linkage = "available_externally")] +#[cfg_attr( + feature = "i-am-libstd", + export_name = "_ZN3std16parking_lot_core11parking_lot9HASHTABLEE" +)] static HASHTABLE: AtomicPtr = AtomicPtr::new(ptr::null_mut()); // Even with 3x more buckets than threads, the memory overhead per thread is From b0280b3b025a6841922aa4339dccfd30b9076c02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20F=C3=A4rnstrand?= Date: Thu, 18 Apr 2019 18:33:25 +0200 Subject: [PATCH 14/14] Enable elision in libstd --- src/elision.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/elision.rs b/src/elision.rs index e8816c4e..02fac525 100644 --- a/src/elision.rs +++ b/src/elision.rs @@ -26,14 +26,17 @@ pub trait AtomicElisionExt { #[inline] pub fn have_elision() -> bool { cfg!(all( - feature = "nightly", + any(feature = "nightly", feature = "i-am-libstd"), any(target_arch = "x86", target_arch = "x86_64"), )) } // This implementation is never actually called because it is guarded by // have_elision(). -#[cfg(not(all(feature = "nightly", any(target_arch = "x86", target_arch = "x86_64"))))] +#[cfg(not(all( + any(feature = "nightly", feature = "i-am-libstd"), + any(target_arch = "x86", target_arch = "x86_64"), +)))] impl AtomicElisionExt for AtomicUsize { type IntType = usize; @@ -48,7 +51,10 @@ impl AtomicElisionExt for AtomicUsize { } } -#[cfg(all(feature = "nightly", any(target_arch = "x86", target_arch = "x86_64")))] +#[cfg(all( + any(feature = "nightly", feature = "i-am-libstd"), + any(target_arch = "x86", target_arch = "x86_64"), +))] impl AtomicElisionExt for AtomicUsize { type IntType = usize;