[RFC 2/2] rust: sync: Add atomic support

Boqun Feng
2024-06-12T22:31:06Z

Provide two atomic types: AtomicI32 and AtomicI64 with the existing
implemenation of C atomics. These atomics have the same semantics of the
corresponding LKMM C atomics, and using one memory (ordering) model
certainly reduces the reasoning difficulty and potential bugs from the
interaction of two different memory models.

Also bump my role to the maintainer of ATOMIC INFRASTRUCTURE to reflect
my responsiblity on these Rust APIs.

Note that `Atomic*::new()`s are implemented vi open coding on struct
atomic*_t. This allows `new()` being a `const` function, so that it can
be used in constant contexts.

Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
---
MAINTAINERS | 4 +-
arch/arm64/kernel/cpufeature.c | 2 +
rust/kernel/sync.rs | 1 +
rust/kernel/sync/atomic.rs | 63 ++
rust/kernel/sync/atomic/impl.rs | 1375 +++++++++++++++++++++++++++++
scripts/atomic/gen-atomics.sh | 1 +
scripts/atomic/gen-rust-atomic.sh | 136 +++
7 files changed, 1581 insertions(+), 1 deletion(-)
create mode 100644 rust/kernel/sync/atomic.rs
create mode 100644 rust/kernel/sync/atomic/impl.rs
create mode 100755 scripts/atomic/gen-rust-atomic.sh

diff --git a/MAINTAINERS b/MAINTAINERS
index d6c90161c7bf..a8528d27b260 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3458,7 +3458,7 @@ F: drivers/input/touchscreen/atmel_mxt_ts.c
ATOMIC INFRASTRUCTURE
M: Will Deacon <will@kernel.org>
M: Peter Zijlstra <peterz@infradead.org>
-R: Boqun Feng <boqun.feng@gmail.com>
+M: Boqun Feng <boqun.feng@gmail.com>
R: Mark Rutland <mark.rutland@arm.com>
L: linux-kernel@vger.kernel.org
S: Maintained
@@ -3467,6 +3467,8 @@ F: arch/*/include/asm/atomic*.h
F: include/*/atomic*.h
F: include/linux/refcount.h
F: scripts/atomic/
+F: rust/kernel/sync/atomic.rs
+F: rust/kernel/sync/atomic/

ATTO EXPRESSSAS SAS/SATA RAID SCSI DRIVER
M: Bradley Grove <linuxdrivers@attotech.com>
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 48e7029f1054..99e6e2b2867f 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -1601,6 +1601,8 @@ static bool
has_cpuid_feature(const struct arm64_cpu_capabilities *entry, int scope)
{
u64 val = read_scoped_sysreg(entry, scope);
+ if (entry->capability == ARM64_HAS_LSE_ATOMICS)
+ return false;
return feature_matches(val, entry);
}

diff --git a/rust/kernel/sync.rs b/rust/kernel/sync.rs
index 0ab20975a3b5..66ac3752ca71 100644
--- a/rust/kernel/sync.rs
+++ b/rust/kernel/sync.rs
@@ -8,6 +8,7 @@
use crate::types::Opaque;

mod arc;
+pub mod atomic;
mod condvar;
pub mod lock;
mod locked_by;
diff --git a/rust/kernel/sync/atomic.rs b/rust/kernel/sync/atomic.rs
new file mode 100644
index 000000000000..b0f852cf1741
--- /dev/null
+++ b/rust/kernel/sync/atomic.rs
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Atomic primitives.
+//!
+//! These primitives have the same semantics as their C counterparts, for precise definitions of
+//! the semantics, please refer to tools/memory-model. Note that Linux Kernel Memory (Consistency)
+//! Model is the only model for Rust development in kernel right now, please avoid to use Rust's
+//! own atomics.
+
+use crate::bindings::{atomic64_t, atomic_t};
+use crate::types::Opaque;
+
+mod r#impl;
+
+/// Atomic 32bit signed integers.
+pub struct AtomicI32(Opaque<atomic_t>);
+
+/// Atomic 64bit signed integers.
+pub struct AtomicI64(Opaque<atomic64_t>);
+
+impl AtomicI32 {
+ /// Creates an atomic variable with initial value `v`.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// # use kernel::sync::atomic::*;
+ ///
+ /// let x = AtomicI32::new(0);
+ ///
+ /// assert_eq!(x.read(), 0);
+ /// assert_eq!(x.fetch_add_relaxed(12), 0);
+ /// assert_eq!(x.read(), 12);
+ /// ```
+ pub const fn new(v: i32) -> Self {
+ AtomicI32(Opaque::new(atomic_t { counter: v }))
+ }
+}
+
+// SAFETY: `AtomicI32` is safe to share among execution contexts because all accesses are atomic.
+unsafe impl Sync for AtomicI32 {}
+
+impl AtomicI64 {
+ /// Creates an atomic variable with initial value `v`.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// # use kernel::sync::atomic::*;
+ ///
+ /// let x = AtomicI64::new(0);
+ ///
+ /// assert_eq!(x.read(), 0);
+ /// assert_eq!(x.fetch_add_relaxed(12), 0);
+ /// assert_eq!(x.read(), 12);
+ /// ```
+ pub const fn new(v: i64) -> Self {
+ AtomicI64(Opaque::new(atomic64_t { counter: v }))
+ }
+}
+
+// SAFETY: `AtomicI64` is safe to share among execution contexts because all accesses are atomic.
+unsafe impl Sync for AtomicI64 {}
diff --git a/rust/kernel/sync/atomic/impl.rs b/rust/kernel/sync/atomic/impl.rs
new file mode 100644
index 000000000000..1bbb0a714834
--- /dev/null
+++ b/rust/kernel/sync/atomic/impl.rs
@@ -0,0 +1,1375 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Generated by scripts/atomic/gen-rust-atomic.sh
+//! DO NOT MODIFY THIS FILE DIRECTLY
+
+use super::*;
+use crate::bindings::*;
+
+impl AtomicI32 {
+ /// See `atomic_read`.
+ #[inline(always)]
+ pub fn read(&self) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_read(self.0.get());
+ }
+ }
+ /// See `atomic_read_acquire`.
+ #[inline(always)]
+ pub fn read_acquire(&self) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_read_acquire(self.0.get());
+ }
+ }
+ /// See `atomic_set`.
+ #[inline(always)]
+ pub fn set(&self, i: i32) {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ atomic_set(self.0.get(), i);
+ }
+ }
+ /// See `atomic_set_release`.
+ #[inline(always)]
+ pub fn set_release(&self, i: i32) {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ atomic_set_release(self.0.get(), i);
+ }
+ }
+ /// See `atomic_add`.
+ #[inline(always)]
+ pub fn add(&self, i: i32) {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ atomic_add(i, self.0.get());
+ }
+ }
+ /// See `atomic_add_return`.
+ #[inline(always)]
+ pub fn add_return(&self, i: i32) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_add_return(i, self.0.get());
+ }
+ }
+ /// See `atomic_add_return_acquire`.
+ #[inline(always)]
+ pub fn add_return_acquire(&self, i: i32) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_add_return_acquire(i, self.0.get());
+ }
+ }
+ /// See `atomic_add_return_release`.
+ #[inline(always)]
+ pub fn add_return_release(&self, i: i32) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_add_return_release(i, self.0.get());
+ }
+ }
+ /// See `atomic_add_return_relaxed`.
+ #[inline(always)]
+ pub fn add_return_relaxed(&self, i: i32) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_add_return_relaxed(i, self.0.get());
+ }
+ }
+ /// See `atomic_fetch_add`.
+ #[inline(always)]
+ pub fn fetch_add(&self, i: i32) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_fetch_add(i, self.0.get());
+ }
+ }
+ /// See `atomic_fetch_add_acquire`.
+ #[inline(always)]
+ pub fn fetch_add_acquire(&self, i: i32) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_fetch_add_acquire(i, self.0.get());
+ }
+ }
+ /// See `atomic_fetch_add_release`.
+ #[inline(always)]
+ pub fn fetch_add_release(&self, i: i32) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_fetch_add_release(i, self.0.get());
+ }
+ }
+ /// See `atomic_fetch_add_relaxed`.
+ #[inline(always)]
+ pub fn fetch_add_relaxed(&self, i: i32) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_fetch_add_relaxed(i, self.0.get());
+ }
+ }
+ /// See `atomic_sub`.
+ #[inline(always)]
+ pub fn sub(&self, i: i32) {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ atomic_sub(i, self.0.get());
+ }
+ }
+ /// See `atomic_sub_return`.
+ #[inline(always)]
+ pub fn sub_return(&self, i: i32) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_sub_return(i, self.0.get());
+ }
+ }
+ /// See `atomic_sub_return_acquire`.
+ #[inline(always)]
+ pub fn sub_return_acquire(&self, i: i32) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_sub_return_acquire(i, self.0.get());
+ }
+ }
+ /// See `atomic_sub_return_release`.
+ #[inline(always)]
+ pub fn sub_return_release(&self, i: i32) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_sub_return_release(i, self.0.get());
+ }
+ }
+ /// See `atomic_sub_return_relaxed`.
+ #[inline(always)]
+ pub fn sub_return_relaxed(&self, i: i32) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_sub_return_relaxed(i, self.0.get());
+ }
+ }
+ /// See `atomic_fetch_sub`.
+ #[inline(always)]
+ pub fn fetch_sub(&self, i: i32) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_fetch_sub(i, self.0.get());
+ }
+ }
+ /// See `atomic_fetch_sub_acquire`.
+ #[inline(always)]
+ pub fn fetch_sub_acquire(&self, i: i32) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_fetch_sub_acquire(i, self.0.get());
+ }
+ }
+ /// See `atomic_fetch_sub_release`.
+ #[inline(always)]
+ pub fn fetch_sub_release(&self, i: i32) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_fetch_sub_release(i, self.0.get());
+ }
+ }
+ /// See `atomic_fetch_sub_relaxed`.
+ #[inline(always)]
+ pub fn fetch_sub_relaxed(&self, i: i32) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_fetch_sub_relaxed(i, self.0.get());
+ }
+ }
+ /// See `atomic_inc`.
+ #[inline(always)]
+ pub fn inc(&self) {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ atomic_inc(self.0.get());
+ }
+ }
+ /// See `atomic_inc_return`.
+ #[inline(always)]
+ pub fn inc_return(&self) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_inc_return(self.0.get());
+ }
+ }
+ /// See `atomic_inc_return_acquire`.
+ #[inline(always)]
+ pub fn inc_return_acquire(&self) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_inc_return_acquire(self.0.get());
+ }
+ }
+ /// See `atomic_inc_return_release`.
+ #[inline(always)]
+ pub fn inc_return_release(&self) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_inc_return_release(self.0.get());
+ }
+ }
+ /// See `atomic_inc_return_relaxed`.
+ #[inline(always)]
+ pub fn inc_return_relaxed(&self) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_inc_return_relaxed(self.0.get());
+ }
+ }
+ /// See `atomic_fetch_inc`.
+ #[inline(always)]
+ pub fn fetch_inc(&self) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_fetch_inc(self.0.get());
+ }
+ }
+ /// See `atomic_fetch_inc_acquire`.
+ #[inline(always)]
+ pub fn fetch_inc_acquire(&self) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_fetch_inc_acquire(self.0.get());
+ }
+ }
+ /// See `atomic_fetch_inc_release`.
+ #[inline(always)]
+ pub fn fetch_inc_release(&self) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_fetch_inc_release(self.0.get());
+ }
+ }
+ /// See `atomic_fetch_inc_relaxed`.
+ #[inline(always)]
+ pub fn fetch_inc_relaxed(&self) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_fetch_inc_relaxed(self.0.get());
+ }
+ }
+ /// See `atomic_dec`.
+ #[inline(always)]
+ pub fn dec(&self) {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ atomic_dec(self.0.get());
+ }
+ }
+ /// See `atomic_dec_return`.
+ #[inline(always)]
+ pub fn dec_return(&self) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_dec_return(self.0.get());
+ }
+ }
+ /// See `atomic_dec_return_acquire`.
+ #[inline(always)]
+ pub fn dec_return_acquire(&self) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_dec_return_acquire(self.0.get());
+ }
+ }
+ /// See `atomic_dec_return_release`.
+ #[inline(always)]
+ pub fn dec_return_release(&self) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_dec_return_release(self.0.get());
+ }
+ }
+ /// See `atomic_dec_return_relaxed`.
+ #[inline(always)]
+ pub fn dec_return_relaxed(&self) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_dec_return_relaxed(self.0.get());
+ }
+ }
+ /// See `atomic_fetch_dec`.
+ #[inline(always)]
+ pub fn fetch_dec(&self) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_fetch_dec(self.0.get());
+ }
+ }
+ /// See `atomic_fetch_dec_acquire`.
+ #[inline(always)]
+ pub fn fetch_dec_acquire(&self) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_fetch_dec_acquire(self.0.get());
+ }
+ }
+ /// See `atomic_fetch_dec_release`.
+ #[inline(always)]
+ pub fn fetch_dec_release(&self) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_fetch_dec_release(self.0.get());
+ }
+ }
+ /// See `atomic_fetch_dec_relaxed`.
+ #[inline(always)]
+ pub fn fetch_dec_relaxed(&self) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_fetch_dec_relaxed(self.0.get());
+ }
+ }
+ /// See `atomic_and`.
+ #[inline(always)]
+ pub fn and(&self, i: i32) {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ atomic_and(i, self.0.get());
+ }
+ }
+ /// See `atomic_fetch_and`.
+ #[inline(always)]
+ pub fn fetch_and(&self, i: i32) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_fetch_and(i, self.0.get());
+ }
+ }
+ /// See `atomic_fetch_and_acquire`.
+ #[inline(always)]
+ pub fn fetch_and_acquire(&self, i: i32) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_fetch_and_acquire(i, self.0.get());
+ }
+ }
+ /// See `atomic_fetch_and_release`.
+ #[inline(always)]
+ pub fn fetch_and_release(&self, i: i32) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_fetch_and_release(i, self.0.get());
+ }
+ }
+ /// See `atomic_fetch_and_relaxed`.
+ #[inline(always)]
+ pub fn fetch_and_relaxed(&self, i: i32) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_fetch_and_relaxed(i, self.0.get());
+ }
+ }
+ /// See `atomic_andnot`.
+ #[inline(always)]
+ pub fn andnot(&self, i: i32) {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ atomic_andnot(i, self.0.get());
+ }
+ }
+ /// See `atomic_fetch_andnot`.
+ #[inline(always)]
+ pub fn fetch_andnot(&self, i: i32) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_fetch_andnot(i, self.0.get());
+ }
+ }
+ /// See `atomic_fetch_andnot_acquire`.
+ #[inline(always)]
+ pub fn fetch_andnot_acquire(&self, i: i32) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_fetch_andnot_acquire(i, self.0.get());
+ }
+ }
+ /// See `atomic_fetch_andnot_release`.
+ #[inline(always)]
+ pub fn fetch_andnot_release(&self, i: i32) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_fetch_andnot_release(i, self.0.get());
+ }
+ }
+ /// See `atomic_fetch_andnot_relaxed`.
+ #[inline(always)]
+ pub fn fetch_andnot_relaxed(&self, i: i32) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_fetch_andnot_relaxed(i, self.0.get());
+ }
+ }
+ /// See `atomic_or`.
+ #[inline(always)]
+ pub fn or(&self, i: i32) {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ atomic_or(i, self.0.get());
+ }
+ }
+ /// See `atomic_fetch_or`.
+ #[inline(always)]
+ pub fn fetch_or(&self, i: i32) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_fetch_or(i, self.0.get());
+ }
+ }
+ /// See `atomic_fetch_or_acquire`.
+ #[inline(always)]
+ pub fn fetch_or_acquire(&self, i: i32) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_fetch_or_acquire(i, self.0.get());
+ }
+ }
+ /// See `atomic_fetch_or_release`.
+ #[inline(always)]
+ pub fn fetch_or_release(&self, i: i32) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_fetch_or_release(i, self.0.get());
+ }
+ }
+ /// See `atomic_fetch_or_relaxed`.
+ #[inline(always)]
+ pub fn fetch_or_relaxed(&self, i: i32) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_fetch_or_relaxed(i, self.0.get());
+ }
+ }
+ /// See `atomic_xor`.
+ #[inline(always)]
+ pub fn xor(&self, i: i32) {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ atomic_xor(i, self.0.get());
+ }
+ }
+ /// See `atomic_fetch_xor`.
+ #[inline(always)]
+ pub fn fetch_xor(&self, i: i32) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_fetch_xor(i, self.0.get());
+ }
+ }
+ /// See `atomic_fetch_xor_acquire`.
+ #[inline(always)]
+ pub fn fetch_xor_acquire(&self, i: i32) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_fetch_xor_acquire(i, self.0.get());
+ }
+ }
+ /// See `atomic_fetch_xor_release`.
+ #[inline(always)]
+ pub fn fetch_xor_release(&self, i: i32) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_fetch_xor_release(i, self.0.get());
+ }
+ }
+ /// See `atomic_fetch_xor_relaxed`.
+ #[inline(always)]
+ pub fn fetch_xor_relaxed(&self, i: i32) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_fetch_xor_relaxed(i, self.0.get());
+ }
+ }
+ /// See `atomic_xchg`.
+ #[inline(always)]
+ pub fn xchg(&self, new: i32) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_xchg(self.0.get(), new);
+ }
+ }
+ /// See `atomic_xchg_acquire`.
+ #[inline(always)]
+ pub fn xchg_acquire(&self, new: i32) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_xchg_acquire(self.0.get(), new);
+ }
+ }
+ /// See `atomic_xchg_release`.
+ #[inline(always)]
+ pub fn xchg_release(&self, new: i32) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_xchg_release(self.0.get(), new);
+ }
+ }
+ /// See `atomic_xchg_relaxed`.
+ #[inline(always)]
+ pub fn xchg_relaxed(&self, new: i32) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_xchg_relaxed(self.0.get(), new);
+ }
+ }
+ /// See `atomic_cmpxchg`.
+ #[inline(always)]
+ pub fn cmpxchg(&self, old: i32, new: i32) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_cmpxchg(self.0.get(), old, new);
+ }
+ }
+ /// See `atomic_cmpxchg_acquire`.
+ #[inline(always)]
+ pub fn cmpxchg_acquire(&self, old: i32, new: i32) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_cmpxchg_acquire(self.0.get(), old, new);
+ }
+ }
+ /// See `atomic_cmpxchg_release`.
+ #[inline(always)]
+ pub fn cmpxchg_release(&self, old: i32, new: i32) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_cmpxchg_release(self.0.get(), old, new);
+ }
+ }
+ /// See `atomic_cmpxchg_relaxed`.
+ #[inline(always)]
+ pub fn cmpxchg_relaxed(&self, old: i32, new: i32) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_cmpxchg_relaxed(self.0.get(), old, new);
+ }
+ }
+ /// See `atomic_try_cmpxchg`.
+ #[inline(always)]
+ pub fn try_cmpxchg(&self, old: &mut i32, new: i32) -> bool {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_try_cmpxchg(self.0.get(), old, new);
+ }
+ }
+ /// See `atomic_try_cmpxchg_acquire`.
+ #[inline(always)]
+ pub fn try_cmpxchg_acquire(&self, old: &mut i32, new: i32) -> bool {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_try_cmpxchg_acquire(self.0.get(), old, new);
+ }
+ }
+ /// See `atomic_try_cmpxchg_release`.
+ #[inline(always)]
+ pub fn try_cmpxchg_release(&self, old: &mut i32, new: i32) -> bool {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_try_cmpxchg_release(self.0.get(), old, new);
+ }
+ }
+ /// See `atomic_try_cmpxchg_relaxed`.
+ #[inline(always)]
+ pub fn try_cmpxchg_relaxed(&self, old: &mut i32, new: i32) -> bool {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_try_cmpxchg_relaxed(self.0.get(), old, new);
+ }
+ }
+ /// See `atomic_sub_and_test`.
+ #[inline(always)]
+ pub fn sub_and_test(&self, i: i32) -> bool {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_sub_and_test(i, self.0.get());
+ }
+ }
+ /// See `atomic_dec_and_test`.
+ #[inline(always)]
+ pub fn dec_and_test(&self) -> bool {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_dec_and_test(self.0.get());
+ }
+ }
+ /// See `atomic_inc_and_test`.
+ #[inline(always)]
+ pub fn inc_and_test(&self) -> bool {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_inc_and_test(self.0.get());
+ }
+ }
+ /// See `atomic_add_negative`.
+ #[inline(always)]
+ pub fn add_negative(&self, i: i32) -> bool {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_add_negative(i, self.0.get());
+ }
+ }
+ /// See `atomic_add_negative_acquire`.
+ #[inline(always)]
+ pub fn add_negative_acquire(&self, i: i32) -> bool {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_add_negative_acquire(i, self.0.get());
+ }
+ }
+ /// See `atomic_add_negative_release`.
+ #[inline(always)]
+ pub fn add_negative_release(&self, i: i32) -> bool {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_add_negative_release(i, self.0.get());
+ }
+ }
+ /// See `atomic_add_negative_relaxed`.
+ #[inline(always)]
+ pub fn add_negative_relaxed(&self, i: i32) -> bool {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_add_negative_relaxed(i, self.0.get());
+ }
+ }
+ /// See `atomic_fetch_add_unless`.
+ #[inline(always)]
+ pub fn fetch_add_unless(&self, a: i32, u: i32) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_fetch_add_unless(self.0.get(), a, u);
+ }
+ }
+ /// See `atomic_add_unless`.
+ #[inline(always)]
+ pub fn add_unless(&self, a: i32, u: i32) -> bool {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_add_unless(self.0.get(), a, u);
+ }
+ }
+ /// See `atomic_inc_not_zero`.
+ #[inline(always)]
+ pub fn inc_not_zero(&self) -> bool {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_inc_not_zero(self.0.get());
+ }
+ }
+ /// See `atomic_inc_unless_negative`.
+ #[inline(always)]
+ pub fn inc_unless_negative(&self) -> bool {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_inc_unless_negative(self.0.get());
+ }
+ }
+ /// See `atomic_dec_unless_positive`.
+ #[inline(always)]
+ pub fn dec_unless_positive(&self) -> bool {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_dec_unless_positive(self.0.get());
+ }
+ }
+ /// See `atomic_dec_if_positive`.
+ #[inline(always)]
+ pub fn dec_if_positive(&self) -> i32 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic_dec_if_positive(self.0.get());
+ }
+ }
+}
+
+impl AtomicI64 {
+ /// See `atomic64_read`.
+ #[inline(always)]
+ pub fn read(&self) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_read(self.0.get());
+ }
+ }
+ /// See `atomic64_read_acquire`.
+ #[inline(always)]
+ pub fn read_acquire(&self) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_read_acquire(self.0.get());
+ }
+ }
+ /// See `atomic64_set`.
+ #[inline(always)]
+ pub fn set(&self, i: i64) {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ atomic64_set(self.0.get(), i);
+ }
+ }
+ /// See `atomic64_set_release`.
+ #[inline(always)]
+ pub fn set_release(&self, i: i64) {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ atomic64_set_release(self.0.get(), i);
+ }
+ }
+ /// See `atomic64_add`.
+ #[inline(always)]
+ pub fn add(&self, i: i64) {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ atomic64_add(i, self.0.get());
+ }
+ }
+ /// See `atomic64_add_return`.
+ #[inline(always)]
+ pub fn add_return(&self, i: i64) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_add_return(i, self.0.get());
+ }
+ }
+ /// See `atomic64_add_return_acquire`.
+ #[inline(always)]
+ pub fn add_return_acquire(&self, i: i64) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_add_return_acquire(i, self.0.get());
+ }
+ }
+ /// See `atomic64_add_return_release`.
+ #[inline(always)]
+ pub fn add_return_release(&self, i: i64) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_add_return_release(i, self.0.get());
+ }
+ }
+ /// See `atomic64_add_return_relaxed`.
+ #[inline(always)]
+ pub fn add_return_relaxed(&self, i: i64) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_add_return_relaxed(i, self.0.get());
+ }
+ }
+ /// See `atomic64_fetch_add`.
+ #[inline(always)]
+ pub fn fetch_add(&self, i: i64) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_fetch_add(i, self.0.get());
+ }
+ }
+ /// See `atomic64_fetch_add_acquire`.
+ #[inline(always)]
+ pub fn fetch_add_acquire(&self, i: i64) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_fetch_add_acquire(i, self.0.get());
+ }
+ }
+ /// See `atomic64_fetch_add_release`.
+ #[inline(always)]
+ pub fn fetch_add_release(&self, i: i64) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_fetch_add_release(i, self.0.get());
+ }
+ }
+ /// See `atomic64_fetch_add_relaxed`.
+ #[inline(always)]
+ pub fn fetch_add_relaxed(&self, i: i64) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_fetch_add_relaxed(i, self.0.get());
+ }
+ }
+ /// See `atomic64_sub`.
+ #[inline(always)]
+ pub fn sub(&self, i: i64) {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ atomic64_sub(i, self.0.get());
+ }
+ }
+ /// See `atomic64_sub_return`.
+ #[inline(always)]
+ pub fn sub_return(&self, i: i64) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_sub_return(i, self.0.get());
+ }
+ }
+ /// See `atomic64_sub_return_acquire`.
+ #[inline(always)]
+ pub fn sub_return_acquire(&self, i: i64) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_sub_return_acquire(i, self.0.get());
+ }
+ }
+ /// See `atomic64_sub_return_release`.
+ #[inline(always)]
+ pub fn sub_return_release(&self, i: i64) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_sub_return_release(i, self.0.get());
+ }
+ }
+ /// See `atomic64_sub_return_relaxed`.
+ #[inline(always)]
+ pub fn sub_return_relaxed(&self, i: i64) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_sub_return_relaxed(i, self.0.get());
+ }
+ }
+ /// See `atomic64_fetch_sub`.
+ #[inline(always)]
+ pub fn fetch_sub(&self, i: i64) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_fetch_sub(i, self.0.get());
+ }
+ }
+ /// See `atomic64_fetch_sub_acquire`.
+ #[inline(always)]
+ pub fn fetch_sub_acquire(&self, i: i64) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_fetch_sub_acquire(i, self.0.get());
+ }
+ }
+ /// See `atomic64_fetch_sub_release`.
+ #[inline(always)]
+ pub fn fetch_sub_release(&self, i: i64) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_fetch_sub_release(i, self.0.get());
+ }
+ }
+ /// See `atomic64_fetch_sub_relaxed`.
+ #[inline(always)]
+ pub fn fetch_sub_relaxed(&self, i: i64) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_fetch_sub_relaxed(i, self.0.get());
+ }
+ }
+ /// See `atomic64_inc`.
+ #[inline(always)]
+ pub fn inc(&self) {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ atomic64_inc(self.0.get());
+ }
+ }
+ /// See `atomic64_inc_return`.
+ #[inline(always)]
+ pub fn inc_return(&self) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_inc_return(self.0.get());
+ }
+ }
+ /// See `atomic64_inc_return_acquire`.
+ #[inline(always)]
+ pub fn inc_return_acquire(&self) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_inc_return_acquire(self.0.get());
+ }
+ }
+ /// See `atomic64_inc_return_release`.
+ #[inline(always)]
+ pub fn inc_return_release(&self) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_inc_return_release(self.0.get());
+ }
+ }
+ /// See `atomic64_inc_return_relaxed`.
+ #[inline(always)]
+ pub fn inc_return_relaxed(&self) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_inc_return_relaxed(self.0.get());
+ }
+ }
+ /// See `atomic64_fetch_inc`.
+ #[inline(always)]
+ pub fn fetch_inc(&self) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_fetch_inc(self.0.get());
+ }
+ }
+ /// See `atomic64_fetch_inc_acquire`.
+ #[inline(always)]
+ pub fn fetch_inc_acquire(&self) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_fetch_inc_acquire(self.0.get());
+ }
+ }
+ /// See `atomic64_fetch_inc_release`.
+ #[inline(always)]
+ pub fn fetch_inc_release(&self) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_fetch_inc_release(self.0.get());
+ }
+ }
+ /// See `atomic64_fetch_inc_relaxed`.
+ #[inline(always)]
+ pub fn fetch_inc_relaxed(&self) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_fetch_inc_relaxed(self.0.get());
+ }
+ }
+ /// See `atomic64_dec`.
+ #[inline(always)]
+ pub fn dec(&self) {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ atomic64_dec(self.0.get());
+ }
+ }
+ /// See `atomic64_dec_return`.
+ #[inline(always)]
+ pub fn dec_return(&self) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_dec_return(self.0.get());
+ }
+ }
+ /// See `atomic64_dec_return_acquire`.
+ #[inline(always)]
+ pub fn dec_return_acquire(&self) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_dec_return_acquire(self.0.get());
+ }
+ }
+ /// See `atomic64_dec_return_release`.
+ #[inline(always)]
+ pub fn dec_return_release(&self) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_dec_return_release(self.0.get());
+ }
+ }
+ /// See `atomic64_dec_return_relaxed`.
+ #[inline(always)]
+ pub fn dec_return_relaxed(&self) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_dec_return_relaxed(self.0.get());
+ }
+ }
+ /// See `atomic64_fetch_dec`.
+ #[inline(always)]
+ pub fn fetch_dec(&self) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_fetch_dec(self.0.get());
+ }
+ }
+ /// See `atomic64_fetch_dec_acquire`.
+ #[inline(always)]
+ pub fn fetch_dec_acquire(&self) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_fetch_dec_acquire(self.0.get());
+ }
+ }
+ /// See `atomic64_fetch_dec_release`.
+ #[inline(always)]
+ pub fn fetch_dec_release(&self) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_fetch_dec_release(self.0.get());
+ }
+ }
+ /// See `atomic64_fetch_dec_relaxed`.
+ #[inline(always)]
+ pub fn fetch_dec_relaxed(&self) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_fetch_dec_relaxed(self.0.get());
+ }
+ }
+ /// See `atomic64_and`.
+ #[inline(always)]
+ pub fn and(&self, i: i64) {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ atomic64_and(i, self.0.get());
+ }
+ }
+ /// See `atomic64_fetch_and`.
+ #[inline(always)]
+ pub fn fetch_and(&self, i: i64) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_fetch_and(i, self.0.get());
+ }
+ }
+ /// See `atomic64_fetch_and_acquire`.
+ #[inline(always)]
+ pub fn fetch_and_acquire(&self, i: i64) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_fetch_and_acquire(i, self.0.get());
+ }
+ }
+ /// See `atomic64_fetch_and_release`.
+ #[inline(always)]
+ pub fn fetch_and_release(&self, i: i64) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_fetch_and_release(i, self.0.get());
+ }
+ }
+ /// See `atomic64_fetch_and_relaxed`.
+ #[inline(always)]
+ pub fn fetch_and_relaxed(&self, i: i64) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_fetch_and_relaxed(i, self.0.get());
+ }
+ }
+ /// See `atomic64_andnot`.
+ #[inline(always)]
+ pub fn andnot(&self, i: i64) {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ atomic64_andnot(i, self.0.get());
+ }
+ }
+ /// See `atomic64_fetch_andnot`.
+ #[inline(always)]
+ pub fn fetch_andnot(&self, i: i64) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_fetch_andnot(i, self.0.get());
+ }
+ }
+ /// See `atomic64_fetch_andnot_acquire`.
+ #[inline(always)]
+ pub fn fetch_andnot_acquire(&self, i: i64) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_fetch_andnot_acquire(i, self.0.get());
+ }
+ }
+ /// See `atomic64_fetch_andnot_release`.
+ #[inline(always)]
+ pub fn fetch_andnot_release(&self, i: i64) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_fetch_andnot_release(i, self.0.get());
+ }
+ }
+ /// See `atomic64_fetch_andnot_relaxed`.
+ #[inline(always)]
+ pub fn fetch_andnot_relaxed(&self, i: i64) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_fetch_andnot_relaxed(i, self.0.get());
+ }
+ }
+ /// See `atomic64_or`.
+ #[inline(always)]
+ pub fn or(&self, i: i64) {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ atomic64_or(i, self.0.get());
+ }
+ }
+ /// See `atomic64_fetch_or`.
+ #[inline(always)]
+ pub fn fetch_or(&self, i: i64) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_fetch_or(i, self.0.get());
+ }
+ }
+ /// See `atomic64_fetch_or_acquire`.
+ #[inline(always)]
+ pub fn fetch_or_acquire(&self, i: i64) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_fetch_or_acquire(i, self.0.get());
+ }
+ }
+ /// See `atomic64_fetch_or_release`.
+ #[inline(always)]
+ pub fn fetch_or_release(&self, i: i64) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_fetch_or_release(i, self.0.get());
+ }
+ }
+ /// See `atomic64_fetch_or_relaxed`.
+ #[inline(always)]
+ pub fn fetch_or_relaxed(&self, i: i64) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_fetch_or_relaxed(i, self.0.get());
+ }
+ }
+ /// See `atomic64_xor`.
+ #[inline(always)]
+ pub fn xor(&self, i: i64) {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ atomic64_xor(i, self.0.get());
+ }
+ }
+ /// See `atomic64_fetch_xor`.
+ #[inline(always)]
+ pub fn fetch_xor(&self, i: i64) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_fetch_xor(i, self.0.get());
+ }
+ }
+ /// See `atomic64_fetch_xor_acquire`.
+ #[inline(always)]
+ pub fn fetch_xor_acquire(&self, i: i64) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_fetch_xor_acquire(i, self.0.get());
+ }
+ }
+ /// See `atomic64_fetch_xor_release`.
+ #[inline(always)]
+ pub fn fetch_xor_release(&self, i: i64) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_fetch_xor_release(i, self.0.get());
+ }
+ }
+ /// See `atomic64_fetch_xor_relaxed`.
+ #[inline(always)]
+ pub fn fetch_xor_relaxed(&self, i: i64) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_fetch_xor_relaxed(i, self.0.get());
+ }
+ }
+ /// See `atomic64_xchg`.
+ #[inline(always)]
+ pub fn xchg(&self, new: i64) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_xchg(self.0.get(), new);
+ }
+ }
+ /// See `atomic64_xchg_acquire`.
+ #[inline(always)]
+ pub fn xchg_acquire(&self, new: i64) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_xchg_acquire(self.0.get(), new);
+ }
+ }
+ /// See `atomic64_xchg_release`.
+ #[inline(always)]
+ pub fn xchg_release(&self, new: i64) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_xchg_release(self.0.get(), new);
+ }
+ }
+ /// See `atomic64_xchg_relaxed`.
+ #[inline(always)]
+ pub fn xchg_relaxed(&self, new: i64) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_xchg_relaxed(self.0.get(), new);
+ }
+ }
+ /// See `atomic64_cmpxchg`.
+ #[inline(always)]
+ pub fn cmpxchg(&self, old: i64, new: i64) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_cmpxchg(self.0.get(), old, new);
+ }
+ }
+ /// See `atomic64_cmpxchg_acquire`.
+ #[inline(always)]
+ pub fn cmpxchg_acquire(&self, old: i64, new: i64) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_cmpxchg_acquire(self.0.get(), old, new);
+ }
+ }
+ /// See `atomic64_cmpxchg_release`.
+ #[inline(always)]
+ pub fn cmpxchg_release(&self, old: i64, new: i64) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_cmpxchg_release(self.0.get(), old, new);
+ }
+ }
+ /// See `atomic64_cmpxchg_relaxed`.
+ #[inline(always)]
+ pub fn cmpxchg_relaxed(&self, old: i64, new: i64) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_cmpxchg_relaxed(self.0.get(), old, new);
+ }
+ }
+ /// See `atomic64_try_cmpxchg`.
+ #[inline(always)]
+ pub fn try_cmpxchg(&self, old: &mut i64, new: i64) -> bool {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_try_cmpxchg(self.0.get(), old, new);
+ }
+ }
+ /// See `atomic64_try_cmpxchg_acquire`.
+ #[inline(always)]
+ pub fn try_cmpxchg_acquire(&self, old: &mut i64, new: i64) -> bool {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_try_cmpxchg_acquire(self.0.get(), old, new);
+ }
+ }
+ /// See `atomic64_try_cmpxchg_release`.
+ #[inline(always)]
+ pub fn try_cmpxchg_release(&self, old: &mut i64, new: i64) -> bool {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_try_cmpxchg_release(self.0.get(), old, new);
+ }
+ }
+ /// See `atomic64_try_cmpxchg_relaxed`.
+ #[inline(always)]
+ pub fn try_cmpxchg_relaxed(&self, old: &mut i64, new: i64) -> bool {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_try_cmpxchg_relaxed(self.0.get(), old, new);
+ }
+ }
+ /// See `atomic64_sub_and_test`.
+ #[inline(always)]
+ pub fn sub_and_test(&self, i: i64) -> bool {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_sub_and_test(i, self.0.get());
+ }
+ }
+ /// See `atomic64_dec_and_test`.
+ #[inline(always)]
+ pub fn dec_and_test(&self) -> bool {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_dec_and_test(self.0.get());
+ }
+ }
+ /// See `atomic64_inc_and_test`.
+ #[inline(always)]
+ pub fn inc_and_test(&self) -> bool {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_inc_and_test(self.0.get());
+ }
+ }
+ /// See `atomic64_add_negative`.
+ #[inline(always)]
+ pub fn add_negative(&self, i: i64) -> bool {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_add_negative(i, self.0.get());
+ }
+ }
+ /// See `atomic64_add_negative_acquire`.
+ #[inline(always)]
+ pub fn add_negative_acquire(&self, i: i64) -> bool {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_add_negative_acquire(i, self.0.get());
+ }
+ }
+ /// See `atomic64_add_negative_release`.
+ #[inline(always)]
+ pub fn add_negative_release(&self, i: i64) -> bool {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_add_negative_release(i, self.0.get());
+ }
+ }
+ /// See `atomic64_add_negative_relaxed`.
+ #[inline(always)]
+ pub fn add_negative_relaxed(&self, i: i64) -> bool {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_add_negative_relaxed(i, self.0.get());
+ }
+ }
+ /// See `atomic64_fetch_add_unless`.
+ #[inline(always)]
+ pub fn fetch_add_unless(&self, a: i64, u: i64) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_fetch_add_unless(self.0.get(), a, u);
+ }
+ }
+ /// See `atomic64_add_unless`.
+ #[inline(always)]
+ pub fn add_unless(&self, a: i64, u: i64) -> bool {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_add_unless(self.0.get(), a, u);
+ }
+ }
+ /// See `atomic64_inc_not_zero`.
+ #[inline(always)]
+ pub fn inc_not_zero(&self) -> bool {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_inc_not_zero(self.0.get());
+ }
+ }
+ /// See `atomic64_inc_unless_negative`.
+ #[inline(always)]
+ pub fn inc_unless_negative(&self) -> bool {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_inc_unless_negative(self.0.get());
+ }
+ }
+ /// See `atomic64_dec_unless_positive`.
+ #[inline(always)]
+ pub fn dec_unless_positive(&self) -> bool {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_dec_unless_positive(self.0.get());
+ }
+ }
+ /// See `atomic64_dec_if_positive`.
+ #[inline(always)]
+ pub fn dec_if_positive(&self) -> i64 {
+ // SAFETY:`self.0.get()` is a valid pointer.
+ unsafe {
+ return atomic64_dec_if_positive(self.0.get());
+ }
+ }
+}
+
+// 258c6b7d580a83146e21973b1068cc92d9e65b87
diff --git a/scripts/atomic/gen-atomics.sh b/scripts/atomic/gen-atomics.sh
index 3927aee034c8..8d250c885c24 100755
--- a/scripts/atomic/gen-atomics.sh
+++ b/scripts/atomic/gen-atomics.sh
@@ -12,6 +12,7 @@ gen-atomic-instrumented.sh linux/atomic/atomic-instrumented.h
gen-atomic-long.sh linux/atomic/atomic-long.h
gen-atomic-fallback.sh linux/atomic/atomic-arch-fallback.h
gen-rust-atomic-helpers.sh ../rust/atomic_helpers.h
+gen-rust-atomic.sh ../rust/kernel/sync/atomic/impl.rs
EOF
while read script header args; do
/bin/sh ${ATOMICDIR}/${script} ${ATOMICTBL} ${args} > ${LINUXDIR}/include/${header}
diff --git a/scripts/atomic/gen-rust-atomic.sh b/scripts/atomic/gen-rust-atomic.sh
new file mode 100755
index 000000000000..491c643301a9
--- /dev/null
+++ b/scripts/atomic/gen-rust-atomic.sh
@@ -0,0 +1,136 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+
+ATOMICDIR=$(dirname $0)
+
+. ${ATOMICDIR}/atomic-tbl.sh
+
+#gen_ret_type(meta, int)
+gen_ret_type() {
+ local meta="$1"; shift
+ local int="$1"; shift
+
+ case "${meta}" in
+ [sv]) printf "";;
+ [bB]) printf -- "-> bool ";;
+ [aiIfFlR]) printf -- "-> ${int} ";;
+ esac
+}
+
+# gen_param_type(arg, int)
+gen_param_type()
+{
+ local type="${1%%:*}"; shift
+ local int="$1"; shift
+
+ case "${type}" in
+ i) type="${int}";;
+ p) type="&mut ${int}";;
+ esac
+
+ printf "${type}"
+}
+
+#gen_param(arg, int)
+gen_param()
+{
+ local arg="$1"; shift
+ local int="$1"; shift
+ local name="$(gen_param_name "${arg}")"
+ local type="$(gen_param_type "${arg}" "${int}")"
+
+ printf "${name}: ${type}"
+}
+
+#gen_params(int, arg...)
+gen_params()
+{
+ local int="$1"; shift
+
+ while [ "$#" -gt 0 ]; do
+ if [[ "$1" != "v" && "$1" != "cv" ]]; then
+ printf ", "
+ gen_param "$1" "${int}"
+ fi
+ shift;
+ done
+}
+
+#gen_args(arg...)
+gen_args()
+{
+ while [ "$#" -gt 0 ]; do
+ if [[ "$1" == "v" || "$1" == "cv" ]]; then
+ printf "self.0.get()"
+ [ "$#" -gt 1 ] && printf ", "
+ else
+ printf "$(gen_param_name "$1")"
+ [ "$#" -gt 1 ] && printf ", "
+ fi
+ shift;
+ done
+}
+
+#gen_proto_order_variant(meta, pfx, name, sfx, order, atomic, ty, int, raw, arg...)
+gen_proto_order_variant()
+{
+ local meta="$1"; shift
+ local pfx="$1"; shift
+ local name="$1"; shift
+ local sfx="$1"; shift
+ local order="$1"; shift
+ local atomic="$1"; shift
+ local ty="$1"; shift
+ local int="$1"; shift
+ local raw="$1"; shift
+
+ local fn_name="${raw}${pfx}${name}${sfx}${order}"
+ local atomicname="${raw}${atomic}_${pfx}${name}${sfx}${order}"
+
+ local ret="$(gen_ret_type "${meta}" "${int}")"
+ local params="$(gen_params "${int}" $@)"
+ local args="$(gen_args "$@")"
+ local retstmt="$(gen_ret_stmt "${meta}")"
+
+cat <<EOF
+ /// See \`${atomicname}\`.
+ #[inline(always)]
+ pub fn ${fn_name}(&self${params}) ${ret}{
+ // SAFETY:\`self.0.get()\` is a valid pointer.
+ unsafe {
+ ${retstmt}${atomicname}(${args});
+ }
+ }
+EOF
+}
+
+cat << EOF
+// SPDX-License-Identifier: GPL-2.0
+
+//! Generated by $0
+//! DO NOT MODIFY THIS FILE DIRECTLY
+
+use super::*;
+use crate::bindings::*;
+
+impl AtomicI32 {
+EOF
+
+grep '^[a-z]' "$1" | while read name meta args; do
+ gen_proto "${meta}" "${name}" "atomic" "AtomicI32" "i32" "" ${args}
+done
+
+cat << EOF
+}
+
+impl AtomicI64 {
+EOF
+
+grep '^[a-z]' "$1" | while read name meta args; do
+ gen_proto "${meta}" "${name}" "atomic64" "AtomicI64" "i64" "" ${args}
+done
+
+cat << EOF
+}
+
+EOF
--
2.45.2