Add generic atomic support for small unsigned integers that have an `AtomicImpl` with the same size and alignment.
Also extend the unit tests. Signed-off-by: Thomas Weißschuh <[email protected]> --- rust/kernel/sync/atomic/predefine.rs | 44 ++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/rust/kernel/sync/atomic/predefine.rs b/rust/kernel/sync/atomic/predefine.rs index 3d63f40791fa..4c1fb5e08dc2 100644 --- a/rust/kernel/sync/atomic/predefine.rs +++ b/rust/kernel/sync/atomic/predefine.rs @@ -113,6 +113,32 @@ fn rhs_into_delta(rhs: isize) -> isize_atomic_repr { } } +// SAFETY: `u8` and `i8` has the same size and alignment, and `u8` is round-trip transmutable to +// `i8`. +unsafe impl super::AtomicType for u8 { + type Repr = i8; +} + +// SAFETY: The wrapping add result of two `i8`s is a valid `u8`. +unsafe impl super::AtomicAdd<u8> for u8 { + fn rhs_into_delta(rhs: u8) -> i8 { + rhs as i8 + } +} + +// SAFETY: `u16` and `i16` has the same size and alignment, and `u16` is round-trip transmutable to +// `i16`. +unsafe impl super::AtomicType for u16 { + type Repr = i16; +} + +// SAFETY: The wrapping add result of two `i16`s is a valid `u16`. +unsafe impl super::AtomicAdd<u16> for u16 { + fn rhs_into_delta(rhs: u16) -> i16 { + rhs as i16 + } +} + // SAFETY: `u32` and `i32` has the same size and alignment, and `u32` is round-trip transmutable to // `i32`. unsafe impl super::AtomicType for u32 { @@ -170,13 +196,13 @@ macro_rules! for_each_type { #[test] fn atomic_basic_tests() { - for_each_type!(42 in [i8, i16, i32, i64, u32, u64, isize, usize] |v| { + for_each_type!(42 in [i8, i16, i32, i64, u8, u16, u32, u64, isize, usize] |v| { let x = Atomic::new(v); assert_eq!(v, x.load(Relaxed)); }); - for_each_type!(42 in [i8, i16, i32, i64, u32, u64, isize, usize] |v| { + for_each_type!(42 in [i8, i16, i32, i64, u8, u16, u32, u64, isize, usize] |v| { let x = Atomic::new(v); let ptr = x.as_ptr(); @@ -187,14 +213,14 @@ fn atomic_basic_tests() { #[test] fn atomic_acquire_release_tests() { - for_each_type!(42 in [i8, i16, i32, i64, u32, u64, isize, usize] |v| { + for_each_type!(42 in [i8, i16, i32, i64, u8, u16, u32, u64, isize, usize] |v| { let x = Atomic::new(0); x.store(v, Release); assert_eq!(v, x.load(Acquire)); }); - for_each_type!(42 in [i8, i16, i32, i64, u32, u64, isize, usize] |v| { + for_each_type!(42 in [i8, i16, i32, i64, u8, u16, u32, u64, isize, usize] |v| { let x = Atomic::new(0); let ptr = x.as_ptr(); @@ -208,7 +234,7 @@ fn atomic_acquire_release_tests() { #[test] fn atomic_xchg_tests() { - for_each_type!(42 in [i8, i16, i32, i64, u32, u64, isize, usize] |v| { + for_each_type!(42 in [i8, i16, i32, i64, u8, u16, u32, u64, isize, usize] |v| { let x = Atomic::new(v); let old = v; @@ -218,7 +244,7 @@ fn atomic_xchg_tests() { assert_eq!(new, x.load(Relaxed)); }); - for_each_type!(42 in [i8, i16, i32, i64, u32, u64, isize, usize] |v| { + for_each_type!(42 in [i8, i16, i32, i64, u8, u16, u32, u64, isize, usize] |v| { let x = Atomic::new(v); let ptr = x.as_ptr(); @@ -233,7 +259,7 @@ fn atomic_xchg_tests() { #[test] fn atomic_cmpxchg_tests() { - for_each_type!(42 in [i8, i16, i32, i64, u32, u64, isize, usize] |v| { + for_each_type!(42 in [i8, i16, i32, i64, u8, u16, u32, u64, isize, usize] |v| { let x = Atomic::new(v); let old = v; @@ -245,7 +271,7 @@ fn atomic_cmpxchg_tests() { assert_eq!(new, x.load(Relaxed)); }); - for_each_type!(42 in [i8, i16, i32, i64, u32, u64, isize, usize] |v| { + for_each_type!(42 in [i8, i16, i32, i64, u8, u16, u32, u64, isize, usize] |v| { let x = Atomic::new(v); let ptr = x.as_ptr(); @@ -263,7 +289,7 @@ fn atomic_cmpxchg_tests() { #[test] fn atomic_arithmetic_tests() { - for_each_type!(42 in [i32, i64, u32, u64, isize, usize] |v| { + for_each_type!(42 in [i32, i64, u64, isize, usize] |v| { let x = Atomic::new(v); assert_eq!(v, x.fetch_add(12, Full)); -- 2.56.0

