[PATCH 4/5] rust: sync: atomic: Add Atomic<*mut T> support

Boqun Feng posted 5 patches 3 weeks, 1 day ago
[PATCH 4/5] rust: sync: atomic: Add Atomic<*mut T> support
Posted by Boqun Feng 3 weeks, 1 day ago
Atomic pointer support is an important piece of synchronization
algorithm, e.g. RCU, hence provide the support for that.

Note that instead of relying on atomic_long or the implementation of
`Atomic<usize>`, a new set of helpers (atomic_ptr_*) is introduced for
atomic pointer specifically, this is because ptr2int casting would
lose the provenance of a pointer and even though in theory there are a
few tricks the provenance can be restored, it'll still be a simpler
implementation if C could provide atomic pointers directly. The side
effects of this approach are: we don't have the arithmetic and logical
operations for pointers yet and the current implementation only works
on ARCH_SUPPORTS_ATOMIC_RMW architectures, but these are implementation
issues and can be added later.

Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
---
 rust/helpers/atomic_ext.c            |  3 +++
 rust/kernel/sync/atomic.rs           | 12 +++++++++++-
 rust/kernel/sync/atomic/internal.rs  | 21 +++++++++++++++------
 rust/kernel/sync/atomic/predefine.rs | 23 +++++++++++++++++++++++
 4 files changed, 52 insertions(+), 7 deletions(-)

diff --git a/rust/helpers/atomic_ext.c b/rust/helpers/atomic_ext.c
index 240218e2e708..c267d5190529 100644
--- a/rust/helpers/atomic_ext.c
+++ b/rust/helpers/atomic_ext.c
@@ -36,6 +36,7 @@ __rust_helper void rust_helper_atomic_##tname##_set_release(type *ptr, type val)
 
 GEN_READ_SET_HELPERS(i8, s8)
 GEN_READ_SET_HELPERS(i16, s16)
+GEN_READ_SET_HELPERS(ptr, const void *)
 
 /*
  * xchg helpers depend on ARCH_SUPPORTS_ATOMIC_RMW and on the
@@ -59,6 +60,7 @@ rust_helper_atomic_##tname##_xchg##suffix(type *ptr, type new)			\
 
 GEN_XCHG_HELPERS(i8, s8)
 GEN_XCHG_HELPERS(i16, s16)
+GEN_XCHG_HELPERS(ptr, const void *)
 
 /*
  * try_cmpxchg helpers depend on ARCH_SUPPORTS_ATOMIC_RMW and on the
@@ -82,3 +84,4 @@ rust_helper_atomic_##tname##_try_cmpxchg##suffix(type *ptr, type *old, type new)
 
 GEN_TRY_CMPXCHG_HELPERS(i8, s8)
 GEN_TRY_CMPXCHG_HELPERS(i16, s16)
+GEN_TRY_CMPXCHG_HELPERS(ptr, const void *)
diff --git a/rust/kernel/sync/atomic.rs b/rust/kernel/sync/atomic.rs
index 4aebeacb961a..4d2a5228c2e4 100644
--- a/rust/kernel/sync/atomic.rs
+++ b/rust/kernel/sync/atomic.rs
@@ -51,6 +51,10 @@
 #[repr(transparent)]
 pub struct Atomic<T: AtomicType>(AtomicRepr<T::Repr>);
 
+// SAFETY: `Atomic<T>` is safe to transfer between execution contexts because of the safety
+// requirement of `AtomicType`.
+unsafe impl<T: AtomicType> Send for Atomic<T> {}
+
 // SAFETY: `Atomic<T>` is safe to share among execution contexts because all accesses are atomic.
 unsafe impl<T: AtomicType> Sync for Atomic<T> {}
 
@@ -68,6 +72,11 @@ unsafe impl<T: AtomicType> Sync for Atomic<T> {}
 ///
 /// - [`Self`] must have the same size and alignment as [`Self::Repr`].
 /// - [`Self`] must be [round-trip transmutable] to  [`Self::Repr`].
+/// - [`Self`] must be safe to transfer between execution contexts, if it's [`Send`], this is
+///   automatically satisfied. The exception is pointer types that are even though marked as
+///   `!Send` (e.g. raw pointers and [`NonNull<T>`]) but requiring `unsafe` to do anything
+///   meaningful on them. This is because transferring pointer values between execution contexts is
+///   safe as long as the actual `unsafe` dereferencing is justified.
 ///
 /// Note that this is more relaxed than requiring the bi-directional transmutability (i.e.
 /// [`transmute()`] is always sound between `U` and `T`) because of the support for atomic
@@ -108,7 +117,8 @@ unsafe impl<T: AtomicType> Sync for Atomic<T> {}
 /// [`transmute()`]: core::mem::transmute
 /// [round-trip transmutable]: AtomicType#round-trip-transmutability
 /// [Examples]: AtomicType#examples
-pub unsafe trait AtomicType: Sized + Send + Copy {
+/// [`NonNull<T>`]: core::ptr::NonNull
+pub unsafe trait AtomicType: Sized + Copy {
     /// The backing atomic implementation type.
     type Repr: AtomicImpl;
 }
diff --git a/rust/kernel/sync/atomic/internal.rs b/rust/kernel/sync/atomic/internal.rs
index 0dac58bca2b3..93f5a7846645 100644
--- a/rust/kernel/sync/atomic/internal.rs
+++ b/rust/kernel/sync/atomic/internal.rs
@@ -7,6 +7,7 @@
 use crate::bindings;
 use crate::macros::paste;
 use core::cell::UnsafeCell;
+use ffi::c_void;
 
 mod private {
     /// Sealed trait marker to disable customized impls on atomic implementation traits.
@@ -14,10 +15,11 @@ pub trait Sealed {}
 }
 
 // The C side supports atomic primitives only for `i32` and `i64` (`atomic_t` and `atomic64_t`),
-// while the Rust side also layers provides atomic support for `i8` and `i16`
-// on top of lower-level C primitives.
+// while the Rust side also provides atomic support for `i8`, `i16` and `*const c_void` on top of
+// lower-level C primitives.
 impl private::Sealed for i8 {}
 impl private::Sealed for i16 {}
+impl private::Sealed for *const c_void {}
 impl private::Sealed for i32 {}
 impl private::Sealed for i64 {}
 
@@ -26,10 +28,10 @@ impl private::Sealed for i64 {}
 /// This trait is sealed, and only types that map directly to the C side atomics
 /// or can be implemented with lower-level C primitives are allowed to implement this:
 ///
-/// - `i8` and `i16` are implemented with lower-level C primitives.
+/// - `i8`, `i16` and `*const c_void` are implemented with lower-level C primitives.
 /// - `i32` map to `atomic_t`
 /// - `i64` map to `atomic64_t`
-pub trait AtomicImpl: Sized + Send + Copy + private::Sealed {
+pub trait AtomicImpl: Sized + Copy + private::Sealed {
     /// The type of the delta in arithmetic or logical operations.
     ///
     /// For example, in `atomic_add(ptr, v)`, it's the type of `v`. Usually it's the same type of
@@ -51,6 +53,13 @@ impl AtomicImpl for i16 {
     type Delta = Self;
 }
 
+// The current helpers of load/store uses `{WRITE,READ}_ONCE()` hence the atomicity is only
+// guaranteed against read-modify-write operations if the architecture supports native atomic RmW.
+#[cfg(CONFIG_ARCH_SUPPORTS_ATOMIC_RMW)]
+impl AtomicImpl for *const c_void {
+    type Delta = isize;
+}
+
 // `atomic_t` implements atomic operations on `i32`.
 impl AtomicImpl for i32 {
     type Delta = Self;
@@ -262,7 +271,7 @@ macro_rules! declare_and_impl_atomic_methods {
 }
 
 declare_and_impl_atomic_methods!(
-    [ i8 => atomic_i8, i16 => atomic_i16, i32 => atomic, i64 => atomic64 ]
+    [ i8 => atomic_i8, i16 => atomic_i16, *const c_void => atomic_ptr, i32 => atomic, i64 => atomic64 ]
     /// Basic atomic operations
     pub trait AtomicBasicOps {
         /// Atomic read (load).
@@ -280,7 +289,7 @@ fn set[release](a: &AtomicRepr<Self>, v: Self) {
 );
 
 declare_and_impl_atomic_methods!(
-    [ i8 => atomic_i8, i16 => atomic_i16, i32 => atomic, i64 => atomic64 ]
+    [ i8 => atomic_i8, i16 => atomic_i16, *const c_void => atomic_ptr, i32 => atomic, i64 => atomic64 ]
     /// Exchange and compare-and-exchange atomic operations
     pub trait AtomicExchangeOps {
         /// Atomic exchange.
diff --git a/rust/kernel/sync/atomic/predefine.rs b/rust/kernel/sync/atomic/predefine.rs
index 42067c6a266c..1a4670d225b5 100644
--- a/rust/kernel/sync/atomic/predefine.rs
+++ b/rust/kernel/sync/atomic/predefine.rs
@@ -4,6 +4,7 @@
 
 use crate::static_assert;
 use core::mem::{align_of, size_of};
+use ffi::c_void;
 
 // Ensure size and alignment requirements are checked.
 static_assert!(size_of::<bool>() == size_of::<i8>());
@@ -28,6 +29,16 @@ unsafe impl super::AtomicType for i16 {
     type Repr = i16;
 }
 
+// SAFETY:
+//
+// - `*mut T` has the same size and alignment with `*const c_void`, and is round-trip
+//   transmutable to `*const c_void`.
+// - `*mut T` is safe to transfer between execution contexts. See the safety requirement of
+//   [`AtomicType`].
+unsafe impl<T: Sized> super::AtomicType for *mut T {
+    type Repr = *const c_void;
+}
+
 // SAFETY: `i32` has the same size and alignment with itself, and is round-trip transmutable to
 // itself.
 unsafe impl super::AtomicType for i32 {
@@ -215,4 +226,16 @@ fn atomic_bool_tests() {
         assert_eq!(false, x.load(Relaxed));
         assert_eq!(Ok(false), x.cmpxchg(false, true, Full));
     }
+
+    #[test]
+    fn atomic_ptr_tests() {
+        let mut v = 42;
+        let mut u = 43;
+        let x = Atomic::new(&raw mut v);
+
+        assert_eq!(x.load(Acquire), &raw mut v);
+        assert_eq!(x.cmpxchg(&raw mut u, &raw mut u, Relaxed), Err(&raw mut v));
+        assert_eq!(x.cmpxchg(&raw mut v, &raw mut u, Relaxed), Ok(&raw mut v));
+        assert_eq!(x.load(Relaxed), &raw mut u);
+    }
 }
-- 
2.51.0
Re: [PATCH 4/5] rust: sync: atomic: Add Atomic<*mut T> support
Posted by FUJITA Tomonori 2 weeks, 6 days ago
On Sat, 17 Jan 2026 20:22:42 +0800
Boqun Feng <boqun.feng@gmail.com> wrote:

> Atomic pointer support is an important piece of synchronization
> algorithm, e.g. RCU, hence provide the support for that.
> 
> Note that instead of relying on atomic_long or the implementation of
> `Atomic<usize>`, a new set of helpers (atomic_ptr_*) is introduced for
> atomic pointer specifically, this is because ptr2int casting would
> lose the provenance of a pointer and even though in theory there are a
> few tricks the provenance can be restored, it'll still be a simpler
> implementation if C could provide atomic pointers directly. The side
> effects of this approach are: we don't have the arithmetic and logical
> operations for pointers yet and the current implementation only works
> on ARCH_SUPPORTS_ATOMIC_RMW architectures, but these are implementation
> issues and can be added later.
> 
> Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
> ---
>  rust/helpers/atomic_ext.c            |  3 +++
>  rust/kernel/sync/atomic.rs           | 12 +++++++++++-
>  rust/kernel/sync/atomic/internal.rs  | 21 +++++++++++++++------
>  rust/kernel/sync/atomic/predefine.rs | 23 +++++++++++++++++++++++
>  4 files changed, 52 insertions(+), 7 deletions(-)

Reviewed-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
Re: [PATCH 4/5] rust: sync: atomic: Add Atomic<*mut T> support
Posted by Dirk Behme 3 weeks ago
On 17.01.26 13:22, Boqun Feng wrote:
> Atomic pointer support is an important piece of synchronization
> algorithm, e.g. RCU, hence provide the support for that.
> 
> Note that instead of relying on atomic_long or the implementation of
> `Atomic<usize>`, a new set of helpers (atomic_ptr_*) is introduced for
> atomic pointer specifically, this is because ptr2int casting would
> lose the provenance of a pointer and even though in theory there are a
> few tricks the provenance can be restored, it'll still be a simpler
> implementation if C could provide atomic pointers directly. The side
> effects of this approach are: we don't have the arithmetic and logical
> operations for pointers yet and the current implementation only works
> on ARCH_SUPPORTS_ATOMIC_RMW architectures, but these are implementation
> issues and can be added later.
> 
> Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
> ---
>  rust/helpers/atomic_ext.c            |  3 +++
>  rust/kernel/sync/atomic.rs           | 12 +++++++++++-
>  rust/kernel/sync/atomic/internal.rs  | 21 +++++++++++++++------
>  rust/kernel/sync/atomic/predefine.rs | 23 +++++++++++++++++++++++
>  4 files changed, 52 insertions(+), 7 deletions(-)
> 
> diff --git a/rust/helpers/atomic_ext.c b/rust/helpers/atomic_ext.c
> index 240218e2e708..c267d5190529 100644
> --- a/rust/helpers/atomic_ext.c
> +++ b/rust/helpers/atomic_ext.c
> @@ -36,6 +36,7 @@ __rust_helper void rust_helper_atomic_##tname##_set_release(type *ptr, type val)
>  
>  GEN_READ_SET_HELPERS(i8, s8)
>  GEN_READ_SET_HELPERS(i16, s16)
> +GEN_READ_SET_HELPERS(ptr, const void *)
>  
>  /*
>   * xchg helpers depend on ARCH_SUPPORTS_ATOMIC_RMW and on the
> @@ -59,6 +60,7 @@ rust_helper_atomic_##tname##_xchg##suffix(type *ptr, type new)			\
>  
>  GEN_XCHG_HELPERS(i8, s8)
>  GEN_XCHG_HELPERS(i16, s16)
> +GEN_XCHG_HELPERS(ptr, const void *)
>  
>  /*
>   * try_cmpxchg helpers depend on ARCH_SUPPORTS_ATOMIC_RMW and on the
> @@ -82,3 +84,4 @@ rust_helper_atomic_##tname##_try_cmpxchg##suffix(type *ptr, type *old, type new)
>  
>  GEN_TRY_CMPXCHG_HELPERS(i8, s8)
>  GEN_TRY_CMPXCHG_HELPERS(i16, s16)
> +GEN_TRY_CMPXCHG_HELPERS(ptr, const void *)
> diff --git a/rust/kernel/sync/atomic.rs b/rust/kernel/sync/atomic.rs
> index 4aebeacb961a..4d2a5228c2e4 100644
> --- a/rust/kernel/sync/atomic.rs
> +++ b/rust/kernel/sync/atomic.rs
> @@ -51,6 +51,10 @@
>  #[repr(transparent)]
>  pub struct Atomic<T: AtomicType>(AtomicRepr<T::Repr>);
>  
> +// SAFETY: `Atomic<T>` is safe to transfer between execution contexts because of the safety
> +// requirement of `AtomicType`.
> +unsafe impl<T: AtomicType> Send for Atomic<T> {}
> +
>  // SAFETY: `Atomic<T>` is safe to share among execution contexts because all accesses are atomic.
>  unsafe impl<T: AtomicType> Sync for Atomic<T> {}
>  
> @@ -68,6 +72,11 @@ unsafe impl<T: AtomicType> Sync for Atomic<T> {}
>  ///
>  /// - [`Self`] must have the same size and alignment as [`Self::Repr`].
>  /// - [`Self`] must be [round-trip transmutable] to  [`Self::Repr`].
> +/// - [`Self`] must be safe to transfer between execution contexts, if it's [`Send`], this is
> +///   automatically satisfied. The exception is pointer types that are even though marked as
> +///   `!Send` (e.g. raw pointers and [`NonNull<T>`]) but requiring `unsafe` to do anything
> +///   meaningful on them. This is because transferring pointer values between execution contexts is
> +///   safe as long as the actual `unsafe` dereferencing is justified.
>  ///
>  /// Note that this is more relaxed than requiring the bi-directional transmutability (i.e.
>  /// [`transmute()`] is always sound between `U` and `T`) because of the support for atomic
> @@ -108,7 +117,8 @@ unsafe impl<T: AtomicType> Sync for Atomic<T> {}
>  /// [`transmute()`]: core::mem::transmute
>  /// [round-trip transmutable]: AtomicType#round-trip-transmutability
>  /// [Examples]: AtomicType#examples
> -pub unsafe trait AtomicType: Sized + Send + Copy {
> +/// [`NonNull<T>`]: core::ptr::NonNull
> +pub unsafe trait AtomicType: Sized + Copy {
>      /// The backing atomic implementation type.
>      type Repr: AtomicImpl;
>  }
> diff --git a/rust/kernel/sync/atomic/internal.rs b/rust/kernel/sync/atomic/internal.rs
> index 0dac58bca2b3..93f5a7846645 100644
> --- a/rust/kernel/sync/atomic/internal.rs
> +++ b/rust/kernel/sync/atomic/internal.rs
> @@ -7,6 +7,7 @@
>  use crate::bindings;
>  use crate::macros::paste;
>  use core::cell::UnsafeCell;
> +use ffi::c_void;
>  
>  mod private {
>      /// Sealed trait marker to disable customized impls on atomic implementation traits.
> @@ -14,10 +15,11 @@ pub trait Sealed {}
>  }
>  
>  // The C side supports atomic primitives only for `i32` and `i64` (`atomic_t` and `atomic64_t`),
> -// while the Rust side also layers provides atomic support for `i8` and `i16`
> -// on top of lower-level C primitives.
> +// while the Rust side also provides atomic support for `i8`, `i16` and `*const c_void` on top of
> +// lower-level C primitives.
>  impl private::Sealed for i8 {}
>  impl private::Sealed for i16 {}
> +impl private::Sealed for *const c_void {}
>  impl private::Sealed for i32 {}
>  impl private::Sealed for i64 {}
>  
> @@ -26,10 +28,10 @@ impl private::Sealed for i64 {}
>  /// This trait is sealed, and only types that map directly to the C side atomics
>  /// or can be implemented with lower-level C primitives are allowed to implement this:
>  ///
> -/// - `i8` and `i16` are implemented with lower-level C primitives.
> +/// - `i8`, `i16` and `*const c_void` are implemented with lower-level C primitives.
>  /// - `i32` map to `atomic_t`
>  /// - `i64` map to `atomic64_t`
> -pub trait AtomicImpl: Sized + Send + Copy + private::Sealed {
> +pub trait AtomicImpl: Sized + Copy + private::Sealed {
>      /// The type of the delta in arithmetic or logical operations.
>      ///
>      /// For example, in `atomic_add(ptr, v)`, it's the type of `v`. Usually it's the same type of
> @@ -51,6 +53,13 @@ impl AtomicImpl for i16 {
>      type Delta = Self;
>  }
>  
> +// The current helpers of load/store uses `{WRITE,READ}_ONCE()` hence the atomicity is only

uses -> use ?

> +// guaranteed against read-modify-write operations if the architecture supports native atomic RmW.
> +#[cfg(CONFIG_ARCH_SUPPORTS_ATOMIC_RMW)]
> +impl AtomicImpl for *const c_void {
> +    type Delta = isize;
> +}

Are all users of this guarded with CONFIG_ARCH_SUPPORTS_ATOMIC_RMW as
well? Or do we want (need?) to cover the
non-CONFIG_ARCH_SUPPORTS_ATOMIC_RMW cases where someone tries to use
this as well?

Best regards

Dirk
Re: [PATCH 4/5] rust: sync: atomic: Add Atomic<*mut T> support
Posted by Boqun Feng 3 weeks ago
On Sun, Jan 18, 2026 at 09:38:36AM +0100, Dirk Behme wrote:
[...]
> >  
> > +// The current helpers of load/store uses `{WRITE,READ}_ONCE()` hence the atomicity is only
> 
> uses -> use ?
> 

Will fix, thank you!

> > +// guaranteed against read-modify-write operations if the architecture supports native atomic RmW.
> > +#[cfg(CONFIG_ARCH_SUPPORTS_ATOMIC_RMW)]
> > +impl AtomicImpl for *const c_void {
> > +    type Delta = isize;
> > +}
> 
> Are all users of this guarded with CONFIG_ARCH_SUPPORTS_ATOMIC_RMW as
> well? Or do we want (need?) to cover the

No, the users don't need to guard with CONFIG_ARCH_SUPPORTS_ATOMIC_RMW,
the purpose of this #[cfg] is to avoid surprise that when
CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=n arch supports Rust, when that happens,
we need to add the support to the helpers of i8/i16/ptr.

> non-CONFIG_ARCH_SUPPORTS_ATOMIC_RMW cases where someone tries to use

Note that these arches are very rare, so we might not have any problem
for a while.

Regards,
Boqun

> this as well?
> 
> Best regards
> 
> Dirk
> 
> 
>
Re: [PATCH 4/5] rust: sync: atomic: Add Atomic<*mut T> support
Posted by Boqun Feng 3 weeks ago
On Sun, Jan 18, 2026 at 10:57:37PM +0800, Boqun Feng wrote:
> On Sun, Jan 18, 2026 at 09:38:36AM +0100, Dirk Behme wrote:
> [...]
> > >  
> > > +// The current helpers of load/store uses `{WRITE,READ}_ONCE()` hence the atomicity is only
> > 
> > uses -> use ?
> > 
> 
> Will fix, thank you!
> 
> > > +// guaranteed against read-modify-write operations if the architecture supports native atomic RmW.
> > > +#[cfg(CONFIG_ARCH_SUPPORTS_ATOMIC_RMW)]
> > > +impl AtomicImpl for *const c_void {
> > > +    type Delta = isize;
> > > +}
> > 
> > Are all users of this guarded with CONFIG_ARCH_SUPPORTS_ATOMIC_RMW as
> > well? Or do we want (need?) to cover the
> 
> No, the users don't need to guard with CONFIG_ARCH_SUPPORTS_ATOMIC_RMW,
> the purpose of this #[cfg] is to avoid surprise that when
> CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=n arch supports Rust, when that happens,
> we need to add the support to the helpers of i8/i16/ptr.
> 

Hmm... I guess at this moment, I probably should do

#[cfg(not(CONFIG_ARCH_SUPPORTS_ATOMIC_RMW))]
static_assert!(false,
               "Support of architectures that don't have native atomic needs to implement helpers in atomic_ext.c");

I can add a patch in the next version if it looks good to everyone.

Regards,
Boqun

> > non-CONFIG_ARCH_SUPPORTS_ATOMIC_RMW cases where someone tries to use
> 
> Note that these arches are very rare, so we might not have any problem
> for a while.
> 
> Regards,
> Boqun
> 
> > this as well?
> > 
> > Best regards
> > 
> > Dirk
> > 
> > 
> >
Re: [PATCH 4/5] rust: sync: atomic: Add Atomic<*mut T> support
Posted by Benno Lossin 2 weeks, 6 days ago
On Sun Jan 18, 2026 at 4:05 PM CET, Boqun Feng wrote:
> On Sun, Jan 18, 2026 at 10:57:37PM +0800, Boqun Feng wrote:
>> On Sun, Jan 18, 2026 at 09:38:36AM +0100, Dirk Behme wrote:
>> [...]
>> > >  
>> > > +// The current helpers of load/store uses `{WRITE,READ}_ONCE()` hence the atomicity is only
>> > 
>> > uses -> use ?
>> > 
>> 
>> Will fix, thank you!
>> 
>> > > +// guaranteed against read-modify-write operations if the architecture supports native atomic RmW.
>> > > +#[cfg(CONFIG_ARCH_SUPPORTS_ATOMIC_RMW)]
>> > > +impl AtomicImpl for *const c_void {
>> > > +    type Delta = isize;
>> > > +}
>> > 
>> > Are all users of this guarded with CONFIG_ARCH_SUPPORTS_ATOMIC_RMW as
>> > well? Or do we want (need?) to cover the
>> 
>> No, the users don't need to guard with CONFIG_ARCH_SUPPORTS_ATOMIC_RMW,
>> the purpose of this #[cfg] is to avoid surprise that when
>> CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=n arch supports Rust, when that happens,
>> we need to add the support to the helpers of i8/i16/ptr.
>> 
>
> Hmm... I guess at this moment, I probably should do
>
> #[cfg(not(CONFIG_ARCH_SUPPORTS_ATOMIC_RMW))]
> static_assert!(false,
>                "Support of architectures that don't have native atomic needs to implement helpers in atomic_ext.c");
>
> I can add a patch in the next version if it looks good to everyone.

I think this is a great idea!

By the way, did you know about `cfg!` [1]?:

    static_assert!(
        cfg!(CONFIG_ARCH_SUPPORTS_ATOMIC_RMW),
        "Support of architectures that don't have native atomic needs to implement helpers in atomic_ext.c",
    );


[1]: https://doc.rust-lang.org/core/macro.cfg.html

Cheers,
Benno
Re: [PATCH 4/5] rust: sync: atomic: Add Atomic<*mut T> support
Posted by Boqun Feng 2 weeks, 6 days ago
On Sun, Jan 18, 2026 at 08:59:09PM +0100, Benno Lossin wrote:
> On Sun Jan 18, 2026 at 4:05 PM CET, Boqun Feng wrote:
> > On Sun, Jan 18, 2026 at 10:57:37PM +0800, Boqun Feng wrote:
> >> On Sun, Jan 18, 2026 at 09:38:36AM +0100, Dirk Behme wrote:
> >> [...]
> >> > >  
> >> > > +// The current helpers of load/store uses `{WRITE,READ}_ONCE()` hence the atomicity is only
> >> > 
> >> > uses -> use ?
> >> > 
> >> 
> >> Will fix, thank you!
> >> 
> >> > > +// guaranteed against read-modify-write operations if the architecture supports native atomic RmW.
> >> > > +#[cfg(CONFIG_ARCH_SUPPORTS_ATOMIC_RMW)]
> >> > > +impl AtomicImpl for *const c_void {
> >> > > +    type Delta = isize;
> >> > > +}
> >> > 
> >> > Are all users of this guarded with CONFIG_ARCH_SUPPORTS_ATOMIC_RMW as
> >> > well? Or do we want (need?) to cover the
> >> 
> >> No, the users don't need to guard with CONFIG_ARCH_SUPPORTS_ATOMIC_RMW,
> >> the purpose of this #[cfg] is to avoid surprise that when
> >> CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=n arch supports Rust, when that happens,
> >> we need to add the support to the helpers of i8/i16/ptr.
> >> 
> >
> > Hmm... I guess at this moment, I probably should do
> >
> > #[cfg(not(CONFIG_ARCH_SUPPORTS_ATOMIC_RMW))]
> > static_assert!(false,
> >                "Support of architectures that don't have native atomic needs to implement helpers in atomic_ext.c");
> >
> > I can add a patch in the next version if it looks good to everyone.
> 
> I think this is a great idea!
> 
> By the way, did you know about `cfg!` [1]?:
> 
>     static_assert!(
>         cfg!(CONFIG_ARCH_SUPPORTS_ATOMIC_RMW),
>         "Support of architectures that don't have native atomic needs to implement helpers in atomic_ext.c",
>     );
> 

Even better! Thanks. I've added a new patch that converts the existing
#[cfg] on impl blocks to this. I've added Suggested-by of both you and
Dirk ;-)

Regards,
Boqun

> 
> [1]: https://doc.rust-lang.org/core/macro.cfg.html
> 
> Cheers,
> Benno
Re: [PATCH 4/5] rust: sync: atomic: Add Atomic<*mut T> support
Posted by Gary Guo 3 weeks, 1 day ago
On Sat Jan 17, 2026 at 12:22 PM GMT, Boqun Feng wrote:
> Atomic pointer support is an important piece of synchronization
> algorithm, e.g. RCU, hence provide the support for that.
>
> Note that instead of relying on atomic_long or the implementation of
> `Atomic<usize>`, a new set of helpers (atomic_ptr_*) is introduced for
> atomic pointer specifically, this is because ptr2int casting would
> lose the provenance of a pointer and even though in theory there are a
> few tricks the provenance can be restored, it'll still be a simpler
> implementation if C could provide atomic pointers directly. The side
> effects of this approach are: we don't have the arithmetic and logical
> operations for pointers yet and the current implementation only works
> on ARCH_SUPPORTS_ATOMIC_RMW architectures, but these are implementation
> issues and can be added later.
>
> Signed-off-by: Boqun Feng <boqun.feng@gmail.com>

I am happy that this is now using dedicated helpers for pointers, and not going
through an intermediate integer which can lose provenance.

Some feedbacks below, but in general LGTM.

Reviewed-by: Gary Guo <gary@garyguo.net>

> ---
>  rust/helpers/atomic_ext.c            |  3 +++
>  rust/kernel/sync/atomic.rs           | 12 +++++++++++-
>  rust/kernel/sync/atomic/internal.rs  | 21 +++++++++++++++------
>  rust/kernel/sync/atomic/predefine.rs | 23 +++++++++++++++++++++++
>  4 files changed, 52 insertions(+), 7 deletions(-)
>
> diff --git a/rust/helpers/atomic_ext.c b/rust/helpers/atomic_ext.c
> index 240218e2e708..c267d5190529 100644
> --- a/rust/helpers/atomic_ext.c
> +++ b/rust/helpers/atomic_ext.c
> @@ -36,6 +36,7 @@ __rust_helper void rust_helper_atomic_##tname##_set_release(type *ptr, type val)
>  
>  GEN_READ_SET_HELPERS(i8, s8)
>  GEN_READ_SET_HELPERS(i16, s16)
> +GEN_READ_SET_HELPERS(ptr, const void *)
>  
>  /*
>   * xchg helpers depend on ARCH_SUPPORTS_ATOMIC_RMW and on the
> @@ -59,6 +60,7 @@ rust_helper_atomic_##tname##_xchg##suffix(type *ptr, type new)			\
>  
>  GEN_XCHG_HELPERS(i8, s8)
>  GEN_XCHG_HELPERS(i16, s16)
> +GEN_XCHG_HELPERS(ptr, const void *)
>  
>  /*
>   * try_cmpxchg helpers depend on ARCH_SUPPORTS_ATOMIC_RMW and on the
> @@ -82,3 +84,4 @@ rust_helper_atomic_##tname##_try_cmpxchg##suffix(type *ptr, type *old, type new)
>  
>  GEN_TRY_CMPXCHG_HELPERS(i8, s8)
>  GEN_TRY_CMPXCHG_HELPERS(i16, s16)
> +GEN_TRY_CMPXCHG_HELPERS(ptr, const void *)
> diff --git a/rust/kernel/sync/atomic.rs b/rust/kernel/sync/atomic.rs
> index 4aebeacb961a..4d2a5228c2e4 100644
> --- a/rust/kernel/sync/atomic.rs
> +++ b/rust/kernel/sync/atomic.rs
> @@ -51,6 +51,10 @@
>  #[repr(transparent)]
>  pub struct Atomic<T: AtomicType>(AtomicRepr<T::Repr>);
>  
> +// SAFETY: `Atomic<T>` is safe to transfer between execution contexts because of the safety
> +// requirement of `AtomicType`.
> +unsafe impl<T: AtomicType> Send for Atomic<T> {}
> +
>  // SAFETY: `Atomic<T>` is safe to share among execution contexts because all accesses are atomic.
>  unsafe impl<T: AtomicType> Sync for Atomic<T> {}
>  
> @@ -68,6 +72,11 @@ unsafe impl<T: AtomicType> Sync for Atomic<T> {}
>  ///
>  /// - [`Self`] must have the same size and alignment as [`Self::Repr`].
>  /// - [`Self`] must be [round-trip transmutable] to  [`Self::Repr`].
> +/// - [`Self`] must be safe to transfer between execution contexts, if it's [`Send`], this is
> +///   automatically satisfied. The exception is pointer types that are even though marked as
> +///   `!Send` (e.g. raw pointers and [`NonNull<T>`]) but requiring `unsafe` to do anything
> +///   meaningful on them. This is because transferring pointer values between execution contexts is
> +///   safe as long as the actual `unsafe` dereferencing is justified.

I think the discussion about `Send` on pointers should be moved to the `impl<T>
AtomicType for *mut T` side.

>  ///
>  /// Note that this is more relaxed than requiring the bi-directional transmutability (i.e.
>  /// [`transmute()`] is always sound between `U` and `T`) because of the support for atomic
> @@ -108,7 +117,8 @@ unsafe impl<T: AtomicType> Sync for Atomic<T> {}
>  /// [`transmute()`]: core::mem::transmute
>  /// [round-trip transmutable]: AtomicType#round-trip-transmutability
>  /// [Examples]: AtomicType#examples
> -pub unsafe trait AtomicType: Sized + Send + Copy {
> +/// [`NonNull<T>`]: core::ptr::NonNull
> +pub unsafe trait AtomicType: Sized + Copy {
>      /// The backing atomic implementation type.
>      type Repr: AtomicImpl;
>  }
> diff --git a/rust/kernel/sync/atomic/internal.rs b/rust/kernel/sync/atomic/internal.rs
> index 0dac58bca2b3..93f5a7846645 100644
> --- a/rust/kernel/sync/atomic/internal.rs
> +++ b/rust/kernel/sync/atomic/internal.rs
> @@ -7,6 +7,7 @@
>  use crate::bindings;
>  use crate::macros::paste;
>  use core::cell::UnsafeCell;
> +use ffi::c_void;
>  
>  mod private {
>      /// Sealed trait marker to disable customized impls on atomic implementation traits.
> @@ -14,10 +15,11 @@ pub trait Sealed {}
>  }
>  
>  // The C side supports atomic primitives only for `i32` and `i64` (`atomic_t` and `atomic64_t`),
> -// while the Rust side also layers provides atomic support for `i8` and `i16`
> -// on top of lower-level C primitives.
> +// while the Rust side also provides atomic support for `i8`, `i16` and `*const c_void` on top of
> +// lower-level C primitives.
>  impl private::Sealed for i8 {}
>  impl private::Sealed for i16 {}
> +impl private::Sealed for *const c_void {}
>  impl private::Sealed for i32 {}
>  impl private::Sealed for i64 {}
>  
> @@ -26,10 +28,10 @@ impl private::Sealed for i64 {}
>  /// This trait is sealed, and only types that map directly to the C side atomics
>  /// or can be implemented with lower-level C primitives are allowed to implement this:
>  ///
> -/// - `i8` and `i16` are implemented with lower-level C primitives.
> +/// - `i8`, `i16` and `*const c_void` are implemented with lower-level C primitives.
>  /// - `i32` map to `atomic_t`
>  /// - `i64` map to `atomic64_t`
> -pub trait AtomicImpl: Sized + Send + Copy + private::Sealed {
> +pub trait AtomicImpl: Sized + Copy + private::Sealed {
>      /// The type of the delta in arithmetic or logical operations.
>      ///
>      /// For example, in `atomic_add(ptr, v)`, it's the type of `v`. Usually it's the same type of
> @@ -51,6 +53,13 @@ impl AtomicImpl for i16 {
>      type Delta = Self;
>  }
>  
> +// The current helpers of load/store uses `{WRITE,READ}_ONCE()` hence the atomicity is only
> +// guaranteed against read-modify-write operations if the architecture supports native atomic RmW.
> +#[cfg(CONFIG_ARCH_SUPPORTS_ATOMIC_RMW)]
> +impl AtomicImpl for *const c_void {
> +    type Delta = isize;
> +}
> +
>  // `atomic_t` implements atomic operations on `i32`.
>  impl AtomicImpl for i32 {
>      type Delta = Self;
> @@ -262,7 +271,7 @@ macro_rules! declare_and_impl_atomic_methods {
>  }
>  
>  declare_and_impl_atomic_methods!(
> -    [ i8 => atomic_i8, i16 => atomic_i16, i32 => atomic, i64 => atomic64 ]
> +    [ i8 => atomic_i8, i16 => atomic_i16, *const c_void => atomic_ptr, i32 => atomic, i64 => atomic64 ]
>      /// Basic atomic operations
>      pub trait AtomicBasicOps {
>          /// Atomic read (load).
> @@ -280,7 +289,7 @@ fn set[release](a: &AtomicRepr<Self>, v: Self) {
>  );
>  
>  declare_and_impl_atomic_methods!(
> -    [ i8 => atomic_i8, i16 => atomic_i16, i32 => atomic, i64 => atomic64 ]
> +    [ i8 => atomic_i8, i16 => atomic_i16, *const c_void => atomic_ptr, i32 => atomic, i64 => atomic64 ]
>      /// Exchange and compare-and-exchange atomic operations
>      pub trait AtomicExchangeOps {
>          /// Atomic exchange.
> diff --git a/rust/kernel/sync/atomic/predefine.rs b/rust/kernel/sync/atomic/predefine.rs
> index 42067c6a266c..1a4670d225b5 100644
> --- a/rust/kernel/sync/atomic/predefine.rs
> +++ b/rust/kernel/sync/atomic/predefine.rs
> @@ -4,6 +4,7 @@
>  
>  use crate::static_assert;
>  use core::mem::{align_of, size_of};
> +use ffi::c_void;
>  
>  // Ensure size and alignment requirements are checked.
>  static_assert!(size_of::<bool>() == size_of::<i8>());
> @@ -28,6 +29,16 @@ unsafe impl super::AtomicType for i16 {
>      type Repr = i16;
>  }
>  
> +// SAFETY:
> +//
> +// - `*mut T` has the same size and alignment with `*const c_void`, and is round-trip
> +//   transmutable to `*const c_void`.
> +// - `*mut T` is safe to transfer between execution contexts. See the safety requirement of
> +//   [`AtomicType`].
> +unsafe impl<T: Sized> super::AtomicType for *mut T {
> +    type Repr = *const c_void;
> +}

How about *const T?

> +
>  // SAFETY: `i32` has the same size and alignment with itself, and is round-trip transmutable to
>  // itself.
>  unsafe impl super::AtomicType for i32 {
> @@ -215,4 +226,16 @@ fn atomic_bool_tests() {
>          assert_eq!(false, x.load(Relaxed));
>          assert_eq!(Ok(false), x.cmpxchg(false, true, Full));
>      }
> +
> +    #[test]
> +    fn atomic_ptr_tests() {
> +        let mut v = 42;
> +        let mut u = 43;
> +        let x = Atomic::new(&raw mut v);
> +
> +        assert_eq!(x.load(Acquire), &raw mut v);
> +        assert_eq!(x.cmpxchg(&raw mut u, &raw mut u, Relaxed), Err(&raw mut v));
> +        assert_eq!(x.cmpxchg(&raw mut v, &raw mut u, Relaxed), Ok(&raw mut v));
> +        assert_eq!(x.load(Relaxed), &raw mut u);
> +    }
>  }
Re: [PATCH 4/5] rust: sync: atomic: Add Atomic<*mut T> support
Posted by Boqun Feng 3 weeks ago
On Sat, Jan 17, 2026 at 05:03:15PM +0000, Gary Guo wrote:
> On Sat Jan 17, 2026 at 12:22 PM GMT, Boqun Feng wrote:
> > Atomic pointer support is an important piece of synchronization
> > algorithm, e.g. RCU, hence provide the support for that.
> >
> > Note that instead of relying on atomic_long or the implementation of
> > `Atomic<usize>`, a new set of helpers (atomic_ptr_*) is introduced for
> > atomic pointer specifically, this is because ptr2int casting would
> > lose the provenance of a pointer and even though in theory there are a
> > few tricks the provenance can be restored, it'll still be a simpler
> > implementation if C could provide atomic pointers directly. The side
> > effects of this approach are: we don't have the arithmetic and logical
> > operations for pointers yet and the current implementation only works
> > on ARCH_SUPPORTS_ATOMIC_RMW architectures, but these are implementation
> > issues and can be added later.
> >
> > Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
> 
> I am happy that this is now using dedicated helpers for pointers, and not going
> through an intermediate integer which can lose provenance.
> 
> Some feedbacks below, but in general LGTM.
> 
> Reviewed-by: Gary Guo <gary@garyguo.net>
> 

Thanks!

> > ---
> > diff --git a/rust/kernel/sync/atomic.rs b/rust/kernel/sync/atomic.rs
[...]
> > index 4aebeacb961a..4d2a5228c2e4 100644
> > --- a/rust/kernel/sync/atomic.rs
> > +++ b/rust/kernel/sync/atomic.rs
> > @@ -51,6 +51,10 @@
> >  #[repr(transparent)]
> >  pub struct Atomic<T: AtomicType>(AtomicRepr<T::Repr>);
> >  
> > +// SAFETY: `Atomic<T>` is safe to transfer between execution contexts because of the safety
> > +// requirement of `AtomicType`.
> > +unsafe impl<T: AtomicType> Send for Atomic<T> {}
> > +
> >  // SAFETY: `Atomic<T>` is safe to share among execution contexts because all accesses are atomic.
> >  unsafe impl<T: AtomicType> Sync for Atomic<T> {}
> >  
> > @@ -68,6 +72,11 @@ unsafe impl<T: AtomicType> Sync for Atomic<T> {}
> >  ///
> >  /// - [`Self`] must have the same size and alignment as [`Self::Repr`].
> >  /// - [`Self`] must be [round-trip transmutable] to  [`Self::Repr`].
> > +/// - [`Self`] must be safe to transfer between execution contexts, if it's [`Send`], this is
> > +///   automatically satisfied. The exception is pointer types that are even though marked as
> > +///   `!Send` (e.g. raw pointers and [`NonNull<T>`]) but requiring `unsafe` to do anything
> > +///   meaningful on them. This is because transferring pointer values between execution contexts is
> > +///   safe as long as the actual `unsafe` dereferencing is justified.
> 
> I think the discussion about `Send` on pointers should be moved to the `impl<T>
> AtomicType for *mut T` side.
> 

The reason I put something here was to answer the potential question
"why don't you require AtomicType being a subtrait of Send?", that's
more of a question for people who read about `AtomicType`, so I figured
we need some explanation. But I'm fine if you think we should move some
of the comments to the impl block, or we duplicate some. Although I
don't think the current version is worse. Considering we do:

    /// - [`Self`] must have the same size and alignment as [`Self::Repr`].
    /// - [`Self`] must be [round-trip transmutable] to  [`Self::Repr`].
    /// - [`Self`] must be safe to transfer between execution contexts, if it's [`Send`], this is
    ///   automatically satisfied.

for AtomicType, I'm not sure someone read about `AtomicType` could have
everything they need to understand why it's not `: Send`.

[...]
> > +// SAFETY:
> > +//
> > +// - `*mut T` has the same size and alignment with `*const c_void`, and is round-trip
> > +//   transmutable to `*const c_void`.
> > +// - `*mut T` is safe to transfer between execution contexts. See the safety requirement of
> > +//   [`AtomicType`].
> > +unsafe impl<T: Sized> super::AtomicType for *mut T {
> > +    type Repr = *const c_void;
> > +}
> 
> How about *const T?
> 

In general I want to avoid const raw pointers since it provides very
little extra compared to mut raw pointers. For compiler optimization,
provenenace is more important than "const vs mut" modifier, for
dereference, it's unsafe anyway and users need to provide reasoning
(including knowing the provenance and other accesses may happen to the
same address), so I feel the type difference of "*const T" vs "*mut T"
doesn't do anything extra either.

Think about it, in Rust std, there are two pointer types only maps to
"*mut T": NonNull<T> (as_ptr() returns a `*mut T`) and AtomicPtr<T>
(as_ptr() returns a `*mut *mut T`). And there is no type like
NonNullConst<T> and AtomicConstPtr<T>. This is a lint to me that we may
not need to support `*const T` in most cases.

But maybe I'm missing something? If you have a good reason, we can
obviously add the support for `*const T`.

Regards,
Boqun

> > +
> >  // SAFETY: `i32` has the same size and alignment with itself, and is round-trip transmutable to
> >  // itself.
> >  unsafe impl super::AtomicType for i32 {
> > @@ -215,4 +226,16 @@ fn atomic_bool_tests() {
> >          assert_eq!(false, x.load(Relaxed));
> >          assert_eq!(Ok(false), x.cmpxchg(false, true, Full));
> >      }
> > +
> > +    #[test]
> > +    fn atomic_ptr_tests() {
> > +        let mut v = 42;
> > +        let mut u = 43;
> > +        let x = Atomic::new(&raw mut v);
> > +
> > +        assert_eq!(x.load(Acquire), &raw mut v);
> > +        assert_eq!(x.cmpxchg(&raw mut u, &raw mut u, Relaxed), Err(&raw mut v));
> > +        assert_eq!(x.cmpxchg(&raw mut v, &raw mut u, Relaxed), Ok(&raw mut v));
> > +        assert_eq!(x.load(Relaxed), &raw mut u);
> > +    }
> >  }
>
Re: [PATCH 4/5] rust: sync: atomic: Add Atomic<*mut T> support
Posted by Alice Ryhl 2 weeks, 5 days ago
On Sun, Jan 18, 2026 at 12:19:35PM +0800, Boqun Feng wrote:
> On Sat, Jan 17, 2026 at 05:03:15PM +0000, Gary Guo wrote:
> > On Sat Jan 17, 2026 at 12:22 PM GMT, Boqun Feng wrote:
> > > +// SAFETY:
> > > +//
> > > +// - `*mut T` has the same size and alignment with `*const c_void`, and is round-trip
> > > +//   transmutable to `*const c_void`.
> > > +// - `*mut T` is safe to transfer between execution contexts. See the safety requirement of
> > > +//   [`AtomicType`].
> > > +unsafe impl<T: Sized> super::AtomicType for *mut T {
> > > +    type Repr = *const c_void;
> > > +}
> > 
> > How about *const T?
> > 
> 
> In general I want to avoid const raw pointers since it provides very
> little extra compared to mut raw pointers. For compiler optimization,
> provenenace is more important than "const vs mut" modifier, for
> dereference, it's unsafe anyway and users need to provide reasoning
> (including knowing the provenance and other accesses may happen to the
> same address), so I feel the type difference of "*const T" vs "*mut T"
> doesn't do anything extra either.
> 
> Think about it, in Rust std, there are two pointer types only maps to
> "*mut T": NonNull<T> (as_ptr() returns a `*mut T`) and AtomicPtr<T>
> (as_ptr() returns a `*mut *mut T`). And there is no type like
> NonNullConst<T> and AtomicConstPtr<T>. This is a lint to me that we may
> not need to support `*const T` in most cases.
> 
> But maybe I'm missing something? If you have a good reason, we can
> obviously add the support for `*const T`.

It was pretty inconvenient in:
https://lore.kernel.org/all/20260117-upgrade-poll-v1-1-179437b7bd49@google.com/
since I had to cast_mut() a bunch of places.

Alice
Re: [PATCH 4/5] rust: sync: atomic: Add Atomic<*mut T> support
Posted by Boqun Feng 2 weeks, 5 days ago
On Tue, Jan 20, 2026 at 12:37:03PM +0000, Alice Ryhl wrote:
> On Sun, Jan 18, 2026 at 12:19:35PM +0800, Boqun Feng wrote:
> > On Sat, Jan 17, 2026 at 05:03:15PM +0000, Gary Guo wrote:
> > > On Sat Jan 17, 2026 at 12:22 PM GMT, Boqun Feng wrote:
> > > > +// SAFETY:
> > > > +//
> > > > +// - `*mut T` has the same size and alignment with `*const c_void`, and is round-trip
> > > > +//   transmutable to `*const c_void`.
> > > > +// - `*mut T` is safe to transfer between execution contexts. See the safety requirement of
> > > > +//   [`AtomicType`].
> > > > +unsafe impl<T: Sized> super::AtomicType for *mut T {
> > > > +    type Repr = *const c_void;
> > > > +}
> > > 
> > > How about *const T?
> > > 
> > 
> > In general I want to avoid const raw pointers since it provides very
> > little extra compared to mut raw pointers. For compiler optimization,
> > provenenace is more important than "const vs mut" modifier, for
> > dereference, it's unsafe anyway and users need to provide reasoning
> > (including knowing the provenance and other accesses may happen to the
> > same address), so I feel the type difference of "*const T" vs "*mut T"
> > doesn't do anything extra either.
> > 
> > Think about it, in Rust std, there are two pointer types only maps to
> > "*mut T": NonNull<T> (as_ptr() returns a `*mut T`) and AtomicPtr<T>
> > (as_ptr() returns a `*mut *mut T`). And there is no type like
> > NonNullConst<T> and AtomicConstPtr<T>. This is a lint to me that we may
> > not need to support `*const T` in most cases.
> > 
> > But maybe I'm missing something? If you have a good reason, we can
> > obviously add the support for `*const T`.
> 
> It was pretty inconvenient in:
> https://lore.kernel.org/all/20260117-upgrade-poll-v1-1-179437b7bd49@google.com/
> since I had to cast_mut() a bunch of places.
> 

Let's add it then ;-)

https://lore.kernel.org/rust-for-linux/20260120140503.62804-1-boqun.feng@gmail.com/

Regards,
Boqun

> Alice
Re: [PATCH 4/5] rust: sync: atomic: Add Atomic<*mut T> support
Posted by Gary Guo 3 weeks ago
On Sun Jan 18, 2026 at 4:19 AM GMT, Boqun Feng wrote:
> On Sat, Jan 17, 2026 at 05:03:15PM +0000, Gary Guo wrote:
>> On Sat Jan 17, 2026 at 12:22 PM GMT, Boqun Feng wrote:
>> > Atomic pointer support is an important piece of synchronization
>> > algorithm, e.g. RCU, hence provide the support for that.
>> >
>> > Note that instead of relying on atomic_long or the implementation of
>> > `Atomic<usize>`, a new set of helpers (atomic_ptr_*) is introduced for
>> > atomic pointer specifically, this is because ptr2int casting would
>> > lose the provenance of a pointer and even though in theory there are a
>> > few tricks the provenance can be restored, it'll still be a simpler
>> > implementation if C could provide atomic pointers directly. The side
>> > effects of this approach are: we don't have the arithmetic and logical
>> > operations for pointers yet and the current implementation only works
>> > on ARCH_SUPPORTS_ATOMIC_RMW architectures, but these are implementation
>> > issues and can be added later.
>> >
>> > Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
>> 
>> I am happy that this is now using dedicated helpers for pointers, and not going
>> through an intermediate integer which can lose provenance.
>> 
>> Some feedbacks below, but in general LGTM.
>> 
>> Reviewed-by: Gary Guo <gary@garyguo.net>
>> 
>
> Thanks!
>
>> > ---
>> > diff --git a/rust/kernel/sync/atomic.rs b/rust/kernel/sync/atomic.rs
> [...]
>> > index 4aebeacb961a..4d2a5228c2e4 100644
>> > --- a/rust/kernel/sync/atomic.rs
>> > +++ b/rust/kernel/sync/atomic.rs
>> > @@ -51,6 +51,10 @@
>> >  #[repr(transparent)]
>> >  pub struct Atomic<T: AtomicType>(AtomicRepr<T::Repr>);
>> >  
>> > +// SAFETY: `Atomic<T>` is safe to transfer between execution contexts because of the safety
>> > +// requirement of `AtomicType`.
>> > +unsafe impl<T: AtomicType> Send for Atomic<T> {}
>> > +
>> >  // SAFETY: `Atomic<T>` is safe to share among execution contexts because all accesses are atomic.
>> >  unsafe impl<T: AtomicType> Sync for Atomic<T> {}
>> >  
>> > @@ -68,6 +72,11 @@ unsafe impl<T: AtomicType> Sync for Atomic<T> {}
>> >  ///
>> >  /// - [`Self`] must have the same size and alignment as [`Self::Repr`].
>> >  /// - [`Self`] must be [round-trip transmutable] to  [`Self::Repr`].
>> > +/// - [`Self`] must be safe to transfer between execution contexts, if it's [`Send`], this is
>> > +///   automatically satisfied. The exception is pointer types that are even though marked as
>> > +///   `!Send` (e.g. raw pointers and [`NonNull<T>`]) but requiring `unsafe` to do anything
>> > +///   meaningful on them. This is because transferring pointer values between execution contexts is
>> > +///   safe as long as the actual `unsafe` dereferencing is justified.
>> 
>> I think the discussion about `Send` on pointers should be moved to the `impl<T>
>> AtomicType for *mut T` side.
>> 
>
> The reason I put something here was to answer the potential question
> "why don't you require AtomicType being a subtrait of Send?", that's
> more of a question for people who read about `AtomicType`, so I figured
> we need some explanation. But I'm fine if you think we should move some
> of the comments to the impl block, or we duplicate some. Although I
> don't think the current version is worse. Considering we do:
>
>     /// - [`Self`] must have the same size and alignment as [`Self::Repr`].
>     /// - [`Self`] must be [round-trip transmutable] to  [`Self::Repr`].
>     /// - [`Self`] must be safe to transfer between execution contexts, if it's [`Send`], this is
>     ///   automatically satisfied.
>
> for AtomicType, I'm not sure someone read about `AtomicType` could have
> everything they need to understand why it's not `: Send`.

Ok.

>
> [...]
>> > +// SAFETY:
>> > +//
>> > +// - `*mut T` has the same size and alignment with `*const c_void`, and is round-trip
>> > +//   transmutable to `*const c_void`.
>> > +// - `*mut T` is safe to transfer between execution contexts. See the safety requirement of
>> > +//   [`AtomicType`].
>> > +unsafe impl<T: Sized> super::AtomicType for *mut T {
>> > +    type Repr = *const c_void;
>> > +}
>> 
>> How about *const T?
>> 
>
> In general I want to avoid const raw pointers since it provides very
> little extra compared to mut raw pointers. For compiler optimization,
> provenenace is more important than "const vs mut" modifier, for
> dereference, it's unsafe anyway and users need to provide reasoning
> (including knowing the provenance and other accesses may happen to the
> same address), so I feel the type difference of "*const T" vs "*mut T"
> doesn't do anything extra either.
>
> Think about it, in Rust std, there are two pointer types only maps to
> "*mut T": NonNull<T> (as_ptr() returns a `*mut T`) and AtomicPtr<T>
> (as_ptr() returns a `*mut *mut T`). And there is no type like
> NonNullConst<T> and AtomicConstPtr<T>. This is a lint to me that we may
> not need to support `*const T` in most cases.

Actually `NonNull` is internally `*const T`, because it's covariant, unlike
`*mut T` which is invariant.

Now, for atomics, it's less likely that you actually want covariance. So this
difference matters less.

>
> But maybe I'm missing something? If you have a good reason, we can
> obviously add the support for `*const T`.

It just feels that it is somewhat inconsistent. There's no good motivation right
now. I am fine to leave it out and add when needed.

Best,
Gary
Re: [PATCH 4/5] rust: sync: atomic: Add Atomic<*mut T> support
Posted by Boqun Feng 2 weeks, 5 days ago
On Sun, Jan 18, 2026 at 03:39:40PM +0000, Gary Guo wrote:
[...]
> >> 
> >> How about *const T?
> >> 
> >
> > In general I want to avoid const raw pointers since it provides very
> > little extra compared to mut raw pointers. For compiler optimization,
> > provenenace is more important than "const vs mut" modifier, for
> > dereference, it's unsafe anyway and users need to provide reasoning
> > (including knowing the provenance and other accesses may happen to the
> > same address), so I feel the type difference of "*const T" vs "*mut T"
> > doesn't do anything extra either.
> >
> > Think about it, in Rust std, there are two pointer types only maps to
> > "*mut T": NonNull<T> (as_ptr() returns a `*mut T`) and AtomicPtr<T>
> > (as_ptr() returns a `*mut *mut T`). And there is no type like
> > NonNullConst<T> and AtomicConstPtr<T>. This is a lint to me that we may
> > not need to support `*const T` in most cases.
> 
> Actually `NonNull` is internally `*const T`, because it's covariant, unlike
> `*mut T` which is invariant.
> 

Ah, right!

> Now, for atomics, it's less likely that you actually want covariance. So this
> difference matters less.
> 

Agreed.

> >
> > But maybe I'm missing something? If you have a good reason, we can
> > obviously add the support for `*const T`.
> 
> It just feels that it is somewhat inconsistent. There's no good motivation right
> now. I am fine to leave it out and add when needed.
> 

Yeah, we can also add it later. Thanks!

Regards,
Boqun

> Best,
> Gary