Skip to content

Conversation

@purplesyringa
Copy link
Contributor

Closes #510.

Another oddity I noticed:

Here's lock_shared_slow:

// Use hardware lock elision to avoid cache conflicts when multiple
// readers try to acquire the lock. We only do this if the lock is
// completely empty since elision handles conflicts poorly.
if have_elision() && *state == 0 {
match self.state.elision_compare_exchange_acquire(0, ONE_READER) {
Ok(_) => return true,
Err(x) => *state = x,
}
}
// This is the same condition as try_lock_shared_fast
#[allow(clippy::collapsible_if)]
if *state & WRITER_BIT != 0 {
if !recursive || *state & READERS_MASK == 0 {
return false;
}
}
if self
.state
.compare_exchange_weak(
*state,
state
.checked_add(ONE_READER)
.expect("RwLock reader count overflow"),
Ordering::Acquire,
Ordering::Relaxed,
)
.is_ok()
{
return true;
}

Note the order of operations: xacquire cmpxchg; check if a writer is alive; lock cmpxchg.

Here's try_lock_shared_slow:

https://github.com/Amanieu/parking_lot/blob/a33cac3ae23646175ae0b84dde4d5a10fb26fc81/src/raw_rwlock.rs#L542-L566\

Note the order of operations: check if a writer is alive; xacquire cmpxchg; lock cmpxchg.

Is there any reason why the orders are different? The latter seems more obvious to me, but I don't know if there's a subtle performance pitfall somewhere.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

try_lock_shared does not spin/wait under contention

1 participant