1use core::cell::UnsafeCell;
2use core::fmt;
3use core::intrinsics;
4use core::intrinsics::AtomicOrdering;
5use core::sync::atomic::Ordering;
6
7macro_rules! atomic_int {
8 (
9 $atomic_type:ident,
10 $int_type:ident
11 ) => {
12 #[repr(align(16))]
13 pub struct $atomic_type {
14 v: UnsafeCell<$int_type>,
15 }
16
17 impl Default for $atomic_type {
18 #[inline]
19 fn default() -> Self {
20 Self::new(Default::default())
21 }
22 }
23
24 impl From<$int_type> for $atomic_type {
25 fn from(v: $int_type) -> Self {
26 Self::new(v)
27 }
28 }
29
30 impl fmt::Debug for $atomic_type {
31 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32 fmt::Debug::fmt(&self.load(Ordering::SeqCst), f)
33 }
34 }
35
36 unsafe impl Sync for $atomic_type {}
37
38 impl $atomic_type {
39 #[inline]
40 pub const fn new(v: $int_type) -> Self {
41 Self {
42 v: UnsafeCell::new(v),
43 }
44 }
45
46 #[inline]
47 pub fn get_mut(&mut self) -> &mut $int_type {
48 self.v.get_mut()
49 }
50
51 #[inline]
52 pub const fn into_inner(self) -> $int_type {
53 self.v.into_inner()
54 }
55
56 #[inline]
57 pub fn load(&self, order: Ordering) -> $int_type {
58 unsafe { atomic_load(self.v.get(), order) }
60 }
61
62 #[inline]
63 pub fn fetch_add(&self, v: $int_type, order: Ordering) -> $int_type {
64 unsafe { atomic_add(self.v.get(), v, order) }
66 }
67
68 pub fn compare_exchange(
69 &self,
70 current: $int_type,
71 new: $int_type,
72 success: Ordering,
73 failure: Ordering,
74 ) -> Result<$int_type, $int_type> {
75 unsafe { atomic_compare_exchange(self.v.get(), current, new, success, failure) }
77 }
78
79 #[inline]
80 pub fn store(&self, val: $int_type, order: Ordering) {
81 unsafe {
83 atomic_store(self.v.get(), val, order);
84 }
85 }
86 }
87 };
88}
89
90atomic_int!(AtomicU128, u128);
91atomic_int!(AtomicI128, i128);
92
93#[inline]
94unsafe fn atomic_load<T: Copy>(dst: *const T, order: Ordering) -> T {
95 unsafe {
96 match order {
98 Ordering::Acquire => intrinsics::atomic_load::<T, { AtomicOrdering::Acquire }>(dst),
99 Ordering::Relaxed => intrinsics::atomic_load::<T, { AtomicOrdering::Relaxed }>(dst),
100 Ordering::SeqCst => intrinsics::atomic_load::<T, { AtomicOrdering::SeqCst }>(dst),
101 Ordering::Release => panic!("there is no such thing as a release load"),
102 Ordering::AcqRel => panic!("there is no such thing as an acquire/release load"),
103 _ => core::hint::unreachable_unchecked(),
104 }
105 }
106}
107
108#[inline]
110unsafe fn atomic_add<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
111 unsafe {
112 match order {
114 Ordering::Acquire => {
115 intrinsics::atomic_xadd::<T, T, { AtomicOrdering::Acquire }>(dst, val)
116 }
117 Ordering::Release => {
118 intrinsics::atomic_xadd::<T, T, { AtomicOrdering::Release }>(dst, val)
119 }
120 Ordering::AcqRel => {
121 intrinsics::atomic_xadd::<T, T, { AtomicOrdering::AcqRel }>(dst, val)
122 }
123 Ordering::Relaxed => {
124 intrinsics::atomic_xadd::<T, T, { AtomicOrdering::Relaxed }>(dst, val)
125 }
126 Ordering::SeqCst => {
127 intrinsics::atomic_xadd::<T, T, { AtomicOrdering::SeqCst }>(dst, val)
128 }
129 _ => core::hint::unreachable_unchecked(),
130 }
131 }
132}
133
134#[inline]
135unsafe fn atomic_compare_exchange<T: Copy>(
136 dst: *mut T,
137 old: T,
138 new: T,
139 success: Ordering,
140 failure: Ordering,
141) -> Result<T, T> {
142 let (val, ok) = unsafe {
145 match (success, failure) {
146 (Ordering::Relaxed, Ordering::Relaxed) => intrinsics::atomic_cxchg::<
147 T,
148 { AtomicOrdering::Relaxed },
149 { AtomicOrdering::Relaxed },
150 >(dst, old, new),
151 (Ordering::Relaxed, Ordering::Acquire) => intrinsics::atomic_cxchg::<
152 T,
153 { AtomicOrdering::Relaxed },
154 { AtomicOrdering::Acquire },
155 >(dst, old, new),
156 (Ordering::Relaxed, Ordering::SeqCst) => {
157 intrinsics::atomic_cxchg::<T, { AtomicOrdering::Relaxed }, { AtomicOrdering::SeqCst }>(
158 dst, old, new,
159 )
160 }
161 (Ordering::Acquire, Ordering::Relaxed) => intrinsics::atomic_cxchg::<
162 T,
163 { AtomicOrdering::Acquire },
164 { AtomicOrdering::Relaxed },
165 >(dst, old, new),
166 (Ordering::Acquire, Ordering::Acquire) => intrinsics::atomic_cxchg::<
167 T,
168 { AtomicOrdering::Acquire },
169 { AtomicOrdering::Acquire },
170 >(dst, old, new),
171 (Ordering::Acquire, Ordering::SeqCst) => {
172 intrinsics::atomic_cxchg::<T, { AtomicOrdering::Acquire }, { AtomicOrdering::SeqCst }>(
173 dst, old, new,
174 )
175 }
176 (Ordering::Release, Ordering::Relaxed) => intrinsics::atomic_cxchg::<
177 T,
178 { AtomicOrdering::Release },
179 { AtomicOrdering::Relaxed },
180 >(dst, old, new),
181 (Ordering::Release, Ordering::Acquire) => intrinsics::atomic_cxchg::<
182 T,
183 { AtomicOrdering::Release },
184 { AtomicOrdering::Acquire },
185 >(dst, old, new),
186 (Ordering::Release, Ordering::SeqCst) => {
187 intrinsics::atomic_cxchg::<T, { AtomicOrdering::Release }, { AtomicOrdering::SeqCst }>(
188 dst, old, new,
189 )
190 }
191 (Ordering::AcqRel, Ordering::Relaxed) => {
192 intrinsics::atomic_cxchg::<T, { AtomicOrdering::AcqRel }, { AtomicOrdering::Relaxed }>(
193 dst, old, new,
194 )
195 }
196 (Ordering::AcqRel, Ordering::Acquire) => {
197 intrinsics::atomic_cxchg::<T, { AtomicOrdering::AcqRel }, { AtomicOrdering::Acquire }>(
198 dst, old, new,
199 )
200 }
201 (Ordering::AcqRel, Ordering::SeqCst) => {
202 intrinsics::atomic_cxchg::<T, { AtomicOrdering::AcqRel }, { AtomicOrdering::SeqCst }>(
203 dst, old, new,
204 )
205 }
206 (Ordering::SeqCst, Ordering::Relaxed) => {
207 intrinsics::atomic_cxchg::<T, { AtomicOrdering::SeqCst }, { AtomicOrdering::Relaxed }>(
208 dst, old, new,
209 )
210 }
211 (Ordering::SeqCst, Ordering::Acquire) => {
212 intrinsics::atomic_cxchg::<T, { AtomicOrdering::SeqCst }, { AtomicOrdering::Acquire }>(
213 dst, old, new,
214 )
215 }
216 (Ordering::SeqCst, Ordering::SeqCst) => {
217 intrinsics::atomic_cxchg::<T, { AtomicOrdering::SeqCst }, { AtomicOrdering::SeqCst }>(
218 dst, old, new,
219 )
220 }
221 (_, Ordering::AcqRel) => {
222 panic!("there is no such thing as an acquire-release failure ordering")
223 }
224 (_, Ordering::Release) => {
225 panic!("there is no such thing as a release failure ordering")
226 }
227 (_, _) => unreachable!(),
228 }
229 };
230 if ok { Ok(val) } else { Err(val) }
231}
232
233#[inline]
234unsafe fn atomic_store<T: Copy>(dst: *mut T, val: T, order: Ordering) {
235 unsafe {
236 match order {
238 Ordering::Release => {
239 intrinsics::atomic_store::<T, { AtomicOrdering::Release }>(dst, val)
240 }
241 Ordering::Relaxed => {
242 intrinsics::atomic_store::<T, { AtomicOrdering::Relaxed }>(dst, val)
243 }
244 Ordering::SeqCst => intrinsics::atomic_store::<T, { AtomicOrdering::SeqCst }>(dst, val),
245 Ordering::Acquire => panic!("there is no such thing as an acquire store"),
246 Ordering::AcqRel => panic!("there is no such thing as an acquire/release store"),
247 _ => core::hint::unreachable_unchecked(),
248 }
249 }
250}