Skip to content

Commit 45ae3c4

Browse files
fbqjannau
authored andcommitted
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/
1 parent 5138ea2 commit 45ae3c4

4 files changed

Lines changed: 81 additions & 0 deletions

File tree

rust/helpers/barrier.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#include <asm/barrier.h>
4+
5+
void rust_helper_smp_mb(void)
6+
{
7+
smp_mb();
8+
}
9+
10+
void rust_helper_smp_wmb(void)
11+
{
12+
smp_wmb();
13+
}
14+
15+
void rust_helper_smp_rmb(void)
16+
{
17+
smp_rmb();
18+
}

rust/helpers/helpers.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include "atomic.c"
1111
#include "auxiliary.c"
12+
#include "barrier.c"
1213
#include "blk.c"
1314
#include "bug.c"
1415
#include "build_assert.c"

rust/kernel/sync.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use pin_init;
1212
mod arc;
1313
pub mod aref;
1414
pub mod atomic;
15+
pub mod barrier;
1516
pub mod completion;
1617
mod condvar;
1718
pub mod lock;

rust/kernel/sync/barrier.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
//! Memory barriers.
4+
//!
5+
//! These primitives have the same semantics as their C counterparts: and the precise definitions
6+
//! of semantics can be found at [`LKMM`].
7+
//!
8+
//! [`LKMM`]: srctree/tools/memory-model/
9+
10+
/// A compiler barrier.
11+
///
12+
/// A barrier that prevents compiler from reordering memory accesses across the barrier.
13+
#[inline(always)]
14+
pub(crate) fn barrier() {
15+
// By default, Rust inline asms are treated as being able to access any memory or flags, hence
16+
// it suffices as a compiler barrier.
17+
//
18+
// SAFETY: An empty asm block.
19+
unsafe { core::arch::asm!("") };
20+
}
21+
22+
/// A full memory barrier.
23+
///
24+
/// A barrier that prevents compiler and CPU from reordering memory accesses across the barrier.
25+
#[inline(always)]
26+
pub fn smp_mb() {
27+
if cfg!(CONFIG_SMP) {
28+
// SAFETY: `smp_mb()` is safe to call.
29+
unsafe { bindings::smp_mb() };
30+
} else {
31+
barrier();
32+
}
33+
}
34+
35+
/// A write-write memory barrier.
36+
///
37+
/// A barrier that prevents compiler and CPU from reordering memory write accesses across the
38+
/// barrier.
39+
#[inline(always)]
40+
pub fn smp_wmb() {
41+
if cfg!(CONFIG_SMP) {
42+
// SAFETY: `smp_wmb()` is safe to call.
43+
unsafe { bindings::smp_wmb() };
44+
} else {
45+
barrier();
46+
}
47+
}
48+
49+
/// A read-read memory barrier.
50+
///
51+
/// A barrier that prevents compiler and CPU from reordering memory read accesses across the
52+
/// barrier.
53+
#[inline(always)]
54+
pub fn smp_rmb() {
55+
if cfg!(CONFIG_SMP) {
56+
// SAFETY: `smp_rmb()` is safe to call.
57+
unsafe { bindings::smp_rmb() };
58+
} else {
59+
barrier();
60+
}
61+
}

0 commit comments

Comments
 (0)