Skip to content

Commit 54df36a

Browse files
authored
Fix fence on non-x86 arch and miri (#16)
1 parent 83ec31a commit 54df36a

File tree

3 files changed

+12
-8
lines changed

3 files changed

+12
-8
lines changed

src/bounded.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,7 @@ impl<T> Bounded<T> {
129129
}
130130
}
131131
} else if stamp.wrapping_add(self.one_lap) == tail + 1 {
132-
crate::full_fence();
133-
let head = self.head.load(Ordering::Relaxed);
132+
let head = crate::full_fence_for_load(|| self.head.load(Ordering::Relaxed));
134133

135134
// If the head lags one lap behind the tail as well...
136135
if head.wrapping_add(self.one_lap) == tail {
@@ -191,8 +190,7 @@ impl<T> Bounded<T> {
191190
}
192191
}
193192
} else if stamp == head {
194-
crate::full_fence();
195-
let tail = self.tail.load(Ordering::Relaxed);
193+
let tail = crate::full_fence_for_load(|| self.tail.load(Ordering::Relaxed));
196194

197195
// If the tail equals the head, that means the queue is empty.
198196
if (tail & !self.mark_bit) == head {

src/lib.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -445,8 +445,11 @@ impl<T> fmt::Display for PushError<T> {
445445

446446
/// Equivalent to `atomic::fence(Ordering::SeqCst)`, but in some cases faster.
447447
#[inline]
448-
fn full_fence() {
449-
if cfg!(any(target_arch = "x86", target_arch = "x86_64")) {
448+
fn full_fence_for_load<T>(load_op: impl FnOnce() -> T) -> T {
449+
if cfg!(all(
450+
any(target_arch = "x86", target_arch = "x86_64"),
451+
not(miri)
452+
)) {
450453
// HACK(stjepang): On x86 architectures there are two different ways of executing
451454
// a `SeqCst` fence.
452455
//
@@ -461,7 +464,11 @@ fn full_fence() {
461464
// x86 platforms is going to optimize this away.
462465
let a = AtomicUsize::new(0);
463466
let _ = a.compare_exchange(0, 1, Ordering::SeqCst, Ordering::SeqCst);
467+
// On x86, `lock cmpxchg; mov` is fine. See also https://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html.
468+
load_op()
464469
} else {
470+
let res = load_op();
465471
atomic::fence(Ordering::SeqCst);
472+
res
466473
}
467474
}

src/unbounded.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,8 +237,7 @@ impl<T> Unbounded<T> {
237237
let mut new_head = head + (1 << SHIFT);
238238

239239
if new_head & MARK_BIT == 0 {
240-
crate::full_fence();
241-
let tail = self.tail.index.load(Ordering::Relaxed);
240+
let tail = crate::full_fence_for_load(|| self.tail.index.load(Ordering::Relaxed));
242241

243242
// If the tail equals the head, that means the queue is empty.
244243
if head >> SHIFT == tail >> SHIFT {

0 commit comments

Comments
 (0)