mirror of
https://github.com/vlang/v.git
synced 2025-08-04 02:07:28 -04:00
sync.stdatomic: add atomic_thread_fence(), cpu_relax() (#24690)
This commit is contained in:
parent
2bc5887398
commit
a9f4a942fb
34
thirdparty/stdatomic/nix/atomic.h
vendored
34
thirdparty/stdatomic/nix/atomic.h
vendored
@ -15,12 +15,46 @@
|
|||||||
#include "atomic_cpp.h"
|
#include "atomic_cpp.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || defined(_M_IX86)
|
||||||
|
/* x86 architecture: uses PAUSE instruction for efficient spinning */
|
||||||
|
#define cpu_relax() __asm__ __volatile__ ("pause")
|
||||||
|
#elif defined(__aarch64__) || defined(_M_ARM64) || defined(__arm__) || defined(_M_ARM)
|
||||||
|
#if defined(__TINYC__)
|
||||||
|
/* TCC compiler limitation: assembly not supported on ARM */
|
||||||
|
#define cpu_relax()
|
||||||
|
#else
|
||||||
|
/* ARM architecture: uses YIELD instruction for power-efficient spinning */
|
||||||
|
#define cpu_relax() __asm__ __volatile__ ("yield" ::: "memory")
|
||||||
|
#endif
|
||||||
|
#elif defined(__riscv) && __riscv_xlen == 64
|
||||||
|
/* RISC-V 64-bit: no dedicated pause instruction, using alternative sequence */
|
||||||
|
#define cpu_relax() __asm__ __volatile__ ( \
|
||||||
|
"fence rw, rw\n\t" /* Full memory barrier (read-write ordering) */ \
|
||||||
|
"andi a0, a0, 0\n\t" /* Dummy arithmetic instruction (always sets a0 = 0) */ \
|
||||||
|
::: "memory", "a0") /* Clobbers memory and a0 register to prevent optimizations */
|
||||||
|
#elif defined(__powerpc64__) || defined(__ppc64__)
|
||||||
|
/* PowerPC 64-bit: use OR instruction for synchronization */
|
||||||
|
#define cpu_relax() __asm__ __volatile__ ("or 1,1,1\n\t" ::: "memory")
|
||||||
|
#elif defined(__mips64)
|
||||||
|
/* MIPS 64-bit: use series of super-scalar NOPs */
|
||||||
|
#define cpu_relax() __asm__ __volatile__ ("ssnop\n\tssnop\n\tssnop\n\t" ::: "memory")
|
||||||
|
#else
|
||||||
|
/* Fallback implementation for unsupported architectures */
|
||||||
|
#define cpu_relax() __asm__ __volatile__ ( \
|
||||||
|
"nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t" /* Series of no-operation instructions */ \
|
||||||
|
::: "memory") /* Memory clobber to prevent instruction reordering */
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __TINYC__
|
#ifdef __TINYC__
|
||||||
|
|
||||||
typedef volatile long long atomic_llong;
|
typedef volatile long long atomic_llong;
|
||||||
typedef volatile unsigned long long atomic_ullong;
|
typedef volatile unsigned long long atomic_ullong;
|
||||||
typedef volatile uintptr_t atomic_uintptr_t;
|
typedef volatile uintptr_t atomic_uintptr_t;
|
||||||
|
|
||||||
|
extern void atomic_thread_fence (int memory_order);
|
||||||
|
extern void __atomic_thread_fence (int memory_order);
|
||||||
|
#define atomic_thread_fence(order) __atomic_thread_fence (order)
|
||||||
|
|
||||||
// use functions for 64, 32 and 8 bit from libatomic directly
|
// use functions for 64, 32 and 8 bit from libatomic directly
|
||||||
// since tcc is not capible to use "generic" C functions
|
// since tcc is not capible to use "generic" C functions
|
||||||
// there is no header file for libatomic so we provide function declarations here
|
// there is no header file for libatomic so we provide function declarations here
|
||||||
|
60
thirdparty/stdatomic/win/atomic.h
vendored
60
thirdparty/stdatomic/win/atomic.h
vendored
@ -24,7 +24,10 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
#ifdef __TINYC__
|
#ifdef _MSC_VER
|
||||||
|
#define cpu_relax() _mm_pause()
|
||||||
|
#else
|
||||||
|
#define cpu_relax() __asm__ __volatile__ ("pause")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define ATOMIC_FLAG_INIT 0
|
#define ATOMIC_FLAG_INIT 0
|
||||||
@ -39,10 +42,59 @@
|
|||||||
|
|
||||||
#define kill_dependency(y) ((void)0)
|
#define kill_dependency(y) ((void)0)
|
||||||
|
|
||||||
|
// memory order policies - we use "sequentially consistent" by default
|
||||||
|
|
||||||
|
#define memory_order_relaxed 0
|
||||||
|
#define memory_order_consume 1
|
||||||
|
#define memory_order_acquire 2
|
||||||
|
#define memory_order_release 3
|
||||||
|
#define memory_order_acq_rel 4
|
||||||
|
#define memory_order_seq_cst 5
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
#define atomic_thread_fence(order) \
|
#define atomic_thread_fence(order) \
|
||||||
((order) == memory_order_seq_cst ? MemoryBarrier() : \
|
do { \
|
||||||
(order) == memory_order_release ? WriteBarrier() : \
|
switch (order) { \
|
||||||
(order) == memory_order_acquire ? ReadBarrier() : (void)0);
|
case memory_order_release: \
|
||||||
|
_WriteBarrier(); \
|
||||||
|
_ReadWriteBarrier(); \
|
||||||
|
break; \
|
||||||
|
case memory_order_acquire: \
|
||||||
|
_ReadBarrier(); \
|
||||||
|
_ReadWriteBarrier(); \
|
||||||
|
break; \
|
||||||
|
case memory_order_acq_rel: \
|
||||||
|
_ReadBarrier(); \
|
||||||
|
_WriteBarrier(); \
|
||||||
|
_ReadWriteBarrier(); \
|
||||||
|
break; \
|
||||||
|
case memory_order_seq_cst: \
|
||||||
|
MemoryBarrier(); \
|
||||||
|
break; \
|
||||||
|
default: /* relaxed, consume */ \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
#else
|
||||||
|
#define atomic_thread_fence(order) do { \
|
||||||
|
switch (order) { \
|
||||||
|
case memory_order_relaxed: \
|
||||||
|
break; \
|
||||||
|
case memory_order_acquire: \
|
||||||
|
case memory_order_consume: \
|
||||||
|
case memory_order_release: \
|
||||||
|
case memory_order_acq_rel: \
|
||||||
|
__asm__ __volatile__ ("" : : : "memory"); \
|
||||||
|
break; \
|
||||||
|
case memory_order_seq_cst: \
|
||||||
|
__asm__ __volatile__ ("mfence" : : : "memory"); \
|
||||||
|
break; \
|
||||||
|
default: \
|
||||||
|
__asm__ __volatile__ ("mfence" : : : "memory"); \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define atomic_signal_fence(order) \
|
#define atomic_signal_fence(order) \
|
||||||
((void)0)
|
((void)0)
|
||||||
|
@ -14,8 +14,6 @@ $if windows {
|
|||||||
$if linux {
|
$if linux {
|
||||||
$if tinyc {
|
$if tinyc {
|
||||||
$if amd64 {
|
$if amd64 {
|
||||||
// Debian/Ubuntu:
|
|
||||||
#flag $when_first_existing('/usr/lib/gcc/x86_64-linux-gnu/6/libatomic.a','/usr/lib/gcc/x86_64-linux-gnu/7/libatomic.a','/usr/lib/gcc/x86_64-linux-gnu/8/libatomic.a','/usr/lib/gcc/x86_64-linux-gnu/9/libatomic.a','/usr/lib/gcc/x86_64-linux-gnu/10/libatomic.a','/usr/lib/gcc/x86_64-linux-gnu/11/libatomic.a','/usr/lib/gcc/x86_64-linux-gnu/12/libatomic.a','/usr/lib/gcc/x86_64-linux-gnu/13/libatomic.a','/usr/lib/gcc/x86_64-linux-gnu/14/libatomic.a')
|
|
||||||
// Redhat/CentOS:
|
// Redhat/CentOS:
|
||||||
#flag $when_first_existing('/usr/lib/gcc/x86_64-redhat-linux/6/libatomic.a','/usr/lib/gcc/x86_64-redhat-linux/7/libatomic.a','/usr/lib/gcc/x86_64-redhat-linux/8/libatomic.a','/usr/lib/gcc/x86_64-redhat-linux/9/libatomic.a','/usr/lib/gcc/x86_64-redhat-linux/10/libatomic.a','/usr/lib/gcc/x86_64-redhat-linux/11/libatomic.a','/usr/lib/gcc/x86_64-redhat-linux/12/libatomic.a','/usr/lib/gcc/x86_64-redhat-linux/13/libatomic.a','/usr/lib/gcc/x86_64-redhat-linux/14/libatomic.a')
|
#flag $when_first_existing('/usr/lib/gcc/x86_64-redhat-linux/6/libatomic.a','/usr/lib/gcc/x86_64-redhat-linux/7/libatomic.a','/usr/lib/gcc/x86_64-redhat-linux/8/libatomic.a','/usr/lib/gcc/x86_64-redhat-linux/9/libatomic.a','/usr/lib/gcc/x86_64-redhat-linux/10/libatomic.a','/usr/lib/gcc/x86_64-redhat-linux/11/libatomic.a','/usr/lib/gcc/x86_64-redhat-linux/12/libatomic.a','/usr/lib/gcc/x86_64-redhat-linux/13/libatomic.a','/usr/lib/gcc/x86_64-redhat-linux/14/libatomic.a')
|
||||||
// Gentoo:
|
// Gentoo:
|
||||||
@ -108,3 +106,6 @@ fn C.atomic_compare_exchange_strong_u64(voidptr, voidptr, u64) bool
|
|||||||
fn C.atomic_exchange_u64(voidptr, u64) u64
|
fn C.atomic_exchange_u64(voidptr, u64) u64
|
||||||
fn C.atomic_fetch_add_u64(voidptr, u64) u64
|
fn C.atomic_fetch_add_u64(voidptr, u64) u64
|
||||||
fn C.atomic_fetch_sub_u64(voidptr, u64) u64
|
fn C.atomic_fetch_sub_u64(voidptr, u64) u64
|
||||||
|
|
||||||
|
fn C.atomic_thread_fence(int)
|
||||||
|
fn C.cpu_relax()
|
||||||
|
@ -271,4 +271,8 @@ fn test_atomic_vals() {
|
|||||||
assert v_voidptr.swap(ptr_2) == ptr_1
|
assert v_voidptr.swap(ptr_2) == ptr_1
|
||||||
assert v_voidptr.compare_and_swap(ptr_2, ptr_1) == true
|
assert v_voidptr.compare_and_swap(ptr_2, ptr_1) == true
|
||||||
assert v_voidptr.load() == ptr_1
|
assert v_voidptr.load() == ptr_1
|
||||||
|
|
||||||
|
// just for compile
|
||||||
|
C.atomic_thread_fence(C.memory_order_relaxed)
|
||||||
|
C.cpu_relax()
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user