Message ID | 20241101060237.1185533-12-boqun.feng@gmail.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | LKMM *generic* atomics in Rust | expand |
On Fri, 1 Nov 2024 at 14:07, Boqun Feng <boqun.feng@gmail.com> wrote: > > Memory barriers are building blocks for concurrent code, hence provide > a minimal set of them. > > The compiler barrier, barrier(), is implemented in inline asm instead of > using core::sync::atomic::compiler_fence() because memory models are > different: kernel's atomics are implemented in inline asm therefore the > compiler barrier should be implemented in inline asm as well. > > Signed-off-by: Boqun Feng <boqun.feng@gmail.com> > --- > rust/helpers/helpers.c | 1 + > rust/kernel/sync.rs | 1 + > rust/kernel/sync/barrier.rs | 67 +++++++++++++++++++++++++++++++++++++ > 3 files changed, 69 insertions(+) > create mode 100644 rust/kernel/sync/barrier.rs > > diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c > index ab5a3f1be241..f4a94833b29d 100644 > --- a/rust/helpers/helpers.c > +++ b/rust/helpers/helpers.c > @@ -8,6 +8,7 @@ > */ > > #include "atomic.c" > +#include "barrier.c" It looks like "barrier.c" is missing, so this isn't compiling for me. I assume it was meant to be added in this patch...? Thanks, -- David
On Fri, Nov 01, 2024 at 02:55:23PM +0800, David Gow wrote: > On Fri, 1 Nov 2024 at 14:07, Boqun Feng <boqun.feng@gmail.com> wrote: > > > > Memory barriers are building blocks for concurrent code, hence provide > > a minimal set of them. > > > > The compiler barrier, barrier(), is implemented in inline asm instead of > > using core::sync::atomic::compiler_fence() because memory models are > > different: kernel's atomics are implemented in inline asm therefore the > > compiler barrier should be implemented in inline asm as well. > > > > Signed-off-by: Boqun Feng <boqun.feng@gmail.com> > > --- > > rust/helpers/helpers.c | 1 + > > rust/kernel/sync.rs | 1 + > > rust/kernel/sync/barrier.rs | 67 +++++++++++++++++++++++++++++++++++++ > > 3 files changed, 69 insertions(+) > > create mode 100644 rust/kernel/sync/barrier.rs > > > > diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c > > index ab5a3f1be241..f4a94833b29d 100644 > > --- a/rust/helpers/helpers.c > > +++ b/rust/helpers/helpers.c > > @@ -8,6 +8,7 @@ > > */ > > > > #include "atomic.c" > > +#include "barrier.c" > > It looks like "barrier.c" is missing, so this isn't compiling for me. > I assume it was meant to be added in this patch...? > Yes, I just send an updated one. Glad being "checking missing files" buddies with you ;-) Thanks! Regards, Boqun > Thanks, > -- David
diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c index ab5a3f1be241..f4a94833b29d 100644 --- a/rust/helpers/helpers.c +++ b/rust/helpers/helpers.c @@ -8,6 +8,7 @@ */ #include "atomic.c" +#include "barrier.c" #include "blk.c" #include "bug.c" #include "build_assert.c" diff --git a/rust/kernel/sync.rs b/rust/kernel/sync.rs index 66ac3752ca71..0d0b19441ae8 100644 --- a/rust/kernel/sync.rs +++ b/rust/kernel/sync.rs @@ -9,6 +9,7 @@ mod arc; pub mod atomic; +pub mod barrier; mod condvar; pub mod lock; mod locked_by; diff --git a/rust/kernel/sync/barrier.rs b/rust/kernel/sync/barrier.rs new file mode 100644 index 000000000000..277aa09747bf --- /dev/null +++ b/rust/kernel/sync/barrier.rs @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Memory barriers. +//! +//! These primitives have the same semantics as their C counterparts: and the precise definitions of +//! semantics can be found at [`LKMM`]. +//! +//! [`LKMM`]: srctree/tools/memory-mode/ + +/// A compiler barrier. +/// +/// An explicic compiler barrier function that prevents the compiler from moving the memory +/// accesses either side of it to the other side. +pub fn barrier() { + // By default, Rust inline asms are treated as being able to access any memory or flags, hence + // it suffices as a compiler barrier. + // + // SAFETY: An empty asm block should be safe. + unsafe { + core::arch::asm!(""); + } +} + +/// A full memory barrier. +/// +/// A barrier function that prevents both the compiler and the CPU from moving the memory accesses +/// either side of it to the other side. +pub fn smp_mb() { + if cfg!(CONFIG_SMP) { + // SAFETY: `smp_mb()` is safe to call. + unsafe { + bindings::smp_mb(); + } + } else { + barrier(); + } +} + +/// A write-write memory barrier. +/// +/// A barrier function that prevents both the compiler and the CPU from moving the memory write +/// accesses either side of it to the other side. +pub fn smp_wmb() { + if cfg!(CONFIG_SMP) { + // SAFETY: `smp_wmb()` is safe to call. + unsafe { + bindings::smp_wmb(); + } + } else { + barrier(); + } +} + +/// A read-read memory barrier. +/// +/// A barrier function that prevents both the compiler and the CPU from moving the memory read +/// accesses either side of it to the other side. +pub fn smp_rmb() { + if cfg!(CONFIG_SMP) { + // SAFETY: `smp_rmb()` is safe to call. + unsafe { + bindings::smp_rmb(); + } + } else { + barrier(); + } +}
Memory barriers are building blocks for concurrent code, hence provide a minimal set of them. The compiler barrier, barrier(), is implemented in inline asm instead of using core::sync::atomic::compiler_fence() because memory models are different: kernel's atomics are implemented in inline asm therefore the compiler barrier should be implemented in inline asm as well. Signed-off-by: Boqun Feng <boqun.feng@gmail.com> --- rust/helpers/helpers.c | 1 + rust/kernel/sync.rs | 1 + rust/kernel/sync/barrier.rs | 67 +++++++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+) create mode 100644 rust/kernel/sync/barrier.rs