FILE
predefine.rs
File preview with syntax highlighting.
linux-6.19.14/rust/kernel/sync/atomic/predefine.rs
1// SPDX-License-Identifier: GPL-2.0 2 3//! Pre-defined atomic types 4 5use crate::static_assert; 6use core::mem::{align_of, size_of}; 7 8// SAFETY: `i32` has the same size and alignment with itself, and is round-trip transmutable to 9// itself. 10unsafe impl super::AtomicType for i32 { 11 type Repr = i32; 12} 13 14// SAFETY: The wrapping add result of two `i32`s is a valid `i32`. 15unsafe impl super::AtomicAdd<i32> for i32 { 16 fn rhs_into_delta(rhs: i32) -> i32 { 17 rhs 18 } 19} 20 21// SAFETY: `i64` has the same size and alignment with itself, and is round-trip transmutable to 22// itself. 23unsafe impl super::AtomicType for i64 { 24 type Repr = i64; 25} 26 27// SAFETY: The wrapping add result of two `i64`s is a valid `i64`. 28unsafe impl super::AtomicAdd<i64> for i64 { 29 fn rhs_into_delta(rhs: i64) -> i64 { 30 rhs 31 } 32} 33 34// Defines an internal type that always maps to the integer type which has the same size alignment 35// as `isize` and `usize`, and `isize` and `usize` are always bi-directional transmutable to 36// `isize_atomic_repr`, which also always implements `AtomicImpl`. 37#[allow(non_camel_case_types)] 38#[cfg(not(testlib))] 39#[cfg(not(CONFIG_64BIT))] 40type isize_atomic_repr = i32; 41#[allow(non_camel_case_types)] 42#[cfg(not(testlib))] 43#[cfg(CONFIG_64BIT)] 44type isize_atomic_repr = i64; 45 46#[allow(non_camel_case_types)] 47#[cfg(testlib)] 48#[cfg(target_pointer_width = "32")] 49type isize_atomic_repr = i32; 50#[allow(non_camel_case_types)] 51#[cfg(testlib)] 52#[cfg(target_pointer_width = "64")] 53type isize_atomic_repr = i64; 54 55// Ensure size and alignment requirements are checked. 56static_assert!(size_of::<isize>() == size_of::<isize_atomic_repr>()); 57static_assert!(align_of::<isize>() == align_of::<isize_atomic_repr>()); 58static_assert!(size_of::<usize>() == size_of::<isize_atomic_repr>()); 59static_assert!(align_of::<usize>() == align_of::<isize_atomic_repr>()); 60 61// SAFETY: `isize` has the same size and alignment with `isize_atomic_repr`, and is round-trip 62// transmutable to `isize_atomic_repr`. 63unsafe impl super::AtomicType for isize { 64 type Repr = isize_atomic_repr; 65} 66 67// SAFETY: The wrapping add result of two `isize_atomic_repr`s is a valid `usize`. 68unsafe impl super::AtomicAdd<isize> for isize { 69 fn rhs_into_delta(rhs: isize) -> isize_atomic_repr { 70 rhs as isize_atomic_repr 71 } 72} 73 74// SAFETY: `u32` and `i32` has the same size and alignment, and `u32` is round-trip transmutable to 75// `i32`. 76unsafe impl super::AtomicType for u32 { 77 type Repr = i32; 78} 79 80// SAFETY: The wrapping add result of two `i32`s is a valid `u32`. 81unsafe impl super::AtomicAdd<u32> for u32 { 82 fn rhs_into_delta(rhs: u32) -> i32 { 83 rhs as i32 84 } 85} 86 87// SAFETY: `u64` and `i64` has the same size and alignment, and `u64` is round-trip transmutable to 88// `i64`. 89unsafe impl super::AtomicType for u64 { 90 type Repr = i64; 91} 92 93// SAFETY: The wrapping add result of two `i64`s is a valid `u64`. 94unsafe impl super::AtomicAdd<u64> for u64 { 95 fn rhs_into_delta(rhs: u64) -> i64 { 96 rhs as i64 97 } 98} 99 100// SAFETY: `usize` has the same size and alignment with `isize_atomic_repr`, and is round-trip 101// transmutable to `isize_atomic_repr`. 102unsafe impl super::AtomicType for usize { 103 type Repr = isize_atomic_repr; 104} 105 106// SAFETY: The wrapping add result of two `isize_atomic_repr`s is a valid `usize`. 107unsafe impl super::AtomicAdd<usize> for usize { 108 fn rhs_into_delta(rhs: usize) -> isize_atomic_repr { 109 rhs as isize_atomic_repr 110 } 111} 112 113use crate::macros::kunit_tests; 114 115#[kunit_tests(rust_atomics)] 116mod tests { 117 use super::super::*; 118 119 // Call $fn($val) with each $type of $val. 120 macro_rules! for_each_type { 121 ($val:literal in [$($type:ty),*] $fn:expr) => { 122 $({ 123 let v: $type = $val; 124 125 $fn(v); 126 })* 127 } 128 } 129 130 #[test] 131 fn atomic_basic_tests() { 132 for_each_type!(42 in [i32, i64, u32, u64, isize, usize] |v| { 133 let x = Atomic::new(v); 134 135 assert_eq!(v, x.load(Relaxed)); 136 }); 137 } 138 139 #[test] 140 fn atomic_xchg_tests() { 141 for_each_type!(42 in [i32, i64, u32, u64, isize, usize] |v| { 142 let x = Atomic::new(v); 143 144 let old = v; 145 let new = v + 1; 146 147 assert_eq!(old, x.xchg(new, Full)); 148 assert_eq!(new, x.load(Relaxed)); 149 }); 150 } 151 152 #[test] 153 fn atomic_cmpxchg_tests() { 154 for_each_type!(42 in [i32, i64, u32, u64, isize, usize] |v| { 155 let x = Atomic::new(v); 156 157 let old = v; 158 let new = v + 1; 159 160 assert_eq!(Err(old), x.cmpxchg(new, new, Full)); 161 assert_eq!(old, x.load(Relaxed)); 162 assert_eq!(Ok(old), x.cmpxchg(old, new, Relaxed)); 163 assert_eq!(new, x.load(Relaxed)); 164 }); 165 } 166 167 #[test] 168 fn atomic_arithmetic_tests() { 169 for_each_type!(42 in [i32, i64, u32, u64, isize, usize] |v| { 170 let x = Atomic::new(v); 171 172 assert_eq!(v, x.fetch_add(12, Full)); 173 assert_eq!(v + 12, x.load(Relaxed)); 174 175 x.add(13, Relaxed); 176 177 assert_eq!(v + 25, x.load(Relaxed)); 178 }); 179 } 180}
~/
Read-only file preview.