kernel/sync/barrier.rs
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)]
14pub(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)]
26pub 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)]
40pub 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)]
54pub 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}