Skip to content

Commit

Permalink
Fix fence on non-x86 arch and miri (#16)
Browse files Browse the repository at this point in the history
  • Loading branch information
taiki-e committed Jul 17, 2022
1 parent 83ec31a commit 54df36a
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 8 deletions.
6 changes: 2 additions & 4 deletions src/bounded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down
11 changes: 9 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
//
Expand All @@ -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
}
}
3 changes: 1 addition & 2 deletions src/unbounded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down

0 comments on commit 54df36a

Please sign in to comment.