mirror of
https://github.com/torvalds/linux.git
synced 2026-01-12 00:42:35 +08:00
rust: sync: Add memory barriers
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/
This commit is contained in:
committed by
Peter Zijlstra
parent
84c6d36bca
commit
d9ea5a41ce
18
rust/helpers/barrier.c
Normal file
18
rust/helpers/barrier.c
Normal file
@@ -0,0 +1,18 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <asm/barrier.h>
|
||||
|
||||
void rust_helper_smp_mb(void)
|
||||
{
|
||||
smp_mb();
|
||||
}
|
||||
|
||||
void rust_helper_smp_wmb(void)
|
||||
{
|
||||
smp_wmb();
|
||||
}
|
||||
|
||||
void rust_helper_smp_rmb(void)
|
||||
{
|
||||
smp_rmb();
|
||||
}
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "atomic.c"
|
||||
#include "auxiliary.c"
|
||||
#include "barrier.c"
|
||||
#include "blk.c"
|
||||
#include "bug.c"
|
||||
#include "build_assert.c"
|
||||
|
||||
@@ -12,6 +12,7 @@ use pin_init;
|
||||
mod arc;
|
||||
pub mod aref;
|
||||
pub mod atomic;
|
||||
pub mod barrier;
|
||||
pub mod completion;
|
||||
mod condvar;
|
||||
pub mod lock;
|
||||
|
||||
61
rust/kernel/sync/barrier.rs
Normal file
61
rust/kernel/sync/barrier.rs
Normal file
@@ -0,0 +1,61 @@
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user