mirror of
https://github.com/torvalds/linux.git
synced 2026-04-18 06:44:00 -04:00
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. Signed-off-by: Boqun Feng <boqun.feng@gmail.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Reviewed-by: Gary Guo <gary@garyguo.net> Reviewed-by: FUJITA Tomonori <fujita.tomonori@gmail.com> Link: https://patch.msgid.link/20260120140503.62804-3-boqun.feng@gmail.com Link: https://patch.msgid.link/20260303201701.12204-8-boqun@kernel.org
88 lines
2.7 KiB
C
88 lines
2.7 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
#include <asm/barrier.h>
|
|
#include <asm/rwonce.h>
|
|
#include <linux/atomic.h>
|
|
|
|
#define GEN_READ_HELPER(tname, type) \
|
|
__rust_helper type rust_helper_atomic_##tname##_read(type *ptr) \
|
|
{ \
|
|
return READ_ONCE(*ptr); \
|
|
}
|
|
|
|
#define GEN_SET_HELPER(tname, type) \
|
|
__rust_helper void rust_helper_atomic_##tname##_set(type *ptr, type 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); \
|
|
}
|
|
|
|
#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); \
|
|
}
|
|
|
|
#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) \
|
|
|
|
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
|
|
* architecture provding xchg() support for i8 and i16.
|
|
*
|
|
* The architectures that currently support Rust (x86_64, armv7,
|
|
* arm64, riscv, and loongarch) satisfy these requirements.
|
|
*/
|
|
#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); \
|
|
}
|
|
|
|
#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) \
|
|
|
|
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
|
|
* architecture provding try_cmpxchg() support for i8 and i16.
|
|
*
|
|
* The architectures that currently support Rust (x86_64, armv7,
|
|
* arm64, riscv, and loongarch) satisfy these requirements.
|
|
*/
|
|
#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); \
|
|
}
|
|
|
|
#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) \
|
|
|
|
GEN_TRY_CMPXCHG_HELPERS(i8, s8)
|
|
GEN_TRY_CMPXCHG_HELPERS(i16, s16)
|
|
GEN_TRY_CMPXCHG_HELPERS(ptr, const void *)
|