Skip to content

Commit

Permalink
Merge pull request #313 from Amanieu/hle_feature
Browse files Browse the repository at this point in the history
  • Loading branch information
Amanieu authored Jan 28, 2022
2 parents 8019473 + b271f84 commit b3c9290
Show file tree
Hide file tree
Showing 4 changed files with 14 additions and 5 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ jobs:
- channel: nightly
feature: nightly
os: ubuntu
- channel: nightly
feature: hardware-lock-elision
os: ubuntu

steps:
- uses: actions/checkout@v2
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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`.

Expand Down Expand Up @@ -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`.
Expand Down
8 changes: 5 additions & 3 deletions src/elision.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,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;

Expand All @@ -50,13 +50,14 @@ 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;

#[inline]
fn elision_compare_exchange_acquire(&self, current: usize, new: usize) -> Result<usize, usize> {
unsafe {
use core::arch::asm;
let prev: usize;
#[cfg(target_pointer_width = "32")]
asm!(
Expand Down Expand Up @@ -87,6 +88,7 @@ impl AtomicElisionExt for AtomicUsize {
#[inline]
fn elision_fetch_sub_release(&self, val: usize) -> usize {
unsafe {
use core::arch::asm;
let prev: usize;
#[cfg(target_pointer_width = "32")]
asm!(
Expand Down

0 comments on commit b3c9290

Please sign in to comment.