1*d9ea5a41SBoqun Feng // SPDX-License-Identifier: GPL-2.0 2*d9ea5a41SBoqun Feng 3*d9ea5a41SBoqun Feng //! Memory barriers. 4*d9ea5a41SBoqun Feng //! 5*d9ea5a41SBoqun Feng //! These primitives have the same semantics as their C counterparts: and the precise definitions 6*d9ea5a41SBoqun Feng //! of semantics can be found at [`LKMM`]. 7*d9ea5a41SBoqun Feng //! 8*d9ea5a41SBoqun Feng //! [`LKMM`]: srctree/tools/memory-model/ 9*d9ea5a41SBoqun Feng 10*d9ea5a41SBoqun Feng /// A compiler barrier. 11*d9ea5a41SBoqun Feng /// 12*d9ea5a41SBoqun Feng /// A barrier that prevents compiler from reordering memory accesses across the barrier. 13*d9ea5a41SBoqun Feng #[inline(always)] 14*d9ea5a41SBoqun Feng pub(crate) fn barrier() { 15*d9ea5a41SBoqun Feng // By default, Rust inline asms are treated as being able to access any memory or flags, hence 16*d9ea5a41SBoqun Feng // it suffices as a compiler barrier. 17*d9ea5a41SBoqun Feng // 18*d9ea5a41SBoqun Feng // SAFETY: An empty asm block. 19*d9ea5a41SBoqun Feng unsafe { core::arch::asm!("") }; 20*d9ea5a41SBoqun Feng } 21*d9ea5a41SBoqun Feng 22*d9ea5a41SBoqun Feng /// A full memory barrier. 23*d9ea5a41SBoqun Feng /// 24*d9ea5a41SBoqun Feng /// A barrier that prevents compiler and CPU from reordering memory accesses across the barrier. 25*d9ea5a41SBoqun Feng #[inline(always)] 26*d9ea5a41SBoqun Feng pub fn smp_mb() { 27*d9ea5a41SBoqun Feng if cfg!(CONFIG_SMP) { 28*d9ea5a41SBoqun Feng // SAFETY: `smp_mb()` is safe to call. 29*d9ea5a41SBoqun Feng unsafe { bindings::smp_mb() }; 30*d9ea5a41SBoqun Feng } else { 31*d9ea5a41SBoqun Feng barrier(); 32*d9ea5a41SBoqun Feng } 33*d9ea5a41SBoqun Feng } 34*d9ea5a41SBoqun Feng 35*d9ea5a41SBoqun Feng /// A write-write memory barrier. 36*d9ea5a41SBoqun Feng /// 37*d9ea5a41SBoqun Feng /// A barrier that prevents compiler and CPU from reordering memory write accesses across the 38*d9ea5a41SBoqun Feng /// barrier. 39*d9ea5a41SBoqun Feng #[inline(always)] 40*d9ea5a41SBoqun Feng pub fn smp_wmb() { 41*d9ea5a41SBoqun Feng if cfg!(CONFIG_SMP) { 42*d9ea5a41SBoqun Feng // SAFETY: `smp_wmb()` is safe to call. 43*d9ea5a41SBoqun Feng unsafe { bindings::smp_wmb() }; 44*d9ea5a41SBoqun Feng } else { 45*d9ea5a41SBoqun Feng barrier(); 46*d9ea5a41SBoqun Feng } 47*d9ea5a41SBoqun Feng } 48*d9ea5a41SBoqun Feng 49*d9ea5a41SBoqun Feng /// A read-read memory barrier. 50*d9ea5a41SBoqun Feng /// 51*d9ea5a41SBoqun Feng /// A barrier that prevents compiler and CPU from reordering memory read accesses across the 52*d9ea5a41SBoqun Feng /// barrier. 53*d9ea5a41SBoqun Feng #[inline(always)] 54*d9ea5a41SBoqun Feng pub fn smp_rmb() { 55*d9ea5a41SBoqun Feng if cfg!(CONFIG_SMP) { 56*d9ea5a41SBoqun Feng // SAFETY: `smp_rmb()` is safe to call. 57*d9ea5a41SBoqun Feng unsafe { bindings::smp_rmb() }; 58*d9ea5a41SBoqun Feng } else { 59*d9ea5a41SBoqun Feng barrier(); 60*d9ea5a41SBoqun Feng } 61*d9ea5a41SBoqun Feng } 62