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)]
barrier()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)]
smp_mb()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)]
smp_wmb()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)]
smp_rmb()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 }
62