rust-for-linux.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Boqun Feng <boqun.feng@gmail.com>
To: linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org,
	lkmm@lists.linux.dev, linux-arch@vger.kernel.org
Cc: "Miguel Ojeda" <ojeda@kernel.org>,
	"Alex Gaynor" <alex.gaynor@gmail.com>,
	"Boqun Feng" <boqun.feng@gmail.com>,
	"Gary Guo" <gary@garyguo.net>,
	"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
	"Benno Lossin" <lossin@kernel.org>,
	"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>
Subject: [PATCH v5 09/10] rust: sync: atomic: Add Atomic<*mut T>
Date: Wed, 18 Jun 2025 09:49:33 -0700	[thread overview]
Message-ID: <20250618164934.19817-10-boqun.feng@gmail.com> (raw)
In-Reply-To: <20250618164934.19817-1-boqun.feng@gmail.com>

Add atomic support for raw pointer values, similar to `isize` and
`usize`, the representation type is selected based on CONFIG_64BIT.

`*mut T` is not `Send`, however `Atomic<*mut T>` definitely needs to be
a `Sync`, and that's the whole point of atomics: being able to have
multiple shared references in different threads so that they can sync
with each other. As a result, a pointer value will be transferred from
one thread to another via `Atomic<*mut T>`:

	<thread 1>		<thread 2>
	x.store(p1, Relaxed);
				let p = x.load(p1, Relaxed);

This means a raw pointer value (`*mut T`) needs to be able to transfer
across thread boundaries, which is essentially `Send`.

To reflect this in the type system, and based on the fact that pointer
values can be transferred safely (only using them to dereference is
unsafe), as suggested by Alice, extend the `AllowAtomic` trait to
include a customized `Send` semantics, that is: `impl AllowAtomic` has
to be safe to be transferred across thread boundaries.

Suggested-by: Alice Ryhl <aliceryhl@google.com>
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
---
 rust/kernel/sync/atomic.rs         | 48 ++++++++++++++++++++++++++++++
 rust/kernel/sync/atomic/generic.rs | 16 ++++++++--
 2 files changed, 61 insertions(+), 3 deletions(-)

diff --git a/rust/kernel/sync/atomic.rs b/rust/kernel/sync/atomic.rs
index 829511f4d582..70920146935f 100644
--- a/rust/kernel/sync/atomic.rs
+++ b/rust/kernel/sync/atomic.rs
@@ -114,6 +114,22 @@ fn delta_into_repr(d: Self::Delta) -> Self::Repr {
         d as Self::Repr
     }
 }
+// SAFETY: A `*mut T` has the same size and the alignment as `i64` for 64bit and the same as `i32`
+// for 32bit. And it's safe to transfer the ownership of a pointer value to another thread.
+unsafe impl<T> generic::AllowAtomic for *mut T {
+    #[cfg(CONFIG_64BIT)]
+    type Repr = i64;
+    #[cfg(not(CONFIG_64BIT))]
+    type Repr = i32;
+
+    fn into_repr(self) -> Self::Repr {
+        self as Self::Repr
+    }
+
+    fn from_repr(repr: Self::Repr) -> Self {
+        repr as Self
+    }
+}
 
 use crate::macros::kunit_tests;
 
@@ -139,6 +155,9 @@ fn atomic_basic_tests() {
 
             assert_eq!(v, x.load(Relaxed));
         });
+
+        let x = Atomic::new(core::ptr::null_mut::<i32>());
+        assert!(x.load(Relaxed).is_null());
     }
 
     #[test]
@@ -182,4 +201,33 @@ fn atomic_arithmetic_tests() {
             assert_eq!(v + 25, x.load(Relaxed));
         });
     }
+
+    #[test]
+    fn atomic_ptr_tests() -> crate::error::Result {
+        use crate::alloc::{flags::GFP_KERNEL, KBox};
+        use core::ptr;
+
+        let x = Atomic::new(ptr::null_mut::<i32>());
+
+        assert!(x.load(Relaxed).is_null());
+
+        let new = KBox::new(42, GFP_KERNEL)?;
+        x.store(ptr::from_mut(KBox::leak(new)), Release);
+
+        let ptr = x.load(Relaxed);
+        assert!(!ptr.is_null());
+
+        // SAFETY: `ptr` is a valid pointer from `KBox::leak()` and the address dependency
+        // guarantees observation of the initialization of `KBox`.
+        assert_eq!(42, unsafe { ptr.read_volatile() });
+
+        x.xchg(ptr::null_mut(), Relaxed);
+        assert!(x.load(Relaxed).is_null());
+
+        // SAFETY: `ptr` is a valid pointer from `KBox::leak()` and no one is currently referencing
+        // the pointer, so it's safety to convert the ownership back to a `KBox`.
+        drop(unsafe { KBox::from_raw(ptr) });
+
+        Ok(())
+    }
 }
diff --git a/rust/kernel/sync/atomic/generic.rs b/rust/kernel/sync/atomic/generic.rs
index 8c5bd90b2619..f496774c1686 100644
--- a/rust/kernel/sync/atomic/generic.rs
+++ b/rust/kernel/sync/atomic/generic.rs
@@ -18,6 +18,10 @@
 #[repr(transparent)]
 pub struct Atomic<T: AllowAtomic>(Opaque<T>);
 
+// SAFETY: `Atomic<T>` is safe to send between execution contexts, because `T` is `AllowAtomic` and
+// `AllowAtomic`'s safety requirement guarantees that.
+unsafe impl<T: AllowAtomic> Send for Atomic<T> {}
+
 // SAFETY: `Atomic<T>` is safe to share among execution contexts because all accesses are atomic.
 unsafe impl<T: AllowAtomic> Sync for Atomic<T> {}
 
@@ -30,8 +34,13 @@ unsafe impl<T: AllowAtomic> Sync for Atomic<T> {}
 ///
 /// # Safety
 ///
-/// [`Self`] must have the same size and alignment as [`Self::Repr`].
-pub unsafe trait AllowAtomic: Sized + Send + Copy {
+/// - [`Self`] must have the same size and alignment as [`Self::Repr`].
+/// - The implementer must guarantee it's safe to transfer ownership from one execution context to
+///   another, this means it has to be a [`Send`], but because `*mut T` is not [`Send`] and that's
+///   the basic type needs to support atomic operations, so this safety requirement is added to
+///   [`AllowAtomic`] trait. This safety requirement is automatically satisfied if the type is a
+///   [`Send`].
+pub unsafe trait AllowAtomic: Sized + Copy {
     /// The backing atomic implementation type.
     type Repr: AtomicImpl;
 
@@ -44,7 +53,8 @@ pub unsafe trait AllowAtomic: Sized + Send + Copy {
 
 // An `AtomicImpl` is automatically an `AllowAtomic`.
 //
-// SAFETY: `T::Repr` is `Self` (i.e. `T`), so they have the same size and alignment.
+// SAFETY: `T::Repr` is `Self` (i.e. `T`), so they have the same size and alignment. And all
+// `AtomicImpl` types are `Send`.
 unsafe impl<T: AtomicImpl> AllowAtomic for T {
     type Repr = Self;
 
-- 
2.39.5 (Apple Git-154)


  parent reply	other threads:[~2025-06-18 16:49 UTC|newest]

Thread overview: 82+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-06-18 16:49 [PATCH v5 00/10] LKMM generic atomics in Rust Boqun Feng
2025-06-18 16:49 ` [PATCH v5 01/10] rust: Introduce atomic API helpers Boqun Feng
2025-06-26  8:44   ` Andreas Hindborg
2025-06-27 14:00     ` Boqun Feng
2025-06-18 16:49 ` [PATCH v5 02/10] rust: sync: Add basic atomic operation mapping framework Boqun Feng
2025-06-26  8:50   ` Andreas Hindborg
2025-06-26 10:17   ` Andreas Hindborg
2025-06-27 14:30     ` Boqun Feng
2025-06-18 16:49 ` [PATCH v5 03/10] rust: sync: atomic: Add ordering annotation types Boqun Feng
2025-06-19 10:31   ` Peter Zijlstra
2025-06-19 12:19     ` Alice Ryhl
2025-06-19 13:29     ` Boqun Feng
2025-06-19 14:32       ` Peter Zijlstra
2025-06-19 15:00         ` Boqun Feng
2025-06-19 15:10           ` Peter Zijlstra
2025-06-19 15:15             ` Boqun Feng
2025-06-19 18:04           ` Alan Stern
2025-06-21 11:18   ` Gary Guo
2025-06-23  2:48     ` Boqun Feng
2025-06-26 12:36   ` Andreas Hindborg
2025-06-27 14:34     ` Boqun Feng
2025-06-27 14:44       ` Boqun Feng
2025-06-18 16:49 ` [PATCH v5 04/10] rust: sync: atomic: Add generic atomics Boqun Feng
2025-06-21 11:32   ` Gary Guo
2025-06-23  5:19     ` Boqun Feng
2025-06-23 11:54       ` Benno Lossin
2025-06-23 12:58         ` Boqun Feng
2025-06-23 18:30       ` Gary Guo
2025-06-23 19:09         ` Boqun Feng
2025-06-23 23:27           ` Benno Lossin
2025-06-24 16:35             ` Boqun Feng
2025-06-26 13:54               ` Benno Lossin
2025-07-04 21:22                 ` Boqun Feng
2025-07-04 22:05                   ` Benno Lossin
2025-07-04 22:30                     ` Boqun Feng
2025-07-04 22:49                       ` Benno Lossin
2025-07-04 23:21                         ` Boqun Feng
2025-07-04 20:25           ` Boqun Feng
2025-07-04 20:45             ` Benno Lossin
2025-07-04 21:17               ` Boqun Feng
2025-07-04 22:38                 ` Benno Lossin
2025-07-04 23:21                   ` Boqun Feng
2025-07-05  8:04                     ` Benno Lossin
2025-07-05 15:38                       ` Boqun Feng
2025-07-05 21:43                         ` Benno Lossin
2025-06-26 12:15   ` Andreas Hindborg
2025-06-27 15:01     ` Boqun Feng
2025-06-30  9:52       ` Andreas Hindborg
2025-06-30 14:44         ` Alan Stern
2025-07-01  8:54           ` Andreas Hindborg
2025-07-01 14:50             ` Boqun Feng
2025-07-02  8:33               ` Andreas Hindborg
2025-06-18 16:49 ` [PATCH v5 05/10] rust: sync: atomic: Add atomic {cmp,}xchg operations Boqun Feng
2025-06-21 11:37   ` Gary Guo
2025-06-23  5:23     ` Boqun Feng
2025-06-26 13:12   ` Andreas Hindborg
2025-06-28  3:03     ` Boqun Feng
2025-06-30 10:16       ` Andreas Hindborg
2025-06-30 14:51         ` Alan Stern
2025-06-30 15:12           ` Boqun Feng
2025-06-27  8:58   ` Benno Lossin
2025-06-27 13:53     ` Boqun Feng
2025-06-28  6:12       ` Benno Lossin
2025-06-28  7:31         ` Boqun Feng
2025-06-28  8:00           ` Benno Lossin
2025-06-30 15:24             ` Boqun Feng
2025-06-30 15:27               ` Boqun Feng
2025-06-30 15:50               ` Benno Lossin
2025-06-18 16:49 ` [PATCH v5 06/10] rust: sync: atomic: Add the framework of arithmetic operations Boqun Feng
2025-06-21 11:41   ` Gary Guo
2025-06-26 12:39   ` Andreas Hindborg
2025-06-28  3:04     ` Boqun Feng
2025-06-18 16:49 ` [PATCH v5 07/10] rust: sync: atomic: Add Atomic<u{32,64}> Boqun Feng
2025-06-26 12:47   ` Andreas Hindborg
2025-06-18 16:49 ` [PATCH v5 08/10] rust: sync: atomic: Add Atomic<{usize,isize}> Boqun Feng
2025-06-26 12:49   ` Andreas Hindborg
2025-06-18 16:49 ` Boqun Feng [this message]
2025-06-18 16:49 ` [PATCH v5 10/10] rust: sync: Add memory barriers Boqun Feng
2025-06-26 13:36   ` Andreas Hindborg
2025-06-28  3:42     ` Boqun Feng
2025-06-30  9:54       ` Andreas Hindborg
2025-06-18 20:22 ` [PATCH v5 00/10] LKMM generic atomics in Rust Alice Ryhl

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=20250618164934.19817-10-boqun.feng@gmail.com \
    --to=boqun.feng@gmail.com \
    --cc=a.hindborg@kernel.org \
    --cc=alex.gaynor@gmail.com \
    --cc=aliceryhl@google.com \
    --cc=bjorn3_gh@protonmail.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=lossin@kernel.org \
    --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=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).