From: "Benno Lossin" <lossin@kernel.org>
To: "Boqun Feng" <boqun.feng@gmail.com>
Cc: linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org,
lkmm@lists.linux.dev, linux-arch@vger.kernel.org,
"Miguel Ojeda" <ojeda@kernel.org>,
"Alex Gaynor" <alex.gaynor@gmail.com>,
"Gary Guo" <gary@garyguo.net>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
"Andreas Hindborg" <a.hindborg@kernel.org>,
"Alice Ryhl" <aliceryhl@google.com>,
"Trevor Gross" <tmgross@umich.edu>,
"Danilo Krummrich" <dakr@kernel.org>,
"Will Deacon" <will@kernel.org>,
"Peter Zijlstra" <peterz@infradead.org>,
"Mark Rutland" <mark.rutland@arm.com>,
"Wedson Almeida Filho" <wedsonaf@gmail.com>,
"Viresh Kumar" <viresh.kumar@linaro.org>,
"Lyude Paul" <lyude@redhat.com>, "Ingo Molnar" <mingo@kernel.org>,
"Mitchell Levy" <levymitchell0@gmail.com>,
"Paul E. McKenney" <paulmck@kernel.org>,
"Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
"Linus Torvalds" <torvalds@linux-foundation.org>,
"Thomas Gleixner" <tglx@linutronix.de>,
"Alan Stern" <stern@rowland.harvard.edu>
Subject: Re: [PATCH v7 6/9] rust: sync: atomic: Add the framework of arithmetic operations
Date: Tue, 15 Jul 2025 20:39:04 +0200 [thread overview]
Message-ID: <DBCUJ4RNRNHP.W4QH5QM3TBHU@kernel.org> (raw)
In-Reply-To: <aHZ-HP1ErzlERfpI@Mac.home>
On Tue Jul 15, 2025 at 6:13 PM CEST, Boqun Feng wrote:
> On Tue, Jul 15, 2025 at 05:45:34PM +0200, Benno Lossin wrote:
>> On Tue Jul 15, 2025 at 3:33 PM CEST, Boqun Feng wrote:
>> > On Tue, Jul 15, 2025 at 01:21:20PM +0200, Benno Lossin wrote:
>> >> On Mon Jul 14, 2025 at 7:36 AM CEST, Boqun Feng wrote:
>> >> > +/// Types that support atomic add operations.
>> >> > +///
>> >> > +/// # Safety
>> >> > +///
>> >> > +/// Wrapping adding any value of type `Self::Repr::Delta` obtained by [`Self::rhs_into_delta()`] to
>> >>
>> >> I don't like "wrapping adding", either we use "`wrapping_add`" or we use
>> >> some other phrasing.
>> >>
>> >
>> > Let's use `wrapping_add` then.
>> >
>> > /// `wrapping_add` any value of type `Self::Repr::Delta` obtained by [`Self::rhs_into_delta()`] to
>> > /// any value of type `Self::Repr` obtained through transmuting a value of type `Self` to must
>> > /// yield a value with a bit pattern also valid for `Self`.
>> >
>> >> > +pub unsafe trait AllowAtomicAdd<Rhs = Self>: AllowAtomic {
>> >>
>> >> Why `Allow*`? I think `AtomicAdd` is better?
>> >>
>> >
>> > To be consistent with `AllowAtomic` (the super trait), if we use
>> > `AtomicAdd` here, should we change `AllowAtomic` to `AtomicBase`?
>>
>> Ideally, we would name that trait just `Atomic` :) But it then
>> conflicts with the `Atomic<T>` struct (this would be motivation to put
>> them in different modules :). I like `AtomicBase` better than
>
> Oh, if we move `Atomic<T>` to atomic.rs and keep atomic::generic, then
> we can name it atomic::generic::Atomic ;-)
That would be an argument for having the `generic` module :)
Well, I'm not so sure about having two types with the same name right
away, so maybe let's discuss this in our meeting.
>> `AllowAtomic`, but maybe there is a better name, how about `AtomicType`?
>>
>
> AtomicType may be better than AtomicBase to me.
Yeah I like it better too.
>> >> > + /// Converts `Rhs` into the `Delta` type of the atomic implementation.
>> >> > + fn rhs_into_delta(rhs: Rhs) -> <Self::Repr as AtomicImpl>::Delta;
>> >> > +}
>> >> > +
>> >> > impl<T: AllowAtomic> Atomic<T> {
>> >> > /// Creates a new atomic `T`.
>> >> > pub const fn new(v: T) -> Self {
>> >> > @@ -462,3 +474,100 @@ fn try_cmpxchg<Ordering: ordering::Any>(&self, old: &mut T, new: T, _: Ordering)
>> >> > ret
>> >> > }
>> >> > }
>> >> > +
>> >> > +impl<T: AllowAtomic> Atomic<T>
>> >> > +where
>> >> > + T::Repr: AtomicHasArithmeticOps,
>> >> > +{
>> >> > + /// Atomic add.
>> >> > + ///
>> >> > + /// Atomically updates `*self` to `(*self).wrapping_add(v)`.
>> >> > + ///
>> >> > + /// # Examples
>> >> > + ///
>> >> > + /// ```
>> >> > + /// use kernel::sync::atomic::{Atomic, Relaxed};
>> >> > + ///
>> >> > + /// let x = Atomic::new(42);
>> >> > + ///
>> >> > + /// assert_eq!(42, x.load(Relaxed));
>> >> > + ///
>> >> > + /// x.add(12, Relaxed);
>> >> > + ///
>> >> > + /// assert_eq!(54, x.load(Relaxed));
>> >> > + /// ```
>> >> > + #[inline(always)]
>> >> > + pub fn add<Rhs, Ordering: ordering::RelaxedOnly>(&self, v: Rhs, _: Ordering)
>> >> > + where
>> >> > + T: AllowAtomicAdd<Rhs>,
>> >> > + {
>> >> > + let v = T::rhs_into_delta(v);
>> >> > + // CAST: Per the safety requirement of `AllowAtomic`, a valid pointer of `T` is a valid
>> >> > + // pointer of `T::Repr` for reads and valid for writes of values transmutable to `T`.
>> >> > + let a = self.as_ptr().cast::<T::Repr>();
>> >> > +
>> >> > + // `*self` remains valid after `atomic_add()` because of the safety requirement of
>> >> > + // `AllowAtomicAdd`.
>> >>
>> >> This part should be moved to the CAST comment above, since we're not
>> >> only writing a value transmuted from `T` into `*self`.
>> >>
>> >
>> > Hmm.. the CAST comment should explain why a pointer of `T` can be a
>> > valid pointer of `T::Repr` because the atomic_add() below is going to
>> > read through the pointer and write value back. The comment starting with
>> > "`*self`" explains the value written is a valid `T`, therefore
>> > conceptually atomic_add() below writes a valid `T` in form of `T::Repr`
>> > into `a`.
>>
>> I see, my interpretation was that if we put it on the cast, then the
>> operation that `atomic_add` does also is valid.
>>
>> But I think this comment should either be part of the `CAST` or the
>> `SAFETY` comment. Going by your interpretation, it would make more sense
>> in the SAFETY one, since there you justify that you're actually writing
>> a value of type `T`.
>>
>
> Hmm.. you're probably right. There are two safety things about
> atomic_add():
>
> - Whether calling it is safe
> - Whether the operation on `a` (a pointer to `T` essentially) is safe.
Well part of calling `T::Repr::atomic_add` is that the pointer is valid.
But it actually isn't valid for all operations, only for the specific
one you have here. If we want to be 100% correct, we actually need to
change the safety comment of `atomic_add` to say that it only requires
the result of `*a + v` to be writable... But that is most likely very
annoying... (note that we also have this issue for `store`)
I'm not too sure on what the right way to do this is. The formal answer
is to "just do it right", but then safety comments really just devolve
into formally proving the correctness of the program. I think -- for now
at least :) -- that we shouldn't do this here & now (since we also have
a lot of other code that isn't using normal good safety comments, let
alone formally correct ones).
> How about the following:
>
> let v = T::rhs_into_delta(v);
> // CAST: Per the safety requirement of `AllowAtomic`, a valid pointer of `T` is a valid
> // pointer of `T::Repr` for reads and valid for writes of values transmutable to `T`.
> let a = self.as_ptr().cast::<T::Repr>();
>
> // `*self` remains valid after `atomic_add()` because of the safety requirement of
> // `AllowAtomicAdd`.
> //
> // SAFETY:
> // - For calling `atomic_add()`:
> // - `a` is aligned to `align_of::<T::Repr>()` because of the safety requirement of
> // `AllowAtomic` and the guarantee of `Atomic::as_ptr()`.
> // - `a` is a valid pointer per the CAST justification above.
> // - For accessing `*a`: the value written is transmutable to `T`
> // due to the safety requirement of `AllowAtomicAdd`.
> unsafe { T::Repr::atomic_add(a, v) };
That looks fine for now. But isn't this duplicating the sentence
starting with `*self`?
---
Cheers,
Benno
next prev parent reply other threads:[~2025-07-15 18:39 UTC|newest]
Thread overview: 50+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-07-14 5:36 [PATCH v7 0/9] LKMM generic atomics in Rust Boqun Feng
2025-07-14 5:36 ` [PATCH v7 1/9] rust: Introduce atomic API helpers Boqun Feng
2025-07-16 9:23 ` Greg Kroah-Hartman
2025-07-16 12:36 ` Miguel Ojeda
2025-07-16 12:47 ` Peter Zijlstra
2025-07-16 12:54 ` Greg Kroah-Hartman
2025-07-16 12:57 ` Miguel Ojeda
2025-07-16 13:04 ` Peter Zijlstra
2025-07-16 12:56 ` Miguel Ojeda
2025-07-14 5:36 ` [PATCH v7 2/9] rust: sync: Add basic atomic operation mapping framework Boqun Feng
2025-07-14 10:03 ` Benno Lossin
2025-07-14 13:42 ` Boqun Feng
2025-07-14 15:00 ` Benno Lossin
2025-07-14 15:34 ` Boqun Feng
2025-07-14 5:36 ` [PATCH v7 3/9] rust: sync: atomic: Add ordering annotation types Boqun Feng
2025-07-14 10:10 ` Benno Lossin
2025-07-14 14:59 ` Boqun Feng
2025-07-14 15:16 ` Benno Lossin
2025-07-14 5:36 ` [PATCH v7 4/9] rust: sync: atomic: Add generic atomics Boqun Feng
2025-07-14 10:30 ` Benno Lossin
2025-07-14 14:21 ` Boqun Feng
2025-07-14 14:30 ` Boqun Feng
2025-07-14 14:34 ` Miguel Ojeda
2025-07-14 14:53 ` Boqun Feng
2025-07-14 15:16 ` Benno Lossin
2025-07-14 15:05 ` Benno Lossin
2025-07-14 15:32 ` Boqun Feng
2025-07-15 9:36 ` Benno Lossin
2025-07-15 13:14 ` Boqun Feng
2025-07-15 15:35 ` Benno Lossin
2025-07-14 5:36 ` [PATCH v7 5/9] rust: sync: atomic: Add atomic {cmp,}xchg operations Boqun Feng
2025-07-14 10:56 ` Benno Lossin
2025-07-14 5:36 ` [PATCH v7 6/9] rust: sync: atomic: Add the framework of arithmetic operations Boqun Feng
2025-07-15 11:21 ` Benno Lossin
2025-07-15 13:33 ` Boqun Feng
2025-07-15 15:45 ` Benno Lossin
2025-07-15 16:13 ` Boqun Feng
2025-07-15 18:39 ` Benno Lossin [this message]
2025-07-15 20:13 ` Boqun Feng
2025-07-16 10:25 ` Benno Lossin
2025-07-16 14:13 ` Boqun Feng
2025-07-16 15:36 ` Benno Lossin
2025-07-16 15:48 ` Boqun Feng
2025-07-16 17:16 ` Benno Lossin
2025-07-16 17:38 ` Boqun Feng
2025-07-14 5:36 ` [PATCH v7 7/9] rust: sync: atomic: Add Atomic<u{32,64}> Boqun Feng
2025-07-14 5:36 ` [PATCH v7 8/9] rust: sync: Add memory barriers Boqun Feng
2025-07-14 5:36 ` [PATCH v7 9/9] rust: sync: atomic: Add Atomic<{usize,isize}> Boqun Feng
2025-07-14 11:06 ` Benno Lossin
2025-07-14 13:47 ` Boqun Feng
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=DBCUJ4RNRNHP.W4QH5QM3TBHU@kernel.org \
--to=lossin@kernel.org \
--cc=a.hindborg@kernel.org \
--cc=alex.gaynor@gmail.com \
--cc=aliceryhl@google.com \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun.feng@gmail.com \
--cc=dakr@kernel.org \
--cc=gary@garyguo.net \
--cc=gregkh@linuxfoundation.org \
--cc=levymitchell0@gmail.com \
--cc=linux-arch@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=lkmm@lists.linux.dev \
--cc=lyude@redhat.com \
--cc=mark.rutland@arm.com \
--cc=mingo@kernel.org \
--cc=ojeda@kernel.org \
--cc=paulmck@kernel.org \
--cc=peterz@infradead.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=stern@rowland.harvard.edu \
--cc=tglx@linutronix.de \
--cc=tmgross@umich.edu \
--cc=torvalds@linux-foundation.org \
--cc=viresh.kumar@linaro.org \
--cc=wedsonaf@gmail.com \
--cc=will@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).