From: Boqun Feng <boqun.feng@gmail.com>
To: David Gow <davidgow@google.com>
Cc: rust-for-linux@vger.kernel.org, rcu@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-arch@vger.kernel.org,
llvm@lists.linux.dev, lkmm@lists.linux.dev,
"Miguel Ojeda" <ojeda@kernel.org>,
"Alex Gaynor" <alex.gaynor@gmail.com>,
"Wedson Almeida Filho" <wedsonaf@gmail.com>,
"Gary Guo" <gary@garyguo.net>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
"Benno Lossin" <benno.lossin@proton.me>,
"Andreas Hindborg" <a.hindborg@samsung.com>,
"Alice Ryhl" <aliceryhl@google.com>,
"Alan Stern" <stern@rowland.harvard.edu>,
"Andrea Parri" <parri.andrea@gmail.com>,
"Will Deacon" <will@kernel.org>,
"Peter Zijlstra" <peterz@infradead.org>,
"Nicholas Piggin" <npiggin@gmail.com>,
"David Howells" <dhowells@redhat.com>,
"Jade Alglave" <j.alglave@ucl.ac.uk>,
"Luc Maranget" <luc.maranget@inria.fr>,
"Paul E. McKenney" <paulmck@kernel.org>,
"Akira Yokosawa" <akiyks@gmail.com>,
"Daniel Lustig" <dlustig@nvidia.com>,
"Joel Fernandes" <joel@joelfernandes.org>,
"Nathan Chancellor" <nathan@kernel.org>,
"Nick Desaulniers" <ndesaulniers@google.com>,
kent.overstreet@gmail.com,
"Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
elver@google.com, "Mark Rutland" <mark.rutland@arm.com>,
"Thomas Gleixner" <tglx@linutronix.de>,
"Ingo Molnar" <mingo@redhat.com>,
"Borislav Petkov" <bp@alien8.de>,
"Dave Hansen" <dave.hansen@linux.intel.com>,
x86@kernel.org, "H. Peter Anvin" <hpa@zytor.com>,
"Catalin Marinas" <catalin.marinas@arm.com>,
torvalds@linux-foundation.org,
linux-arm-kernel@lists.infradead.org,
linux-fsdevel@vger.kernel.org, "Trevor Gross" <tmgross@umich.edu>,
dakr@redhat.com, "Frederic Weisbecker" <frederic@kernel.org>,
"Neeraj Upadhyay" <neeraj.upadhyay@kernel.org>,
"Josh Triplett" <josh@joshtriplett.org>,
"Uladzislau Rezki" <urezki@gmail.com>,
"Steven Rostedt" <rostedt@goodmis.org>,
"Mathieu Desnoyers" <mathieu.desnoyers@efficios.com>,
"Lai Jiangshan" <jiangshanlai@gmail.com>,
Zqiang <qiang.zhang1211@gmail.com>,
"Paul Walmsley" <paul.walmsley@sifive.com>,
"Palmer Dabbelt" <palmer@dabbelt.com>,
"Albert Ou" <aou@eecs.berkeley.edu>,
linux-riscv@lists.infradead.org
Subject: Re: [RFC v2 00/13] LKMM *generic* atomics in Rust
Date: Mon, 21 Apr 2025 09:27:28 -0700 [thread overview]
Message-ID: <aAZx8GARiCW-pq9_@boqun-archlinux> (raw)
In-Reply-To: <CABVgOSm1cDcrsgYutooRG-ZLuzMypAO+ndNFyPy2w3_5B84TSQ@mail.gmail.com>
On Sat, Nov 02, 2024 at 03:35:36PM +0800, David Gow wrote:
> On Fri, 1 Nov 2024 at 14:04, Boqun Feng <boqun.feng@gmail.com> wrote:
> >
> > Hi,
> >
> > This is another RFC version of LKMM atomics in Rust, you can find the
> > previous versions:
> >
> > v1: https://lore.kernel.org/rust-for-linux/20240612223025.1158537-1-boqun.feng@gmail.com/
> > wip: https://lore.kernel.org/rust-for-linux/20240322233838.868874-1-boqun.feng@gmail.com/
> >
> > I add a few more people Cced this time, so if you're curious about why
> > we choose to implement LKMM atomics instead of using the Rust ones, you
> > can find some explanation:
> >
> > * In my Kangrejos talk: https://lwn.net/Articles/993785/
> > * In Linus' email: https://lore.kernel.org/rust-for-linux/CAHk-=whkQk=zq5XiMcaU3xj4v69+jyoP-y6Sywhq-TvxSSvfEA@mail.gmail.com/
> >
> > This time, I try implementing a generic atomic type `Atomic<T>`, since
> > Benno and Gary suggested last time, and also Rust standard library is
> > also going to that direction [1].
> >
> > Honestly, a generic atomic type is still not quite necessary for myself,
> > but here are a few reasons that it's useful:
> >
> > * It's useful for type alias, for example, if you have:
> >
> > type c_long = isize;
> >
> > Then `Atomic<c_clong>` and `Atomic<isize>` is the same type,
> > this may make FFI code (mapping a C type to a Rust type or vice
> > versa) more readable.
> >
> > * In kernel, we sometimes switch atomic to percpu for better
> > scalabity, percpu is naturally a generic type, because it can
> > have data that is larger than machine word size. Making atomic
> > generic ease the potential switching/refactoring.
> >
> > * Generic atomics provide all the functionalities that non-generic
> > atomics could have.
> >
> > That said, currently "generic" is limited to a few types: the type must
> > be the same size as atomic_t or atomic64_t, other than basic types, only
> > #[repr(<basic types>)] struct can be used in a `Atomic<T>`.
> >
> > Also this is not a full feature set patchset, things like different
> > arithmetic operations and bit operations are still missing, they can be
> > either future work or for future versions.
> >
> > I included an RCU pointer implementation as one example of the usage, so
> > a patch from Danilo is added, but I will drop it once his patch merged.
> >
> > This is based on today's rust-next, and I've run all kunit tests from
> > the doc test on x86, arm64 and riscv.
> >
> > Feedbacks and comments are welcome! Thanks.
> >
> > Regards,
> > Boqun
> >
> > [1]: https://github.com/rust-lang/rust/issues/130539
> >
>
> Thanks, Boqun.
>
Hi David,
> I played around a bit with porting the blk-mq atomic code to this. As
> neither an expert in Rust nor an expert in atomics, this is probably
> both non-idiomatic and wrong, but unlike the `core` atomics, it
> provides an Atomic::<u64> on 32-bit systems, which gets UML's 32-bit
> build working again.
>
> Diff below -- I'm not likely to have much time to work on this again
> soon, so feel free to pick it up/fix it if it suits.
>
Thanks. These look good to me, however, I think I prefer Gary's patch
for this:
https://lore.kernel.org/lkml/20250219201602.1898383-4-gary@garyguo.net/
therefore, I won't take this into the next version. But thank you for
taking a look!
Regards,
Boqun
> Thanks,
> -- David
>
> ---
> diff --git a/rust/kernel/block/mq/operations.rs
> b/rust/kernel/block/mq/operations.rs
> index 9ba7fdfeb4b2..822d64230e11 100644
> --- a/rust/kernel/block/mq/operations.rs
> +++ b/rust/kernel/block/mq/operations.rs
> @@ -11,7 +11,8 @@
> error::{from_result, Result},
> types::ARef,
> };
> -use core::{marker::PhantomData, sync::atomic::AtomicU64,
> sync::atomic::Ordering};
> +use core::marker::PhantomData;
> +use kernel::sync::atomic::{Atomic, Relaxed};
>
> /// Implement this trait to interface blk-mq as block devices.
> ///
> @@ -77,7 +78,7 @@ impl<T: Operations> OperationsVTable<T> {
> let request = unsafe { &*(*bd).rq.cast::<Request<T>>() };
>
> // One refcount for the ARef, one for being in flight
> - request.wrapper_ref().refcount().store(2, Ordering::Relaxed);
> + request.wrapper_ref().refcount().store(2, Relaxed);
>
> // SAFETY:
> // - We own a refcount that we took above. We pass that to `ARef`.
> @@ -186,7 +187,7 @@ impl<T: Operations> OperationsVTable<T> {
>
> // SAFETY: The refcount field is allocated but not initialized, so
> // it is valid for writes.
> - unsafe {
> RequestDataWrapper::refcount_ptr(pdu.as_ptr()).write(AtomicU64::new(0))
> };
> + unsafe {
> RequestDataWrapper::refcount_ptr(pdu.as_ptr()).write(Atomic::<u64>::new(0))
> };
>
> Ok(0)
> })
> diff --git a/rust/kernel/block/mq/request.rs b/rust/kernel/block/mq/request.rs
> index 7943f43b9575..8d4060d65159 100644
> --- a/rust/kernel/block/mq/request.rs
> +++ b/rust/kernel/block/mq/request.rs
> @@ -13,8 +13,8 @@
> use core::{
> marker::PhantomData,
> ptr::{addr_of_mut, NonNull},
> - sync::atomic::{AtomicU64, Ordering},
> };
> +use kernel::sync::atomic::{Atomic, Relaxed};
>
> /// A wrapper around a blk-mq [`struct request`]. This represents an
> IO request.
> ///
> @@ -102,8 +102,7 @@ fn try_set_end(this: ARef<Self>) -> Result<*mut
> bindings::request, ARef<Self>> {
> if let Err(_old) = this.wrapper_ref().refcount().compare_exchange(
> 2,
> 0,
> - Ordering::Relaxed,
> - Ordering::Relaxed,
> + Relaxed
> ) {
> return Err(this);
> }
> @@ -168,13 +167,13 @@ pub(crate) struct RequestDataWrapper {
> /// - 0: The request is owned by C block layer.
> /// - 1: The request is owned by Rust abstractions but there are
> no [`ARef`] references to it.
> /// - 2+: There are [`ARef`] references to the request.
> - refcount: AtomicU64,
> + refcount: Atomic::<u64>,
> }
>
> impl RequestDataWrapper {
> /// Return a reference to the refcount of the request that is embedding
> /// `self`.
> - pub(crate) fn refcount(&self) -> &AtomicU64 {
> + pub(crate) fn refcount(&self) -> &Atomic::<u64> {
> &self.refcount
> }
>
> @@ -184,7 +183,7 @@ pub(crate) fn refcount(&self) -> &AtomicU64 {
> /// # Safety
> ///
> /// - `this` must point to a live allocation of at least the size
> of `Self`.
> - pub(crate) unsafe fn refcount_ptr(this: *mut Self) -> *mut AtomicU64 {
> + pub(crate) unsafe fn refcount_ptr(this: *mut Self) -> *mut Atomic::<u64> {
> // SAFETY: Because of the safety requirements of this function, the
> // field projection is safe.
> unsafe { addr_of_mut!((*this).refcount) }
> @@ -202,28 +201,22 @@ unsafe impl<T: Operations> Sync for Request<T> {}
>
> /// Store the result of `op(target.load())` in target, returning new value of
> /// target.
> -fn atomic_relaxed_op_return(target: &AtomicU64, op: impl Fn(u64) ->
> u64) -> u64 {
> - let old = target.fetch_update(Ordering::Relaxed,
> Ordering::Relaxed, |x| Some(op(x)));
> -
> - // SAFETY: Because the operation passed to `fetch_update` above always
> - // return `Some`, `old` will always be `Ok`.
> - let old = unsafe { old.unwrap_unchecked() };
> -
> - op(old)
> +fn atomic_relaxed_op_return(target: &Atomic::<u64>, op: impl Fn(u64)
> -> u64) -> u64 {
> + let old = target.load(Relaxed);
> + let new_val = op(old);
> + target.compare_exchange(old, new_val, Relaxed);
> + old
> }
>
> /// Store the result of `op(target.load)` in `target` if `target.load() !=
> /// pred`, returning [`true`] if the target was updated.
> -fn atomic_relaxed_op_unless(target: &AtomicU64, op: impl Fn(u64) ->
> u64, pred: u64) -> bool {
> - target
> - .fetch_update(Ordering::Relaxed, Ordering::Relaxed, |x| {
> - if x == pred {
> - None
> - } else {
> - Some(op(x))
> - }
> - })
> - .is_ok()
> +fn atomic_relaxed_op_unless(target: &Atomic::<u64>, op: impl Fn(u64)
> -> u64, pred: u64) -> bool {
> + let old = target.load(Relaxed);
> + if old == pred {
> + false
> + } else {
> + target.compare_exchange(old, op(old), Relaxed).is_ok()
> + }
> }
>
> // SAFETY: All instances of `Request<T>` are reference counted. This
prev parent reply other threads:[~2025-04-21 16:27 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-11-01 6:02 [RFC v2 00/13] LKMM *generic* atomics in Rust Boqun Feng
2024-11-01 6:02 ` [RFC v2 01/13] rust: Introduce atomic API helpers Boqun Feng
2024-11-01 6:02 ` [RFC v2 02/13] rust: sync: Add basic atomic operation mapping framework Boqun Feng
2024-12-12 10:51 ` Alice Ryhl
2024-12-12 17:07 ` Boqun Feng
2024-12-13 14:37 ` Alice Ryhl
2024-12-13 20:28 ` Boqun Feng
2024-11-01 6:02 ` [RFC v2 03/13] rust: sync: atomic: Add ordering annotation types Boqun Feng
2024-11-01 6:02 ` [RFC v2 04/13] rust: sync: atomic: Add generic atomics Boqun Feng
2024-12-12 10:57 ` Alice Ryhl
2024-12-12 17:34 ` Boqun Feng
2024-12-13 14:32 ` Alice Ryhl
2024-12-13 20:13 ` Boqun Feng
2024-11-01 6:02 ` [RFC v2 05/13] rust: sync: atomic: Add atomic {cmp,}xchg operations Boqun Feng
2024-11-01 6:02 ` [RFC v2 06/13] rust: sync: atomic: Add the framework of arithmetic operations Boqun Feng
2024-11-01 6:02 ` [RFC v2 07/13] rust: sync: atomic: Add Atomic<u{32,64}> Boqun Feng
2024-11-01 6:02 ` [RFC v2 08/13] rust: sync: atomic: Add Atomic<{usize,isize}> Boqun Feng
2024-11-01 6:02 ` [RFC v2 09/13] rust: sync: atomic: Add Atomic<*mut T> Boqun Feng
2024-11-01 6:02 ` [RFC v2 10/13] rust: sync: atomic: Add arithmetic ops for " Boqun Feng
2024-11-01 6:02 ` [RFC v2 11/13] rust: sync: Add memory barriers Boqun Feng
2024-11-01 6:55 ` David Gow
2024-11-01 7:04 ` Boqun Feng
2024-11-01 7:01 ` [RFC v2.1 " Boqun Feng
2024-11-01 6:02 ` [RFC v2 12/13] rust: add rcu abstraction Boqun Feng
2024-11-01 6:02 ` [RFC v2 13/13] rust: sync: rcu: Add RCU protected pointer Boqun Feng
2024-11-01 14:30 ` [RFC v2 00/13] LKMM *generic* atomics in Rust Miguel Ojeda
2024-11-02 7:35 ` David Gow
2025-04-21 16:27 ` Boqun Feng [this message]
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=aAZx8GARiCW-pq9_@boqun-archlinux \
--to=boqun.feng@gmail.com \
--cc=a.hindborg@samsung.com \
--cc=akiyks@gmail.com \
--cc=alex.gaynor@gmail.com \
--cc=aliceryhl@google.com \
--cc=aou@eecs.berkeley.edu \
--cc=benno.lossin@proton.me \
--cc=bjorn3_gh@protonmail.com \
--cc=bp@alien8.de \
--cc=catalin.marinas@arm.com \
--cc=dakr@redhat.com \
--cc=dave.hansen@linux.intel.com \
--cc=davidgow@google.com \
--cc=dhowells@redhat.com \
--cc=dlustig@nvidia.com \
--cc=elver@google.com \
--cc=frederic@kernel.org \
--cc=gary@garyguo.net \
--cc=gregkh@linuxfoundation.org \
--cc=hpa@zytor.com \
--cc=j.alglave@ucl.ac.uk \
--cc=jiangshanlai@gmail.com \
--cc=joel@joelfernandes.org \
--cc=josh@joshtriplett.org \
--cc=kent.overstreet@gmail.com \
--cc=linux-arch@vger.kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-riscv@lists.infradead.org \
--cc=lkmm@lists.linux.dev \
--cc=llvm@lists.linux.dev \
--cc=luc.maranget@inria.fr \
--cc=mark.rutland@arm.com \
--cc=mathieu.desnoyers@efficios.com \
--cc=mingo@redhat.com \
--cc=nathan@kernel.org \
--cc=ndesaulniers@google.com \
--cc=neeraj.upadhyay@kernel.org \
--cc=npiggin@gmail.com \
--cc=ojeda@kernel.org \
--cc=palmer@dabbelt.com \
--cc=parri.andrea@gmail.com \
--cc=paul.walmsley@sifive.com \
--cc=paulmck@kernel.org \
--cc=peterz@infradead.org \
--cc=qiang.zhang1211@gmail.com \
--cc=rcu@vger.kernel.org \
--cc=rostedt@goodmis.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=urezki@gmail.com \
--cc=wedsonaf@gmail.com \
--cc=will@kernel.org \
--cc=x86@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).