summaryrefslogtreecommitdiff
path: root/rust/kernel
diff options
context:
space:
mode:
authorBoqun Feng <boqun.feng@gmail.com>2025-09-04 21:41:36 -0700
committerPeter Zijlstra <peterz@infradead.org>2025-09-15 09:38:34 +0200
commitd9ea5a41cef80dc8103f4114b072b27364f2e06a (patch)
treec00263765c7e37f63fd2a2015ac843fbac3ad5c3 /rust/kernel
parent84c6d36bcaf98a8c0533cd334a624d536d20879b (diff)
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/
Diffstat (limited to 'rust/kernel')
-rw-r--r--rust/kernel/sync.rs1
-rw-r--r--rust/kernel/sync/barrier.rs61
2 files changed, 62 insertions, 0 deletions
diff --git a/rust/kernel/sync.rs b/rust/kernel/sync.rs
index 7e962e5429d2..bf8943c88a89 100644
--- a/rust/kernel/sync.rs
+++ b/rust/kernel/sync.rs
@@ -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;
diff --git a/rust/kernel/sync/barrier.rs b/rust/kernel/sync/barrier.rs
new file mode 100644
index 000000000000..8f2d435fcd94
--- /dev/null
+++ b/rust/kernel/sync/barrier.rs
@@ -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();
+ }
+}