Skip to main content

kernel/
relaxed_atomic.rs

1// Copyright 2026 The Fuchsia Authors
2//
3// Use of this source code is governed by a MIT-style
4// license that can be found in the LICENSE file or at
5// https://opensource.org/licenses/MIT
6
7use core::sync::atomic::{
8    AtomicI8, AtomicI16, AtomicI32, AtomicI64, AtomicIsize, AtomicU8, AtomicU16, AtomicU32,
9    AtomicU64, AtomicUsize,
10};
11
12use paste::paste;
13
14/// Wrapper around atomic types that assumes `Ordering::Relaxed` for all
15/// operations to simplify pure relaxed use cases.
16#[repr(transparent)]
17#[derive(Debug, Default)]
18pub struct RelaxedAtomic<T> {
19    wrapped: T,
20}
21
22// Use a macro to stamp out a bunch of implementations until generic_atomic is stabilized.
23// https://github.com/rust-lang/rust/issues/130539.
24#[macro_export]
25macro_rules! impl_relaxed_atomic {
26    ($atomic_type:ident, $prim_type:ty) => {
27        impl $crate::relaxed_atomic::RelaxedAtomic<$atomic_type> {
28            /// Creates a new `RelaxedAtomic`.
29            #[inline]
30            pub const fn new(value: $prim_type) -> Self {
31                Self { wrapped: $atomic_type::new(value) }
32            }
33
34            /// Loads the value with relaxed ordering.
35            #[inline]
36            pub fn load(&self) -> $prim_type {
37                self.wrapped.load(::core::sync::atomic::Ordering::Relaxed)
38            }
39
40            /// Stores the value with relaxed ordering.
41            #[inline]
42            pub fn store(&self, desired: $prim_type) {
43                self.wrapped.store(desired, ::core::sync::atomic::Ordering::Relaxed)
44            }
45
46            /// Adds to the current value, returning the previous value, with relaxed ordering.
47            #[inline]
48            pub fn fetch_add(&self, value: $prim_type) -> $prim_type {
49                self.wrapped.fetch_add(value, ::core::sync::atomic::Ordering::Relaxed)
50            }
51
52            /// Subtracts from the current value, returning the previous value, with relaxed
53            /// ordering.
54            #[inline]
55            pub fn fetch_sub(&self, value: $prim_type) -> $prim_type {
56                self.wrapped.fetch_sub(value, ::core::sync::atomic::Ordering::Relaxed)
57            }
58
59            /// Bitwise "and" with the current value, returning the previous value, with relaxed
60            /// ordering.
61            #[inline]
62            pub fn fetch_and(&self, value: $prim_type) -> $prim_type {
63                self.wrapped.fetch_and(value, ::core::sync::atomic::Ordering::Relaxed)
64            }
65
66            /// Bitwise "or" with the current value, returning the previous value, with relaxed
67            /// ordering.
68            #[inline]
69            pub fn fetch_or(&self, value: $prim_type) -> $prim_type {
70                self.wrapped.fetch_or(value, ::core::sync::atomic::Ordering::Relaxed)
71            }
72        }
73        paste! {
74            pub type [<Relaxed $atomic_type>] = $crate::relaxed_atomic::RelaxedAtomic<$atomic_type>;
75        }
76    };
77}
78
79impl_relaxed_atomic!(AtomicI8, i8);
80impl_relaxed_atomic!(AtomicI16, i16);
81impl_relaxed_atomic!(AtomicI32, i32);
82impl_relaxed_atomic!(AtomicI64, i64);
83impl_relaxed_atomic!(AtomicIsize, isize);
84impl_relaxed_atomic!(AtomicU8, u8);
85impl_relaxed_atomic!(AtomicU16, u16);
86impl_relaxed_atomic!(AtomicU32, u32);
87impl_relaxed_atomic!(AtomicU64, u64);
88impl_relaxed_atomic!(AtomicUsize, usize);