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 } 62