Skip to content

Commit b8c011e

Browse files
fbqjannau
authored andcommitted
rust: sync: atomic: Add Atomic<u{32,64}>
Add generic atomic support for basic unsigned types that have an `AtomicImpl` with the same size and alignment. Unit tests are added including Atomic<i32> and Atomic<i64>. Signed-off-by: Boqun Feng <boqun.feng@gmail.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Reviewed-by: Alice Ryhl <aliceryhl@google.com> Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org> Reviewed-by: Benno Lossin <lossin@kernel.org> Reviewed-by: Elle Rhumsaa <elle@weathered-steel.dev> Link: https://lore.kernel.org/all/20250719030827.61357-8-boqun.feng@gmail.com/
1 parent a023a97 commit b8c011e

1 file changed

Lines changed: 95 additions & 0 deletions

File tree

rust/kernel/sync/atomic/predefine.rs

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,98 @@ unsafe impl super::AtomicAdd<i64> for i64 {
2727
rhs
2828
}
2929
}
30+
31+
// SAFETY: `u32` and `i32` has the same size and alignment, and `u32` is round-trip transmutable to
32+
// `i32`.
33+
unsafe impl super::AtomicType for u32 {
34+
type Repr = i32;
35+
}
36+
37+
// SAFETY: The wrapping add result of two `i32`s is a valid `u32`.
38+
unsafe impl super::AtomicAdd<u32> for u32 {
39+
fn rhs_into_delta(rhs: u32) -> i32 {
40+
rhs as i32
41+
}
42+
}
43+
44+
// SAFETY: `u64` and `i64` has the same size and alignment, and `u64` is round-trip transmutable to
45+
// `i64`.
46+
unsafe impl super::AtomicType for u64 {
47+
type Repr = i64;
48+
}
49+
50+
// SAFETY: The wrapping add result of two `i64`s is a valid `u64`.
51+
unsafe impl super::AtomicAdd<u64> for u64 {
52+
fn rhs_into_delta(rhs: u64) -> i64 {
53+
rhs as i64
54+
}
55+
}
56+
57+
use crate::macros::kunit_tests;
58+
59+
#[kunit_tests(rust_atomics)]
60+
mod tests {
61+
use super::super::*;
62+
63+
// Call $fn($val) with each $type of $val.
64+
macro_rules! for_each_type {
65+
($val:literal in [$($type:ty),*] $fn:expr) => {
66+
$({
67+
let v: $type = $val;
68+
69+
$fn(v);
70+
})*
71+
}
72+
}
73+
74+
#[test]
75+
fn atomic_basic_tests() {
76+
for_each_type!(42 in [i32, i64, u32, u64] |v| {
77+
let x = Atomic::new(v);
78+
79+
assert_eq!(v, x.load(Relaxed));
80+
});
81+
}
82+
83+
#[test]
84+
fn atomic_xchg_tests() {
85+
for_each_type!(42 in [i32, i64, u32, u64] |v| {
86+
let x = Atomic::new(v);
87+
88+
let old = v;
89+
let new = v + 1;
90+
91+
assert_eq!(old, x.xchg(new, Full));
92+
assert_eq!(new, x.load(Relaxed));
93+
});
94+
}
95+
96+
#[test]
97+
fn atomic_cmpxchg_tests() {
98+
for_each_type!(42 in [i32, i64, u32, u64] |v| {
99+
let x = Atomic::new(v);
100+
101+
let old = v;
102+
let new = v + 1;
103+
104+
assert_eq!(Err(old), x.cmpxchg(new, new, Full));
105+
assert_eq!(old, x.load(Relaxed));
106+
assert_eq!(Ok(old), x.cmpxchg(old, new, Relaxed));
107+
assert_eq!(new, x.load(Relaxed));
108+
});
109+
}
110+
111+
#[test]
112+
fn atomic_arithmetic_tests() {
113+
for_each_type!(42 in [i32, i64, u32, u64] |v| {
114+
let x = Atomic::new(v);
115+
116+
assert_eq!(v, x.fetch_add(12, Full));
117+
assert_eq!(v + 12, x.load(Relaxed));
118+
119+
x.add(13, Relaxed);
120+
121+
assert_eq!(v + 25, x.load(Relaxed));
122+
});
123+
}
124+
}

0 commit comments

Comments
 (0)