mirror of
https://github.com/torvalds/linux.git
synced 2025-11-01 09:09:47 +02:00
Memory barriers are building blocks for concurrent code, hence provide a minimal set of them. The compiler barrier, barrier(), is implemented in inline asm instead of using core::sync::atomic::compiler_fence() because memory models are different: kernel's atomics are implemented in inline asm therefore the compiler barrier should be implemented in inline asm as well. Also it's currently only public to the kernel crate until there's a reasonable driver usage. Signed-off-by: Boqun Feng <boqun.feng@gmail.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Reviewed-by: Alice Ryhl <aliceryhl@google.com> Reviewed-by: Elle Rhumsaa <elle@weathered-steel.dev> Link: https://lore.kernel.org/all/20250719030827.61357-10-boqun.feng@gmail.com/
61 lines
1.6 KiB
Rust
61 lines
1.6 KiB
Rust
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
//! Memory barriers.
|
|
//!
|
|
//! These primitives have the same semantics as their C counterparts: and the precise definitions
|
|
//! of semantics can be found at [`LKMM`].
|
|
//!
|
|
//! [`LKMM`]: srctree/tools/memory-model/
|
|
|
|
/// A compiler barrier.
|
|
///
|
|
/// A barrier that prevents compiler from reordering memory accesses across the barrier.
|
|
#[inline(always)]
|
|
pub(crate) fn barrier() {
|
|
// By default, Rust inline asms are treated as being able to access any memory or flags, hence
|
|
// it suffices as a compiler barrier.
|
|
//
|
|
// SAFETY: An empty asm block.
|
|
unsafe { core::arch::asm!("") };
|
|
}
|
|
|
|
/// A full memory barrier.
|
|
///
|
|
/// A barrier that prevents compiler and CPU from reordering memory accesses across the barrier.
|
|
#[inline(always)]
|
|
pub fn smp_mb() {
|
|
if cfg!(CONFIG_SMP) {
|
|
// SAFETY: `smp_mb()` is safe to call.
|
|
unsafe { bindings::smp_mb() };
|
|
} else {
|
|
barrier();
|
|
}
|
|
}
|
|
|
|
/// A write-write memory barrier.
|
|
///
|
|
/// A barrier that prevents compiler and CPU from reordering memory write accesses across the
|
|
/// barrier.
|
|
#[inline(always)]
|
|
pub fn smp_wmb() {
|
|
if cfg!(CONFIG_SMP) {
|
|
// SAFETY: `smp_wmb()` is safe to call.
|
|
unsafe { bindings::smp_wmb() };
|
|
} else {
|
|
barrier();
|
|
}
|
|
}
|
|
|
|
/// A read-read memory barrier.
|
|
///
|
|
/// A barrier that prevents compiler and CPU from reordering memory read accesses across the
|
|
/// barrier.
|
|
#[inline(always)]
|
|
pub fn smp_rmb() {
|
|
if cfg!(CONFIG_SMP) {
|
|
// SAFETY: `smp_rmb()` is safe to call.
|
|
unsafe { bindings::smp_rmb() };
|
|
} else {
|
|
barrier();
|
|
}
|
|
}
|