Skip to content

Commit

Permalink
refact: use relaxed ordering for park loop
Browse files Browse the repository at this point in the history
  • Loading branch information
pedromfedricci committed Nov 7, 2024
1 parent 64e6d78 commit 1a61232
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 24 deletions.
4 changes: 2 additions & 2 deletions src/inner/barging/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,12 @@ impl<T: ?Sized, L: Lock, Ws, Wq> Mutex<T, L, Ws, Wq> {
///
/// This function does not guarantee strong ordering, only atomicity.
pub fn is_locked(&self) -> bool {
self.lock.is_locked()
self.lock.is_locked_relaxed()
}

/// Unlocks this mutex.
pub fn unlock(&self) {
self.lock.notify();
self.lock.notify_release();
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/inner/raw/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ impl<T: ?Sized, L: Lock, W: Wait> Mutex<T, L, W> {
fence(Acquire);
// Notify our successor that they hold the lock.
// SAFETY: We already verified that our successor is not null.
unsafe { &*next }.lock.notify();
unsafe { &*next }.lock.notify_release();
}
}

Expand Down
8 changes: 4 additions & 4 deletions src/lock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,11 @@ pub trait Lock {
/// Returns `true` if the lock is currently held.
///
/// This function does not guarantee strong ordering, only atomicity.
fn is_locked(&self) -> bool;
fn is_locked_relaxed(&self) -> bool;

/// Changes the state of the lock and, possibly, notifies that change
/// to some other interested party.
fn notify(&self);
fn notify_release(&self);
}

/// The waiting policy that should be applied while the lock state has not
Expand Down Expand Up @@ -123,11 +123,11 @@ impl Lock for AtomicBool {
}
}

fn is_locked(&self) -> bool {
fn is_locked_relaxed(&self) -> bool {
self.load(Relaxed)
}

fn notify(&self) {
fn notify_release(&self) {
self.store(false, Release);
}
}
34 changes: 17 additions & 17 deletions src/parking/parker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ pub trait ParkerT {
/// Returns `true` if the lock is currently held.
///
/// This function does not guarantee strong ordering, only atomicity.
fn is_locked(&self) -> bool;
fn is_locked_relaxed(&self) -> bool;

/// Tries to lock this mutex with acquire load.
///
Expand All @@ -66,13 +66,13 @@ pub trait ParkerT {
/// to safeguard agains spurious wake-ups if they are possible. That is,
/// this function should only unblock once a corresponding unpark call has
/// been issued to this parked thread.
fn park_loop(&self);
fn park_loop_relaxed(&self);

/// Atomically makes the handle’s token available if it is not already.
///
/// Implementors of this function are expected to call the platform's
/// specific API for thread unparking.
fn unpark(&self);
fn unpark_release(&self);
}

impl Lock for Parker {
Expand Down Expand Up @@ -110,7 +110,7 @@ impl Lock for Parker {
// Block the thread with a relaxed loop untin either all attempts have
// already been made or the lock has been handed over to this thread.
while !parker.should_park() {
if ParkerT::is_locked(self) {
if ParkerT::is_locked_relaxed(self) {
// Whenever the thread is not ready to be put to sleep yet and
// it also fails to acquire the lock, then update parker's
// state and apply its associated relax operation.
Expand All @@ -124,15 +124,15 @@ impl Lock for Parker {
}
// The limit of attempts have been reached and the lock remains locked,
// then park the thread. The parking loop will handle spurious wakeups.
ParkerT::park_loop(self);
ParkerT::park_loop_relaxed(self);
}

fn is_locked(&self) -> bool {
ParkerT::is_locked(self)
fn is_locked_relaxed(&self) -> bool {
ParkerT::is_locked_relaxed(self)
}

fn notify(&self) {
ParkerT::unpark(self);
fn notify_release(&self) {
ParkerT::unpark_release(self);
}
}

Expand Down Expand Up @@ -173,17 +173,17 @@ mod common {
self.state.compare_exchange_weak(UNLOCKED, LOCKED, Acquire, Relaxed).is_ok()
}

fn is_locked(&self) -> bool {
fn is_locked_relaxed(&self) -> bool {
self.state.load(Relaxed) == LOCKED
}

fn park_loop(&self) {
while self.state.load(Acquire) == LOCKED {
fn park_loop_relaxed(&self) {
while self.state.load(Relaxed) == LOCKED {
atomic_wait::wait(&self.state, LOCKED);
}
}

fn unpark(&self) {
fn unpark_release(&self) {
let state = &self.state;
// TODO: 1.82.0 supports native syntax:
// let ptr = &raw const self.state;
Expand Down Expand Up @@ -231,17 +231,17 @@ mod loom {
self.locked.compare_exchange_weak(UNLOCKED, LOCKED, Acquire, Relaxed).is_ok()
}

fn is_locked(&self) -> bool {
fn is_locked_relaxed(&self) -> bool {
self.locked.load(Relaxed) == LOCKED
}

fn park_loop(&self) {
while self.locked.load(Acquire) == LOCKED {
fn park_loop_relaxed(&self) {
while self.locked.load(Relaxed) == LOCKED {
thread::yield_now();
}
}

fn unpark(&self) {
fn unpark_release(&self) {
self.locked.store(UNLOCKED, Release);
thread::yield_now();
}
Expand Down

0 comments on commit 1a61232

Please sign in to comment.