[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <aW_rHVoiMm4ev0e8@tardis-2.local>
Date: Wed, 21 Jan 2026 04:52:45 +0800
From: Boqun Feng <boqun.feng@...il.com>
To: Marco Elver <elver@...gle.com>
Cc: Gary Guo <gary@...yguo.net>, linux-kernel@...r.kernel.org,
rust-for-linux@...r.kernel.org, linux-fsdevel@...r.kernel.org,
kasan-dev@...glegroups.com, Will Deacon <will@...nel.org>,
Peter Zijlstra <peterz@...radead.org>,
Mark Rutland <mark.rutland@....com>,
Miguel Ojeda <ojeda@...nel.org>,
Björn Roy Baron <bjorn3_gh@...tonmail.com>,
Benno Lossin <lossin@...nel.org>,
Andreas Hindborg <a.hindborg@...nel.org>,
Alice Ryhl <aliceryhl@...gle.com>, Trevor Gross <tmgross@...ch.edu>,
Danilo Krummrich <dakr@...nel.org>,
Elle Rhumsaa <elle@...thered-steel.dev>,
"Paul E. McKenney" <paulmck@...nel.org>,
FUJITA Tomonori <fujita.tomonori@...il.com>
Subject: Re: [PATCH 2/2] rust: sync: atomic: Add atomic operation helpers
over raw pointers
On Tue, Jan 20, 2026 at 06:10:40PM +0100, Marco Elver wrote:
> On Tue, 20 Jan 2026 at 17:47, Gary Guo <gary@...yguo.net> wrote:
> >
[...]
> > >> +
> > >> +/// Atomic load over raw pointers.
> > >> +///
> > >> +/// This function provides a short-cut of `Atomic::from_ptr().load(..)`, and can be used to work
> > >> +/// with C side on synchronizations:
> > >> +///
> > >> +/// - `atomic_load(.., Relaxed)` maps to `READ_ONCE()` when using for inter-thread communication.
> > >> +/// - `atomic_load(.., Acquire)` maps to `smp_load_acquire()`.
> > >
> > > I'm late to the party and may have missed some discussion, but it might
Thanks for bringing this up ;-)
> > > want restating in the documentation and/or commit log:
> > >
> > > READ_ONCE is meant to be a dependency-ordering primitive, i.e. be more
> > > like memory_order_consume than it is memory_order_relaxed. This has, to
> > > the best of my knowledge, not changed; otherwise lots of kernel code
> > > would be broken.
Our C's atomic_long_read() is the same, that is it's like
memory_order_consume instead memory_order_relaxed.
> >
> > On the Rust-side documentation we mentioned that `Relaxed` always preserve
> > dependency ordering, so yes, it is closer to `consume` in the C11 model.
>
> Alright, I missed this.
> Is this actually enforced, or like the C side's use of "volatile",
> relies on luck?
>
I wouldn't call it luck ;-) but we rely on the same thing that C has:
implementing by using READ_ONCE().
> > > It is known to be brittle [1]. So the recommendation
> > > above is unsound; well, it's as unsound as implementing READ_ONCE with a
> > > volatile load.
> >
> > Sorry, which part of this is unsound? You mean that the dependency ordering is
> > actually lost when it's not supposed to be? Even so, it'll be only a problem on
> > specific users that uses `Relaxed` to carry ordering?
>
> Correct.
>
> > Users that use `Relaxed` for things that don't require any ordering would still
> > be fine?
>
> Yes.
>
> > > While Alice's series tried to expose READ_ONCE as-is to the Rust side
> > > (via volatile), so that Rust inherits the exact same semantics (including
> > > its implementation flaw), the recommendation above is doubling down on
> > > the unsoundness by proposing Relaxed to map to READ_ONCE.
> > >
> > > [1] https://lpc.events/event/16/contributions/1174/attachments/1108/2121/Status%20Report%20-%20Broken%20Dependency%20Orderings%20in%20the%20Linux%20Kernel.pdf
> > >
> >
> > I think this is a longstanding debate on whether we should actually depend on
> > dependency ordering or just upgrade everything needs it to acquire. But this
> > isn't really specific to Rust, and whatever is decided is global to the full
> > LKMM.
>
> Indeed, but the implementation on the C vs. Rust side differ
> substantially, so assuming it'll work on the Rust side just because
> "volatile" works more or less on the C side is a leap I wouldn't want
> to take in my codebase.
>
Which part of the implementation is different between C and Rust? We
implement all Relaxed atomics in Rust the same way as C: using C's
READ_ONCE() and WRITE_ONCE().
> > > Furthermore, LTO arm64 promotes READ_ONCE to an acquire (see
> > > arch/arm64/include/asm/rwonce.h):
So are our C's atomic_read() and Rust's Atomic::load().
> > >
> > > /*
> > > * When building with LTO, there is an increased risk of the compiler
> > > * converting an address dependency headed by a READ_ONCE() invocation
> > > * into a control dependency and consequently allowing for harmful
> > > * reordering by the CPU.
> > > *
> > > * Ensure that such transformations are harmless by overriding the generic
> > > * READ_ONCE() definition with one that provides RCpc acquire semantics
> > > * when building with LTO.
> > > */
> > >
> > > So for all intents and purposes, the only sound mapping when pairing
> > > READ_ONCE() with an atomic load on the Rust side is to use Acquire
> > > ordering.
> >
> > LLVM handles address dependency much saner than GCC does. It for example won't
> > turn address comparing equal into meaning that the pointer can be interchanged
> > (as provenance won't match). Currently only address comparision to NULL or
> > static can have effect on pointer provenance.
> >
> > Although, last time I asked if we can rely on this for address dependency, I
> > didn't get an affirmitive answer -- but I think in practice it won't be lost (as
> > currently implemented).
>
> There is no guarantee here, and this can change with every new
> release. In most cases where it matters it works today, but the
> compiler (specifically LLVM) does break dependencies even if rarely
> [1].
>
> > Furthermore, Rust code currently does not participate in LTO.
>
> LTO is not the problem, aggressive compiler optimizations (as
> discussed in [1]) are. And Rust, by virtue of its strong type system,
> appears to give the compiler a lot more leeway how it optimizes code.
> So I think the Rust side is in greater danger here than the C with LTO
> side. But I'm speculating (pun intended) ...
>
> However, given "Relaxed" for the Rust side is already defined to
> "carry dependencies" then in isolation my original comment is moot and
> does not apply to this particular patch. At face value the promised
> semantics are ok, but the implementation (just like "volatile" for C)
> probably are not. But that appears to be beyond this patch, so feel
Implementation-wise, READ_ONCE() is used the same as C for
atomic_read(), so Rust and C are on the same boat.
Regards,
Boqun
> free to ignore.
Powered by blists - more mailing lists