[PATCH v5 08/10] rust: sync: atomic: Add Atomic<{usize,isize}>
Boqun Feng <[email protected]>
| 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 necessarity of creating `atomic_long_*` helpers, which could save the binary size of kernel if inline helpers are not available. Signed-off-by: Boqun Feng <[email protected]> --- rust/kernel/sync/atomic.rs | 58 +++++++++++++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 4 deletions(-) diff --git a/rust/kernel/sync/atomic.rs b/rust/kernel/sync/atomic.rs index 965a3db554d9..829511f4d582 100644 --- a/rust/kernel/sync/atomic.rs +++ b/rust/kernel/sync/atomic.rs @@ -65,6 +65,56 @@ fn delta_into_repr(d: Self::Delta) -> Self::Repr { } } +// SAFETY: `usize` has the same size and the alignment as `i64` for 64bit and the same as `i32` for +// 32bit. +unsafe impl generic::AllowAtomic for usize { + #[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 + } +} + +impl generic::AllowAtomicArithmetic for usize { + type Delta = usize; + + fn delta_into_repr(d: Self::Delta) -> Self::Repr { + d as Self::Repr + } +} + +// SAFETY: `isize` has the same size and the alignment as `i64` for 64bit and the same as `i32` for +// 32bit. +unsafe impl generic::AllowAtomic for isize { + #[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 + } +} + +impl generic::AllowAtomicArithmetic for isize { + type Delta = isize; + + fn delta_into_repr(d: Self::Delta) -> Self::Repr { + d as Self::Repr + } +} + use crate::macros::kunit_tests; #[kunit_tests(rust_atomics)] @@ -84,7 +134,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)); @@ -93,7 +143,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; @@ -106,7 +156,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; @@ -121,7 +171,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)