kernel/sync/atomic.rs
1// SPDX-License-Identifier: GPL-2.0
2
3//! Atomic primitives.
4//!
5//! These primitives have the same semantics as their C counterparts: and the precise definitions of
6//! semantics can be found at [`LKMM`]. Note that Linux Kernel Memory (Consistency) Model is the
7//! only model for Rust code in kernel, and Rust's own atomics should be avoided.
8//!
9//! # Data races
10//!
11//! [`LKMM`] atomics have different rules regarding data races:
12//!
13//! - A normal write from C side is treated as an atomic write if
14//! CONFIG_KCSAN_ASSUME_PLAIN_WRITES_ATOMIC=y.
15//! - Mixed-size atomic accesses don't cause data races.
16//!
17//! [`LKMM`]: srctree/tools/memory-model/
18
19mod internal;
20pub mod ordering;
21mod predefine;
22
23pub use internal::AtomicImpl;
24pub use ordering::{Acquire, Full, Relaxed, Release};
25
26pub(crate) use internal::{AtomicArithmeticOps, AtomicBasicOps, AtomicExchangeOps};
27
28use crate::build_error;
29use internal::AtomicRepr;
30use ordering::OrderingType;
31
32/// A memory location which can be safely modified from multiple execution contexts.
33///
34/// This has the same size, alignment and bit validity as the underlying type `T`. And it disables
35/// niche optimization for the same reason as [`UnsafeCell`].
36///
37/// The atomic operations are implemented in a way that is fully compatible with the [Linux Kernel
38/// Memory (Consistency) Model][LKMM], hence they should be modeled as the corresponding
39/// [`LKMM`][LKMM] atomic primitives. With the help of [`Atomic::from_ptr()`] and
40/// [`Atomic::as_ptr()`], this provides a way to interact with [C-side atomic operations]
41/// (including those without the `atomic` prefix, e.g. `READ_ONCE()`, `WRITE_ONCE()`,
42/// `smp_load_acquire()` and `smp_store_release()`).
43///
44/// # Invariants
45///
46/// `self.0` is a valid `T`.
47///
48/// [`UnsafeCell`]: core::cell::UnsafeCell
49/// [LKMM]: srctree/tools/memory-model/
50/// [C-side atomic operations]: srctree/Documentation/atomic_t.txt
51#[repr(transparent)]
52pub struct Atomic<T: AtomicType>(AtomicRepr<T::Repr>);
53
54// SAFETY: `Atomic<T>` is safe to share among execution contexts because all accesses are atomic.
55unsafe impl<T: AtomicType> Sync for Atomic<T> {}
56
57/// Types that support basic atomic operations.
58///
59/// # Round-trip transmutability
60///
61/// `T` is round-trip transmutable to `U` if and only if both of these properties hold:
62///
63/// - Any valid bit pattern for `T` is also a valid bit pattern for `U`.
64/// - Transmuting (e.g. using [`transmute()`]) a value of type `T` to `U` and then to `T` again
65/// yields a value that is in all aspects equivalent to the original value.
66///
67/// # Safety
68///
69/// - [`Self`] must have the same size and alignment as [`Self::Repr`].
70/// - [`Self`] must be [round-trip transmutable] to [`Self::Repr`].
71///
72/// Note that this is more relaxed than requiring the bi-directional transmutability (i.e.
73/// [`transmute()`] is always sound between `U` and `T`) because of the support for atomic
74/// variables over unit-only enums, see [Examples].
75///
76/// # Limitations
77///
78/// Because C primitives are used to implement the atomic operations, and a C function requires a
79/// valid object of a type to operate on (i.e. no `MaybeUninit<_>`), hence at the Rust <-> C
80/// surface, only types with all the bits initialized can be passed. As a result, types like `(u8,
81/// u16)` (padding bytes are uninitialized) are currently not supported.
82///
83/// # Examples
84///
85/// A unit-only enum that implements [`AtomicType`]:
86///
87/// ```
88/// use kernel::sync::atomic::{AtomicType, Atomic, Relaxed};
89///
90/// #[derive(Clone, Copy, PartialEq, Eq)]
91/// #[repr(i32)]
92/// enum State {
93/// Uninit = 0,
94/// Working = 1,
95/// Done = 2,
96/// };
97///
98/// // SAFETY: `State` and `i32` has the same size and alignment, and it's round-trip
99/// // transmutable to `i32`.
100/// unsafe impl AtomicType for State {
101/// type Repr = i32;
102/// }
103///
104/// let s = Atomic::new(State::Uninit);
105///
106/// assert_eq!(State::Uninit, s.load(Relaxed));
107/// ```
108/// [`transmute()`]: core::mem::transmute
109/// [round-trip transmutable]: AtomicType#round-trip-transmutability
110/// [Examples]: AtomicType#examples
111pub unsafe trait AtomicType: Sized + Send + Copy {
112 /// The backing atomic implementation type.
113 type Repr: AtomicImpl;
114}
115
116/// Types that support atomic add operations.
117///
118/// # Safety
119///
120// TODO: Properly defines `wrapping_add` in the following comment.
121/// `wrapping_add` any value of type `Self::Repr::Delta` obtained by [`Self::rhs_into_delta()`] to
122/// any value of type `Self::Repr` obtained through transmuting a value of type `Self` to must
123/// yield a value with a bit pattern also valid for `Self`.
124pub unsafe trait AtomicAdd<Rhs = Self>: AtomicType {
125 /// Converts `Rhs` into the `Delta` type of the atomic implementation.
126 fn rhs_into_delta(rhs: Rhs) -> <Self::Repr as AtomicImpl>::Delta;
127}
128
129#[inline(always)]
130const fn into_repr<T: AtomicType>(v: T) -> T::Repr {
131 // SAFETY: Per the safety requirement of `AtomicType`, `T` is round-trip transmutable to
132 // `T::Repr`, therefore the transmute operation is sound.
133 unsafe { core::mem::transmute_copy(&v) }
134}
135
136/// # Safety
137///
138/// `r` must be a valid bit pattern of `T`.
139#[inline(always)]
140const unsafe fn from_repr<T: AtomicType>(r: T::Repr) -> T {
141 // SAFETY: Per the safety requirement of the function, the transmute operation is sound.
142 unsafe { core::mem::transmute_copy(&r) }
143}
144
145impl<T: AtomicType> Atomic<T> {
146 /// Creates a new atomic `T`.
147 pub const fn new(v: T) -> Self {
148 // INVARIANT: Per the safety requirement of `AtomicType`, `into_repr(v)` is a valid `T`.
149 Self(AtomicRepr::new(into_repr(v)))
150 }
151
152 /// Creates a reference to an atomic `T` from a pointer of `T`.
153 ///
154 /// This usually is used when communicating with C side or manipulating a C struct, see
155 /// examples below.
156 ///
157 /// # Safety
158 ///
159 /// - `ptr` is aligned to `align_of::<T>()`.
160 /// - `ptr` is valid for reads and writes for `'a`.
161 /// - For the duration of `'a`, other accesses to `*ptr` must not cause data races (defined
162 /// by [`LKMM`]) against atomic operations on the returned reference. Note that if all other
163 /// accesses are atomic, then this safety requirement is trivially fulfilled.
164 ///
165 /// [`LKMM`]: srctree/tools/memory-model
166 ///
167 /// # Examples
168 ///
169 /// Using [`Atomic::from_ptr()`] combined with [`Atomic::load()`] or [`Atomic::store()`] can
170 /// achieve the same functionality as `READ_ONCE()`/`smp_load_acquire()` or
171 /// `WRITE_ONCE()`/`smp_store_release()` in C side:
172 ///
173 /// ```
174 /// # use kernel::types::Opaque;
175 /// use kernel::sync::atomic::{Atomic, Relaxed, Release};
176 ///
177 /// // Assume there is a C struct `foo`.
178 /// mod cbindings {
179 /// #[repr(C)]
180 /// pub(crate) struct foo {
181 /// pub(crate) a: i32,
182 /// pub(crate) b: i32
183 /// }
184 /// }
185 ///
186 /// let tmp = Opaque::new(cbindings::foo { a: 1, b: 2 });
187 ///
188 /// // struct foo *foo_ptr = ..;
189 /// let foo_ptr = tmp.get();
190 ///
191 /// // SAFETY: `foo_ptr` is valid, and `.a` is in bounds.
192 /// let foo_a_ptr = unsafe { &raw mut (*foo_ptr).a };
193 ///
194 /// // a = READ_ONCE(foo_ptr->a);
195 /// //
196 /// // SAFETY: `foo_a_ptr` is valid for read, and all other accesses on it is atomic, so no
197 /// // data race.
198 /// let a = unsafe { Atomic::from_ptr(foo_a_ptr) }.load(Relaxed);
199 /// # assert_eq!(a, 1);
200 ///
201 /// // smp_store_release(&foo_ptr->a, 2);
202 /// //
203 /// // SAFETY: `foo_a_ptr` is valid for writes, and all other accesses on it is atomic, so
204 /// // no data race.
205 /// unsafe { Atomic::from_ptr(foo_a_ptr) }.store(2, Release);
206 /// ```
207 pub unsafe fn from_ptr<'a>(ptr: *mut T) -> &'a Self {
208 // CAST: `T` and `Atomic<T>` have the same size, alignment and bit validity.
209 // SAFETY: Per function safety requirement, `ptr` is a valid pointer and the object will
210 // live long enough. It's safe to return a `&Atomic<T>` because function safety requirement
211 // guarantees other accesses won't cause data races.
212 unsafe { &*ptr.cast::<Self>() }
213 }
214
215 /// Returns a pointer to the underlying atomic `T`.
216 ///
217 /// Note that use of the return pointer must not cause data races defined by [`LKMM`].
218 ///
219 /// # Guarantees
220 ///
221 /// The returned pointer is valid and properly aligned (i.e. aligned to [`align_of::<T>()`]).
222 ///
223 /// [`LKMM`]: srctree/tools/memory-model
224 /// [`align_of::<T>()`]: core::mem::align_of
225 pub const fn as_ptr(&self) -> *mut T {
226 // GUARANTEE: Per the function guarantee of `AtomicRepr::as_ptr()`, the `self.0.as_ptr()`
227 // must be a valid and properly aligned pointer for `T::Repr`, and per the safety guarantee
228 // of `AtomicType`, it's a valid and properly aligned pointer of `T`.
229 self.0.as_ptr().cast()
230 }
231
232 /// Returns a mutable reference to the underlying atomic `T`.
233 ///
234 /// This is safe because the mutable reference of the atomic `T` guarantees exclusive access.
235 pub fn get_mut(&mut self) -> &mut T {
236 // CAST: `T` and `T::Repr` has the same size and alignment per the safety requirement of
237 // `AtomicType`, and per the type invariants `self.0` is a valid `T`, therefore the casting
238 // result is a valid pointer of `T`.
239 // SAFETY: The pointer is valid per the CAST comment above, and the mutable reference
240 // guarantees exclusive access.
241 unsafe { &mut *self.0.as_ptr().cast() }
242 }
243}
244
245impl<T: AtomicType> Atomic<T>
246where
247 T::Repr: AtomicBasicOps,
248{
249 /// Loads the value from the atomic `T`.
250 ///
251 /// # Examples
252 ///
253 /// ```
254 /// use kernel::sync::atomic::{Atomic, Relaxed};
255 ///
256 /// let x = Atomic::new(42i32);
257 ///
258 /// assert_eq!(42, x.load(Relaxed));
259 ///
260 /// let x = Atomic::new(42i64);
261 ///
262 /// assert_eq!(42, x.load(Relaxed));
263 /// ```
264 #[doc(alias("atomic_read", "atomic64_read"))]
265 #[inline(always)]
266 pub fn load<Ordering: ordering::AcquireOrRelaxed>(&self, _: Ordering) -> T {
267 let v = {
268 match Ordering::TYPE {
269 OrderingType::Relaxed => T::Repr::atomic_read(&self.0),
270 OrderingType::Acquire => T::Repr::atomic_read_acquire(&self.0),
271 _ => build_error!("Wrong ordering"),
272 }
273 };
274
275 // SAFETY: `v` comes from reading `self.0`, which is a valid `T` per the type invariants.
276 unsafe { from_repr(v) }
277 }
278
279 /// Stores a value to the atomic `T`.
280 ///
281 /// # Examples
282 ///
283 /// ```
284 /// use kernel::sync::atomic::{Atomic, Relaxed};
285 ///
286 /// let x = Atomic::new(42i32);
287 ///
288 /// assert_eq!(42, x.load(Relaxed));
289 ///
290 /// x.store(43, Relaxed);
291 ///
292 /// assert_eq!(43, x.load(Relaxed));
293 /// ```
294 #[doc(alias("atomic_set", "atomic64_set"))]
295 #[inline(always)]
296 pub fn store<Ordering: ordering::ReleaseOrRelaxed>(&self, v: T, _: Ordering) {
297 let v = into_repr(v);
298
299 // INVARIANT: `v` is a valid `T`, and is stored to `self.0` by `atomic_set*()`.
300 match Ordering::TYPE {
301 OrderingType::Relaxed => T::Repr::atomic_set(&self.0, v),
302 OrderingType::Release => T::Repr::atomic_set_release(&self.0, v),
303 _ => build_error!("Wrong ordering"),
304 }
305 }
306}
307
308impl<T: AtomicType + core::fmt::Debug> core::fmt::Debug for Atomic<T>
309where
310 T::Repr: AtomicBasicOps,
311{
312 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
313 core::fmt::Debug::fmt(&self.load(Relaxed), f)
314 }
315}
316
317impl<T: AtomicType> Atomic<T>
318where
319 T::Repr: AtomicExchangeOps,
320{
321 /// Atomic exchange.
322 ///
323 /// Atomically updates `*self` to `v` and returns the old value of `*self`.
324 ///
325 /// # Examples
326 ///
327 /// ```
328 /// use kernel::sync::atomic::{Atomic, Acquire, Relaxed};
329 ///
330 /// let x = Atomic::new(42);
331 ///
332 /// assert_eq!(42, x.xchg(52, Acquire));
333 /// assert_eq!(52, x.load(Relaxed));
334 /// ```
335 #[doc(alias("atomic_xchg", "atomic64_xchg", "swap"))]
336 #[inline(always)]
337 pub fn xchg<Ordering: ordering::Ordering>(&self, v: T, _: Ordering) -> T {
338 let v = into_repr(v);
339
340 // INVARIANT: `self.0` is a valid `T` after `atomic_xchg*()` because `v` is transmutable to
341 // `T`.
342 let ret = {
343 match Ordering::TYPE {
344 OrderingType::Full => T::Repr::atomic_xchg(&self.0, v),
345 OrderingType::Acquire => T::Repr::atomic_xchg_acquire(&self.0, v),
346 OrderingType::Release => T::Repr::atomic_xchg_release(&self.0, v),
347 OrderingType::Relaxed => T::Repr::atomic_xchg_relaxed(&self.0, v),
348 }
349 };
350
351 // SAFETY: `ret` comes from reading `*self`, which is a valid `T` per type invariants.
352 unsafe { from_repr(ret) }
353 }
354
355 /// Atomic compare and exchange.
356 ///
357 /// If `*self` == `old`, atomically updates `*self` to `new`. Otherwise, `*self` is not
358 /// modified.
359 ///
360 /// Compare: The comparison is done via the byte level comparison between `*self` and `old`.
361 ///
362 /// Ordering: When succeeds, provides the corresponding ordering as the `Ordering` type
363 /// parameter indicates, and a failed one doesn't provide any ordering, the load part of a
364 /// failed cmpxchg is a [`Relaxed`] load.
365 ///
366 /// Returns `Ok(value)` if cmpxchg succeeds, and `value` is guaranteed to be equal to `old`,
367 /// otherwise returns `Err(value)`, and `value` is the current value of `*self`.
368 ///
369 /// # Examples
370 ///
371 /// ```
372 /// use kernel::sync::atomic::{Atomic, Full, Relaxed};
373 ///
374 /// let x = Atomic::new(42);
375 ///
376 /// // Checks whether cmpxchg succeeded.
377 /// let success = x.cmpxchg(52, 64, Relaxed).is_ok();
378 /// # assert!(!success);
379 ///
380 /// // Checks whether cmpxchg failed.
381 /// let failure = x.cmpxchg(52, 64, Relaxed).is_err();
382 /// # assert!(failure);
383 ///
384 /// // Uses the old value if failed, probably re-try cmpxchg.
385 /// match x.cmpxchg(52, 64, Relaxed) {
386 /// Ok(_) => { },
387 /// Err(old) => {
388 /// // do something with `old`.
389 /// # assert_eq!(old, 42);
390 /// }
391 /// }
392 ///
393 /// // Uses the latest value regardlessly, same as atomic_cmpxchg() in C.
394 /// let latest = x.cmpxchg(42, 64, Full).unwrap_or_else(|old| old);
395 /// # assert_eq!(42, latest);
396 /// assert_eq!(64, x.load(Relaxed));
397 /// ```
398 ///
399 /// [`Relaxed`]: ordering::Relaxed
400 #[doc(alias(
401 "atomic_cmpxchg",
402 "atomic64_cmpxchg",
403 "atomic_try_cmpxchg",
404 "atomic64_try_cmpxchg",
405 "compare_exchange"
406 ))]
407 #[inline(always)]
408 pub fn cmpxchg<Ordering: ordering::Ordering>(
409 &self,
410 mut old: T,
411 new: T,
412 o: Ordering,
413 ) -> Result<T, T> {
414 // Note on code generation:
415 //
416 // try_cmpxchg() is used to implement cmpxchg(), and if the helper functions are inlined,
417 // the compiler is able to figure out that branch is not needed if the users don't care
418 // about whether the operation succeeds or not. One exception is on x86, due to commit
419 // 44fe84459faf ("locking/atomic: Fix atomic_try_cmpxchg() semantics"), the
420 // atomic_try_cmpxchg() on x86 has a branch even if the caller doesn't care about the
421 // success of cmpxchg and only wants to use the old value. For example, for code like:
422 //
423 // let latest = x.cmpxchg(42, 64, Full).unwrap_or_else(|old| old);
424 //
425 // It will still generate code:
426 //
427 // movl $0x40, %ecx
428 // movl $0x34, %eax
429 // lock
430 // cmpxchgl %ecx, 0x4(%rsp)
431 // jne 1f
432 // 2:
433 // ...
434 // 1: movl %eax, %ecx
435 // jmp 2b
436 //
437 // This might be "fixed" by introducing a try_cmpxchg_exclusive() that knows the "*old"
438 // location in the C function is always safe to write.
439 if self.try_cmpxchg(&mut old, new, o) {
440 Ok(old)
441 } else {
442 Err(old)
443 }
444 }
445
446 /// Atomic compare and exchange and returns whether the operation succeeds.
447 ///
448 /// If `*self` == `old`, atomically updates `*self` to `new`. Otherwise, `*self` is not
449 /// modified, `*old` is updated to the current value of `*self`.
450 ///
451 /// "Compare" and "Ordering" part are the same as [`Atomic::cmpxchg()`].
452 ///
453 /// Returns `true` means the cmpxchg succeeds otherwise returns `false`.
454 #[inline(always)]
455 fn try_cmpxchg<Ordering: ordering::Ordering>(&self, old: &mut T, new: T, _: Ordering) -> bool {
456 let mut tmp = into_repr(*old);
457 let new = into_repr(new);
458
459 // INVARIANT: `self.0` is a valid `T` after `atomic_try_cmpxchg*()` because `new` is
460 // transmutable to `T`.
461 let ret = {
462 match Ordering::TYPE {
463 OrderingType::Full => T::Repr::atomic_try_cmpxchg(&self.0, &mut tmp, new),
464 OrderingType::Acquire => {
465 T::Repr::atomic_try_cmpxchg_acquire(&self.0, &mut tmp, new)
466 }
467 OrderingType::Release => {
468 T::Repr::atomic_try_cmpxchg_release(&self.0, &mut tmp, new)
469 }
470 OrderingType::Relaxed => {
471 T::Repr::atomic_try_cmpxchg_relaxed(&self.0, &mut tmp, new)
472 }
473 }
474 };
475
476 // SAFETY: `tmp` comes from reading `*self`, which is a valid `T` per type invariants.
477 *old = unsafe { from_repr(tmp) };
478
479 ret
480 }
481}
482
483impl<T: AtomicType> Atomic<T>
484where
485 T::Repr: AtomicArithmeticOps,
486{
487 /// Atomic add.
488 ///
489 /// Atomically updates `*self` to `(*self).wrapping_add(v)`.
490 ///
491 /// # Examples
492 ///
493 /// ```
494 /// use kernel::sync::atomic::{Atomic, Relaxed};
495 ///
496 /// let x = Atomic::new(42);
497 ///
498 /// assert_eq!(42, x.load(Relaxed));
499 ///
500 /// x.add(12, Relaxed);
501 ///
502 /// assert_eq!(54, x.load(Relaxed));
503 /// ```
504 #[inline(always)]
505 pub fn add<Rhs>(&self, v: Rhs, _: ordering::Relaxed)
506 where
507 T: AtomicAdd<Rhs>,
508 {
509 let v = T::rhs_into_delta(v);
510
511 // INVARIANT: `self.0` is a valid `T` after `atomic_add()` due to safety requirement of
512 // `AtomicAdd`.
513 T::Repr::atomic_add(&self.0, v);
514 }
515
516 /// Atomic fetch and add.
517 ///
518 /// Atomically updates `*self` to `(*self).wrapping_add(v)`, and returns the value of `*self`
519 /// before the update.
520 ///
521 /// # Examples
522 ///
523 /// ```
524 /// use kernel::sync::atomic::{Atomic, Acquire, Full, Relaxed};
525 ///
526 /// let x = Atomic::new(42);
527 ///
528 /// assert_eq!(42, x.load(Relaxed));
529 ///
530 /// assert_eq!(54, { x.fetch_add(12, Acquire); x.load(Relaxed) });
531 ///
532 /// let x = Atomic::new(42);
533 ///
534 /// assert_eq!(42, x.load(Relaxed));
535 ///
536 /// assert_eq!(54, { x.fetch_add(12, Full); x.load(Relaxed) } );
537 /// ```
538 #[inline(always)]
539 pub fn fetch_add<Rhs, Ordering: ordering::Ordering>(&self, v: Rhs, _: Ordering) -> T
540 where
541 T: AtomicAdd<Rhs>,
542 {
543 let v = T::rhs_into_delta(v);
544
545 // INVARIANT: `self.0` is a valid `T` after `atomic_fetch_add*()` due to safety requirement
546 // of `AtomicAdd`.
547 let ret = {
548 match Ordering::TYPE {
549 OrderingType::Full => T::Repr::atomic_fetch_add(&self.0, v),
550 OrderingType::Acquire => T::Repr::atomic_fetch_add_acquire(&self.0, v),
551 OrderingType::Release => T::Repr::atomic_fetch_add_release(&self.0, v),
552 OrderingType::Relaxed => T::Repr::atomic_fetch_add_relaxed(&self.0, v),
553 }
554 };
555
556 // SAFETY: `ret` comes from reading `self.0`, which is a valid `T` per type invariants.
557 unsafe { from_repr(ret) }
558 }
559}