[PATCH RFC 02/11] rust: sync: atomic: Add Atomic<u{8,16}>

From: Thomas Weißschuh

Date: Sun Oct 11 2026 - 08:53:21 EST


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 <linux@xxxxxxxxxxxxxx>
---
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