Re: [PATCH v5 10/10] rust: sync: Add memory barriers

Andreas Hindborg <[email protected]>
Newsgroups dev.linux.lists.lkmm,org.kernel.vger.linux-arch,org.kernel.vger.linux-kernel,org.kernel.vger.rust-for-linux
Message-ID <[email protected]>
"Boqun Feng" <[email protected]> writes:

> 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. Also it's
> currently only public to the kernel crate until there's a reasonable
> driver usage.
>
> Signed-off-by: Boqun Feng <[email protected]>
> ---
>  rust/helpers/barrier.c      | 18 ++++++++++
>  rust/helpers/helpers.c      |  1 +
>  rust/kernel/sync.rs         |  1 +
>  rust/kernel/sync/barrier.rs | 67 +++++++++++++++++++++++++++++++++++++
>  4 files changed, 87 insertions(+)
>  create mode 100644 rust/helpers/barrier.c
>  create mode 100644 rust/kernel/sync/barrier.rs
>
> diff --git a/rust/helpers/barrier.c b/rust/helpers/barrier.c
> new file mode 100644
> index 000000000000..cdf28ce8e511
> --- /dev/null
> +++ b/rust/helpers/barrier.c
> @@ -0,0 +1,18 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#include <asm/barrier.h>
> +
> +void rust_helper_smp_mb(void)
> +{
> +	smp_mb();
> +}
> +
> +void rust_helper_smp_wmb(void)
> +{
> +	smp_wmb();
> +}
> +
> +void rust_helper_smp_rmb(void)
> +{
> +	smp_rmb();
> +}
> diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c
> index 83e89f6a68fb..8ddfc8f84e87 100644
> --- a/rust/helpers/helpers.c
> +++ b/rust/helpers/helpers.c
> @@ -9,6 +9,7 @@
>
>  #include "atomic.c"
>  #include "auxiliary.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 b620027e0641..c7c0e552bafe 100644
> --- a/rust/kernel/sync.rs
> +++ b/rust/kernel/sync.rs
> @@ -11,6 +11,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..36a5c70e6716
> --- /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/

Typo in link target.

> +
> +/// 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.

Typo in "explicit".

How about:

  A compiler barrier. Prevents the compiler from reordering
  memory access instructions across the barrier.


> +pub(crate) 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.


  A barrier that prevents compiler and CPU from reordering memory access
  instructions across the barrier.

> +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.

  A barrier that prevents compiler and CPU from reordering memory write
  instructions across the barrier.

> +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.

  A barrier that prevents compiler and CPU from reordering memory read
  instructions across the barrier.

> +pub fn smp_rmb() {
> +    if cfg!(CONFIG_SMP) {
> +        // SAFETY: `smp_rmb()` is safe to call.
> +        unsafe {
> +            bindings::smp_rmb();
> +        }
> +    } else {
> +        barrier();
> +    }
> +}


Best regards,
Andreas Hindborg
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.