Skip to content

Commit 9946f02

Browse files
committed
Use inline assembly in full_fence
1 parent 8c55219 commit 9946f02

File tree

5 files changed

+22
-28
lines changed

5 files changed

+22
-28
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ jobs:
6666
matrix:
6767
# When updating this, the reminder to update the minimum supported
6868
# Rust version in Cargo.toml.
69-
rust: ['1.39']
69+
rust: ['1.59']
7070
steps:
7171
- uses: actions/checkout@v3
7272
- name: Install Rust

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ name = "event-listener"
66
version = "2.5.3"
77
authors = ["Stjepan Glavina <[email protected]>"]
88
edition = "2018"
9-
rust-version = "1.39"
9+
rust-version = "1.59"
1010
description = "Notify async tasks or threads"
1111
license = "Apache-2.0 OR MIT"
1212
repository = "https://github.com/smol-rs/event-listener"

src/lib.rs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -110,16 +110,6 @@ pub mod prelude {
110110
pub use crate::{IntoNotification, Notification};
111111
}
112112

113-
/// 1.39-compatible replacement for `matches!`
114-
macro_rules! matches {
115-
($expr:expr, $($pattern:pat)|+ $(if $guard: expr)?) => {
116-
match $expr {
117-
$($pattern)|+ $(if $guard)? => true,
118-
_ => false,
119-
}
120-
};
121-
}
122-
123113
/// Inner state of [`Event`].
124114
struct Inner<T> {
125115
/// The number of notified entries, or `usize::MAX` if all of them have been notified.

src/notify.rs

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! The `Notification` trait for specifying notification.
22
3-
use crate::sync::atomic::{self, AtomicUsize, Ordering};
3+
use crate::sync::atomic::{self, Ordering};
44
use core::fmt;
55

66
pub(crate) use __private::Internal;
@@ -555,27 +555,31 @@ impl_for_numeric_types! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
555555
/// Equivalent to `atomic::fence(Ordering::SeqCst)`, but in some cases faster.
556556
#[inline]
557557
pub(super) fn full_fence() {
558-
if cfg!(all(
559-
any(target_arch = "x86", target_arch = "x86_64"),
560-
not(miri)
561-
)) {
558+
#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), not(miri), not(loom)))]
559+
{
560+
use core::{arch::asm, cell::UnsafeCell};
562561
// HACK(stjepang): On x86 architectures there are two different ways of executing
563562
// a `SeqCst` fence.
564563
//
565564
// 1. `atomic::fence(SeqCst)`, which compiles into a `mfence` instruction.
566-
// 2. `_.compare_exchange(_, _, SeqCst, SeqCst)`, which compiles into a `lock cmpxchg` instruction.
565+
// 2. A `lock <op>` instruction.
567566
//
568567
// Both instructions have the effect of a full barrier, but empirical benchmarks have shown
569568
// that the second one is sometimes a bit faster.
570-
//
571-
// The ideal solution here would be to use inline assembly, but we're instead creating a
572-
// temporary atomic variable and compare-and-exchanging its value. No sane compiler to
573-
// x86 platforms is going to optimize this away.
574-
atomic::compiler_fence(Ordering::SeqCst);
575-
let a = AtomicUsize::new(0);
576-
let _ = a.compare_exchange(0, 1, Ordering::SeqCst, Ordering::SeqCst);
577-
atomic::compiler_fence(Ordering::SeqCst);
578-
} else {
569+
let a = UnsafeCell::new(0_usize);
570+
// It is common to use `lock or` here, but when using a local variable, `lock not`, which
571+
// does not change the flag, should be slightly more efficient.
572+
// Refs: https://www.felixcloutier.com/x86/not
573+
unsafe {
574+
#[cfg(target_pointer_width = "64")]
575+
asm!("lock not qword ptr [{0}]", in(reg) a.get(), options(nostack, preserves_flags));
576+
#[cfg(target_pointer_width = "32")]
577+
asm!("lock not dword ptr [{0:e}]", in(reg) a.get(), options(nostack, preserves_flags));
578+
}
579+
return;
580+
}
581+
#[allow(unreachable_code)]
582+
{
579583
atomic::fence(Ordering::SeqCst);
580584
}
581585
}

strategy/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name = "event-listener-strategy"
33
version = "0.1.0"
44
edition = "2018"
55
authors = ["John Nunley <[email protected]>"]
6-
rust-version = "1.39"
6+
rust-version = "1.59"
77
description = "Block or poll on event_listener easily"
88
license = "Apache-2.0 OR MIT"
99
repository = "https://github.com/smol-rs/event-listener"

0 commit comments

Comments
 (0)