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}