Rust atomic changes for v7.1
Subsystems (3)
Boqun Feng
maintainerHi Peter,
Please pull these changes of Rust atomic in v7.1 into tip/locking/core. Major changes are the atomic pointer support and a boolean-like AtomicFlag type (using a byte if arch support efficient xchg/cmpxchg over bytes otherwise 4 bytes). Thanks!
Regards,
Boqun
The following changes since commit 3dcef70e41ab13483803c536ddea8d5f1803ee25:
ww-mutex: Fix the ww_acquire_ctx function annotations (2026-02-27 16:40:20 +0100)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/boqun/linux.git tags/rust-atomic.20260303a
for you to fetch changes up to 68d1c8ac7f0b1f0de92a803b9b71090fd1b86d17:
rust: atomic: Update a safety comment in impl of fetch_add() (2026-03-03 11:55:57 -0800)
----------------------------------------------------------------
Rust atomic changes for v7.1
* Add Atomic<ptr> support.
* Add an AtomicFlag type for boolean-like usage with architecture-specific performance optimization.
* Add unsafe atomic operations over raw pointers.
* Add fetch_sub() for atomic types.
* Documentation and example improvements. -----BEGIN PGP SIGNATURE-----
iQFFBAABCAAvFiEEj5IosQTPz8XU1wRHSXnow7UH+rgFAmmnPU0RHGJvcXVuQGtl cm5lbC5vcmcACgkQSXnow7UH+rgKrgf/UNZb0CmIG7d2jN1GsTHwYa8disAGlWFk KOSTMNn83WICVhIIqUqrRcvSzR0FLwpp1jOH0lMYzZlfxQBOIoVc82xXD2SLLjAa 2VS/vknOitxAsChFceKs7w+hcQD168xSbDqo/dSxI/KO+OMQUxLqTW0zKTVYZhij JIfv57Nv1331J+gnwici6/q3cBqP14Hv968cZ5Dw8tqWJMpMuqJPQLsgKg5um6Y0 hzpgXLkkB8Vg02qku/YdkcBFCvxWz5CifOpmLWNum+B82emELHmKhpOUdticuWof iUkqygu4Un+QAcKb+8LG3L30UW3GBw4kEHpb357jc/EqZHvhX5aEYg== =CYTx
-----END PGP SIGNATURE-----
----------------------------------------------------------------
Andreas Hindborg (3):
rust: sync: atomic: Add fetch_sub()
rust: sync: atomic: Update documentation for fetch_add()
rust: atomic: Update a safety comment in impl of fetch_add()
Boqun Feng (7):
rust: sync: atomic: Remove bound T: Sync for Atomic::from_ptr()
rust: helpers: Generify the definitions of rust_helper_*_{read,set}*
rust: helpers: Generify the definitions of rust_helper_*_xchg*
rust: helpers: Generify the definitions of rust_helper_*_cmpxchg*
rust: sync: atomic: Clarify the need of CONFIG_ARCH_SUPPORTS_ATOMIC_RMW
rust: sync: atomic: Add Atomic<*{mut,const} T> support
rust: sync: atomic: Add atomic operation helpers over raw pointers
FUJITA Tomonori (3):
rust: sync: atomic: Add example for Atomic::get_mut()
rust: sync: atomic: Add performance-optimal Flag type for atomic booleans
rust: list: Use AtomicFlag in AtomicTracker
rust/helpers/atomic_ext.c | 158 ++++++------------ rust/kernel/list/arc.rs | 8 +- rust/kernel/sync/atomic.rs | 310 +++++++++++++++++++++++++++++++++-- rust/kernel/sync/atomic/internal.rs | 44 +++-- rust/kernel/sync/atomic/predefine.rs | 109 ++++++++++++ 5 files changed, 496 insertions(+), 133 deletions(-)
Boqun Feng
maintainerPATCH 1/13 rust: sync: atomic: Remove bound `T: Sync` for `Atomic::from_ptr()`
From: Boqun Feng <[email protected]>
Originally, Atomic::from_ptr() requires T being a Sync because I thought having the ability to do from_ptr() meant multiplle &Atomic<T>s shared by different threads, which was identical (or similar) to multiple &Ts shared by different threads. Hence T was required to be Sync. However this is not true, since &Atomic<T> is not the same at &T. Moreover, having this bound makes Atomic::<*mut T>::from_ptr() impossible, which is definitely not intended. Therefore remove the T: Sync bound.
[boqun: Fix title typo spotted by Alice & Gary]
--- rust/kernel/sync/atomic.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
rust/kernel/sync/atomic.rs +1 -4
@@ -204,10 +204,7 @@ pub const fn new(v: T) -> Self {/// // no data race. /// unsafe { Atomic::from_ptr(foo_a_ptr) }.store(2, Release); /// ``` -pub unsafe fn from_ptr <'a>(ptr: *mut T ) -> &'aSelf -where -T :Sync , - { +pub unsafe fn from_ptr <'a>(ptr: *mut T ) -> &'aSelf {// CAST: `T` and `Atomic<T>` have the same size, alignment and bit validity. // SAFETY: Per function safety requirement, `ptr` is a valid pointer and the object will // live long enough. It's safe to return a `&Atomic<T>` because function safety requirement
Signature · 1 line
2.50.1 (Apple Git-155)
[tip: locking/core] rust: sync: atomic: Remove bound `T: Sync` for `Atomic::from_ptr()`
The following commit has been merged into the locking/core branch of tip:
The following commit has been merged into the locking/core branch of tip:
Commit-ID: 4a5dc632e0b603ec1cbbf87b78de86b4b6359cff Gitweb: https://git.kernel.org/tip/4a5dc632e0b603ec1cbbf87b78de86b4b6359cff Author: Boqun Feng <[email protected]> AuthorDate: Tue, 03 Mar 2026 12:16:49 -08:00 Committer: Peter Zijlstra <[email protected]> CommitterDate: Sun, 08 Mar 2026 11:06:47 +01:00
rust: sync: atomic: Remove bound T: Sync for Atomic::from_ptr()
Originally, Atomic::from_ptr() requires T being a Sync because I thought having the ability to do from_ptr() meant multiplle &Atomic<T>s shared by different threads, which was identical (or similar) to multiple &Ts shared by different threads. Hence T was required to be Sync. However this is not true, since &Atomic<T> is not the same at &T. Moreover, having this bound makes Atomic::<*mut T>::from_ptr() impossible, which is definitely not intended. Therefore remove the T: Sync bound.
[boqun: Fix title typo spotted by Alice & Gary]
--- rust/kernel/sync/atomic.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
rust/kernel/sync/atomic.rs +1 -4
@@ -204,10 +204,7 @@ impl<T: AtomicType> Atomic<T> {/// // no data race. /// unsafe { Atomic::from_ptr(foo_a_ptr) }.store(2, Release); /// ``` -pub unsafe fn from_ptr <'a>(ptr: *mut T ) -> &'aSelf -where -T :Sync , - { +pub unsafe fn from_ptr <'a>(ptr: *mut T ) -> &'aSelf {// CAST: `T` and `Atomic<T>` have the same size, alignment and bit validity. // SAFETY: Per function safety requirement, `ptr` is a valid pointer and the object will // live long enough. It's safe to return a `&Atomic<T>` because function safety requirement
Boqun Feng
maintainerPATCH 2/13 rust: sync: atomic: Add example for Atomic::get_mut()
In reply to Boqun FengFrom: FUJITA Tomonori <[email protected]>
Add an example for Atomic::get_mut(). No functional change.
--- rust/kernel/sync/atomic.rs | 11 +++++++++++ 1 file changed, 11 insertions(+)
rust/kernel/sync/atomic.rs +11 -0
@@ -232,6 +232,17 @@ pub const fn as_ptr(&self) -> *mut T {/// Returns a mutable reference to the underlying atomic `T`. /// /// This is safe because the mutable reference of the atomic `T` guarantees exclusive access. +/// +/// # Examples +/// +/// ``` +/// use kernel::sync::atomic::{Atomic, Relaxed}; +/// +/// let mut atomic_val = Atomic::new(0u32); +/// let val_mut = atomic_val.get_mut(); +/// *val_mut = 101; +/// assert_eq!(101, atomic_val.load(Relaxed)); +/// ``` pub fn get_mut (&mut self) -> &mut T {// CAST: `T` and `T::Repr` has the same size and alignment per the safety requirement of // `AtomicType`, and per the type invariants `self.0` is a valid `T`, therefore the casting
Signature · 1 line
2.50.1 (Apple Git-155)
[tip: locking/core] rust: sync: atomic: Add example for Atomic::get_mut()
The following commit has been merged into the locking/core branch of tip:
The following commit has been merged into the locking/core branch of tip:
Commit-ID: bebf7bdc62537b9ef4700c6402f1c2aa206a9b50 Gitweb: https://git.kernel.org/tip/bebf7bdc62537b9ef4700c6402f1c2aa206a9b50 Author: FUJITA Tomonori <[email protected]> AuthorDate: Tue, 03 Mar 2026 12:16:50 -08:00 Committer: Peter Zijlstra <[email protected]> CommitterDate: Sun, 08 Mar 2026 11:06:48 +01:00
rust: sync: atomic: Add example for Atomic::get_mut()
Add an example for Atomic::get_mut(). No functional change.
--- rust/kernel/sync/atomic.rs | 11 +++++++++++ 1 file changed, 11 insertions(+)
rust/kernel/sync/atomic.rs +11 -0
@@ -232,6 +232,17 @@ impl<T: AtomicType> Atomic<T> {/// Returns a mutable reference to the underlying atomic `T`. /// /// This is safe because the mutable reference of the atomic `T` guarantees exclusive access. +/// +/// # Examples +/// +/// ``` +/// use kernel::sync::atomic::{Atomic, Relaxed}; +/// +/// let mut atomic_val = Atomic::new(0u32); +/// let val_mut = atomic_val.get_mut(); +/// *val_mut = 101; +/// assert_eq!(101, atomic_val.load(Relaxed)); +/// ``` pub fn get_mut (&mut self) -> &mut T {// CAST: `T` and `T::Repr` has the same size and alignment per the safety requirement of // `AtomicType`, and per the type invariants `self.0` is a valid `T`, therefore the casting
Boqun Feng
maintainerPATCH 3/13 rust: helpers: Generify the definitions of rust_helper_*_{read,set}*
In reply to Boqun FengFrom: Boqun Feng <[email protected]>
To support atomic pointers, more {read,set} helpers will be introduced, hence define macros to generate these helpers to ease the introduction of the future helpers.
--- rust/helpers/atomic_ext.c | 53 +++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 30 deletions(-)
rust/helpers/atomic_ext.c +23 -30
@@ -4,45 +4,38 @@#include <asm/rwonce.h> #include <linux/atomic.h> -__rust_helper s8 rust_helper_atomic_i8_read(s8 *ptr) -{ -return READ_ONCE (*ptr); -} - -__rust_helper s8 rust_helper_atomic_i8_read_acquire(s8 *ptr) -{ -return smp_load_acquire (ptr); -} - -__rust_helper s16 rust_helper_atomic_i16_read(s16 *ptr) -{ -return READ_ONCE (*ptr); +#define GEN_READ_HELPER (tname, type) \ +__rust_helper type rust_helper_atomic_##tname##_read(type *ptr) \ +{ \ + return READ_ONCE(*ptr); \ } -__rust_helper s16 rust_helper_atomic_i16_read_acquire(s16 *ptr) -{ -return smp_load_acquire (ptr); +#define GEN_SET_HELPER (tname, type) \ +__rust_helper void rust_helper_atomic_##tname##_set(type *ptr, type val) \ +{ \ + WRITE_ONCE(*ptr, val); \ } -__rust_helper void rust_helper_atomic_i8_set(s8 *ptr, s8 val) -{ -WRITE_ONCE (*ptr, val); +#define GEN_READ_ACQUIRE_HELPER (tname, type) \ +__rust_helper type rust_helper_atomic_##tname##_read_acquire(type *ptr) \ +{ \ + return smp_load_acquire(ptr); \ } -__rust_helper void rust_helper_atomic_i8_set_release(s8 *ptr, s8 val) -{ -smp_store_release (ptr, val); +#define GEN_SET_RELEASE_HELPER (tname, type) \ +__rust_helper void rust_helper_atomic_##tname##_set_release(type *ptr, type val)\ +{ \ + smp_store_release(ptr, val); \ } -__rust_helper void rust_helper_atomic_i16_set(s16 *ptr, s16 val) -{ -WRITE_ONCE (*ptr, val); -} +#define GEN_READ_SET_HELPERS (tname, type) \ + GEN_READ_HELPER(tname, type) \ + GEN_SET_HELPER(tname, type) \ + GEN_READ_ACQUIRE_HELPER(tname, type) \ + GEN_SET_RELEASE_HELPER(tname, type) \ -__rust_helper void rust_helper_atomic_i16_set_release(s16 *ptr, s16 val) -{ -smp_store_release (ptr, val); -} +GEN_READ_SET_HELPERS(i8, s8) +GEN_READ_SET_HELPERS (i16, s16)/* * xchg helpers depend on ARCH_SUPPORTS_ATOMIC_RMW and on the
Signature · 1 line
2.50.1 (Apple Git-155)
[tip: locking/core] rust: helpers: Generify the definitions of rust_helper_*_{read,set}*
The following commit has been merged into the locking/core branch of tip:
The following commit has been merged into the locking/core branch of tip:
Commit-ID: ecc8e9fbaac35c8e5cced26f740f846506c4737b Gitweb: https://git.kernel.org/tip/ecc8e9fbaac35c8e5cced26f740f846506c4737b Author: Boqun Feng <[email protected]> AuthorDate: Tue, 03 Mar 2026 12:16:51 -08:00 Committer: Peter Zijlstra <[email protected]> CommitterDate: Sun, 08 Mar 2026 11:06:48 +01:00
rust: helpers: Generify the definitions of rust_helper_*_{read,set}*
To support atomic pointers, more {read,set} helpers will be introduced, hence define macros to generate these helpers to ease the introduction of the future helpers.
--- rust/helpers/atomic_ext.c | 53 ++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 30 deletions(-)
rust/helpers/atomic_ext.c +23 -30
@@ -4,45 +4,38 @@#include <asm/rwonce.h> #include <linux/atomic.h> -__rust_helper s8 rust_helper_atomic_i8_read(s8 *ptr) -{ -return READ_ONCE (*ptr); -} - -__rust_helper s8 rust_helper_atomic_i8_read_acquire(s8 *ptr) -{ -return smp_load_acquire (ptr); -} - -__rust_helper s16 rust_helper_atomic_i16_read(s16 *ptr) -{ -return READ_ONCE (*ptr); +#define GEN_READ_HELPER (tname, type) \ +__rust_helper type rust_helper_atomic_##tname##_read(type *ptr) \ +{ \ + return READ_ONCE(*ptr); \ } -__rust_helper s16 rust_helper_atomic_i16_read_acquire(s16 *ptr) -{ -return smp_load_acquire (ptr); +#define GEN_SET_HELPER (tname, type) \ +__rust_helper void rust_helper_atomic_##tname##_set(type *ptr, type val) \ +{ \ + WRITE_ONCE(*ptr, val); \ } -__rust_helper void rust_helper_atomic_i8_set(s8 *ptr, s8 val) -{ -WRITE_ONCE (*ptr, val); +#define GEN_READ_ACQUIRE_HELPER (tname, type) \ +__rust_helper type rust_helper_atomic_##tname##_read_acquire(type *ptr) \ +{ \ + return smp_load_acquire(ptr); \ } -__rust_helper void rust_helper_atomic_i8_set_release(s8 *ptr, s8 val) -{ -smp_store_release (ptr, val); +#define GEN_SET_RELEASE_HELPER (tname, type) \ +__rust_helper void rust_helper_atomic_##tname##_set_release(type *ptr, type val)\ +{ \ + smp_store_release(ptr, val); \ } -__rust_helper void rust_helper_atomic_i16_set(s16 *ptr, s16 val) -{ -WRITE_ONCE (*ptr, val); -} +#define GEN_READ_SET_HELPERS (tname, type) \ + GEN_READ_HELPER(tname, type) \ + GEN_SET_HELPER(tname, type) \ + GEN_READ_ACQUIRE_HELPER(tname, type) \ + GEN_SET_RELEASE_HELPER(tname, type) \ -__rust_helper void rust_helper_atomic_i16_set_release(s16 *ptr, s16 val) -{ -smp_store_release (ptr, val); -} +GEN_READ_SET_HELPERS(i8, s8) +GEN_READ_SET_HELPERS (i16, s16)/* * xchg helpers depend on ARCH_SUPPORTS_ATOMIC_RMW and on the
Boqun Feng
maintainerPATCH 4/13 rust: helpers: Generify the definitions of rust_helper_*_xchg*
In reply to Boqun FengFrom: Boqun Feng <[email protected]>
To support atomic pointers, more xchg helpers will be introduced, hence define macros to generate these helpers to ease the introduction of the future helpers.
--- rust/helpers/atomic_ext.c | 48 ++++++++++----------------------------- 1 file changed, 12 insertions(+), 36 deletions(-)
rust/helpers/atomic_ext.c +12 -36
@@ -44,45 +44,21 @@ GEN_READ_SET_HELPERS(i16, s16)* The architectures that currently support Rust (x86_64, armv7, * arm64, riscv, and loongarch) satisfy these requirements. */ -__rust_helper s8 rust_helper_atomic_i8_xchg(s8 *ptr, s8 new) -{ -return xchg (ptr, new); -} - -__rust_helper s16 rust_helper_atomic_i16_xchg(s16 *ptr, s16 new) -{ -return xchg (ptr, new); -} - -__rust_helper s8 rust_helper_atomic_i8_xchg_acquire(s8 *ptr, s8 new) -{ -return xchg_acquire (ptr, new); -} - -__rust_helper s16 rust_helper_atomic_i16_xchg_acquire(s16 *ptr, s16 new) -{ -return xchg_acquire (ptr, new); -} - -__rust_helper s8 rust_helper_atomic_i8_xchg_release(s8 *ptr, s8 new) -{ -return xchg_release (ptr, new); -} - -__rust_helper s16 rust_helper_atomic_i16_xchg_release(s16 *ptr, s16 new) -{ -return xchg_release (ptr, new); +#define GEN_XCHG_HELPER (tname, type, suffix) \ +__rust_helper type \ +rust_helper_atomic_##tname##_xchg##suffix(type *ptr, type new) \ +{ \ + return xchg##suffix(ptr, new); \ } -__rust_helper s8 rust_helper_atomic_i8_xchg_relaxed(s8 *ptr, s8 new) -{ -return xchg_relaxed (ptr, new); -} +#define GEN_XCHG_HELPERS (tname, type) \ + GEN_XCHG_HELPER(tname, type, ) \ + GEN_XCHG_HELPER(tname, type, _acquire) \ + GEN_XCHG_HELPER(tname, type, _release) \ + GEN_XCHG_HELPER(tname, type, _relaxed) \ -__rust_helper s16 rust_helper_atomic_i16_xchg_relaxed(s16 *ptr, s16 new) -{ -return xchg_relaxed (ptr, new); -} +GEN_XCHG_HELPERS(i8, s8) +GEN_XCHG_HELPERS (i16, s16)/* * try_cmpxchg helpers depend on ARCH_SUPPORTS_ATOMIC_RMW and on the
Signature · 1 line
2.50.1 (Apple Git-155)
[tip: locking/core] rust: helpers: Generify the definitions of rust_helper_*_xchg*
The following commit has been merged into the locking/core branch of tip:
The following commit has been merged into the locking/core branch of tip:
Commit-ID: f92d22b00e3f75fad2efd965b20d49b4e763b792 Gitweb: https://git.kernel.org/tip/f92d22b00e3f75fad2efd965b20d49b4e763b792 Author: Boqun Feng <[email protected]> AuthorDate: Tue, 03 Mar 2026 12:16:52 -08:00 Committer: Peter Zijlstra <[email protected]> CommitterDate: Sun, 08 Mar 2026 11:06:48 +01:00
rust: helpers: Generify the definitions of rust_helper_*_xchg*
To support atomic pointers, more xchg helpers will be introduced, hence define macros to generate these helpers to ease the introduction of the future helpers.
--- rust/helpers/atomic_ext.c | 48 +++++++++----------------------------- 1 file changed, 12 insertions(+), 36 deletions(-)
rust/helpers/atomic_ext.c +12 -36
@@ -44,45 +44,21 @@ GEN_READ_SET_HELPERS(i16, s16)* The architectures that currently support Rust (x86_64, armv7, * arm64, riscv, and loongarch) satisfy these requirements. */ -__rust_helper s8 rust_helper_atomic_i8_xchg(s8 *ptr, s8 new) -{ -return xchg (ptr, new); -} - -__rust_helper s16 rust_helper_atomic_i16_xchg(s16 *ptr, s16 new) -{ -return xchg (ptr, new); -} - -__rust_helper s8 rust_helper_atomic_i8_xchg_acquire(s8 *ptr, s8 new) -{ -return xchg_acquire (ptr, new); -} - -__rust_helper s16 rust_helper_atomic_i16_xchg_acquire(s16 *ptr, s16 new) -{ -return xchg_acquire (ptr, new); -} - -__rust_helper s8 rust_helper_atomic_i8_xchg_release(s8 *ptr, s8 new) -{ -return xchg_release (ptr, new); -} - -__rust_helper s16 rust_helper_atomic_i16_xchg_release(s16 *ptr, s16 new) -{ -return xchg_release (ptr, new); +#define GEN_XCHG_HELPER (tname, type, suffix) \ +__rust_helper type \ +rust_helper_atomic_##tname##_xchg##suffix(type *ptr, type new) \ +{ \ + return xchg##suffix(ptr, new); \ } -__rust_helper s8 rust_helper_atomic_i8_xchg_relaxed(s8 *ptr, s8 new) -{ -return xchg_relaxed (ptr, new); -} +#define GEN_XCHG_HELPERS (tname, type) \ + GEN_XCHG_HELPER(tname, type, ) \ + GEN_XCHG_HELPER(tname, type, _acquire) \ + GEN_XCHG_HELPER(tname, type, _release) \ + GEN_XCHG_HELPER(tname, type, _relaxed) \ -__rust_helper s16 rust_helper_atomic_i16_xchg_relaxed(s16 *ptr, s16 new) -{ -return xchg_relaxed (ptr, new); -} +GEN_XCHG_HELPERS(i8, s8) +GEN_XCHG_HELPERS (i16, s16)/* * try_cmpxchg helpers depend on ARCH_SUPPORTS_ATOMIC_RMW and on the
Boqun Feng
maintainerPATCH 5/13 rust: helpers: Generify the definitions of rust_helper_*_cmpxchg*
In reply to Boqun FengFrom: Boqun Feng <[email protected]>
To support atomic pointers, more cmpxchg helpers will be introduced, hence define macros to generate these helpers to ease the introduction of the future helpers.
--- rust/helpers/atomic_ext.c | 48 ++++++++++----------------------------- 1 file changed, 12 insertions(+), 36 deletions(-)
rust/helpers/atomic_ext.c +12 -36
@@ -67,42 +67,18 @@ GEN_XCHG_HELPERS(i16, s16)* The architectures that currently support Rust (x86_64, armv7, * arm64, riscv, and loongarch) satisfy these requirements. */ -__rust_helper bool rust_helper_atomic_i8_try_cmpxchg(s8 *ptr, s8 *old, s8 new) -{ -return try_cmpxchg (ptr, old, new); -} - -__rust_helper bool rust_helper_atomic_i16_try_cmpxchg(s16 *ptr, s16 *old, s16 new) -{ -return try_cmpxchg (ptr, old, new); -} - -__rust_helper bool rust_helper_atomic_i8_try_cmpxchg_acquire(s8 *ptr, s8 *old, s8 new) -{ -return try_cmpxchg_acquire (ptr, old, new); -} - -__rust_helper bool rust_helper_atomic_i16_try_cmpxchg_acquire(s16 *ptr, s16 *old, s16 new) -{ -return try_cmpxchg_acquire (ptr, old, new); -} - -__rust_helper bool rust_helper_atomic_i8_try_cmpxchg_release(s8 *ptr, s8 *old, s8 new) -{ -return try_cmpxchg_release (ptr, old, new); -} - -__rust_helper bool rust_helper_atomic_i16_try_cmpxchg_release(s16 *ptr, s16 *old, s16 new) -{ -return try_cmpxchg_release (ptr, old, new); +#define GEN_TRY_CMPXCHG_HELPER (tname, type, suffix) \ +__rust_helper bool \ +rust_helper_atomic_##tname##_try_cmpxchg##suffix(type *ptr, type *old, type new)\ +{ \ + return try_cmpxchg##suffix(ptr, old, new); \ } -__rust_helper bool rust_helper_atomic_i8_try_cmpxchg_relaxed(s8 *ptr, s8 *old, s8 new) -{ -return try_cmpxchg_relaxed (ptr, old, new); -} +#define GEN_TRY_CMPXCHG_HELPERS (tname, type) \ + GEN_TRY_CMPXCHG_HELPER(tname, type, ) \ + GEN_TRY_CMPXCHG_HELPER(tname, type, _acquire) \ + GEN_TRY_CMPXCHG_HELPER(tname, type, _release) \ + GEN_TRY_CMPXCHG_HELPER(tname, type, _relaxed) \ -__rust_helper bool rust_helper_atomic_i16_try_cmpxchg_relaxed(s16 *ptr, s16 *old, s16 new) -{ -return try_cmpxchg_relaxed (ptr, old, new); -} +GEN_TRY_CMPXCHG_HELPERS(i8, s8) +GEN_TRY_CMPXCHG_HELPERS (i16, s16)
Signature · 1 line
2.50.1 (Apple Git-155)
[tip: locking/core] rust: helpers: Generify the definitions of rust_helper_*_cmpxchg*
The following commit has been merged into the locking/core branch of tip:
The following commit has been merged into the locking/core branch of tip:
Commit-ID: a92236bf239cc01fd40d9cbe98fc8b9924c42a82 Gitweb: https://git.kernel.org/tip/a92236bf239cc01fd40d9cbe98fc8b9924c42a82 Author: Boqun Feng <[email protected]> AuthorDate: Tue, 03 Mar 2026 12:16:53 -08:00 Committer: Peter Zijlstra <[email protected]> CommitterDate: Sun, 08 Mar 2026 11:06:48 +01:00
rust: helpers: Generify the definitions of rust_helper_*_cmpxchg*
To support atomic pointers, more cmpxchg helpers will be introduced, hence define macros to generate these helpers to ease the introduction of the future helpers.
--- rust/helpers/atomic_ext.c | 48 +++++++++----------------------------- 1 file changed, 12 insertions(+), 36 deletions(-)
rust/helpers/atomic_ext.c +12 -36
@@ -67,42 +67,18 @@ GEN_XCHG_HELPERS(i16, s16)* The architectures that currently support Rust (x86_64, armv7, * arm64, riscv, and loongarch) satisfy these requirements. */ -__rust_helper bool rust_helper_atomic_i8_try_cmpxchg(s8 *ptr, s8 *old, s8 new) -{ -return try_cmpxchg (ptr, old, new); -} - -__rust_helper bool rust_helper_atomic_i16_try_cmpxchg(s16 *ptr, s16 *old, s16 new) -{ -return try_cmpxchg (ptr, old, new); -} - -__rust_helper bool rust_helper_atomic_i8_try_cmpxchg_acquire(s8 *ptr, s8 *old, s8 new) -{ -return try_cmpxchg_acquire (ptr, old, new); -} - -__rust_helper bool rust_helper_atomic_i16_try_cmpxchg_acquire(s16 *ptr, s16 *old, s16 new) -{ -return try_cmpxchg_acquire (ptr, old, new); -} - -__rust_helper bool rust_helper_atomic_i8_try_cmpxchg_release(s8 *ptr, s8 *old, s8 new) -{ -return try_cmpxchg_release (ptr, old, new); -} - -__rust_helper bool rust_helper_atomic_i16_try_cmpxchg_release(s16 *ptr, s16 *old, s16 new) -{ -return try_cmpxchg_release (ptr, old, new); +#define GEN_TRY_CMPXCHG_HELPER (tname, type, suffix) \ +__rust_helper bool \ +rust_helper_atomic_##tname##_try_cmpxchg##suffix(type *ptr, type *old, type new)\ +{ \ + return try_cmpxchg##suffix(ptr, old, new); \ } -__rust_helper bool rust_helper_atomic_i8_try_cmpxchg_relaxed(s8 *ptr, s8 *old, s8 new) -{ -return try_cmpxchg_relaxed (ptr, old, new); -} +#define GEN_TRY_CMPXCHG_HELPERS (tname, type) \ + GEN_TRY_CMPXCHG_HELPER(tname, type, ) \ + GEN_TRY_CMPXCHG_HELPER(tname, type, _acquire) \ + GEN_TRY_CMPXCHG_HELPER(tname, type, _release) \ + GEN_TRY_CMPXCHG_HELPER(tname, type, _relaxed) \ -__rust_helper bool rust_helper_atomic_i16_try_cmpxchg_relaxed(s16 *ptr, s16 *old, s16 new) -{ -return try_cmpxchg_relaxed (ptr, old, new); -} +GEN_TRY_CMPXCHG_HELPERS(i8, s8) +GEN_TRY_CMPXCHG_HELPERS (i16, s16)
Boqun Feng
maintainerPATCH 6/13 rust: sync: atomic: Clarify the need of CONFIG_ARCH_SUPPORTS_ATOMIC_RMW
In reply to Boqun FengFrom: Boqun Feng <[email protected]>
Currently, since all the architectures that support Rust all have CONFIG_ARCH_SUPPORTS_ATOMIC_RMW selected, the helpers of atomic load/store on i8 and i16 relies on CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y. It's generally fine since most of architectures support that.
The plan for CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=n architectures is adding their (probably lock-based) atomic load/store for i8 and i16 as their atomic_{read,set}() and atomic64_{read,set}() counterpart when they plans to support Rust.
Hence use a statis_assert!() to check this and remind the future us the need of the helpers. This is more clear than the #[cfg] on impl blocks of i8 and i16.
--- rust/kernel/sync/atomic/internal.rs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-)
rust/kernel/sync/atomic/internal.rs +13 -6
@@ -37,16 +37,23 @@ pub trait AtomicImpl: Sized + Send + Copy + private::Sealed {type Delta ; } -// The current helpers of load/store uses `{WRITE,READ}_ONCE()` hence the atomicity is only -// guaranteed against read-modify-write operations if the architecture supports native atomic RmW. -#[cfg( CONFIG_ARCH_SUPPORTS_ATOMIC_RMW )] +// The current helpers of load/store of atomic `i8` and `i16` use `{WRITE,READ}_ONCE()` hence the +// atomicity is only guaranteed against read-modify-write operations if the architecture supports +// native atomic RmW. +// +// In the future when a CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=n architecture plans to support Rust, the +// load/store helpers that guarantee atomicity against RmW operations (usually via a lock) need to +// be added. +crate ::static_assert!( +cfg! (CONFIG_ARCH_SUPPORTS_ATOMIC_RMW ), +"The current implementation of atomic i8/i16/ptr relies on the architecure being \ +ARCH_SUPPORTS_ATOMIC_RMW" +); +impl AtomicImpl for i8 {type Delta =Self ; } -// The current helpers of load/store uses `{WRITE,READ}_ONCE()` hence the atomicity is only -// guaranteed against read-modify-write operations if the architecture supports native atomic RmW. -#[cfg( CONFIG_ARCH_SUPPORTS_ATOMIC_RMW )] impl AtomicImpl for i16 {type Delta =Self ; }
Signature · 1 line
2.50.1 (Apple Git-155)
[tip: locking/core] rust: sync: atomic: Clarify the need of CONFIG_ARCH_SUPPORTS_ATOMIC_RMW
The following commit has been merged into the locking/core branch of tip:
The following commit has been merged into the locking/core branch of tip:
Commit-ID: 553c02fb588d4310193eba80f75b43b20befd1d2 Gitweb: https://git.kernel.org/tip/553c02fb588d4310193eba80f75b43b20befd1d2 Author: Boqun Feng <[email protected]> AuthorDate: Tue, 03 Mar 2026 12:16:54 -08:00 Committer: Peter Zijlstra <[email protected]> CommitterDate: Sun, 08 Mar 2026 11:06:49 +01:00
rust: sync: atomic: Clarify the need of CONFIG_ARCH_SUPPORTS_ATOMIC_RMW
Currently, since all the architectures that support Rust all have CONFIG_ARCH_SUPPORTS_ATOMIC_RMW selected, the helpers of atomic load/store on i8 and i16 relies on CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y. It's generally fine since most of architectures support that.
The plan for CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=n architectures is adding their (probably lock-based) atomic load/store for i8 and i16 as their atomic_{read,set}() and atomic64_{read,set}() counterpart when they plans to support Rust.
Hence use a statis_assert!() to check this and remind the future us the need of the helpers. This is more clear than the #[cfg] on impl blocks of i8 and i16.
--- rust/kernel/sync/atomic/internal.rs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-)
rust/kernel/sync/atomic/internal.rs +13 -6
@@ -37,16 +37,23 @@ pub trait AtomicImpl: Sized + Send + Copy + private::Sealed {type Delta ; } -// The current helpers of load/store uses `{WRITE,READ}_ONCE()` hence the atomicity is only -// guaranteed against read-modify-write operations if the architecture supports native atomic RmW. -#[cfg( CONFIG_ARCH_SUPPORTS_ATOMIC_RMW )] +// The current helpers of load/store of atomic `i8` and `i16` use `{WRITE,READ}_ONCE()` hence the +// atomicity is only guaranteed against read-modify-write operations if the architecture supports +// native atomic RmW. +// +// In the future when a CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=n architecture plans to support Rust, the +// load/store helpers that guarantee atomicity against RmW operations (usually via a lock) need to +// be added. +crate ::static_assert!( +cfg! (CONFIG_ARCH_SUPPORTS_ATOMIC_RMW ), +"The current implementation of atomic i8/i16/ptr relies on the architecure being \ +ARCH_SUPPORTS_ATOMIC_RMW" +); +impl AtomicImpl for i8 {type Delta =Self ; } -// The current helpers of load/store uses `{WRITE,READ}_ONCE()` hence the atomicity is only -// guaranteed against read-modify-write operations if the architecture supports native atomic RmW. -#[cfg( CONFIG_ARCH_SUPPORTS_ATOMIC_RMW )] impl AtomicImpl for i16 {type Delta =Self ; }
Boqun Feng
maintainerPATCH 7/13 rust: sync: atomic: Add Atomic<*{mut,const} T> support
In reply to Boqun FengFrom: Boqun Feng <[email protected]>
Atomic pointer support is an important piece of synchronization algorithm, e.g. RCU, hence provide the support for that.
Note that instead of relying on atomic_long or the implementation of Atomic<usize>, a new set of helpers (atomic_ptr_*) is introduced for atomic pointer specifically, this is because ptr2int casting would lose the provenance of a pointer and even though in theory there are a few tricks the provenance can be restored, it'll still be a simpler implementation if C could provide atomic pointers directly. The side effects of this approach are: we don't have the arithmetic and logical operations for pointers yet and the current implementation only works on ARCH_SUPPORTS_ATOMIC_RMW architectures, but these are implementation issues and can be added later.
--- rust/helpers/atomic_ext.c | 3 ++ rust/kernel/sync/atomic.rs | 12 +++++++- rust/kernel/sync/atomic/internal.rs | 24 +++++++++------ rust/kernel/sync/atomic/predefine.rs | 46 ++++++++++++++++++++++++++++ 4 files changed, 75 insertions(+), 10 deletions(-)
rust/helpers/atomic_ext.c +3 -0
@@ -36,6 +36,7 @@ __rust_helper void rust_helper_atomic_##tname##_set_release(type *ptr, type val) GEN_READ_SET_HELPERS(i8, s8) GEN_READ_SET_HELPERS(i16, s16) +GEN_READ_SET_HELPERS(ptr, const void *)/* * xchg helpers depend on ARCH_SUPPORTS_ATOMIC_RMW and on the
@@ -59,6 +60,7 @@ rust_helper_atomic_##tname##_xchg##suffix(type *ptr, type new) \ GEN_XCHG_HELPERS(i8, s8) GEN_XCHG_HELPERS(i16, s16) +GEN_XCHG_HELPERS(ptr, const void *)/* * try_cmpxchg helpers depend on ARCH_SUPPORTS_ATOMIC_RMW and on the
@@ -82,3 +84,4 @@ rust_helper_atomic_##tname##_try_cmpxchg##suffix(type *ptr, type *old, type new) GEN_TRY_CMPXCHG_HELPERS(i8, s8) GEN_TRY_CMPXCHG_HELPERS(i16, s16) +GEN_TRY_CMPXCHG_HELPERS(ptr, const void *)
rust/kernel/sync/atomic.rs +11 -1
@@ -51,6 +51,10 @@#[repr(transparent)] pub struct Atomic <T :AtomicType >(AtomicRepr <T ::Repr >); +// SAFETY: `Atomic<T>` is safe to transfer between execution contexts because of the safety +// requirement of `AtomicType`. +unsafe impl <T :AtomicType >Send for Atomic <T > {} +// SAFETY: `Atomic<T>` is safe to share among execution contexts because all accesses are atomic. unsafe impl <T :AtomicType >Sync for Atomic <T > {}
@@ -68,6 +72,11 @@ unsafe impl<T: AtomicType> Sync for Atomic<T> {}/// /// - [`Self`] must have the same size and alignment as [`Self::Repr`]. /// - [`Self`] must be [round-trip transmutable] to [`Self::Repr`]. +/// - [`Self`] must be safe to transfer between execution contexts, if it's [`Send`], this is +/// automatically satisfied. The exception is pointer types that are even though marked as +/// `!Send` (e.g. raw pointers and [`NonNull<T>`]) but requiring `unsafe` to do anything +/// meaningful on them. This is because transferring pointer values between execution contexts is +/// safe as long as the actual `unsafe` dereferencing is justified. /// /// Note that this is more relaxed than requiring the bi-directional transmutability (i.e. /// [`transmute()`] is always sound between `U` and `T`) because of the support for atomic
@@ -108,7 +117,8 @@ unsafe impl<T: AtomicType> Sync for Atomic<T> {}/// [`transmute()`]: core::mem::transmute /// [round-trip transmutable]: AtomicType#round-trip-transmutability /// [Examples]: AtomicType#examples -pub unsafe trait AtomicType :Sized +Send +Copy { +/// [`NonNull<T>`]: core::ptr::NonNull +pub unsafe trait AtomicType :Sized +Copy {/// The backing atomic implementation type. type Repr :AtomicImpl ; }
rust/kernel/sync/atomic/internal.rs +15 -9
@@ -7,6 +7,7 @@use crate ::bindings;use crate ::macros::paste;use core::cell::UnsafeCell ; +use ffi::c_void;mod private {/// Sealed trait marker to disable customized impls on atomic implementation traits.
@@ -14,10 +15,11 @@ pub trait Sealed {} }// The C side supports atomic primitives only for `i32` and `i64` (`atomic_t` and `atomic64_t`), -// while the Rust side also layers provides atomic support for `i8` and `i16` -// on top of lower-level C primitives. +// while the Rust side also provides atomic support for `i8`, `i16` and `*const c_void` on top of +// lower-level C primitives. impl private::Sealed for i8 {}impl private::Sealed for i16 {} +impl private::Sealed for *const c_void {}impl private::Sealed for i32 {}impl private::Sealed for i64 {}
@@ -26,10 +28,10 @@ impl private::Sealed for i64 {}/// This trait is sealed, and only types that map directly to the C side atomics /// or can be implemented with lower-level C primitives are allowed to implement this: /// -/// - `i8` and `i16` are implemented with lower-level C primitives. +/// - `i8`, `i16` and `*const c_void` are implemented with lower-level C primitives. /// - `i32` map to `atomic_t` /// - `i64` map to `atomic64_t` -pub trait AtomicImpl :Sized +Send +Copy + private::Sealed { +pub trait AtomicImpl :Sized +Copy + private::Sealed {/// The type of the delta in arithmetic or logical operations. /// /// For example, in `atomic_add(ptr, v)`, it's the type of `v`. Usually it's the same type of
@@ -37,9 +39,9 @@ pub trait AtomicImpl: Sized + Send + Copy + private::Sealed {type Delta ; } -// The current helpers of load/store of atomic `i8` and `i16` use `{WRITE,READ}_ONCE()` hence the -// atomicity is only guaranteed against read-modify-write operations if the architecture supports -// native atomic RmW. +// The current helpers of load/store of atomic `i8`, `i16` and pointers use `{WRITE,READ}_ONCE()` +// hence the atomicity is only guaranteed against read-modify-write operations if the architecture +// supports native atomic RmW. // // In the future when a CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=n architecture plans to support Rust, the // load/store helpers that guarantee atomicity against RmW operations (usually via a lock) need to
@@ -58,6 +60,10 @@ impl AtomicImpl for i16 {type Delta =Self ; } +impl AtomicImpl for *const c_void { +type Delta =isize ; +} +// `atomic_t` implements atomic operations on `i32`. impl AtomicImpl for i32 {type Delta =Self ;
@@ -269,7 +275,7 @@ macro_rules! declare_and_impl_atomic_methods { }declare_and_impl_atomic_methods! ( - [i8 => atomic_i8,i16 => atomic_i16,i32 => atomic,i64 => atomic64 ] + [i8 => atomic_i8,i16 => atomic_i16, *const c_void => atomic_ptr,i32 => atomic,i64 => atomic64 ]/// Basic atomic operations pub trait AtomicBasicOps {/// Atomic read (load).
@@ -287,7 +293,7 @@ fn set[release](a: &AtomicRepr<Self>, v: Self) { );declare_and_impl_atomic_methods! ( - [i8 => atomic_i8,i16 => atomic_i16,i32 => atomic,i64 => atomic64 ] + [i8 => atomic_i8,i16 => atomic_i16, *const c_void => atomic_ptr,i32 => atomic,i64 => atomic64 ]/// Exchange and compare-and-exchange atomic operations pub trait AtomicExchangeOps {/// Atomic exchange.
rust/kernel/sync/atomic/predefine.rs +46 -0
62 lines not on this page · raw message
Signature · 1 line
2.50.1 (Apple Git-155)
[tip: locking/core] rust: sync: atomic: Add Atomic<*{mut,const} T> support
The following commit has been merged into the locking/core branch of tip:
The following commit has been merged into the locking/core branch of tip:
Commit-ID: ac8f06ade38a49f7725cc219fc6e90d1d4708d2b Gitweb: https://git.kernel.org/tip/ac8f06ade38a49f7725cc219fc6e90d1d4708d2b Author: Boqun Feng <[email protected]> AuthorDate: Tue, 03 Mar 2026 12:16:55 -08:00 Committer: Peter Zijlstra <[email protected]> CommitterDate: Sun, 08 Mar 2026 11:06:49 +01:00
rust: sync: atomic: Add Atomic<*{mut,const} T> support
Atomic pointer support is an important piece of synchronization algorithm, e.g. RCU, hence provide the support for that.
Note that instead of relying on atomic_long or the implementation of Atomic<usize>, a new set of helpers (atomic_ptr_*) is introduced for atomic pointer specifically, this is because ptr2int casting would lose the provenance of a pointer and even though in theory there are a few tricks the provenance can be restored, it'll still be a simpler implementation if C could provide atomic pointers directly. The side effects of this approach are: we don't have the arithmetic and logical operations for pointers yet and the current implementation only works on ARCH_SUPPORTS_ATOMIC_RMW architectures, but these are implementation issues and can be added later.
--- rust/helpers/atomic_ext.c | 3 ++- rust/kernel/sync/atomic.rs | 12 ++++++- rust/kernel/sync/atomic/internal.rs | 24 ++++++++------ rust/kernel/sync/atomic/predefine.rs | 46 +++++++++++++++++++++++++++- 4 files changed, 75 insertions(+), 10 deletions(-)
rust/helpers/atomic_ext.c +3 -0
@@ -36,6 +36,7 @@ __rust_helper void rust_helper_atomic_##tname##_set_release(type *ptr, type val) GEN_READ_SET_HELPERS(i8, s8) GEN_READ_SET_HELPERS(i16, s16) +GEN_READ_SET_HELPERS(ptr, const void *)/* * xchg helpers depend on ARCH_SUPPORTS_ATOMIC_RMW and on the
@@ -59,6 +60,7 @@ rust_helper_atomic_##tname##_xchg##suffix(type *ptr, type new) \ GEN_XCHG_HELPERS(i8, s8) GEN_XCHG_HELPERS(i16, s16) +GEN_XCHG_HELPERS(ptr, const void *)/* * try_cmpxchg helpers depend on ARCH_SUPPORTS_ATOMIC_RMW and on the
@@ -82,3 +84,4 @@ rust_helper_atomic_##tname##_try_cmpxchg##suffix(type *ptr, type *old, type new) GEN_TRY_CMPXCHG_HELPERS(i8, s8) GEN_TRY_CMPXCHG_HELPERS(i16, s16) +GEN_TRY_CMPXCHG_HELPERS(ptr, const void *)
rust/kernel/sync/atomic.rs +11 -1
@@ -51,6 +51,10 @@ use ordering::OrderingType;#[repr(transparent)] pub struct Atomic <T :AtomicType >(AtomicRepr <T ::Repr >); +// SAFETY: `Atomic<T>` is safe to transfer between execution contexts because of the safety +// requirement of `AtomicType`. +unsafe impl <T :AtomicType >Send for Atomic <T > {} +// SAFETY: `Atomic<T>` is safe to share among execution contexts because all accesses are atomic. unsafe impl <T :AtomicType >Sync for Atomic <T > {}
@@ -68,6 +72,11 @@ unsafe impl<T: AtomicType> Sync for Atomic<T> {}/// /// - [`Self`] must have the same size and alignment as [`Self::Repr`]. /// - [`Self`] must be [round-trip transmutable] to [`Self::Repr`]. +/// - [`Self`] must be safe to transfer between execution contexts, if it's [`Send`], this is +/// automatically satisfied. The exception is pointer types that are even though marked as +/// `!Send` (e.g. raw pointers and [`NonNull<T>`]) but requiring `unsafe` to do anything +/// meaningful on them. This is because transferring pointer values between execution contexts is +/// safe as long as the actual `unsafe` dereferencing is justified. /// /// Note that this is more relaxed than requiring the bi-directional transmutability (i.e. /// [`transmute()`] is always sound between `U` and `T`) because of the support for atomic
@@ -108,7 +117,8 @@ unsafe impl<T: AtomicType> Sync for Atomic<T> {}/// [`transmute()`]: core::mem::transmute /// [round-trip transmutable]: AtomicType#round-trip-transmutability /// [Examples]: AtomicType#examples -pub unsafe trait AtomicType :Sized +Send +Copy { +/// [`NonNull<T>`]: core::ptr::NonNull +pub unsafe trait AtomicType :Sized +Copy {/// The backing atomic implementation type. type Repr :AtomicImpl ; }
rust/kernel/sync/atomic/internal.rs +15 -9
@@ -7,6 +7,7 @@use crate ::bindings;use crate ::macros::paste;use core::cell::UnsafeCell ; +use ffi::c_void;mod private {/// Sealed trait marker to disable customized impls on atomic implementation traits.
@@ -14,10 +15,11 @@ mod private { }// The C side supports atomic primitives only for `i32` and `i64` (`atomic_t` and `atomic64_t`), -// while the Rust side also layers provides atomic support for `i8` and `i16` -// on top of lower-level C primitives. +// while the Rust side also provides atomic support for `i8`, `i16` and `*const c_void` on top of +// lower-level C primitives. impl private::Sealed for i8 {}impl private::Sealed for i16 {} +impl private::Sealed for *const c_void {}impl private::Sealed for i32 {}impl private::Sealed for i64 {}
@@ -26,10 +28,10 @@ impl private::Sealed for i64 {}/// This trait is sealed, and only types that map directly to the C side atomics /// or can be implemented with lower-level C primitives are allowed to implement this: /// -/// - `i8` and `i16` are implemented with lower-level C primitives. +/// - `i8`, `i16` and `*const c_void` are implemented with lower-level C primitives. /// - `i32` map to `atomic_t` /// - `i64` map to `atomic64_t` -pub trait AtomicImpl :Sized +Send +Copy + private::Sealed { +pub trait AtomicImpl :Sized +Copy + private::Sealed {/// The type of the delta in arithmetic or logical operations. /// /// For example, in `atomic_add(ptr, v)`, it's the type of `v`. Usually it's the same type of
@@ -37,9 +39,9 @@ pub trait AtomicImpl: Sized + Send + Copy + private::Sealed {type Delta ; } -// The current helpers of load/store of atomic `i8` and `i16` use `{WRITE,READ}_ONCE()` hence the -// atomicity is only guaranteed against read-modify-write operations if the architecture supports -// native atomic RmW. +// The current helpers of load/store of atomic `i8`, `i16` and pointers use `{WRITE,READ}_ONCE()` +// hence the atomicity is only guaranteed against read-modify-write operations if the architecture +// supports native atomic RmW. // // In the future when a CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=n architecture plans to support Rust, the // load/store helpers that guarantee atomicity against RmW operations (usually via a lock) need to
@@ -58,6 +60,10 @@ impl AtomicImpl for i16 {type Delta =Self ; } +impl AtomicImpl for *const c_void { +type Delta =isize ; +} +// `atomic_t` implements atomic operations on `i32`. impl AtomicImpl for i32 {type Delta =Self ;
@@ -269,7 +275,7 @@ macro_rules! declare_and_impl_atomic_methods { }declare_and_impl_atomic_methods! ( - [i8 => atomic_i8,i16 => atomic_i16,i32 => atomic,i64 => atomic64 ] + [i8 => atomic_i8,i16 => atomic_i16, *const c_void => atomic_ptr,i32 => atomic,i64 => atomic64 ]/// Basic atomic operations pub trait AtomicBasicOps {/// Atomic read (load).
@@ -287,7 +293,7 @@ declare_and_impl_atomic_methods!( );declare_and_impl_atomic_methods! ( - [i8 => atomic_i8,i16 => atomic_i16,i32 => atomic,i64 => atomic64 ] + [i8 => atomic_i8,i16 => atomic_i16, *const c_void => atomic_ptr,i32 => atomic,i64 => atomic64 ]/// Exchange and compare-and-exchange atomic operations pub trait AtomicExchangeOps {/// Atomic exchange.
rust/kernel/sync/atomic/predefine.rs +46 -0
62 lines not on this page · raw message
Boqun Feng
maintainerPATCH 8/13 rust: sync: atomic: Add performance-optimal Flag type for atomic booleans
In reply to Boqun FengFrom: FUJITA Tomonori <[email protected]>
Add AtomicFlag type for boolean flags.
Document when AtomicFlag is generally preferable to Atomic<bool>: in particular, when RMW operations such as xchg()/cmpxchg() may be used and minimizing memory usage is not the top priority. On some architectures without byte-sized RMW instructions, Atomic<bool> can be slower for RMW operations.
--- rust/kernel/sync/atomic.rs | 125 +++++++++++++++++++++++++++ rust/kernel/sync/atomic/predefine.rs | 17 ++++ 2 files changed, 142 insertions(+)
rust/kernel/sync/atomic.rs +125 -0
@@ -578,3 +578,128 @@ pub fn fetch_add<Rhs, Ordering: ordering::Ordering>(&self, v: Rhs, _: Ordering)unsafe {from_repr (ret) } } } + +#[cfg(any( CONFIG_X86_64 , CONFIG_UML , CONFIG_ARM , CONFIG_ARM64 ))] +#[repr( C )] +#[derive( Clone , Copy )] +struct Flag { + bool_field:bool , +} + +/// # Invariants +/// +/// `padding` must be all zeroes. +#[cfg(not(any( CONFIG_X86_64 , CONFIG_UML , CONFIG_ARM , CONFIG_ARM64 )))] +#[repr( C , align( 4 ))] +#[derive( Clone , Copy )] +struct Flag { +#[cfg(target_endian = "big" )] + padding: [u8 ;3 ], + bool_field:bool , +#[cfg(target_endian = "little" )] + padding: [u8 ;3 ], +} + +impl Flag { +#[inline(always)] +const fn new (b:bool ) ->Self { +// INVARIANT: `padding` is all zeroes. +Self { + bool_field: b, +#[cfg(not(any( CONFIG_X86_64 , CONFIG_UML , CONFIG_ARM , CONFIG_ARM64 )))] + padding: [0 ;3 ], + } + } +} + +// SAFETY: `Flag` and `Repr` have the same size and alignment, and `Flag` is round-trip +// transmutable to the selected representation (`i8` or `i32`). +unsafe impl AtomicType for Flag { +#[cfg(any( CONFIG_X86_64 , CONFIG_UML , CONFIG_ARM , CONFIG_ARM64 ))] +type Repr =i8 ; +#[cfg(not(any( CONFIG_X86_64 , CONFIG_UML , CONFIG_ARM , CONFIG_ARM64 )))] +type Repr =i32 ; +} + +/// An atomic flag type intended to be backed by performance-optimal integer type. +/// +/// The backing integer type is an implementation detail; it may vary by architecture and change +/// in the future. +/// +/// [`AtomicFlag`] is generally preferable to [`Atomic<bool>`] when you need read-modify-write +/// (RMW) operations (e.g. [`Atomic::xchg()`]/[`Atomic::cmpxchg()`]) or when [`Atomic<bool>`] does +/// not save memory due to padding. On some architectures that do not support byte-sized atomic +/// RMW operations, RMW operations on [`Atomic<bool>`] are slower. +/// +/// If you only use [`Atomic::load()`]/[`Atomic::store()`], [`Atomic<bool>`] is fine. +/// +/// # Examples +/// +/// ``` +/// use kernel::sync::atomic::{AtomicFlag, Relaxed}; +/// +/// let flag = AtomicFlag::new(false); +/// assert_eq!(false, flag.load(Relaxed)); +/// flag.store(true, Relaxed); +/// assert_eq!(true, flag.load(Relaxed)); +/// ``` +pub struct AtomicFlag (Atomic <Flag >); + +impl AtomicFlag { +/// Creates a new atomic flag. +#[inline(always)] +pub const fn new (b:bool ) ->Self { +Self (Atomic ::new (Flag ::new (b))) + } + +/// Returns a mutable reference to the underlying flag as a [`bool`]. +/// +/// This is safe because the mutable reference of the atomic flag guarantees exclusive access. +/// +/// # Examples +/// +/// ``` +/// use kernel::sync::atomic::{AtomicFlag, Relaxed}; +/// +/// let mut atomic_flag = AtomicFlag::new(false); +/// assert_eq!(false, atomic_flag.load(Relaxed)); +/// *atomic_flag.get_mut() = true; +/// assert_eq!(true, atomic_flag.load(Relaxed)); +/// ``` +#[inline(always)] +pub fn get_mut (&mut self) -> &mut bool { + &mut self.0 .get_mut ().bool_field + } + +/// Loads the value from the atomic flag. +#[inline(always)] +pub fn load <Ordering : ordering::AcquireOrRelaxed >(&self, o:Ordering ) ->bool { + self.0 .load (o).bool_field + } + +/// Stores a value to the atomic flag. +#[inline(always)] +pub fn store <Ordering : ordering::ReleaseOrRelaxed >(&self, v:bool , o:Ordering ) { + self.0 .store (Flag ::new (v), o); + } + +/// Stores a value to the atomic flag and returns the previous value. +#[inline(always)] +pub fn xchg <Ordering : ordering::Ordering >(&self, new:bool , o:Ordering ) ->bool { + self.0 .xchg (Flag ::new (new), o).bool_field + } + +/// Store a value to the atomic flag if the current value is equal to `old`. +#[inline(always)] +pub fn cmpxchg <Ordering : ordering::Ordering >( + &self, + old:bool , + new:bool , + o:Ordering , + ) ->Result <bool ,bool > { +match self.0 .cmpxchg (Flag ::new (old),Flag ::new (new), o) { +Ok (_) =>Ok (old), +Err (f) =>Err (f.bool_field), + } + } +}
rust/kernel/sync/atomic/predefine.rs +17 -0
@@ -272,4 +272,21 @@ fn atomic_ptr_tests() { );assert_eq! (x.load (Relaxed ), &raw const u); } + +#[test] +fn atomic_flag_tests () { +let mut flag =AtomicFlag ::new (false ); + +assert_eq! (false , flag.load (Relaxed )); + + *flag.get_mut () =true ; +assert_eq! (true , flag.load (Relaxed )); + +assert_eq! (true , flag.xchg (false ,Relaxed )); +assert_eq! (false , flag.load (Relaxed )); + + *flag.get_mut () =true ; +assert_eq! (Ok (true ), flag.cmpxchg (true ,false ,Full )); +assert_eq! (false , flag.load (Relaxed )); + } }
Signature · 1 line
2.50.1 (Apple Git-155)
[tip: locking/core] rust: sync: atomic: Add performance-optimal Flag type for atomic booleans
The following commit has been merged into the locking/core branch of tip:
The following commit has been merged into the locking/core branch of tip:
Commit-ID: ec6fc66ac39b1a6c0b06a828eff8d21928e56b60 Gitweb: https://git.kernel.org/tip/ec6fc66ac39b1a6c0b06a828eff8d21928e56b60 Author: FUJITA Tomonori <[email protected]> AuthorDate: Tue, 03 Mar 2026 12:16:56 -08:00 Committer: Peter Zijlstra <[email protected]> CommitterDate: Sun, 08 Mar 2026 11:06:49 +01:00
rust: sync: atomic: Add performance-optimal Flag type for atomic booleans
Add AtomicFlag type for boolean flags.
Document when AtomicFlag is generally preferable to Atomic<bool>: in particular, when RMW operations such as xchg()/cmpxchg() may be used and minimizing memory usage is not the top priority. On some architectures without byte-sized RMW instructions, Atomic<bool> can be slower for RMW operations.
--- rust/kernel/sync/atomic.rs | 125 ++++++++++++++++++++++++++- rust/kernel/sync/atomic/predefine.rs | 17 ++++- 2 files changed, 142 insertions(+)
rust/kernel/sync/atomic.rs +125 -0
@@ -578,3 +578,128 @@ whereunsafe {from_repr (ret) } } } + +#[cfg(any( CONFIG_X86_64 , CONFIG_UML , CONFIG_ARM , CONFIG_ARM64 ))] +#[repr( C )] +#[derive( Clone , Copy )] +struct Flag { + bool_field:bool , +} + +/// # Invariants +/// +/// `padding` must be all zeroes. +#[cfg(not(any( CONFIG_X86_64 , CONFIG_UML , CONFIG_ARM , CONFIG_ARM64 )))] +#[repr( C , align( 4 ))] +#[derive( Clone , Copy )] +struct Flag { +#[cfg(target_endian = "big" )] + padding: [u8 ;3 ], + bool_field:bool , +#[cfg(target_endian = "little" )] + padding: [u8 ;3 ], +} + +impl Flag { +#[inline(always)] +const fn new (b:bool ) ->Self { +// INVARIANT: `padding` is all zeroes. +Self { + bool_field: b, +#[cfg(not(any( CONFIG_X86_64 , CONFIG_UML , CONFIG_ARM , CONFIG_ARM64 )))] + padding: [0 ;3 ], + } + } +} + +// SAFETY: `Flag` and `Repr` have the same size and alignment, and `Flag` is round-trip +// transmutable to the selected representation (`i8` or `i32`). +unsafe impl AtomicType for Flag { +#[cfg(any( CONFIG_X86_64 , CONFIG_UML , CONFIG_ARM , CONFIG_ARM64 ))] +type Repr =i8 ; +#[cfg(not(any( CONFIG_X86_64 , CONFIG_UML , CONFIG_ARM , CONFIG_ARM64 )))] +type Repr =i32 ; +} + +/// An atomic flag type intended to be backed by performance-optimal integer type. +/// +/// The backing integer type is an implementation detail; it may vary by architecture and change +/// in the future. +/// +/// [`AtomicFlag`] is generally preferable to [`Atomic<bool>`] when you need read-modify-write +/// (RMW) operations (e.g. [`Atomic::xchg()`]/[`Atomic::cmpxchg()`]) or when [`Atomic<bool>`] does +/// not save memory due to padding. On some architectures that do not support byte-sized atomic +/// RMW operations, RMW operations on [`Atomic<bool>`] are slower. +/// +/// If you only use [`Atomic::load()`]/[`Atomic::store()`], [`Atomic<bool>`] is fine. +/// +/// # Examples +/// +/// ``` +/// use kernel::sync::atomic::{AtomicFlag, Relaxed}; +/// +/// let flag = AtomicFlag::new(false); +/// assert_eq!(false, flag.load(Relaxed)); +/// flag.store(true, Relaxed); +/// assert_eq!(true, flag.load(Relaxed)); +/// ``` +pub struct AtomicFlag (Atomic <Flag >); + +impl AtomicFlag { +/// Creates a new atomic flag. +#[inline(always)] +pub const fn new (b:bool ) ->Self { +Self (Atomic ::new (Flag ::new (b))) + } + +/// Returns a mutable reference to the underlying flag as a [`bool`]. +/// +/// This is safe because the mutable reference of the atomic flag guarantees exclusive access. +/// +/// # Examples +/// +/// ``` +/// use kernel::sync::atomic::{AtomicFlag, Relaxed}; +/// +/// let mut atomic_flag = AtomicFlag::new(false); +/// assert_eq!(false, atomic_flag.load(Relaxed)); +/// *atomic_flag.get_mut() = true; +/// assert_eq!(true, atomic_flag.load(Relaxed)); +/// ``` +#[inline(always)] +pub fn get_mut (&mut self) -> &mut bool { + &mut self.0 .get_mut ().bool_field + } + +/// Loads the value from the atomic flag. +#[inline(always)] +pub fn load <Ordering : ordering::AcquireOrRelaxed >(&self, o:Ordering ) ->bool { + self.0 .load (o).bool_field + } + +/// Stores a value to the atomic flag. +#[inline(always)] +pub fn store <Ordering : ordering::ReleaseOrRelaxed >(&self, v:bool , o:Ordering ) { + self.0 .store (Flag ::new (v), o); + } + +/// Stores a value to the atomic flag and returns the previous value. +#[inline(always)] +pub fn xchg <Ordering : ordering::Ordering >(&self, new:bool , o:Ordering ) ->bool { + self.0 .xchg (Flag ::new (new), o).bool_field + } + +/// Store a value to the atomic flag if the current value is equal to `old`. +#[inline(always)] +pub fn cmpxchg <Ordering : ordering::Ordering >( + &self, + old:bool , + new:bool , + o:Ordering , + ) ->Result <bool ,bool > { +match self.0 .cmpxchg (Flag ::new (old),Flag ::new (new), o) { +Ok (_) =>Ok (old), +Err (f) =>Err (f.bool_field), + } + } +}
rust/kernel/sync/atomic/predefine.rs +17 -0
@@ -272,4 +272,21 @@ mod tests { );assert_eq! (x.load (Relaxed ), &raw const u); } + +#[test] +fn atomic_flag_tests () { +let mut flag =AtomicFlag ::new (false ); + +assert_eq! (false , flag.load (Relaxed )); + + *flag.get_mut () =true ; +assert_eq! (true , flag.load (Relaxed )); + +assert_eq! (true , flag.xchg (false ,Relaxed )); +assert_eq! (false , flag.load (Relaxed )); + + *flag.get_mut () =true ; +assert_eq! (Ok (true ), flag.cmpxchg (true ,false ,Full )); +assert_eq! (false , flag.load (Relaxed )); + } }
Boqun Feng
maintainerPATCH 9/13 rust: list: Use AtomicFlag in AtomicTracker
In reply to Boqun FengFrom: FUJITA Tomonori <[email protected]>
Make AtomicTracker use AtomicFlag instead of Atomic<bool> to avoid slow byte-sized RMWs on architectures that don't support them.
--- rust/kernel/list/arc.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
rust/kernel/list/arc.rs +4 -4
@@ -6,7 +6,7 @@use crate ::alloc::{AllocError ,Flags };use crate ::prelude::*; -use crate ::sync::atomic::{ordering,Atomic }; +use crate ::sync::atomic::{ordering,AtomicFlag };use crate ::sync::{Arc ,ArcBorrow ,UniqueArc };use core::marker::PhantomPinned ;use core::ops::Deref ;
@@ -469,7 +469,7 @@ impl<T, U, const ID: u64> core::ops::DispatchFromDyn<ListArc<U, ID>> for ListArc/// If the boolean is `false`, then there is no [`ListArc`] for this value. #[repr(transparent)] pub struct AtomicTracker <const ID :u64 =0 > { - inner:Atomic <bool >, + inner:AtomicFlag ,// This value needs to be pinned to justify the INVARIANT: comment in `AtomicTracker::new`. _pin:PhantomPinned , }
@@ -480,12 +480,12 @@ pub fn new() -> impl PinInit<Self> {// INVARIANT: Pin-init initializers can't be used on an existing `Arc`, so this value will // not be constructed in an `Arc` that already has a `ListArc`. Self { - inner:Atomic ::new (false ), + inner:AtomicFlag ::new (false ), _pin:PhantomPinned , } } -fn project_inner (self:Pin <&mut Self >) -> &mut Atomic <bool > { +fn project_inner (self:Pin <&mut Self >) -> &mut AtomicFlag {// SAFETY: The `inner` field is not structurally pinned, so we may obtain a mutable // reference to it even if we only have a pinned reference to `self`. unsafe { &mut Pin ::into_inner_unchecked (self).inner }
Signature · 1 line
2.50.1 (Apple Git-155)
[tip: locking/core] rust: list: Use AtomicFlag in AtomicTracker
The following commit has been merged into the locking/core branch of tip:
The following commit has been merged into the locking/core branch of tip:
Commit-ID: 282866207020b15c2afc4d43b1ca0c5d96c9032d Gitweb: https://git.kernel.org/tip/282866207020b15c2afc4d43b1ca0c5d96c9032d Author: FUJITA Tomonori <[email protected]> AuthorDate: Tue, 03 Mar 2026 12:16:57 -08:00 Committer: Peter Zijlstra <[email protected]> CommitterDate: Sun, 08 Mar 2026 11:06:50 +01:00
rust: list: Use AtomicFlag in AtomicTracker
Make AtomicTracker use AtomicFlag instead of Atomic<bool> to avoid slow byte-sized RMWs on architectures that don't support them.
--- rust/kernel/list/arc.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
rust/kernel/list/arc.rs +4 -4
@@ -6,7 +6,7 @@use crate ::alloc::{AllocError ,Flags };use crate ::prelude::*; -use crate ::sync::atomic::{ordering,Atomic }; +use crate ::sync::atomic::{ordering,AtomicFlag };use crate ::sync::{Arc ,ArcBorrow ,UniqueArc };use core::marker::PhantomPinned ;use core::ops::Deref ;
@@ -469,7 +469,7 @@ where/// If the boolean is `false`, then there is no [`ListArc`] for this value. #[repr(transparent)] pub struct AtomicTracker <const ID :u64 =0 > { - inner:Atomic <bool >, + inner:AtomicFlag ,// This value needs to be pinned to justify the INVARIANT: comment in `AtomicTracker::new`. _pin:PhantomPinned , }
@@ -480,12 +480,12 @@ impl<const ID: u64> AtomicTracker<ID> {// INVARIANT: Pin-init initializers can't be used on an existing `Arc`, so this value will // not be constructed in an `Arc` that already has a `ListArc`. Self { - inner:Atomic ::new (false ), + inner:AtomicFlag ::new (false ), _pin:PhantomPinned , } } -fn project_inner (self:Pin <&mut Self >) -> &mut Atomic <bool > { +fn project_inner (self:Pin <&mut Self >) -> &mut AtomicFlag {// SAFETY: The `inner` field is not structurally pinned, so we may obtain a mutable // reference to it even if we only have a pinned reference to `self`. unsafe { &mut Pin ::into_inner_unchecked (self).inner }
Boqun Feng
maintainerPATCH 10/13 rust: sync: atomic: Add atomic operation helpers over raw pointers
In reply to Boqun FengFrom: Boqun Feng <[email protected]>
In order to synchronize with C or external memory, atomic operations over raw pointers are need. Although there is already an Atomic::from_ptr() to provide a &Atomic<T>, it's more convenient to have helpers that directly perform atomic operations on raw pointers. Hence a few are added, which are basically an Atomic::from_ptr().op() wrapper.
Note: for naming, since atomic_xchg() and atomic_cmpxchg() have a conflict naming to 32bit C atomic xchg/cmpxchg, hence the helpers are just named as xchg() and cmpxchg(). For atomic_load() and atomic_store(), their 32bit C counterparts are atomic_read() and atomic_set(), so keep the atomic_ prefix.
[boqun: Fix typo spotted by Alice and fix broken sentence spotted by Gary]
--- rust/kernel/sync/atomic.rs | 104 +++++++++++++++++++++++++++ rust/kernel/sync/atomic/predefine.rs | 46 ++++++++++++ 2 files changed, 150 insertions(+)
rust/kernel/sync/atomic.rs +104 -0
@@ -703,3 +703,107 @@ pub fn cmpxchg<Ordering: ordering::Ordering>( } } } + +/// Atomic load over raw pointers. +/// +/// This function provides a short-cut of `Atomic::from_ptr().load(..)`, and can be used to work +/// with C side on synchronizations: +/// +/// - `atomic_load(.., Relaxed)` maps to `READ_ONCE()` when used for inter-thread communication. +/// - `atomic_load(.., Acquire)` maps to `smp_load_acquire()`. +/// +/// # Safety +/// +/// - `ptr` is a valid pointer to `T` and aligned to `align_of::<T>()`. +/// - If there is a concurrent store from kernel (C or Rust), it has to be atomic. +#[doc(alias( "READ_ONCE" , "smp_load_acquire" ))] +#[inline(always)] +pub unsafe fn atomic_load <T :AtomicType ,Ordering : ordering::AcquireOrRelaxed >( + ptr: *mut T , + o:Ordering , +) ->T +where +T ::Repr :AtomicBasicOps , +{ +// SAFETY: Per the function safety requirement, `ptr` is valid and aligned to +// `align_of::<T>()`, and all concurrent stores from kernel are atomic, hence no data race per +// LKMM. +unsafe {Atomic ::from_ptr (ptr) }.load (o) +} + +/// Atomic store over raw pointers. +/// +/// This function provides a short-cut of `Atomic::from_ptr().load(..)`, and can be used to work +/// with C side on synchronizations: +/// +/// - `atomic_store(.., Relaxed)` maps to `WRITE_ONCE()` when used for inter-thread communication. +/// - `atomic_load(.., Release)` maps to `smp_store_release()`. +/// +/// # Safety +/// +/// - `ptr` is a valid pointer to `T` and aligned to `align_of::<T>()`. +/// - If there is a concurrent access from kernel (C or Rust), it has to be atomic. +#[doc(alias( "WRITE_ONCE" , "smp_store_release" ))] +#[inline(always)] +pub unsafe fn atomic_store <T :AtomicType ,Ordering : ordering::ReleaseOrRelaxed >( + ptr: *mut T , + v:T , + o:Ordering , +)where +T ::Repr :AtomicBasicOps , +{ +// SAFETY: Per the function safety requirement, `ptr` is valid and aligned to +// `align_of::<T>()`, and all concurrent accesses from kernel are atomic, hence no data race +// per LKMM. +unsafe {Atomic ::from_ptr (ptr) }.store (v, o); +} + +/// Atomic exchange over raw pointers. +/// +/// This function provides a short-cut of `Atomic::from_ptr().xchg(..)`, and can be used to work +/// with C side on synchronizations. +/// +/// # Safety +/// +/// - `ptr` is a valid pointer to `T` and aligned to `align_of::<T>()`. +/// - If there is a concurrent access from kernel (C or Rust), it has to be atomic. +#[inline(always)] +pub unsafe fn xchg <T :AtomicType ,Ordering : ordering::Ordering >( + ptr: *mut T , + new:T , + o:Ordering , +) ->T +where +T ::Repr :AtomicExchangeOps , +{ +// SAFETY: Per the function safety requirement, `ptr` is valid and aligned to +// `align_of::<T>()`, and all concurrent accesses from kernel are atomic, hence no data race +// per LKMM. +unsafe {Atomic ::from_ptr (ptr) }.xchg (new, o) +} + +/// Atomic compare and exchange over raw pointers. +/// +/// This function provides a short-cut of `Atomic::from_ptr().cmpxchg(..)`, and can be used to work +/// with C side on synchronizations. +/// +/// # Safety +/// +/// - `ptr` is a valid pointer to `T` and aligned to `align_of::<T>()`. +/// - If there is a concurrent access from kernel (C or Rust), it has to be atomic. +#[doc(alias( "try_cmpxchg" ))] +#[inline(always)] +pub unsafe fn cmpxchg <T :AtomicType ,Ordering : ordering::Ordering >( + ptr: *mut T , + old:T , + new:T , + o:Ordering , +) ->Result <T ,T > +where +T ::Repr :AtomicExchangeOps , +{ +// SAFETY: Per the function safety requirement, `ptr` is valid and aligned to +// `align_of::<T>()`, and all concurrent accesses from kernel are atomic, hence no data race +// per LKMM. +unsafe {Atomic ::from_ptr (ptr) }.cmpxchg (old, new, o) +}
rust/kernel/sync/atomic/predefine.rs +46 -0
70 lines not on this page · raw message
Signature · 1 line
2.50.1 (Apple Git-155)
[tip: locking/core] rust: sync: atomic: Add atomic operation helpers over raw pointers
The following commit has been merged into the locking/core branch of tip:
The following commit has been merged into the locking/core branch of tip:
Commit-ID: e2f9c86f33abb89d3e52436018f58e5fb951cc04 Gitweb: https://git.kernel.org/tip/e2f9c86f33abb89d3e52436018f58e5fb951cc04 Author: Boqun Feng <[email protected]> AuthorDate: Tue, 03 Mar 2026 12:16:58 -08:00 Committer: Peter Zijlstra <[email protected]> CommitterDate: Sun, 08 Mar 2026 11:06:50 +01:00
rust: sync: atomic: Add atomic operation helpers over raw pointers
In order to synchronize with C or external memory, atomic operations over raw pointers are need. Although there is already an Atomic::from_ptr() to provide a &Atomic<T>, it's more convenient to have helpers that directly perform atomic operations on raw pointers. Hence a few are added, which are basically an Atomic::from_ptr().op() wrapper.
Note: for naming, since atomic_xchg() and atomic_cmpxchg() have a conflict naming to 32bit C atomic xchg/cmpxchg, hence the helpers are just named as xchg() and cmpxchg(). For atomic_load() and atomic_store(), their 32bit C counterparts are atomic_read() and atomic_set(), so keep the atomic_ prefix.
[boqun: Fix typo spotted by Alice and fix broken sentence spotted by Gary]
--- rust/kernel/sync/atomic.rs | 104 ++++++++++++++++++++++++++- rust/kernel/sync/atomic/predefine.rs | 46 ++++++++++++- 2 files changed, 150 insertions(+)
rust/kernel/sync/atomic.rs +104 -0
@@ -703,3 +703,107 @@ impl AtomicFlag { } } } + +/// Atomic load over raw pointers. +/// +/// This function provides a short-cut of `Atomic::from_ptr().load(..)`, and can be used to work +/// with C side on synchronizations: +/// +/// - `atomic_load(.., Relaxed)` maps to `READ_ONCE()` when used for inter-thread communication. +/// - `atomic_load(.., Acquire)` maps to `smp_load_acquire()`. +/// +/// # Safety +/// +/// - `ptr` is a valid pointer to `T` and aligned to `align_of::<T>()`. +/// - If there is a concurrent store from kernel (C or Rust), it has to be atomic. +#[doc(alias( "READ_ONCE" , "smp_load_acquire" ))] +#[inline(always)] +pub unsafe fn atomic_load <T :AtomicType ,Ordering : ordering::AcquireOrRelaxed >( + ptr: *mut T , + o:Ordering , +) ->T +where +T ::Repr :AtomicBasicOps , +{ +// SAFETY: Per the function safety requirement, `ptr` is valid and aligned to +// `align_of::<T>()`, and all concurrent stores from kernel are atomic, hence no data race per +// LKMM. +unsafe {Atomic ::from_ptr (ptr) }.load (o) +} + +/// Atomic store over raw pointers. +/// +/// This function provides a short-cut of `Atomic::from_ptr().load(..)`, and can be used to work +/// with C side on synchronizations: +/// +/// - `atomic_store(.., Relaxed)` maps to `WRITE_ONCE()` when used for inter-thread communication. +/// - `atomic_load(.., Release)` maps to `smp_store_release()`. +/// +/// # Safety +/// +/// - `ptr` is a valid pointer to `T` and aligned to `align_of::<T>()`. +/// - If there is a concurrent access from kernel (C or Rust), it has to be atomic. +#[doc(alias( "WRITE_ONCE" , "smp_store_release" ))] +#[inline(always)] +pub unsafe fn atomic_store <T :AtomicType ,Ordering : ordering::ReleaseOrRelaxed >( + ptr: *mut T , + v:T , + o:Ordering , +)where +T ::Repr :AtomicBasicOps , +{ +// SAFETY: Per the function safety requirement, `ptr` is valid and aligned to +// `align_of::<T>()`, and all concurrent accesses from kernel are atomic, hence no data race +// per LKMM. +unsafe {Atomic ::from_ptr (ptr) }.store (v, o); +} + +/// Atomic exchange over raw pointers. +/// +/// This function provides a short-cut of `Atomic::from_ptr().xchg(..)`, and can be used to work +/// with C side on synchronizations. +/// +/// # Safety +/// +/// - `ptr` is a valid pointer to `T` and aligned to `align_of::<T>()`. +/// - If there is a concurrent access from kernel (C or Rust), it has to be atomic. +#[inline(always)] +pub unsafe fn xchg <T :AtomicType ,Ordering : ordering::Ordering >( + ptr: *mut T , + new:T , + o:Ordering , +) ->T +where +T ::Repr :AtomicExchangeOps , +{ +// SAFETY: Per the function safety requirement, `ptr` is valid and aligned to +// `align_of::<T>()`, and all concurrent accesses from kernel are atomic, hence no data race +// per LKMM. +unsafe {Atomic ::from_ptr (ptr) }.xchg (new, o) +} + +/// Atomic compare and exchange over raw pointers. +/// +/// This function provides a short-cut of `Atomic::from_ptr().cmpxchg(..)`, and can be used to work +/// with C side on synchronizations. +/// +/// # Safety +/// +/// - `ptr` is a valid pointer to `T` and aligned to `align_of::<T>()`. +/// - If there is a concurrent access from kernel (C or Rust), it has to be atomic. +#[doc(alias( "try_cmpxchg" ))] +#[inline(always)] +pub unsafe fn cmpxchg <T :AtomicType ,Ordering : ordering::Ordering >( + ptr: *mut T , + old:T , + new:T , + o:Ordering , +) ->Result <T ,T > +where +T ::Repr :AtomicExchangeOps , +{ +// SAFETY: Per the function safety requirement, `ptr` is valid and aligned to +// `align_of::<T>()`, and all concurrent accesses from kernel are atomic, hence no data race +// per LKMM. +unsafe {Atomic ::from_ptr (ptr) }.cmpxchg (old, new, o) +}
rust/kernel/sync/atomic/predefine.rs +46 -0
70 lines not on this page · raw message
Boqun Feng
maintainerPATCH 11/13 rust: sync: atomic: Add fetch_sub()
In reply to Boqun FengFrom: Andreas Hindborg <[email protected]>
Add Atomic::fetch_sub() with implementation and documentation in line with existing Atomic::fetch_add() implementation.
--- rust/kernel/sync/atomic.rs | 43 +++++++++++++++++++++++++++++ rust/kernel/sync/atomic/internal.rs | 5 ++++ 2 files changed, 48 insertions(+)
rust/kernel/sync/atomic.rs +43 -0
@@ -577,6 +577,49 @@ pub fn fetch_add<Rhs, Ordering: ordering::Ordering>(&self, v: Rhs, _: Ordering)// SAFETY: `ret` comes from reading `self.0`, which is a valid `T` per type invariants. unsafe {from_repr (ret) } } + +/// Atomic fetch and subtract. +/// +/// Atomically updates `*self` to `(*self).wrapping_sub(v)`, and returns the value of `*self` +/// before the update. +/// +/// # Examples +/// +/// ``` +/// use kernel::sync::atomic::{Atomic, Acquire, Full, Relaxed}; +/// +/// let x = Atomic::new(42); +/// assert_eq!(42, x.load(Relaxed)); +/// assert_eq!(42, x.fetch_sub(12, Acquire)); +/// assert_eq!(30, x.load(Relaxed)); +/// +/// let x = Atomic::new(42); +/// assert_eq!(42, x.load(Relaxed)); +/// assert_eq!(42, x.fetch_sub(12, Full)); +/// assert_eq!(30, x.load(Relaxed)); +/// ``` +#[inline(always)] +pub fn fetch_sub <Rhs ,Ordering : ordering::Ordering >(&self, v:Rhs , _:Ordering ) ->T +where +// Types that support addition also support subtraction. +T :AtomicAdd <Rhs >, + { +let v =T ::rhs_into_delta (v); + +// INVARIANT: `self.0` is a valid `T` after `atomic_fetch_sub*()` due to safety requirement +// of `AtomicAdd`. +let ret = { +match Ordering ::TYPE { +OrderingType ::Full =>T ::Repr ::atomic_fetch_sub (&self.0 , v), +OrderingType ::Acquire =>T ::Repr ::atomic_fetch_sub_acquire (&self.0 , v), +OrderingType ::Release =>T ::Repr ::atomic_fetch_sub_release (&self.0 , v), +OrderingType ::Relaxed =>T ::Repr ::atomic_fetch_sub_relaxed (&self.0 , v), + } + }; + +// SAFETY: `ret` comes from reading `self.0`, which is a valid `T` per type invariants. +unsafe {from_repr (ret) } + } }#[cfg(any( CONFIG_X86_64 , CONFIG_UML , CONFIG_ARM , CONFIG_ARM64 ))]
rust/kernel/sync/atomic/internal.rs +5 -0
@@ -340,5 +340,10 @@ fn fetch_add[acquire, release, relaxed](a: &AtomicRepr<Self>, v: Self::Delta) ->// SAFETY: `a.as_ptr()` is valid and properly aligned. unsafe { bindings::#call(v, a.as_ptr().cast()) } } + + fn fetch_sub[acquire, release, relaxed](a: &AtomicRepr<Self>, v: Self::Delta) -> Self { +// SAFETY: `a.as_ptr()` guarantees the returned pointer is valid and properly aligned. + unsafe { bindings::#call(v, a.as_ptr().cast()) } + } } );
Signature · 1 line
2.50.1 (Apple Git-155)
[tip: locking/core] rust: sync: atomic: Add fetch_sub()
The following commit has been merged into the locking/core branch of tip:
The following commit has been merged into the locking/core branch of tip:
Commit-ID: c49cf341090b53d2afa4dc7c8007ddeefbb3b37f Gitweb: https://git.kernel.org/tip/c49cf341090b53d2afa4dc7c8007ddeefbb3b37f Author: Andreas Hindborg <[email protected]> AuthorDate: Tue, 03 Mar 2026 12:16:59 -08:00 Committer: Peter Zijlstra <[email protected]> CommitterDate: Sun, 08 Mar 2026 11:06:50 +01:00
rust: sync: atomic: Add fetch_sub()
Add Atomic::fetch_sub() with implementation and documentation in line with existing Atomic::fetch_add() implementation.
--- rust/kernel/sync/atomic.rs | 43 ++++++++++++++++++++++++++++- rust/kernel/sync/atomic/internal.rs | 5 +++- 2 files changed, 48 insertions(+)
rust/kernel/sync/atomic.rs +43 -0
@@ -577,6 +577,49 @@ where// SAFETY: `ret` comes from reading `self.0`, which is a valid `T` per type invariants. unsafe {from_repr (ret) } } + +/// Atomic fetch and subtract. +/// +/// Atomically updates `*self` to `(*self).wrapping_sub(v)`, and returns the value of `*self` +/// before the update. +/// +/// # Examples +/// +/// ``` +/// use kernel::sync::atomic::{Atomic, Acquire, Full, Relaxed}; +/// +/// let x = Atomic::new(42); +/// assert_eq!(42, x.load(Relaxed)); +/// assert_eq!(42, x.fetch_sub(12, Acquire)); +/// assert_eq!(30, x.load(Relaxed)); +/// +/// let x = Atomic::new(42); +/// assert_eq!(42, x.load(Relaxed)); +/// assert_eq!(42, x.fetch_sub(12, Full)); +/// assert_eq!(30, x.load(Relaxed)); +/// ``` +#[inline(always)] +pub fn fetch_sub <Rhs ,Ordering : ordering::Ordering >(&self, v:Rhs , _:Ordering ) ->T +where +// Types that support addition also support subtraction. +T :AtomicAdd <Rhs >, + { +let v =T ::rhs_into_delta (v); + +// INVARIANT: `self.0` is a valid `T` after `atomic_fetch_sub*()` due to safety requirement +// of `AtomicAdd`. +let ret = { +match Ordering ::TYPE { +OrderingType ::Full =>T ::Repr ::atomic_fetch_sub (&self.0 , v), +OrderingType ::Acquire =>T ::Repr ::atomic_fetch_sub_acquire (&self.0 , v), +OrderingType ::Release =>T ::Repr ::atomic_fetch_sub_release (&self.0 , v), +OrderingType ::Relaxed =>T ::Repr ::atomic_fetch_sub_relaxed (&self.0 , v), + } + }; + +// SAFETY: `ret` comes from reading `self.0`, which is a valid `T` per type invariants. +unsafe {from_repr (ret) } + } }#[cfg(any( CONFIG_X86_64 , CONFIG_UML , CONFIG_ARM , CONFIG_ARM64 ))]
rust/kernel/sync/atomic/internal.rs +5 -0
@@ -340,5 +340,10 @@ declare_and_impl_atomic_methods!(// SAFETY: `a.as_ptr()` is valid and properly aligned. unsafe { bindings::#call(v, a.as_ptr().cast()) } } + + fn fetch_sub[acquire, release, relaxed](a: &AtomicRepr<Self>, v: Self::Delta) -> Self { +// SAFETY: `a.as_ptr()` guarantees the returned pointer is valid and properly aligned. + unsafe { bindings::#call(v, a.as_ptr().cast()) } + } } );
Boqun Feng
maintainerPATCH 12/13 rust: sync: atomic: Update documentation for `fetch_add()`
In reply to Boqun FengFrom: Andreas Hindborg <[email protected]>
The documentation for fetch_add() does not indicate that the original value is returned by fetch_add(). Update the documentation so this is clear.
--- rust/kernel/sync/atomic.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-)
rust/kernel/sync/atomic.rs +4 -6
@@ -545,16 +545,14 @@ pub fn add<Rhs>(&self, v: Rhs, _: ordering::Relaxed)/// use kernel::sync::atomic::{Atomic, Acquire, Full, Relaxed}; /// /// let x = Atomic::new(42); -/// /// assert_eq!(42, x.load(Relaxed)); -/// -/// assert_eq!(54, { x.fetch_add(12, Acquire); x.load(Relaxed) }); +/// assert_eq!(42, x.fetch_add(12, Acquire)); +/// assert_eq!(54, x.load(Relaxed)); /// /// let x = Atomic::new(42); -/// /// assert_eq!(42, x.load(Relaxed)); -/// -/// assert_eq!(54, { x.fetch_add(12, Full); x.load(Relaxed) } ); +/// assert_eq!(42, x.fetch_add(12, Full)); +/// assert_eq!(54, x.load(Relaxed)); /// ``` #[inline(always)] pub fn fetch_add <Rhs ,Ordering : ordering::Ordering >(&self, v:Rhs , _:Ordering ) ->T
Signature · 1 line
2.50.1 (Apple Git-155)
[tip: locking/core] rust: sync: atomic: Update documentation for `fetch_add()`
The following commit has been merged into the locking/core branch of tip:
The following commit has been merged into the locking/core branch of tip:
Commit-ID: 0b864375d93d1509821def9c4b15f845d314a5d2 Gitweb: https://git.kernel.org/tip/0b864375d93d1509821def9c4b15f845d314a5d2 Author: Andreas Hindborg <[email protected]> AuthorDate: Tue, 03 Mar 2026 12:17:00 -08:00 Committer: Peter Zijlstra <[email protected]> CommitterDate: Sun, 08 Mar 2026 11:06:51 +01:00
rust: sync: atomic: Update documentation for fetch_add()
The documentation for fetch_add() does not indicate that the original value is returned by fetch_add(). Update the documentation so this is clear.
--- rust/kernel/sync/atomic.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-)
rust/kernel/sync/atomic.rs +4 -6
@@ -545,16 +545,14 @@ where/// use kernel::sync::atomic::{Atomic, Acquire, Full, Relaxed}; /// /// let x = Atomic::new(42); -/// /// assert_eq!(42, x.load(Relaxed)); -/// -/// assert_eq!(54, { x.fetch_add(12, Acquire); x.load(Relaxed) }); +/// assert_eq!(42, x.fetch_add(12, Acquire)); +/// assert_eq!(54, x.load(Relaxed)); /// /// let x = Atomic::new(42); -/// /// assert_eq!(42, x.load(Relaxed)); -/// -/// assert_eq!(54, { x.fetch_add(12, Full); x.load(Relaxed) } ); +/// assert_eq!(42, x.fetch_add(12, Full)); +/// assert_eq!(54, x.load(Relaxed)); /// ``` #[inline(always)] pub fn fetch_add <Rhs ,Ordering : ordering::Ordering >(&self, v:Rhs , _:Ordering ) ->T
Boqun Feng
maintainerPATCH 13/13 rust: atomic: Update a safety comment in impl of `fetch_add()`
In reply to Boqun FengFrom: Andreas Hindborg <[email protected]>
The safety comment used in the implementation of fetch_add() could be read as just saying something it is true without justifying it. Update the safety comment to include justification.
--- rust/kernel/sync/atomic/internal.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
rust/kernel/sync/atomic/internal.rs +1 -1
@@ -337,7 +337,7 @@ fn add[](a: &AtomicRepr<Self>, v: Self::Delta) {/// Atomically updates `*a` to `(*a).wrapping_add(v)`, and returns the value of `*a` /// before the update. fn fetch_add[acquire, release, relaxed](a: &AtomicRepr<Self>, v: Self::Delta) -> Self { -// SAFETY: `a.as_ptr()` is valid and properly aligned. +// SAFETY: `a.as_ptr()` guarantees the returned pointer is valid and properly aligned. unsafe { bindings::#call(v, a.as_ptr().cast()) } }
Signature · 1 line
2.50.1 (Apple Git-155)
[tip: locking/core] rust: atomic: Update a safety comment in impl of `fetch_add()`
The following commit has been merged into the locking/core branch of tip:
The following commit has been merged into the locking/core branch of tip:
Commit-ID: b91d5d4bcf1266257a9e0199e1b4ad7fa8771baa Gitweb: https://git.kernel.org/tip/b91d5d4bcf1266257a9e0199e1b4ad7fa8771baa Author: Andreas Hindborg <[email protected]> AuthorDate: Tue, 03 Mar 2026 12:17:01 -08:00 Committer: Peter Zijlstra <[email protected]> CommitterDate: Sun, 08 Mar 2026 11:06:51 +01:00
rust: atomic: Update a safety comment in impl of fetch_add()
The safety comment used in the implementation of fetch_add() could be read as just saying something it is true without justifying it. Update the safety comment to include justification.
--- rust/kernel/sync/atomic/internal.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
rust/kernel/sync/atomic/internal.rs +1 -1
@@ -337,7 +337,7 @@ declare_and_impl_atomic_methods!(/// Atomically updates `*a` to `(*a).wrapping_add(v)`, and returns the value of `*a` /// before the update. fn fetch_add[acquire, release, relaxed](a: &AtomicRepr<Self>, v: Self::Delta) -> Self { -// SAFETY: `a.as_ptr()` is valid and properly aligned. +// SAFETY: `a.as_ptr()` guarantees the returned pointer is valid and properly aligned. unsafe { bindings::#call(v, a.as_ptr().cast()) } }
Boqun Feng
maintainerQuoted 7 lines · Boqun Feng
Hi Peter,
Please pull these changes of Rust atomic in v7.1 into tip/locking/core. Major changes are the atomic pointer support and a boolean-like AtomicFlag type (using a byte if arch support efficient xchg/cmpxchg over bytes otherwise 4 bytes). Thanks!
Gentle ping ;-) Thanks!
Regards,
Boqun
Quoted 26 lines
Regards,
BoqunThe following changes since commit
3dcef70e41ab13483803c536ddea8d5f1803ee25:ww-mutex: Fix the
ww_acquire_ctxfunction annotations (2026-02-27 16:40:20 +0100)are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/boqun/linux.gittags/rust-atomic.20260303afor you to fetch changes up to
68d1c8ac7f0b1f0de92a803b9b71090fd1b86d17:rust: atomic: Update a safety comment in impl of
fetch_add()(2026-03-03 11:55:57 -0800)----------------------------------------------------------------
Rust atomic changes for v7.1* Add Atomic<ptr> support.
* Add an AtomicFlag type for boolean-like usage with architecture-specific performance optimization.
* Add unsafe atomic operations over raw pointers.
* Addfetch_sub()for atomic types.
* Documentation and example improvements. -----BEGIN PGP SIGNATURE-----
[...]