[PATCH v6 9/9] rust: sync: atomic: Add Atomic<{usize,isize}>
Boqun Feng <[email protected]> Wed, 9 Jul 2025 23:00:52 -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. Reviewed-by: Alice Ryhl <[email protected]> Reviewed-by: Andreas Hindborg <[email protected]> Signed-off-by: Boqun Feng <[email protected]> --- rust/kernel/sync/atomic.rs | 48 ++++++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/rust/kernel/sync/atomic.rs b/rust/kernel/sync/atomic.rs index e676bc7d9275..e1e40757d7b5 100644 --- a/rust/kernel/sync/atomic.rs +++ b/rust/kernel/sync/atomic.rs @@ -53,6 +53,26 @@ fn delta_into_repr(d: Self::Delta) -> Self::Repr { } } +// SAFETY: For 32bit kernel, `isize` has the same size and alignment with `i32` and is round-trip +// transmutable to it, for 64bit kernel `isize` has the same size and alignment with `i64` and is +// round-trip transmutable to it. +unsafe impl generic::AllowAtomic for isize { + #[cfg(not(CONFIG_64BIT))] + type Repr = i32; + #[cfg(CONFIG_64BIT)] + type Repr = i64; +} + +// SAFETY: `isize` is always sound to transmute back from `i32` or `i64` when their sizes are the +// same. +unsafe impl generic::AllowAtomicArithmetic for isize { + type Delta = Self; + + fn delta_into_repr(d: Self::Delta) -> Self::Repr { + d as Self::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 { @@ -83,6 +103,26 @@ fn delta_into_repr(d: Self::Delta) -> Self::Repr { } } +// SAFETY: For 32bit kernel, `usize` has the same size and alignment with `i32` and is round-trip +// transmutable to it, for 64bit kernel `usize` has the same size and alignment with `i64` and is +// round-trip transmutable to it. +unsafe impl generic::AllowAtomic for usize { + #[cfg(not(CONFIG_64BIT))] + type Repr = i32; + #[cfg(CONFIG_64BIT)] + type Repr = i64; +} + +// SAFETY: `usize` is always sound to transmute back from `i32` or `i64` when their sizes are the +// same. +unsafe impl generic::AllowAtomicArithmetic for usize { + type Delta = Self; + + fn delta_into_repr(d: Self::Delta) -> Self::Repr { + d as Self::Repr + } +} + use crate::macros::kunit_tests; #[kunit_tests(rust_atomics)] @@ -102,7 +142,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)); @@ -111,7 +151,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; @@ -124,7 +164,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; @@ -139,7 +179,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)