xref: /linux/rust/kernel/sync/barrier.rs (revision 88b489385bfe3713497a63c0dcf4dd7852cf4568)
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