Skip to main content

kernel/
relaxed_atomic.rs

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