diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index bace0eb7..81b35765 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -25,6 +25,9 @@ jobs: - channel: nightly feature: nightly os: ubuntu + - channel: nightly + feature: hardware-lock-elision + os: ubuntu steps: - uses: actions/checkout@v2 diff --git a/Cargo.toml b/Cargo.toml index 9c72cc6d..b672feb1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,6 +28,7 @@ nightly = ["parking_lot_core/nightly", "lock_api/nightly"] deadlock_detection = ["parking_lot_core/deadlock_detection"] serde = ["lock_api/serde"] send_guard = [] +hardware-lock-elision = [] [workspace] exclude = ["benchmark"] diff --git a/README.md b/README.md index fa37d14e..fe87ef6e 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,7 @@ in the Rust standard library: library versions of those types. 7. `RwLock` takes advantage of hardware lock elision on processors that support it, which can lead to huge performance wins with many readers. + This must be enabled with the `hardware-lock-elision` feature. 8. `RwLock` uses a task-fair locking policy, which avoids reader and writer starvation, whereas the standard library version makes no guarantees. 9. `Condvar` is guaranteed not to produce spurious wakeups. A thread will @@ -93,8 +94,6 @@ There are a few restrictions when using this library on stable Rust: - You will have to use the `const_*` functions (e.g. `const_mutex(val)`) to statically initialize the locking primitives. Using e.g. `Mutex::new(val)` does not work on stable Rust yet. -- `RwLock` will not be able to take advantage of hardware lock elision for - readers, which improves performance when there are multiple readers. - The `wasm32-unknown-unknown` target is only supported on nightly and requires `-C target-feature=+atomics` in `RUSTFLAGS`. @@ -126,6 +125,10 @@ To allow sending `MutexGuard`s and `RwLock*Guard`s to other threads, enable the Note that the `deadlock_detection` and `send_guard` features are incompatible and cannot be used together. +Hardware lock elision support for x86 can be enabled with the +`hardware-lock-elision` feature. This requires Rust 1.59 due to the use of +inline assembly. + The core parking lot API is provided by the `parking_lot_core` crate. It is separate from the synchronization primitives in the `parking_lot` crate so that changes to the core API do not cause breaking changes for users of `parking_lot`. diff --git a/src/elision.rs b/src/elision.rs index dae39cb5..74d1da6d 100644 --- a/src/elision.rs +++ b/src/elision.rs @@ -26,14 +26,14 @@ pub trait AtomicElisionExt { #[inline] pub fn have_elision() -> bool { cfg!(all( - feature = "nightly", + feature = "hardware-lock-elision", 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(feature = "hardware-lock-elision", any(target_arch = "x86", target_arch = "x86_64"))))] impl AtomicElisionExt for AtomicUsize { type IntType = usize; @@ -48,7 +48,7 @@ impl AtomicElisionExt for AtomicUsize { } } -#[cfg(all(feature = "nightly", any(target_arch = "x86", target_arch = "x86_64")))] +#[cfg(all(feature = "hardware-lock-elision", any(target_arch = "x86", target_arch = "x86_64")))] impl AtomicElisionExt for AtomicUsize { type IntType = usize; diff --git a/src/lib.rs b/src/lib.rs index 27b41a87..03639a68 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,7 +11,6 @@ #![warn(missing_docs)] #![warn(rust_2018_idioms)] -#![cfg_attr(feature = "nightly", feature(asm))] mod condvar; mod elision;