1use crate::static_assert;
6use core::mem::{align_of, size_of};
7use ffi::c_void;
8
9static_assert!(size_of::<bool>() == size_of::<i8>());
11static_assert!(align_of::<bool>() == align_of::<i8>());
12
13unsafe impl super::AtomicType for bool {
17 type Repr = i8;
18}
19
20unsafe impl super::AtomicType for i8 {
23 type Repr = i8;
24}
25
26unsafe impl super::AtomicType for i16 {
29 type Repr = i16;
30}
31
32unsafe impl<T: Sized> super::AtomicType for *mut T {
39 type Repr = *const c_void;
40}
41
42unsafe impl<T: Sized> super::AtomicType for *const T {
49 type Repr = *const c_void;
50}
51
52unsafe impl super::AtomicType for i32 {
55 type Repr = i32;
56}
57
58unsafe impl super::AtomicAdd<i32> for i32 {
60 fn rhs_into_delta(rhs: i32) -> i32 {
61 rhs
62 }
63}
64
65unsafe impl super::AtomicType for i64 {
68 type Repr = i64;
69}
70
71unsafe impl super::AtomicAdd<i64> for i64 {
73 fn rhs_into_delta(rhs: i64) -> i64 {
74 rhs
75 }
76}
77
78#[allow(non_camel_case_types)]
82#[cfg(not(testlib))]
83#[cfg(not(CONFIG_64BIT))]
84type isize_atomic_repr = i32;
85#[allow(non_camel_case_types)]
86#[cfg(not(testlib))]
87#[cfg(CONFIG_64BIT)]
88type isize_atomic_repr = i64;
89
90#[allow(non_camel_case_types)]
91#[cfg(testlib)]
92#[cfg(target_pointer_width = "32")]
93type isize_atomic_repr = i32;
94#[allow(non_camel_case_types)]
95#[cfg(testlib)]
96#[cfg(target_pointer_width = "64")]
97type isize_atomic_repr = i64;
98
99static_assert!(size_of::<isize>() == size_of::<isize_atomic_repr>());
101static_assert!(align_of::<isize>() == align_of::<isize_atomic_repr>());
102static_assert!(size_of::<usize>() == size_of::<isize_atomic_repr>());
103static_assert!(align_of::<usize>() == align_of::<isize_atomic_repr>());
104
105unsafe impl super::AtomicType for isize {
108 type Repr = isize_atomic_repr;
109}
110
111unsafe impl super::AtomicAdd<isize> for isize {
113 fn rhs_into_delta(rhs: isize) -> isize_atomic_repr {
114 rhs as isize_atomic_repr
115 }
116}
117
118unsafe impl super::AtomicType for u32 {
121 type Repr = i32;
122}
123
124unsafe impl super::AtomicAdd<u32> for u32 {
126 fn rhs_into_delta(rhs: u32) -> i32 {
127 rhs as i32
128 }
129}
130
131unsafe impl super::AtomicType for u64 {
134 type Repr = i64;
135}
136
137unsafe impl super::AtomicAdd<u64> for u64 {
139 fn rhs_into_delta(rhs: u64) -> i64 {
140 rhs as i64
141 }
142}
143
144unsafe impl super::AtomicType for usize {
147 type Repr = isize_atomic_repr;
148}
149
150unsafe impl super::AtomicAdd<usize> for usize {
152 fn rhs_into_delta(rhs: usize) -> isize_atomic_repr {
153 rhs as isize_atomic_repr
154 }
155}
156
157#[cfg(CONFIG_RUST_ATOMICS_KUNIT_TEST)]
158#[macros::kunit_tests(rust_atomics)]
159mod tests {
160 use super::super::*;
161
162 macro_rules! for_each_type {
164 ($val:literal in [$($type:ty),*] $fn:expr) => {
165 $({
166 let v: $type = $val;
167
168 $fn(v);
169 })*
170 }
171 }
172
173 #[test]
174 fn atomic_basic_tests() {
175 for_each_type!(42 in [i8, i16, i32, i64, u32, u64, isize, usize] |v| {
176 let x = Atomic::new(v);
177
178 assert_eq!(v, x.load(Relaxed));
179 });
180
181 for_each_type!(42 in [i8, i16, i32, i64, u32, u64, isize, usize] |v| {
182 let x = Atomic::new(v);
183 let ptr = x.as_ptr();
184
185 assert_eq!(v, unsafe { atomic_load(ptr, Relaxed) });
187 });
188 }
189
190 #[test]
191 fn atomic_acquire_release_tests() {
192 for_each_type!(42 in [i8, i16, i32, i64, u32, u64, isize, usize] |v| {
193 let x = Atomic::new(0);
194
195 x.store(v, Release);
196 assert_eq!(v, x.load(Acquire));
197 });
198
199 for_each_type!(42 in [i8, i16, i32, i64, u32, u64, isize, usize] |v| {
200 let x = Atomic::new(0);
201 let ptr = x.as_ptr();
202
203 unsafe { atomic_store(ptr, v, Release) };
205
206 assert_eq!(v, unsafe { atomic_load(ptr, Acquire) });
208 });
209 }
210
211 #[test]
212 fn atomic_xchg_tests() {
213 for_each_type!(42 in [i8, i16, i32, i64, u32, u64, isize, usize] |v| {
214 let x = Atomic::new(v);
215
216 let old = v;
217 let new = v + 1;
218
219 assert_eq!(old, x.xchg(new, Full));
220 assert_eq!(new, x.load(Relaxed));
221 });
222
223 for_each_type!(42 in [i8, i16, i32, i64, u32, u64, isize, usize] |v| {
224 let x = Atomic::new(v);
225 let ptr = x.as_ptr();
226
227 let old = v;
228 let new = v + 1;
229
230 assert_eq!(old, unsafe { xchg(ptr, new, Full) });
232 assert_eq!(new, x.load(Relaxed));
233 });
234 }
235
236 #[test]
237 fn atomic_cmpxchg_tests() {
238 for_each_type!(42 in [i8, i16, i32, i64, u32, u64, isize, usize] |v| {
239 let x = Atomic::new(v);
240
241 let old = v;
242 let new = v + 1;
243
244 assert_eq!(Err(old), x.cmpxchg(new, new, Full));
245 assert_eq!(old, x.load(Relaxed));
246 assert_eq!(Ok(old), x.cmpxchg(old, new, Relaxed));
247 assert_eq!(new, x.load(Relaxed));
248 });
249
250 for_each_type!(42 in [i8, i16, i32, i64, u32, u64, isize, usize] |v| {
251 let x = Atomic::new(v);
252 let ptr = x.as_ptr();
253
254 let old = v;
255 let new = v + 1;
256
257 assert_eq!(Err(old), unsafe { cmpxchg(ptr, new, new, Full) });
259 assert_eq!(old, x.load(Relaxed));
260 assert_eq!(Ok(old), unsafe { cmpxchg(ptr, old, new, Relaxed) });
262 assert_eq!(new, x.load(Relaxed));
263 });
264 }
265
266 #[test]
267 fn atomic_arithmetic_tests() {
268 for_each_type!(42 in [i32, i64, u32, u64, isize, usize] |v| {
269 let x = Atomic::new(v);
270
271 assert_eq!(v, x.fetch_add(12, Full));
272 assert_eq!(v + 12, x.load(Relaxed));
273
274 x.add(13, Relaxed);
275
276 assert_eq!(v + 25, x.load(Relaxed));
277 });
278 }
279
280 #[test]
281 fn atomic_bool_tests() {
282 let x = Atomic::new(false);
283
284 assert_eq!(false, x.load(Relaxed));
285 x.store(true, Relaxed);
286 assert_eq!(true, x.load(Relaxed));
287
288 assert_eq!(true, x.xchg(false, Relaxed));
289 assert_eq!(false, x.load(Relaxed));
290
291 assert_eq!(Err(false), x.cmpxchg(true, true, Relaxed));
292 assert_eq!(false, x.load(Relaxed));
293 assert_eq!(Ok(false), x.cmpxchg(false, true, Full));
294 }
295
296 #[test]
297 fn atomic_ptr_tests() {
298 let mut v = 42;
299 let mut u = 43;
300 let x = Atomic::new(&raw mut v);
301
302 assert_eq!(x.load(Acquire), &raw mut v);
303 assert_eq!(x.cmpxchg(&raw mut u, &raw mut u, Relaxed), Err(&raw mut v));
304 assert_eq!(x.cmpxchg(&raw mut v, &raw mut u, Relaxed), Ok(&raw mut v));
305 assert_eq!(x.load(Relaxed), &raw mut u);
306
307 let x = Atomic::new(&raw const v);
308
309 assert_eq!(x.load(Acquire), &raw const v);
310 assert_eq!(
311 x.cmpxchg(&raw const u, &raw const u, Relaxed),
312 Err(&raw const v)
313 );
314 assert_eq!(
315 x.cmpxchg(&raw const v, &raw const u, Relaxed),
316 Ok(&raw const v)
317 );
318 assert_eq!(x.load(Relaxed), &raw const u);
319 }
320
321 #[test]
322 fn atomic_flag_tests() {
323 let mut flag = AtomicFlag::new(false);
324
325 assert_eq!(false, flag.load(Relaxed));
326
327 *flag.get_mut() = true;
328 assert_eq!(true, flag.load(Relaxed));
329
330 assert_eq!(true, flag.xchg(false, Relaxed));
331 assert_eq!(false, flag.load(Relaxed));
332
333 *flag.get_mut() = true;
334 assert_eq!(Ok(true), flag.cmpxchg(true, false, Full));
335 assert_eq!(false, flag.load(Relaxed));
336 }
337}