[PATCH v7 9/9] rust: sync: atomic: Add Atomic<{usize,isize}>
Boqun Feng <[email protected]> Sun, 13 Jul 2025 22:36:56 -0700
| Newsgroups | dev.linux.lists.lkmm,org.kernel.vger.linux-arch,org.kernel.vger.linux-kernel,org.kernel.vger.rust-for-linux |
|---|---|
| Message-ID | <[email protected]> |
Add generic atomic support for `usize` and `isize`. Note that instead of mapping directly to `atomic_long_t`, the represention type (`AllowAtomic::Repr`) is selected based on CONFIG_64BIT. This reduces the necessity of creating `atomic_long_*` helpers, which could save the binary size of kernel if inline helpers are not available. To do so, an internal type `isize_atomic_repr` is defined, it's `i32` in 32bit kernel and `i64` in 64bit kernel. Reviewed-by: Alice Ryhl <[email protected]> Reviewed-by: Andreas Hindborg <[email protected]> Reviewed-by: Benno Lossin <[email protected]> Signed-off-by: Boqun Feng <[email protected]> --- rust/kernel/sync/atomic.rs | 50 +++++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/rust/kernel/sync/atomic.rs b/rust/kernel/sync/atomic.rs index eb4a47d7e2f3..3c1bb0c4d396 100644 --- a/rust/kernel/sync/atomic.rs +++ b/rust/kernel/sync/atomic.rs @@ -49,6 +49,35 @@ fn rhs_into_delta(rhs: i64) -> i64 { } } +// Defines an internal type that always maps to the integer type which has the same size alignment +// as `isize` and `usize`, and `isize` and `usize` are always bi-directional transmutable to +// `isize_atomic_repr`, which also always implements `AtomicImpl`. +#[allow(non_camel_case_types)] +#[cfg(not(CONFIG_64BIT))] +type isize_atomic_repr = i32; +#[allow(non_camel_case_types)] +#[cfg(CONFIG_64BIT)] +type isize_atomic_repr = i64; + +// Ensure size and alignment requirements are checked. +crate::static_assert!(core::mem::size_of::<isize>() == core::mem::size_of::<isize_atomic_repr>()); +crate::static_assert!(core::mem::align_of::<isize>() == core::mem::align_of::<isize_atomic_repr>()); +crate::static_assert!(core::mem::size_of::<usize>() == core::mem::size_of::<isize_atomic_repr>()); +crate::static_assert!(core::mem::align_of::<usize>() == core::mem::align_of::<isize_atomic_repr>()); + +// SAFETY: `isize` has the same size and alignment with `isize_atomic_repr`, and is round-trip +// transmutable to `isize_atomic_repr`. +unsafe impl generic::AllowAtomic for isize { + type Repr = isize_atomic_repr; +} + +// SAFETY: The wrapping add result of two `isize_atomic_repr`s is a valid `usize`. +unsafe impl generic::AllowAtomicAdd<isize> for isize { + fn rhs_into_delta(rhs: isize) -> isize_atomic_repr { + rhs as isize_atomic_repr + } +} + // SAFETY: `u32` and `i32` has the same size and alignment, and `u32` is round-trip transmutable to // `i32`. unsafe impl generic::AllowAtomic for u32 { @@ -75,6 +104,19 @@ fn rhs_into_delta(rhs: u64) -> i64 { } } +// SAFETY: `usize` has the same size and alignment with `isize_atomic_repr`, and is round-trip +// transmutable to `isize_atomic_repr`. +unsafe impl generic::AllowAtomic for usize { + type Repr = isize_atomic_repr; +} + +// SAFETY: The wrapping add result of two `isize_atomic_repr`s is a valid `usize`. +unsafe impl generic::AllowAtomicAdd<usize> for usize { + fn rhs_into_delta(rhs: usize) -> isize_atomic_repr { + rhs as isize_atomic_repr + } +} + use crate::macros::kunit_tests; #[kunit_tests(rust_atomics)] @@ -94,7 +136,7 @@ macro_rules! for_each_type { #[test] fn atomic_basic_tests() { - for_each_type!(42 in [i32, i64, u32, u64] |v| { + for_each_type!(42 in [i32, i64, u32, u64, isize, usize] |v| { let x = Atomic::new(v); assert_eq!(v, x.load(Relaxed)); @@ -103,7 +145,7 @@ fn atomic_basic_tests() { #[test] fn atomic_xchg_tests() { - for_each_type!(42 in [i32, i64, u32, u64] |v| { + for_each_type!(42 in [i32, i64, u32, u64, isize, usize] |v| { let x = Atomic::new(v); let old = v; @@ -116,7 +158,7 @@ fn atomic_xchg_tests() { #[test] fn atomic_cmpxchg_tests() { - for_each_type!(42 in [i32, i64, u32, u64] |v| { + for_each_type!(42 in [i32, i64, u32, u64, isize, usize] |v| { let x = Atomic::new(v); let old = v; @@ -131,7 +173,7 @@ fn atomic_cmpxchg_tests() { #[test] fn atomic_arithmetic_tests() { - for_each_type!(42 in [i32, i64, u32, u64] |v| { + for_each_type!(42 in [i32, i64, u32, u64, isize, usize] |v| { let x = Atomic::new(v); assert_eq!(v, x.fetch_add(12, Full)); -- 2.39.5 (Apple Git-154)