Skip to main content

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}