mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs.git
synced 2026-10-30 22:03:17 +01: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 <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Reviewed-by: Alice Ryhl <[email protected]> Reviewed-by: Elle Rhumsaa <[email protected]> Link: https://lore.kernel.org/all/[email protected]/
62 lines
1.6 KiB
Rust
62 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();
|
|
}
|
|
}
|