Fix fence on non-x86 arch and miri (#16)

This commit is contained in:
Taiki Endo 2022-07-17 22:33:35 +09:00 committed by GitHub
parent 83ec31aac4
commit 54df36a543
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 12 additions and 8 deletions

View File

@ -129,8 +129,7 @@ impl<T> Bounded<T> {
}
}
} else if stamp.wrapping_add(self.one_lap) == tail + 1 {
crate::full_fence();
let head = self.head.load(Ordering::Relaxed);
let head = crate::full_fence_for_load(|| self.head.load(Ordering::Relaxed));
// If the head lags one lap behind the tail as well...
if head.wrapping_add(self.one_lap) == tail {
@ -191,8 +190,7 @@ impl<T> Bounded<T> {
}
}
} else if stamp == head {
crate::full_fence();
let tail = self.tail.load(Ordering::Relaxed);
let tail = crate::full_fence_for_load(|| self.tail.load(Ordering::Relaxed));
// If the tail equals the head, that means the queue is empty.
if (tail & !self.mark_bit) == head {

View File

@ -445,8 +445,11 @@ impl<T> fmt::Display for PushError<T> {
/// Equivalent to `atomic::fence(Ordering::SeqCst)`, but in some cases faster.
#[inline]
fn full_fence() {
if cfg!(any(target_arch = "x86", target_arch = "x86_64")) {
fn full_fence_for_load<T>(load_op: impl FnOnce() -> T) -> T {
if cfg!(all(
any(target_arch = "x86", target_arch = "x86_64"),
not(miri)
)) {
// HACK(stjepang): On x86 architectures there are two different ways of executing
// a `SeqCst` fence.
//
@ -461,7 +464,11 @@ fn full_fence() {
// x86 platforms is going to optimize this away.
let a = AtomicUsize::new(0);
let _ = a.compare_exchange(0, 1, Ordering::SeqCst, Ordering::SeqCst);
// On x86, `lock cmpxchg; mov` is fine. See also https://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html.
load_op()
} else {
let res = load_op();
atomic::fence(Ordering::SeqCst);
res
}
}

View File

@ -237,8 +237,7 @@ impl<T> Unbounded<T> {
let mut new_head = head + (1 << SHIFT);
if new_head & MARK_BIT == 0 {
crate::full_fence();
let tail = self.tail.index.load(Ordering::Relaxed);
let tail = crate::full_fence_for_load(|| self.tail.index.load(Ordering::Relaxed));
// If the tail equals the head, that means the queue is empty.
if head >> SHIFT == tail >> SHIFT {