Initial project import

This commit is contained in:
Agila Forge Importer committed 2026-07-13 15:20:32 +00:00
commit 23f2d29e32
11957 files changed
+1754577

No files matched your search

+94
View File
@@ -0,0 +1,94 @@
/* ---------------------------------------------- */
#if defined __i386__
#define endbr32
.text
.global _V_atomic_thread_fence
.type _V_atomic_thread_fence, %function
_V_atomic_thread_fence:
endbr32
lock orl $0x0,(%esp)
ret
#endif //__i386__
/* ---------------------------------------------- */
#if defined __x86_64__ && !defined _WIN32
#define endbr64
.text
.global __atomic_thread_fence
.type __atomic_thread_fence, %function
__atomic_thread_fence:
endbr64
lock orq $0x0,(%rsp)
ret
#endif //__x86_64__ && !_WIN32
/* ---------------------------------------------- */
#if defined __x86_64__ && defined _WIN32
.text
.global _V_atomic_thread_fence
.type _V_atomic_thread_fence, %function
_V_atomic_thread_fence:
lock orq $0x0,(%rsp)
ret
#endif //__x86_64__ && _WIN32
/* ---------------------------------------------- */
#if defined __arm__
.text
#ifndef __TINYC__
.arch armv6k
.syntax unified
#endif
.global _V_atomic_thread_fence
.type _V_atomic_thread_fence, %function
_V_atomic_thread_fence:
#ifdef __TINYC__
.int 0xee070fba
.int 0xe12fff1e
#else
mcr p15, #0, r0, c7, c10, #5
bx lr
#endif
#endif //__arm__
/* ---------------------------------------------- */
#if defined __aarch64__
.text
.global _V_atomic_thread_fence
.type _V_atomic_thread_fence, %function
_V_atomic_thread_fence:
#ifdef __TINYC__
.int 0xd5033bbf
.int 0xd65f03c0
#else
dmb ish
ret
#endif
#endif //__aarch64__
/* ---------------------------------------------- */
#if defined __riscv
.text
.global _V_atomic_thread_fence
.type _V_atomic_thread_fence, %function
_V_atomic_thread_fence:
#ifdef __TINYC__
.int 0x0330000f
.short 0x8082
#else
fence rw,rw
ret
#endif
#endif //__riscv
+876
View File
@@ -0,0 +1,876 @@
/*
Compatibility header for stdatomic.h that works for all compilers supported by V.
For TCC, we use libatomic from the OS.
*/
#ifndef __ATOMIC_H
#define __ATOMIC_H
#ifndef __cplusplus
// If C just use stdatomic.h
#ifndef __TINYC__
#include <stdatomic.h>
#endif
#else
// CPP wrapper for atomic operations that are compatible with C
#include "atomic_cpp.h"
#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)
#ifdef __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__
typedef volatile long long atomic_llong;
typedef volatile unsigned long long atomic_ullong;
typedef volatile uintptr_t atomic_uintptr_t;
extern void atomic_thread_fence (int memory_order);
extern void __atomic_thread_fence (int memory_order);
// TinyCC relies on its runtime atomics support for thread fences.
#if !defined(__APPLE__)
#define atomic_thread_fence(order) __atomic_thread_fence(order)
#endif
// use functions for 64, 32 and 8 bit from libatomic directly
// since tcc is not capible to use "generic" C functions
// there is no header file for libatomic so we provide function declarations here
extern unsigned long long __atomic_load_8(unsigned long long* x, int mo);
extern void __atomic_store_8(unsigned long long* x, unsigned long long y, int mo);
extern _Bool __atomic_compare_exchange_8(unsigned long long* x, unsigned long long* expected, unsigned long long y, int mo, int mo2);
extern unsigned long long __atomic_exchange_8(unsigned long long* x, unsigned long long y, int mo);
extern unsigned long long __atomic_fetch_add_8(unsigned long long* x, unsigned long long y, int mo);
extern unsigned long long __atomic_fetch_sub_8(unsigned long long* x, unsigned long long y, int mo);
extern unsigned long long __atomic_fetch_and_8(unsigned long long* x, unsigned long long y, int mo);
extern unsigned long long __atomic_fetch_or_8(unsigned long long* x, unsigned long long y, int mo);
extern unsigned long long __atomic_fetch_xor_8(unsigned long long* x, unsigned long long y, int mo);
extern unsigned int __atomic_load_4(unsigned int* x, int mo);
extern void __atomic_store_4(unsigned int* x, unsigned int y, int mo);
extern _Bool __atomic_compare_exchange_4(unsigned int* x, unsigned int* expected, unsigned int y, int mo, int mo2);
extern unsigned int __atomic_exchange_4(unsigned int* x, unsigned int y, int mo);
extern unsigned int __atomic_fetch_add_4(unsigned int* x, unsigned int y, int mo);
extern unsigned int __atomic_fetch_sub_4(unsigned int* x, unsigned int y, int mo);
extern unsigned int __atomic_fetch_and_4(unsigned int* x, unsigned int y, int mo);
extern unsigned int __atomic_fetch_or_4(unsigned int* x, unsigned int y, int mo);
extern unsigned int __atomic_fetch_xor_4(unsigned int* x, unsigned int y, int mo);
extern unsigned short __atomic_load_2(unsigned short* x, int mo);
extern void __atomic_store_2(unsigned short* x, unsigned short y, int mo);
extern _Bool __atomic_compare_exchange_2(unsigned short* x, unsigned short* expected, unsigned short y, int mo, int mo2);
extern unsigned short __atomic_exchange_2(unsigned short* x, unsigned short y, int mo);
extern unsigned short __atomic_fetch_add_2(unsigned short* x, unsigned short y, int mo);
extern unsigned short __atomic_fetch_sub_2(unsigned short* x, unsigned short y, int mo);
extern unsigned short __atomic_fetch_and_2(unsigned short* x, unsigned short y, int mo);
extern unsigned short __atomic_fetch_or_2(unsigned short* x, unsigned short y, int mo);
extern unsigned short __atomic_fetch_xor_2(unsigned short* x, unsigned short y, int mo);
extern unsigned char __atomic_load_1(unsigned char* x, int mo);
extern void __atomic_store_1(unsigned char* x, unsigned char y, int mo);
extern _Bool __atomic_compare_exchange_1(unsigned char* x, unsigned char* expected, unsigned char y, int mo, int mo2);
extern unsigned char __atomic_exchange_1(unsigned char* x, unsigned char y, int mo);
extern unsigned char __atomic_fetch_add_1(unsigned char* x, unsigned char y, int mo);
extern unsigned char __atomic_fetch_sub_1(unsigned char* x, unsigned char y, int mo);
extern unsigned char __atomic_fetch_and_1(unsigned char* x, unsigned char y, int mo);
extern unsigned char __atomic_fetch_or_1(unsigned char* x, unsigned char y, int mo);
extern unsigned char __atomic_fetch_xor_1(unsigned char* x, unsigned char y, int mo);
// The default functions should work with pointers so we have to decide based on pointer size
#if UINTPTR_MAX == 0xFFFFFFFF
#define atomic_load_explicit __atomic_load_4
#define atomic_store_explicit __atomic_store_4
#define atomic_compare_exchange_weak_explicit __atomic_compare_exchange_4
#define atomic_compare_exchange_strong_explicit __atomic_compare_exchange_4
#define atomic_exchange_explicit __atomic_exchange_4
#define atomic_fetch_add_explicit __atomic_fetch_add_4
#define atomic_fetch_sub_explicit __atomic_sub_fetch_4
#else
#define atomic_load_explicit __atomic_load_8
#define atomic_store_explicit __atomic_store_8
#define atomic_compare_exchange_weak_explicit __atomic_compare_exchange_8
#define atomic_compare_exchange_strong_explicit __atomic_compare_exchange_8
#define atomic_exchange_explicit __atomic_exchange_8
#define atomic_fetch_add_explicit __atomic_fetch_add_8
#define atomic_fetch_sub_explicit __atomic_sub_fetch_8
#endif
// 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
static inline void** atomic_load(void** x) {
return (void**)atomic_load_explicit((unsigned long long*)x, memory_order_seq_cst);
}
static inline void atomic_store(void** x, void* y) {
atomic_store_explicit((unsigned long long*)x, (uintptr_t)y, memory_order_seq_cst);
}
static inline int atomic_compare_exchange_weak(void** x, void** expected, intptr_t y) {
return (int)atomic_compare_exchange_weak_explicit((unsigned long long*)x, (unsigned long long*)expected, (uintptr_t)y, memory_order_seq_cst, memory_order_seq_cst);
}
static inline int atomic_compare_exchange_strong(void** x, void** expected, intptr_t y) {
return (int)atomic_compare_exchange_strong_explicit((unsigned long long*)x, (unsigned long long*)expected, (uintptr_t)y, memory_order_seq_cst, memory_order_seq_cst);
}
static inline uintptr_t atomic_exchange(void** x, void* y) {
return atomic_exchange_explicit((unsigned long long*)x, (uintptr_t)y, memory_order_seq_cst);
}
static inline uintptr_t atomic_fetch_add(uintptr_t* x, uintptr_t y) {
return atomic_fetch_add_explicit(x, y, memory_order_seq_cst);
}
static inline uintptr_t atomic_fetch_sub(uintptr_t* x, uintptr_t y) {
return atomic_fetch_sub_explicit(x, y, memory_order_seq_cst);
}
static inline uintptr_t atomic_fetch_and(uintptr_t* x, uintptr_t y) {
return atomic_fetch_and_explicit(x, y, memory_order_seq_cst);
}
static inline uintptr_t atomic_fetch_or(uintptr_t* x, uintptr_t y) {
return atomic_fetch_or_explicit(x, y, memory_order_seq_cst);
}
static inline uintptr_t atomic_fetch_xor(uintptr_t* x, uintptr_t y) {
return atomic_fetch_xor_explicit(x, y, memory_order_seq_cst);
}
#define atomic_load_ptr atomic_load
#define atomic_store_ptr atomic_store
#define atomic_compare_exchange_weak_ptr atomic_compare_exchange_weak
#define atomic_compare_exchange_strong_ptr atomic_compare_exchange_strong
#define atomic_exchange_ptr atomic_exchange
#define atomic_fetch_add_ptr atomic_fetch_add
#define atomic_fetch_sub_ptr atomic_fetch_sub
#define atomic_fetch_and_ptr atomic_fetch_and
#define atomic_fetch_or_ptr atomic_fetch_or
#define atomic_fetch_xor_ptr atomic_fetch_xor
// specialized versions for 64 bit
static inline unsigned long long atomic_load_u64(unsigned long long* x) {
return __atomic_load_8(x, memory_order_seq_cst);
}
static inline void atomic_store_u64(unsigned long long* x, unsigned long long y) {
__atomic_store_8(x, y, memory_order_seq_cst);
}
static inline int atomic_compare_exchange_weak_u64(unsigned long long* x, unsigned long long* expected, unsigned long long y) {
return (int)__atomic_compare_exchange_8(x, expected, y, memory_order_seq_cst, memory_order_seq_cst);
}
static inline int atomic_compare_exchange_strong_u64(unsigned long long* x, unsigned long long* expected, unsigned long long y) {
return (int)__atomic_compare_exchange_8(x, expected, y, memory_order_seq_cst, memory_order_seq_cst);
}
static inline unsigned long long atomic_exchange_u64(unsigned long long* x, unsigned long long y) {
return __atomic_exchange_8(x, y, memory_order_seq_cst);
}
static inline unsigned long long atomic_fetch_add_u64(unsigned long long* x, unsigned long long y) {
return __atomic_fetch_add_8(x, y, memory_order_seq_cst);
}
static inline unsigned long long atomic_fetch_sub_u64(unsigned long long* x, unsigned long long y) {
return __atomic_fetch_sub_8(x, y, memory_order_seq_cst);
}
static inline unsigned long long atomic_fetch_and_u64(unsigned long long* x, unsigned long long y) {
return __atomic_fetch_and_8(x, y, memory_order_seq_cst);
}
static inline unsigned long long atomic_fetch_or_u64(unsigned long long* x, unsigned long long y) {
return __atomic_fetch_or_8(x, y, memory_order_seq_cst);
}
static inline unsigned long long atomic_fetch_xor_u64(unsigned long long* x, unsigned long long y) {
return __atomic_fetch_xor_8(x, y, memory_order_seq_cst);
}
static inline unsigned atomic_load_u32(unsigned* x) {
return __atomic_load_4(x, memory_order_seq_cst);
}
static inline void atomic_store_u32(unsigned* x, unsigned y) {
__atomic_store_4(x, y, memory_order_seq_cst);
}
static inline int atomic_compare_exchange_weak_u32(unsigned* x, unsigned* expected, unsigned y) {
return (int)__atomic_compare_exchange_4(x, expected, y, memory_order_seq_cst, memory_order_seq_cst);
}
static inline int atomic_compare_exchange_strong_u32(unsigned* x, unsigned* expected, unsigned y) {
return (int)__atomic_compare_exchange_4(x, expected, y, memory_order_seq_cst, memory_order_seq_cst);
}
static inline unsigned atomic_exchange_u32(unsigned* x, unsigned y) {
return __atomic_exchange_4(x, y, memory_order_seq_cst);
}
static inline unsigned atomic_fetch_add_u32(unsigned* x, unsigned y) {
return __atomic_fetch_add_4(x, y, memory_order_seq_cst);
}
static inline unsigned atomic_fetch_sub_u32(unsigned* x, unsigned y) {
return __atomic_fetch_sub_4(x, y, memory_order_seq_cst);
}
static inline unsigned atomic_fetch_and_u32(unsigned* x, unsigned y) {
return __atomic_fetch_and_4(x, y, memory_order_seq_cst);
}
static inline unsigned atomic_fetch_or_u32(unsigned* x, unsigned y) {
return __atomic_fetch_or_4(x, y, memory_order_seq_cst);
}
static inline unsigned atomic_fetch_xor_u32(unsigned* x, unsigned y) {
return __atomic_fetch_xor_4(x, y, memory_order_seq_cst);
}
static inline unsigned short atomic_load_u16(unsigned short* x) {
return __atomic_load_2(x, memory_order_seq_cst);
}
static inline void atomic_store_u16(void* x, unsigned short y) {
__atomic_store_2(x, y, memory_order_seq_cst);
}
static inline int atomic_compare_exchange_weak_u16(void* x, unsigned short* expected, unsigned short y) {
return (int)__atomic_compare_exchange_2(x, expected, y, memory_order_seq_cst, memory_order_seq_cst);
}
static inline int atomic_compare_exchange_strong_u16(unsigned short* x, unsigned short* expected, unsigned short y) {
return (int)__atomic_compare_exchange_2(x, expected, y, memory_order_seq_cst, memory_order_seq_cst);
}
static inline unsigned short atomic_exchange_u16(unsigned short* x, unsigned short y) {
return __atomic_exchange_2(x, y, memory_order_seq_cst);
}
static inline unsigned short atomic_fetch_add_u16(unsigned short* x, unsigned short y) {
return __atomic_fetch_add_2(x, y, memory_order_seq_cst);
}
static inline unsigned short atomic_fetch_sub_u16(unsigned short* x, unsigned short y) {
return __atomic_fetch_sub_2(x, y, memory_order_seq_cst);
}
static inline unsigned short atomic_fetch_and_u16(unsigned short* x, unsigned short y) {
return __atomic_fetch_and_2(x, y, memory_order_seq_cst);
}
static inline unsigned short atomic_fetch_or_u16(unsigned short* x, unsigned short y) {
return __atomic_fetch_or_2(x, y, memory_order_seq_cst);
}
static inline unsigned short atomic_fetch_xor_u16(unsigned short* x, unsigned short y) {
return __atomic_fetch_xor_2(x, y, memory_order_seq_cst);
}
static inline unsigned char atomic_load_byte(unsigned char* x) {
return __atomic_load_1(x, memory_order_seq_cst);
}
static inline void atomic_store_byte(unsigned char* x, unsigned char y) {
__atomic_store_1(x, y, memory_order_seq_cst);
}
static inline int atomic_compare_exchange_weak_byte(unsigned char* x, unsigned char* expected, unsigned char y) {
return __atomic_compare_exchange_1(x, expected, y, memory_order_seq_cst, memory_order_seq_cst);
}
static inline int atomic_compare_exchange_strong_byte(unsigned char* x, unsigned char* expected, unsigned char y) {
return __atomic_compare_exchange_1(x, expected, y, memory_order_seq_cst, memory_order_seq_cst);
}
static inline unsigned char atomic_exchange_byte(unsigned char* x, unsigned char y) {
return __atomic_exchange_1(x, y, memory_order_seq_cst);
}
static inline unsigned char atomic_fetch_add_byte(unsigned char* x, unsigned char y) {
return __atomic_fetch_add_1(x, y, memory_order_seq_cst);
}
static inline unsigned char atomic_fetch_sub_byte(unsigned char* x, unsigned char y) {
return __atomic_fetch_sub_1(x, y, memory_order_seq_cst);
}
static inline unsigned char atomic_fetch_and_byte(unsigned char* x, unsigned char y) {
return __atomic_fetch_and_1(x, y, memory_order_seq_cst);
}
static inline unsigned char atomic_fetch_or_byte(unsigned char* x, unsigned char y) {
return __atomic_fetch_or_1(x, y, memory_order_seq_cst);
}
static inline unsigned char atomic_fetch_xor_byte(unsigned char* x, unsigned char y) {
return __atomic_fetch_xor_1(x, y, memory_order_seq_cst);
}
#ifdef __aarch64__
// must has an `extern` to link with libatomic.a
// acq_rel version
extern inline _Bool __aarch64_cas1_acq_rel(unsigned char*ptr, unsigned char*expected, unsigned char desired) {
return __atomic_compare_exchange_1(
ptr,
expected,
desired,
memory_order_acq_rel,
memory_order_acquire
);
}
extern inline _Bool __aarch64_cas2_acq_rel(unsigned short*ptr, unsigned short*expected, unsigned short desired) {
return __atomic_compare_exchange_2(
ptr,
expected,
desired,
memory_order_acq_rel,
memory_order_acquire
);
}
extern inline _Bool __aarch64_cas4_acq_rel(unsigned int*ptr, unsigned int*expected, unsigned int desired) {
return __atomic_compare_exchange_4(
ptr,
expected,
desired,
memory_order_acq_rel,
memory_order_acquire
);
}
extern inline _Bool __aarch64_cas8_acq_rel(unsigned long long*ptr, unsigned long long*expected, unsigned long long desired) {
return __atomic_compare_exchange_8(
ptr,
expected,
desired,
memory_order_acq_rel,
memory_order_acquire
);
}
extern inline char __aarch64_ldadd1_acq_rel(char*ptr, char value) {
return __atomic_fetch_add_1(
(unsigned char*)ptr,
(unsigned char)value,
memory_order_acq_rel
);
}
extern inline short __aarch64_ldadd2_acq_rel(short*ptr, short value) {
return __atomic_fetch_add_2(
(unsigned short*)ptr,
(unsigned short)value,
memory_order_acq_rel
);
}
extern inline int __aarch64_ldadd4_acq_rel(int*ptr, int value) {
return __atomic_fetch_add_4(
(unsigned int*)ptr,
(unsigned int)value,
memory_order_acq_rel
);
}
extern inline long long __aarch64_ldadd8_acq_rel(long long*ptr, long long value) {
return __atomic_fetch_add_8(
(unsigned long long*)ptr,
(unsigned long long)value,
memory_order_acq_rel
);
}
extern inline unsigned char __aarch64_swp1_acq_rel(unsigned char*ptr, unsigned char newval) {
return __atomic_exchange_1(
ptr,
newval,
memory_order_acq_rel
);
}
extern inline unsigned short __aarch64_swp2_acq_rel(unsigned short*ptr, unsigned short newval) {
return __atomic_exchange_2(
ptr,
newval,
memory_order_acq_rel
);
}
extern inline unsigned int __aarch64_swp4_acq_rel(unsigned int*ptr, unsigned int newval) {
return __atomic_exchange_4(
ptr,
newval,
memory_order_acq_rel
);
}
extern inline unsigned long long __aarch64_swp8_acq_rel(unsigned long long*ptr, unsigned long long newval) {
return __atomic_exchange_8(
ptr,
newval,
memory_order_acq_rel
);
}
extern inline unsigned char __aarch64_ldclr1_acq_rel(unsigned char*ptr, unsigned char mask) {
return __atomic_fetch_and_1(
ptr,
~mask,
memory_order_acq_rel
);
}
extern inline unsigned short __aarch64_ldclr2_acq_rel(unsigned short*ptr, unsigned short mask) {
return __atomic_fetch_and_2(
ptr,
~mask,
memory_order_acq_rel
);
}
extern inline unsigned int __aarch64_ldclr4_acq_rel(unsigned int*ptr, unsigned int mask) {
return __atomic_fetch_and_4(
ptr,
~mask,
memory_order_acq_rel
);
}
extern inline unsigned long long __aarch64_ldclr8_acq_rel(unsigned long long*ptr, unsigned long long mask) {
return __atomic_fetch_and_8(
ptr,
~mask,
memory_order_acq_rel
);
}
extern inline unsigned char __aarch64_ldset1_acq_rel(unsigned char*ptr, unsigned char mask) {
return __atomic_fetch_or_1(
ptr,
mask,
memory_order_acq_rel
);
}
extern inline unsigned short __aarch64_ldset2_acq_rel(unsigned short*ptr, unsigned short mask) {
return __atomic_fetch_or_2(
ptr,
mask,
memory_order_acq_rel
);
}
extern inline unsigned int __aarch64_ldset4_acq_rel(unsigned int*ptr, unsigned int mask) {
return __atomic_fetch_or_4(
ptr,
mask,
memory_order_acq_rel
);
}
extern inline unsigned long long __aarch64_ldset8_acq_rel(unsigned long long*ptr, unsigned long long mask) {
return __atomic_fetch_or_8(
ptr,
mask,
memory_order_acq_rel
);
}
extern inline unsigned char __aarch64_ldeor1_acq_rel(unsigned char*ptr, unsigned char mask) {
return __atomic_fetch_xor_1(
ptr,
mask,
memory_order_acq_rel
);
}
extern inline unsigned short __aarch64_ldeor2_acq_rel(unsigned short*ptr, unsigned short mask) {
return __atomic_fetch_xor_2(
ptr,
mask,
memory_order_acq_rel
);
}
extern inline unsigned int __aarch64_ldeor4_acq_rel(unsigned int*ptr, unsigned int mask) {
return __atomic_fetch_xor_4(
ptr,
mask,
memory_order_acq_rel
);
}
extern inline unsigned long long __aarch64_ldeor8_acq_rel(unsigned long long*ptr, unsigned long long mask) {
return __atomic_fetch_xor_8(
ptr,
mask,
memory_order_acq_rel
);
}
// relax version
extern inline _Bool __aarch64_cas1_relax(unsigned char*ptr, unsigned char*expected, unsigned char desired) {
return __atomic_compare_exchange_1(
ptr,
expected,
desired,
memory_order_relaxed,
memory_order_relaxed
);
}
extern inline _Bool __aarch64_cas2_relax(unsigned short*ptr, unsigned short*expected, unsigned short desired) {
return __atomic_compare_exchange_2(
ptr,
expected,
desired,
memory_order_relaxed,
memory_order_relaxed
);
}
extern inline _Bool __aarch64_cas4_relax(unsigned int*ptr, unsigned int*expected, unsigned int desired) {
return __atomic_compare_exchange_4(
ptr,
expected,
desired,
memory_order_relaxed,
memory_order_relaxed
);
}
extern inline _Bool __aarch64_cas8_relax(unsigned long long*ptr, unsigned long long*expected, unsigned long long desired) {
return __atomic_compare_exchange_8(
ptr,
expected,
desired,
memory_order_relaxed,
memory_order_relaxed
);
}
extern inline char __aarch64_ldadd1_relax(char*ptr, char value) {
return __atomic_fetch_add_1(
(unsigned char*)ptr,
(unsigned char)value,
memory_order_relaxed
);
}
extern inline short __aarch64_ldadd2_relax(short*ptr, short value) {
return __atomic_fetch_add_2(
(unsigned short*)ptr,
(unsigned short)value,
memory_order_relaxed
);
}
extern inline int __aarch64_ldadd4_relax(int*ptr, int value) {
return __atomic_fetch_add_4(
(unsigned int*)ptr,
(unsigned int)value,
memory_order_relaxed
);
}
extern inline long long __aarch64_ldadd8_relax(long long*ptr, long long value) {
return __atomic_fetch_add_8(
(unsigned long long*)ptr,
(unsigned long long)value,
memory_order_relaxed
);
}
extern inline unsigned char __aarch64_swp1_relax(unsigned char*ptr, unsigned char newval) {
return __atomic_exchange_1(
ptr,
newval,
memory_order_relaxed
);
}
extern inline unsigned short __aarch64_swp2_relax(unsigned short*ptr, unsigned short newval) {
return __atomic_exchange_2(
ptr,
newval,
memory_order_relaxed
);
}
extern inline unsigned int __aarch64_swp4_relax(unsigned int*ptr, unsigned int newval) {
return __atomic_exchange_4(
ptr,
newval,
memory_order_relaxed
);
}
extern inline unsigned long long __aarch64_swp8_relax(unsigned long long*ptr, unsigned long long newval) {
return __atomic_exchange_8(
ptr,
newval,
memory_order_relaxed
);
}
extern inline unsigned char __aarch64_ldclr1_relax(unsigned char*ptr, unsigned char mask) {
return __atomic_fetch_and_1(
ptr,
~mask,
memory_order_relaxed
);
}
extern inline unsigned short __aarch64_ldclr2_relax(unsigned short*ptr, unsigned short mask) {
return __atomic_fetch_and_2(
ptr,
~mask,
memory_order_relaxed
);
}
extern inline unsigned int __aarch64_ldclr4_relax(unsigned int*ptr, unsigned int mask) {
return __atomic_fetch_and_4(
ptr,
~mask,
memory_order_relaxed
);
}
extern inline unsigned long long __aarch64_ldclr8_relax(unsigned long long*ptr, unsigned long long mask) {
return __atomic_fetch_and_8(
ptr,
~mask,
memory_order_relaxed
);
}
extern inline unsigned char __aarch64_ldset1_relax(unsigned char*ptr, unsigned char mask) {
return __atomic_fetch_or_1(
ptr,
mask,
memory_order_relaxed
);
}
extern inline unsigned short __aarch64_ldset2_relax(unsigned short*ptr, unsigned short mask) {
return __atomic_fetch_or_2(
ptr,
mask,
memory_order_relaxed
);
}
extern inline unsigned int __aarch64_ldset4_relax(unsigned int*ptr, unsigned int mask) {
return __atomic_fetch_or_4(
ptr,
mask,
memory_order_relaxed
);
}
extern inline unsigned long long __aarch64_ldset8_relax(unsigned long long*ptr, unsigned long long mask) {
return __atomic_fetch_or_8(
ptr,
mask,
memory_order_relaxed
);
}
extern inline unsigned char __aarch64_ldeor1_relax(unsigned char*ptr, unsigned char mask) {
return __atomic_fetch_xor_1(
ptr,
mask,
memory_order_relaxed
);
}
extern inline unsigned short __aarch64_ldeor2_relax(unsigned short*ptr, unsigned short mask) {
return __atomic_fetch_xor_2(
ptr,
mask,
memory_order_relaxed
);
}
extern inline unsigned int __aarch64_ldeor4_relax(unsigned int*ptr, unsigned int mask) {
return __atomic_fetch_xor_4(
ptr,
mask,
memory_order_relaxed
);
}
extern inline unsigned long long __aarch64_ldeor8_relax(unsigned long long*ptr, unsigned long long mask) {
return __atomic_fetch_xor_8(
ptr,
mask,
memory_order_relaxed
);
}
#endif // __aarch64__
#else
// Since V might be confused with "generic" C functions either we provide special versions
// for gcc/clang, too
static inline unsigned long long atomic_load_u64(uint64_t* x) {
return atomic_load_explicit((_Atomic (uint64_t)*)x, memory_order_seq_cst);
}
static inline void atomic_store_u64(uint64_t* x, uint64_t y) {
atomic_store_explicit((_Atomic(uint64_t)*)x, y, memory_order_seq_cst);
}
static inline int atomic_compare_exchange_weak_u64(uint64_t* x, uint64_t* expected, uint64_t y) {
return (int)atomic_compare_exchange_weak_explicit((_Atomic(uint64_t)*)x, expected, y, memory_order_seq_cst, memory_order_seq_cst);
}
static inline int atomic_compare_exchange_strong_u64(uint64_t* x, uint64_t* expected, uint64_t y) {
return (int)atomic_compare_exchange_strong_explicit((_Atomic(uint64_t)*)x, expected, y, memory_order_seq_cst, memory_order_seq_cst);
}
static inline unsigned long long atomic_exchange_u64(uint64_t* x, uint64_t y) {
return atomic_exchange_explicit((_Atomic(uint64_t)*)x, y, memory_order_seq_cst);
}
static inline unsigned long long atomic_fetch_add_u64(uint64_t* x, uint64_t y) {
return atomic_fetch_add_explicit((_Atomic(uint64_t)*)x, y, memory_order_seq_cst);
}
static inline unsigned long long atomic_fetch_sub_u64(uint64_t* x, uint64_t y) {
return atomic_fetch_sub_explicit((_Atomic(uint64_t)*)x, y, memory_order_seq_cst);
}
static inline unsigned long long atomic_fetch_and_u64(uint64_t* x, uint64_t y) {
return atomic_fetch_and_explicit((_Atomic(uint64_t)*)x, y, memory_order_seq_cst);
}
static inline unsigned long long atomic_fetch_or_u64(uint64_t* x, uint64_t y) {
return atomic_fetch_or_explicit((_Atomic(uint64_t)*)x, y, memory_order_seq_cst);
}
static inline unsigned long long atomic_fetch_xor_u64(uint64_t* x, uint64_t y) {
return atomic_fetch_xor_explicit((_Atomic(uint64_t)*)x, y, memory_order_seq_cst);
}
static inline void* atomic_load_ptr(void** x) {
return (void*)atomic_load_explicit((_Atomic(uintptr_t)*)x, memory_order_seq_cst);
}
static inline void atomic_store_ptr(void** x, void* y) {
atomic_store_explicit((_Atomic(uintptr_t)*)x, (uintptr_t)y, memory_order_seq_cst);
}
static inline int atomic_compare_exchange_weak_ptr(void** x, void** expected, intptr_t y) {
return (int)atomic_compare_exchange_weak_explicit((_Atomic(uintptr_t)*)x, (unsigned long *)expected, (uintptr_t)y, memory_order_seq_cst, memory_order_seq_cst);
}
static inline int atomic_compare_exchange_strong_ptr(void** x, void** expected, intptr_t y) {
return (int)atomic_compare_exchange_strong_explicit((_Atomic(uintptr_t)*)x, (unsigned long *)expected, (uintptr_t)y, memory_order_seq_cst, memory_order_seq_cst);
}
static inline void* atomic_exchange_ptr(void** x, void* y) {
return (void*)atomic_exchange_explicit((_Atomic(uintptr_t)*)x, (uintptr_t)y, memory_order_seq_cst);
}
static inline void* atomic_fetch_add_ptr(void** x, void* y) {
return (void*)atomic_fetch_add_explicit((_Atomic(uintptr_t)*)x, (uintptr_t)y, memory_order_seq_cst);
}
static inline void* atomic_fetch_sub_ptr(void** x, void* y) {
return (void*)atomic_fetch_sub_explicit((_Atomic(uintptr_t)*)x, (uintptr_t)y, memory_order_seq_cst);
}
static inline void* atomic_fetch_and_ptr(void** x, void* y) {
return (void*)atomic_fetch_and_explicit((_Atomic(uintptr_t)*)x, (uintptr_t)y, memory_order_seq_cst);
}
static inline void* atomic_fetch_or_ptr(void** x, void* y) {
return (void*)atomic_fetch_or_explicit((_Atomic(uintptr_t)*)x, (uintptr_t)y, memory_order_seq_cst);
}
static inline void* atomic_fetch_xor_ptr(void** x, void* y) {
return (void*)atomic_fetch_xor_explicit((_Atomic(uintptr_t)*)x, (uintptr_t)y, memory_order_seq_cst);
}
static inline unsigned atomic_load_u32(unsigned* x) {
return atomic_load_explicit((_Atomic(unsigned)*)x, memory_order_seq_cst);
}
static inline void atomic_store_u32(unsigned* x, unsigned y) {
atomic_store_explicit((_Atomic(unsigned)*)x, y, memory_order_seq_cst);
}
static inline int atomic_compare_exchange_weak_u32(unsigned* x, unsigned* expected, unsigned y) {
return (int)atomic_compare_exchange_weak_explicit((_Atomic(unsigned)*)x, expected, y, memory_order_seq_cst, memory_order_seq_cst);
}
static inline int atomic_compare_exchange_strong_u32(unsigned* x, unsigned* expected, unsigned y) {
return (int)atomic_compare_exchange_strong_explicit((_Atomic(unsigned)*)x, expected, y, memory_order_seq_cst, memory_order_seq_cst);
}
static inline unsigned atomic_exchange_u32(unsigned* x, unsigned y) {
return atomic_exchange_explicit((_Atomic(unsigned)*)x, y, memory_order_seq_cst);
}
static inline unsigned atomic_fetch_add_u32(unsigned* x, unsigned y) {
return atomic_fetch_add_explicit((_Atomic(unsigned)*)x, y, memory_order_seq_cst);
}
static inline unsigned atomic_fetch_sub_u32(unsigned* x, unsigned y) {
return atomic_fetch_sub_explicit((_Atomic(unsigned)*)x, y, memory_order_seq_cst);
}
static inline unsigned atomic_fetch_and_u32(unsigned* x, unsigned y) {
return atomic_fetch_and_explicit((_Atomic(unsigned)*)x, y, memory_order_seq_cst);
}
static inline unsigned atomic_fetch_or_u32(unsigned* x, unsigned y) {
return atomic_fetch_or_explicit((_Atomic(unsigned)*)x, y, memory_order_seq_cst);
}
static inline unsigned atomic_fetch_xor_u32(unsigned* x, unsigned y) {
return atomic_fetch_xor_explicit((_Atomic(unsigned)*)x, y, memory_order_seq_cst);
}
static inline unsigned short atomic_load_u16(unsigned short* x) {
return atomic_load_explicit((_Atomic(unsigned short)*)x, memory_order_seq_cst);
}
static inline void atomic_store_u16(void* x, unsigned short y) {
atomic_store_explicit((_Atomic(unsigned short)*)x, y, memory_order_seq_cst);
}
static inline int atomic_compare_exchange_weak_u16(void* x, unsigned short* expected, unsigned short y) {
return (int)atomic_compare_exchange_weak_explicit((_Atomic(unsigned short)*)x, expected, y, memory_order_seq_cst, memory_order_seq_cst);
}
static inline int atomic_compare_exchange_strong_u16(unsigned short* x, unsigned short* expected, unsigned short y) {
return (int)atomic_compare_exchange_strong_explicit((_Atomic(unsigned short)*)x, expected, y, memory_order_seq_cst, memory_order_seq_cst);
}
static inline unsigned short atomic_exchange_u16(unsigned short* x, unsigned short y) {
return atomic_exchange_explicit((_Atomic(unsigned short)*)x, y, memory_order_seq_cst);
}
static inline unsigned short atomic_fetch_add_u16(unsigned short* x, unsigned short y) {
return atomic_fetch_add_explicit((_Atomic(unsigned short)*)x, y, memory_order_seq_cst);
}
static inline unsigned short atomic_fetch_sub_u16(unsigned short* x, unsigned short y) {
return atomic_fetch_sub_explicit((_Atomic(unsigned short)*)x, y, memory_order_seq_cst);
}
static inline unsigned short atomic_fetch_and_u16(unsigned short* x, unsigned short y) {
return atomic_fetch_and_explicit((_Atomic(unsigned short)*)x, y, memory_order_seq_cst);
}
static inline unsigned short atomic_fetch_or_u16(unsigned short* x, unsigned short y) {
return atomic_fetch_or_explicit((_Atomic(unsigned short)*)x, y, memory_order_seq_cst);
}
static inline unsigned short atomic_fetch_xor_u16(unsigned short* x, unsigned short y) {
return atomic_fetch_xor_explicit((_Atomic(unsigned short)*)x, y, memory_order_seq_cst);
}
static inline unsigned char atomic_load_byte(unsigned char* x) {
return atomic_load_explicit((_Atomic(unsigned char)*)x, memory_order_seq_cst);
}
static inline void atomic_store_byte(unsigned char* x, unsigned char y) {
atomic_store_explicit((_Atomic(unsigned char)*)x, y, memory_order_seq_cst);
}
static inline int atomic_compare_exchange_weak_byte(unsigned char* x, unsigned char* expected, unsigned char y) {
return (int)atomic_compare_exchange_weak_explicit((_Atomic(unsigned char)*)x, expected, y, memory_order_seq_cst, memory_order_seq_cst);
}
static inline int atomic_compare_exchange_strong_byte(unsigned char* x, unsigned char* expected, unsigned char y) {
return (int)atomic_compare_exchange_strong_explicit((_Atomic(unsigned char)*)x, expected, y, memory_order_seq_cst, memory_order_seq_cst);
}
static inline unsigned char atomic_exchange_byte(unsigned char* x, unsigned char y) {
return atomic_exchange_explicit((_Atomic(unsigned char)*)x, y, memory_order_seq_cst);
}
static inline unsigned char atomic_fetch_add_byte(unsigned char* x, unsigned char y) {
return atomic_fetch_add_explicit((_Atomic(unsigned char)*)x, y, memory_order_seq_cst);
}
static inline unsigned char atomic_fetch_sub_byte(unsigned char* x, unsigned char y) {
return atomic_fetch_sub_explicit((_Atomic(unsigned char)*)x, y, memory_order_seq_cst);
}
static inline unsigned char atomic_fetch_and_byte(unsigned char* x, unsigned char y) {
return atomic_fetch_and_explicit((_Atomic(unsigned char)*)x, y, memory_order_seq_cst);
}
static inline unsigned char atomic_fetch_or_byte(unsigned char* x, unsigned char y) {
return atomic_fetch_or_explicit((_Atomic(unsigned char)*)x, y, memory_order_seq_cst);
}
static inline unsigned char atomic_fetch_xor_byte(unsigned char* x, unsigned char y) {
return atomic_fetch_xor_explicit((_Atomic(unsigned char)*)x, y, memory_order_seq_cst);
}
#endif
#endif
+551
View File
@@ -0,0 +1,551 @@
// Source: https://android.googlesource.com/platform/bionic/+/lollipop-release/libc/include/stdatomic.h
/*-
* Copyright (c) 2011 Ed Schouten <ed@FreeBSD.org>
* David Chisnall <theraven@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _STDATOMIC_H_
#define _STDATOMIC_H_
#include <sys/cdefs.h>
#if defined(__cplusplus)
#ifdef __clang__
#if __has_feature(cxx_atomic)
#define _STDATOMIC_HAVE_ATOMIC
#endif
#else /* gcc */
#if __GNUC_PREREQ(4, 7)
#define _STDATOMIC_HAVE_ATOMIC
#endif
#endif
#endif
#ifdef _STDATOMIC_HAVE_ATOMIC
#include "cpp/atomic.h"
#undef _Atomic
/* Also defined by <atomic> for gcc. But not used in macros. */
/* Also a clang intrinsic. */
/* Should not be used by client code before this file is */
/* included. The definitions in <atomic> themselves see */
/* the old definition, as they should. */
/* Client code sees the following definition. */
#define _Atomic(t) std::atomic<t>
using std::atomic_bool;
using std::atomic_char;
using std::atomic_char16_t;
using std::atomic_char32_t;
using std::atomic_compare_exchange_strong;
using std::atomic_compare_exchange_strong_explicit;
using std::atomic_compare_exchange_weak;
using std::atomic_compare_exchange_weak_explicit;
using std::atomic_exchange;
using std::atomic_exchange_explicit;
using std::atomic_fetch_add;
using std::atomic_fetch_add_explicit;
using std::atomic_fetch_and;
using std::atomic_fetch_and_explicit;
using std::atomic_fetch_or;
using std::atomic_fetch_or_explicit;
using std::atomic_fetch_sub;
using std::atomic_fetch_sub_explicit;
using std::atomic_fetch_xor;
using std::atomic_fetch_xor_explicit;
using std::atomic_init;
using std::atomic_int;
using std::atomic_int_fast16_t;
using std::atomic_int_fast32_t;
using std::atomic_int_fast64_t;
using std::atomic_int_fast8_t;
using std::atomic_int_least16_t;
using std::atomic_int_least32_t;
using std::atomic_int_least64_t;
using std::atomic_int_least8_t;
using std::atomic_intmax_t;
using std::atomic_intptr_t;
using std::atomic_is_lock_free;
using std::atomic_llong;
using std::atomic_load;
using std::atomic_load_explicit;
using std::atomic_long;
using std::atomic_ptrdiff_t;
using std::atomic_schar;
using std::atomic_short;
using std::atomic_signal_fence;
using std::atomic_size_t;
using std::atomic_store;
using std::atomic_store_explicit;
using std::atomic_thread_fence;
using std::atomic_uchar;
using std::atomic_uint;
using std::atomic_uint_fast16_t;
using std::atomic_uint_fast32_t;
using std::atomic_uint_fast64_t;
using std::atomic_uint_fast8_t;
using std::atomic_uint_least16_t;
using std::atomic_uint_least32_t;
using std::atomic_uint_least64_t;
using std::atomic_uint_least8_t;
using std::atomic_uintmax_t;
using std::atomic_uintptr_t;
using std::atomic_ullong;
using std::atomic_ulong;
using std::atomic_ushort;
using std::atomic_wchar_t;
using std::memory_order;
using std::memory_order_acq_rel;
using std::memory_order_consume;
using std::memory_order_relaxed;
using std::memory_order_release;
using std::memory_order_seq_cst;
#define memory_order_relaxed std::memory_order_relaxed
#define memory_order_consume std::memory_order_consume
#define memory_order_acquire std::memory_order_acquire
#define memory_order_release std::memory_order_release
#define memory_order_acq_rel std::memory_order_acq_rel
#define memory_order_seq_cst std::memory_order_seq_cst
#else /* <atomic> unavailable, possibly because this is C, not C++ */
#include <sys/types.h>
#include <stdbool.h>
/*
* C: Do it ourselves.
* Note that the runtime representation defined here should be compatible
* with the C++ one, i.e. an _Atomic(T) needs to contain the same
* bits as a T.
*/
#include <stddef.h> /* For ptrdiff_t. */
#include <stdint.h> /* TODO: Should pollute namespace less. */
#if __STDC_VERSION__ >= 201112L
#include <uchar.h> /* For char16_t and char32_t. */
#endif
#ifdef __clang__
#if __has_extension(c_atomic) || __has_extension(cxx_atomic)
#define __CLANG_ATOMICS
#else
#error "stdatomic.h does not support your compiler"
#endif
#if __has_builtin(__sync_swap)
#define __HAS_BUILTIN_SYNC_SWAP
#endif
#else
#if __GNUC_PREREQ(4, 7)
#define __GNUC_ATOMICS
#else
#define __SYNC_ATOMICS
#ifdef __cplusplus
#define __ATOMICS_AVOID_DOT_INIT
#endif
#endif
#endif
/*
* 7.17.1 Atomic lock-free macros.
*/
#ifdef __GCC_ATOMIC_BOOL_LOCK_FREE
#define ATOMIC_BOOL_LOCK_FREE __GCC_ATOMIC_BOOL_LOCK_FREE
#elif defined(__SYNC_ATOMICS)
#define ATOMIC_BOOL_LOCK_FREE 2 /* For all modern platforms */
#endif
#ifdef __GCC_ATOMIC_CHAR_LOCK_FREE
#define ATOMIC_CHAR_LOCK_FREE __GCC_ATOMIC_CHAR_LOCK_FREE
#elif defined(__SYNC_ATOMICS)
#define ATOMIC_CHAR_LOCK_FREE 2
#endif
#ifdef __GCC_ATOMIC_CHAR16_T_LOCK_FREE
#define ATOMIC_CHAR16_T_LOCK_FREE __GCC_ATOMIC_CHAR16_T_LOCK_FREE
#elif defined(__SYNC_ATOMICS)
#define ATOMIC_CHAR16_T_LOCK_FREE 2
#endif
#ifdef __GCC_ATOMIC_CHAR32_T_LOCK_FREE
#define ATOMIC_CHAR32_T_LOCK_FREE __GCC_ATOMIC_CHAR32_T_LOCK_FREE
#elif defined(__SYNC_ATOMICS)
#define ATOMIC_CHAR32_T_LOCK_FREE 2
#endif
#ifdef __GCC_ATOMIC_WCHAR_T_LOCK_FREE
#define ATOMIC_WCHAR_T_LOCK_FREE __GCC_ATOMIC_WCHAR_T_LOCK_FREE
#elif defined(__SYNC_ATOMICS)
#define ATOMIC_WCHAR_T_LOCK_FREE 2
#endif
#ifdef __GCC_ATOMIC_SHORT_LOCK_FREE
#define ATOMIC_SHORT_LOCK_FREE __GCC_ATOMIC_SHORT_LOCK_FREE
#elif defined(__SYNC_ATOMICS)
#define ATOMIC_SHORT_LOCK_FREE 2
#endif
#ifdef __GCC_ATOMIC_INT_LOCK_FREE
#define ATOMIC_INT_LOCK_FREE __GCC_ATOMIC_INT_LOCK_FREE
#elif defined(__SYNC_ATOMICS)
#define ATOMIC_INT_LOCK_FREE 2
#endif
#ifdef __GCC_ATOMIC_LONG_LOCK_FREE
#define ATOMIC_LONG_LOCK_FREE __GCC_ATOMIC_LONG_LOCK_FREE
#elif defined(__SYNC_ATOMICS)
#define ATOMIC_LONG_LOCK_FREE 2
#endif
#ifdef __GCC_ATOMIC_LLONG_LOCK_FREE
#define ATOMIC_LLONG_LOCK_FREE __GCC_ATOMIC_LLONG_LOCK_FREE
#elif defined(__SYNC_ATOMICS)
#define ATOMIC_LLONG_LOCK_FREE 1 /* maybe */
#endif
#ifdef __GCC_ATOMIC_POINTER_LOCK_FREE
#define ATOMIC_POINTER_LOCK_FREE __GCC_ATOMIC_POINTER_LOCK_FREE
#elif defined(__SYNC_ATOMICS)
#define ATOMIC_POINTER_LOCK_FREE 2
#endif
/*
* 7.17.2 Initialization.
*/
#if defined(__CLANG_ATOMICS)
#define ATOMIC_VAR_INIT(value) (value)
#define atomic_init(obj, value) __c11_atomic_init(obj, value)
#else
#ifdef __ATOMICS_AVOID_DOT_INIT
#define ATOMIC_VAR_INIT(value) \
{ \
value \
}
#else
#define ATOMIC_VAR_INIT(value) \
{ \
.__val = (value) \
}
#endif
#define atomic_init(obj, value) ((void)((obj)->__val = (value)))
#endif
/*
* Clang and recent GCC both provide predefined macros for the memory
* orderings. If we are using a compiler that doesn't define them, use the
* clang values - these will be ignored in the fallback path.
*/
#ifndef __ATOMIC_RELAXED
#define __ATOMIC_RELAXED 0
#endif
#ifndef __ATOMIC_CONSUME
#define __ATOMIC_CONSUME 1
#endif
#ifndef __ATOMIC_ACQUIRE
#define __ATOMIC_ACQUIRE 2
#endif
#ifndef __ATOMIC_RELEASE
#define __ATOMIC_RELEASE 3
#endif
#ifndef __ATOMIC_ACQ_REL
#define __ATOMIC_ACQ_REL 4
#endif
#ifndef __ATOMIC_SEQ_CST
#define __ATOMIC_SEQ_CST 5
#endif
/*
* 7.17.3 Order and consistency.
*
* The memory_order_* constants that denote the barrier behaviour of the
* atomic operations.
* The enum values must be identical to those used by the
* C++ <atomic> header.
*/
typedef enum
{
memory_order_relaxed = __ATOMIC_RELAXED,
memory_order_consume = __ATOMIC_CONSUME,
memory_order_acquire = __ATOMIC_ACQUIRE,
memory_order_release = __ATOMIC_RELEASE,
memory_order_acq_rel = __ATOMIC_ACQ_REL,
memory_order_seq_cst = __ATOMIC_SEQ_CST
} memory_order;
/*
* 7.17.4 Fences.
*/
static __inline void
atomic_thread_fence(memory_order __order __attribute__((unused)))
{
#ifdef __CLANG_ATOMICS
__c11_atomic_thread_fence(__order);
#elif defined(__GNUC_ATOMICS)
__atomic_thread_fence(__order);
#else
__sync_synchronize();
#endif
}
static __inline void
atomic_signal_fence(memory_order __order __attribute__((unused)))
{
#ifdef __CLANG_ATOMICS
__c11_atomic_signal_fence(__order);
#elif defined(__GNUC_ATOMICS)
__atomic_signal_fence(__order);
#else
__asm volatile("" ::
: "memory");
#endif
}
/*
* 7.17.5 Lock-free property.
*/
#if defined(_KERNEL)
/* Atomics in kernelspace are always lock-free. */
#define atomic_is_lock_free(obj) \
((void)(obj), (_Bool)1)
#elif defined(__CLANG_ATOMICS)
#define atomic_is_lock_free(obj) \
__c11_atomic_is_lock_free(sizeof(*(obj)))
#elif defined(__GNUC_ATOMICS)
#define atomic_is_lock_free(obj) \
__atomic_is_lock_free(sizeof((obj)->__val), &(obj)->__val)
#else
#define atomic_is_lock_free(obj) \
((void)(obj), sizeof((obj)->__val) <= sizeof(void *))
#endif
/*
* 7.17.6 Atomic integer types.
*/
#ifndef __CLANG_ATOMICS
/*
* No native support for _Atomic(). Place object in structure to prevent
* most forms of direct non-atomic access.
*/
#define _Atomic(T) \
struct \
{ \
T volatile __val; \
}
#endif
typedef _Atomic(bool) atomic_bool;
typedef _Atomic(char) atomic_char;
typedef _Atomic(signed char) atomic_schar;
typedef _Atomic(unsigned char) atomic_uchar;
typedef _Atomic(short) atomic_short;
typedef _Atomic(unsigned short) atomic_ushort;
typedef _Atomic(int) atomic_int;
typedef _Atomic(unsigned int) atomic_uint;
typedef _Atomic(long) atomic_long;
typedef _Atomic(unsigned long) atomic_ulong;
typedef _Atomic(long long) atomic_llong;
typedef _Atomic(unsigned long long) atomic_ullong;
#if __STDC_VERSION__ >= 201112L || __cplusplus >= 201103L
typedef _Atomic(char16_t) atomic_char16_t;
typedef _Atomic(char32_t) atomic_char32_t;
#endif
typedef _Atomic(wchar_t) atomic_wchar_t;
typedef _Atomic(int_least8_t) atomic_int_least8_t;
typedef _Atomic(uint_least8_t) atomic_uint_least8_t;
typedef _Atomic(int_least16_t) atomic_int_least16_t;
typedef _Atomic(uint_least16_t) atomic_uint_least16_t;
typedef _Atomic(int_least32_t) atomic_int_least32_t;
typedef _Atomic(uint_least32_t) atomic_uint_least32_t;
typedef _Atomic(int_least64_t) atomic_int_least64_t;
typedef _Atomic(uint_least64_t) atomic_uint_least64_t;
typedef _Atomic(int_fast8_t) atomic_int_fast8_t;
typedef _Atomic(uint_fast8_t) atomic_uint_fast8_t;
typedef _Atomic(int_fast16_t) atomic_int_fast16_t;
typedef _Atomic(uint_fast16_t) atomic_uint_fast16_t;
typedef _Atomic(int_fast32_t) atomic_int_fast32_t;
typedef _Atomic(uint_fast32_t) atomic_uint_fast32_t;
typedef _Atomic(int_fast64_t) atomic_int_fast64_t;
typedef _Atomic(uint_fast64_t) atomic_uint_fast64_t;
typedef _Atomic(intptr_t) atomic_intptr_t;
typedef _Atomic(uintptr_t) atomic_uintptr_t;
typedef _Atomic(size_t) atomic_size_t;
typedef _Atomic(ptrdiff_t) atomic_ptrdiff_t;
typedef _Atomic(intmax_t) atomic_intmax_t;
typedef _Atomic(uintmax_t) atomic_uintmax_t;
/*
* 7.17.7 Operations on atomic types.
*/
/*
* Compiler-specific operations.
*/
#if defined(__CLANG_ATOMICS)
#define atomic_compare_exchange_strong_explicit(object, expected, \
desired, success, failure) \
__c11_atomic_compare_exchange_strong(object, expected, desired, \
success, failure)
#define atomic_compare_exchange_weak_explicit(object, expected, \
desired, success, failure) \
__c11_atomic_compare_exchange_weak(object, expected, desired, \
success, failure)
#define atomic_exchange_explicit(object, desired, order) \
__c11_atomic_exchange(object, desired, order)
#define atomic_fetch_add_explicit(object, operand, order) \
__c11_atomic_fetch_add(object, operand, order)
#define atomic_fetch_and_explicit(object, operand, order) \
__c11_atomic_fetch_and(object, operand, order)
#define atomic_fetch_or_explicit(object, operand, order) \
__c11_atomic_fetch_or(object, operand, order)
#define atomic_fetch_sub_explicit(object, operand, order) \
__c11_atomic_fetch_sub(object, operand, order)
#define atomic_fetch_xor_explicit(object, operand, order) \
__c11_atomic_fetch_xor(object, operand, order)
#define atomic_load_explicit(object, order) \
__c11_atomic_load(object, order)
#define atomic_store_explicit(object, desired, order) \
__c11_atomic_store(object, desired, order)
#elif defined(__GNUC_ATOMICS)
#define atomic_compare_exchange_strong_explicit(object, expected, \
desired, success, failure) \
__atomic_compare_exchange_n(&(object)->__val, expected, \
desired, 0, success, failure)
#define atomic_compare_exchange_weak_explicit(object, expected, \
desired, success, failure) \
__atomic_compare_exchange_n(&(object)->__val, expected, \
desired, 1, success, failure)
#define atomic_exchange_explicit(object, desired, order) \
__atomic_exchange_n(&(object)->__val, desired, order)
#define atomic_fetch_add_explicit(object, operand, order) \
__atomic_fetch_add(&(object)->__val, operand, order)
#define atomic_fetch_and_explicit(object, operand, order) \
__atomic_fetch_and(&(object)->__val, operand, order)
#define atomic_fetch_or_explicit(object, operand, order) \
__atomic_fetch_or(&(object)->__val, operand, order)
#define atomic_fetch_sub_explicit(object, operand, order) \
__atomic_fetch_sub(&(object)->__val, operand, order)
#define atomic_fetch_xor_explicit(object, operand, order) \
__atomic_fetch_xor(&(object)->__val, operand, order)
#define atomic_load_explicit(object, order) \
__atomic_load_n(&(object)->__val, order)
#define atomic_store_explicit(object, desired, order) \
__atomic_store_n(&(object)->__val, desired, order)
#else
#define __atomic_apply_stride(object, operand) \
(((__typeof__((object)->__val))0) + (operand))
#define atomic_compare_exchange_strong_explicit(object, expected, \
desired, success, failure) __extension__({ \
__typeof__(expected) __ep = (expected); \
__typeof__(*__ep) __e = *__ep; \
(void)(success); \
(void)(failure); \
(bool)((*__ep = __sync_val_compare_and_swap(&(object)->__val, \
__e, desired)) == __e); \
})
#define atomic_compare_exchange_weak_explicit(object, expected, \
desired, success, failure) \
atomic_compare_exchange_strong_explicit(object, expected, \
desired, success, failure)
#ifdef __HAS_BUILTIN_SYNC_SWAP
/* Clang provides a full-barrier atomic exchange - use it if available. */
#define atomic_exchange_explicit(object, desired, order) \
((void)(order), __sync_swap(&(object)->__val, desired))
#else
/*
* __sync_lock_test_and_set() is only an acquire barrier in theory (although in
* practice it is usually a full barrier) so we need an explicit barrier before
* it.
*/
#define atomic_exchange_explicit(object, desired, order) \
__extension__({ \
__typeof__(object) __o = (object); \
__typeof__(desired) __d = (desired); \
(void)(order); \
__sync_synchronize(); \
__sync_lock_test_and_set(&(__o)->__val, __d); \
})
#endif
#define atomic_fetch_add_explicit(object, operand, order) \
((void)(order), __sync_fetch_and_add(&(object)->__val, \
__atomic_apply_stride(object, operand)))
#define atomic_fetch_and_explicit(object, operand, order) \
((void)(order), __sync_fetch_and_and(&(object)->__val, operand))
#define atomic_fetch_or_explicit(object, operand, order) \
((void)(order), __sync_fetch_and_or(&(object)->__val, operand))
#define atomic_fetch_sub_explicit(object, operand, order) \
((void)(order), __sync_fetch_and_sub(&(object)->__val, \
__atomic_apply_stride(object, operand)))
#define atomic_fetch_xor_explicit(object, operand, order) \
((void)(order), __sync_fetch_and_xor(&(object)->__val, operand))
#define atomic_load_explicit(object, order) \
((void)(order), __sync_fetch_and_add(&(object)->__val, 0))
#define atomic_store_explicit(object, desired, order) \
((void)atomic_exchange_explicit(object, desired, order))
#endif
/*
* Convenience functions.
*
* Don't provide these in kernel space. In kernel space, we should be
* disciplined enough to always provide explicit barriers.
*/
#ifndef _KERNEL
#define atomic_compare_exchange_strong(object, expected, desired) \
atomic_compare_exchange_strong_explicit(object, expected, \
desired, memory_order_seq_cst, memory_order_seq_cst)
#define atomic_compare_exchange_weak(object, expected, desired) \
atomic_compare_exchange_weak_explicit(object, expected, \
desired, memory_order_seq_cst, memory_order_seq_cst)
#define atomic_exchange(object, desired) \
atomic_exchange_explicit(object, desired, memory_order_seq_cst)
#define atomic_fetch_add(object, operand) \
atomic_fetch_add_explicit(object, operand, memory_order_seq_cst)
#define atomic_fetch_and(object, operand) \
atomic_fetch_and_explicit(object, operand, memory_order_seq_cst)
#define atomic_fetch_or(object, operand) \
atomic_fetch_or_explicit(object, operand, memory_order_seq_cst)
#define atomic_fetch_sub(object, operand) \
atomic_fetch_sub_explicit(object, operand, memory_order_seq_cst)
#define atomic_fetch_xor(object, operand) \
atomic_fetch_xor_explicit(object, operand, memory_order_seq_cst)
#define atomic_load(object) \
atomic_load_explicit(object, memory_order_seq_cst)
#define atomic_store(object, desired) \
atomic_store_explicit(object, desired, memory_order_seq_cst)
#endif /* !_KERNEL */
/*
* 7.17.8 Atomic flag type and operations.
*
* XXX: Assume atomic_bool can be used as an atomic_flag. Is there some
* kind of compiler built-in type we could use?
*/
typedef struct
{
atomic_bool __flag;
} atomic_flag;
#define ATOMIC_FLAG_INIT \
{ \
ATOMIC_VAR_INIT(false) \
}
static __inline bool
atomic_flag_test_and_set_explicit(volatile atomic_flag *__object,
memory_order __order)
{
return (atomic_exchange_explicit(&__object->__flag, 1, __order));
}
static __inline void
atomic_flag_clear_explicit(volatile atomic_flag *__object, memory_order __order)
{
atomic_store_explicit(&__object->__flag, 0, __order);
}
#ifndef _KERNEL
static __inline bool
atomic_flag_test_and_set(volatile atomic_flag *__object)
{
return (atomic_flag_test_and_set_explicit(__object,
memory_order_seq_cst));
}
static __inline void
atomic_flag_clear(volatile atomic_flag *__object)
{
atomic_flag_clear_explicit(__object, memory_order_seq_cst);
}
#endif /* !_KERNEL */
#endif /* <atomic> unavailable */
#endif /* !_STDATOMIC_H_ */
+102
View File
@@ -0,0 +1,102 @@
import os
fn main() {
if os.args.len <= 1 {
eprintln('please specify a C++ compiler')
exit(1)
}
cc := os.args[1]
if os.execute('${os.quoted_path(cc)} -v').exit_code != 0 {
eprintln('please specify a valid C++ compiler')
exit(1)
}
cc_type, cc_version, cc_os := get_cc_info(cc)
triple := '${cc_type}-${cc_version}-${cc_os}'
println('compiler: ${triple}')
search_paths := get_search_paths(cc)
atomic_path := find_file(search_paths, 'atomic') or {
eprintln(err)
exit(2)
}
bitsatomicbase_path := find_file(search_paths, 'bits/atomic_base.h') or {
if cc_os == 'linux' {
eprintln(err)
exit(2)
}
'no_file' // bits/atomic_base.h is only used on linux
}
patch_atomic(os.join_path(os.dir(@FILE), 'atomic.h'), atomic_path) or {
eprintln(err)
exit(2)
}
if bitsatomicbase_path != 'no_file' {
patch_bitsatomicbase(os.join_path(os.dir(@FILE), 'bitsatomicbase.h'), bitsatomicbase_path) or {
eprintln(err)
exit(2)
}
}
println('${atomic_path}:::${bitsatomicbase_path}')
}
fn get_cc_info(cc string) (string, string, string) {
cc_type := if cc.contains('clang') {
'clang'
} else if cc.contains('g') {
'gcc'
} else {
eprintln('only gcc and clang are supported')
exit(1)
'none'
}
lines := os.execute('${os.quoted_path(cc)} -v').output.split('\n')
// gcc and clang both have the same way way to say what version they have and what the host target triple is
cc_version :=
lines.filter(it.contains('${cc_type} version '))[0].all_after('${cc_type} version ').all_before('.')
cc_os := lines.filter(it.starts_with('Target: '))[0].all_after('Target: ').split('-')[2]
return cc_type, cc_version, if cc_os.contains('darwin') {
'darwin' // remove 20.6.0 from darwin20.6.0
} else {
cc_os
}
}
fn get_search_paths(cc string) []string {
result := os.execute('${os.quoted_path(cc)} -v -x c++ /dev/null').output
lines := result.split('\n')
search_path := lines[lines.index('#include <...> search starts here:') + 1..lines.index('End of search list.')]
return search_path.map(os.real_path(it.all_before('(').trim_space()))
}
fn find_file(search_paths []string, file string) !string {
for search_path in search_paths {
if os.exists(os.join_path(search_path, file)) {
return os.join_path(search_path, file)
}
}
return error('${file} not found')
}
fn patch_atomic(outfile string, infile string) ! {
lines := os.read_file(infile)!.split('\n')
outlines := lines.filter(!it.contains('atomic(const atomic&) = delete;'))
outtext := outlines.join('\n').replace('#include <bits/atomic_base.h>',
'#include "bitsatomicbase.h"')
os.write_file(outfile, outtext)!
}
fn patch_bitsatomicbase(outfile string, infile string) ! {
lines := os.read_file(infile)!.split('\n')
outlines := lines.filter(!it.contains('__atomic_base(const __atomic_base&) = delete;'))
outtext := outlines.join('\n').replace('#include <bits/atomic_base.h>',
'#include "bitsatomicbase.h"')
os.write_file(outfile, outtext)!
}
+559
View File
@@ -0,0 +1,559 @@
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef COMPAT_ATOMICS_WIN32_STDATOMIC_H
#define COMPAT_ATOMICS_WIN32_STDATOMIC_H
#define WIN32_LEAN_AND_MEAN
#include <stddef.h>
#include <stdint.h>
#include <windows.h>
#ifdef _MSC_VER
#define cpu_relax() _mm_pause()
#else
#define cpu_relax() __asm__ __volatile__ ("pause")
#endif
#define ATOMIC_FLAG_INIT 0
#define ATOMIC_VAR_INIT(value) (value)
#define atomic_init(obj, value) \
do \
{ \
*(obj) = (value); \
} while (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) \
do { \
switch (order) { \
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) \
((void)0)
#define atomic_is_lock_free(obj) 0
typedef intptr_t atomic_flag;
typedef _Atomic bool atomic_bool;
typedef _Atomic char atomic_char;
typedef _Atomic signed char atomic_schar;
typedef _Atomic unsigned char atomic_uchar;
typedef _Atomic short atomic_short;
typedef _Atomic unsigned short atomic_ushort;
typedef _Atomic int atomic_int;
typedef _Atomic unsigned int atomic_uint;
typedef _Atomic long atomic_long;
typedef _Atomic unsigned long atomic_ulong;
typedef _Atomic long long atomic_llong;
typedef _Atomic unsigned long long atomic_ullong;
typedef intptr_t atomic_wchar_t;
typedef intptr_t atomic_int_least8_t;
typedef intptr_t atomic_uint_least8_t;
typedef intptr_t atomic_int_least16_t;
typedef intptr_t atomic_uint_least16_t;
typedef intptr_t atomic_int_least32_t;
typedef intptr_t atomic_uint_least32_t;
typedef intptr_t atomic_int_least64_t;
typedef intptr_t atomic_uint_least64_t;
typedef intptr_t atomic_int_fast8_t;
typedef intptr_t atomic_uint_fast8_t;
typedef intptr_t atomic_int_fast16_t;
typedef intptr_t atomic_uint_fast16_t;
typedef intptr_t atomic_int_fast32_t;
typedef intptr_t atomic_uint_fast32_t;
typedef intptr_t atomic_int_fast64_t;
typedef intptr_t atomic_uint_fast64_t;
typedef _Atomic intptr_t atomic_intptr_t;
typedef _Atomic uintptr_t atomic_uintptr_t;
typedef _Atomic size_t atomic_size_t;
typedef intptr_t atomic_ptrdiff_t;
typedef intptr_t atomic_intmax_t;
typedef intptr_t atomic_uintmax_t;
#ifdef __TINYC__
/*
For TCC it is missing the x64 version of _InterlockedExchangeAdd64 so we
fake it (works the same) with InterlockedCompareExchange64 until it
succeeds
*/
__CRT_INLINE LONGLONG _InterlockedExchangeAdd64(LONGLONG volatile *Addend, LONGLONG Value)
{
LONGLONG Old;
do
{
Old = *Addend;
} while (InterlockedCompareExchange64(Addend, Old + Value, Old) != Old);
return Old;
}
__CRT_INLINE LONG _InterlockedExchangeAdd(LONG volatile *Addend, LONG Value)
{
LONG Old;
do
{
Old = *Addend;
} while (InterlockedCompareExchange(Addend, Old + Value, Old) != Old);
return Old;
}
#ifndef InterlockedIncrement64
#define InterlockedIncrement64 _InterlockedExchangeAdd64
#endif
#endif
#define atomic_store(object, desired) \
do \
{ \
MemoryBarrier(); \
*(object) = (desired); \
MemoryBarrier(); \
} while (0)
#define atomic_store_explicit(object, desired, order) \
atomic_store(object, desired)
#define atomic_load(object) \
(MemoryBarrier(), *(object))
#define atomic_load_explicit(object, order) \
atomic_load(object)
#define atomic_exchange(object, desired) \
InterlockedExchangePointer(object, desired)
#define atomic_exchange_explicit(object, desired, order) \
atomic_exchange(object, desired)
static inline int atomic_compare_exchange_strong(intptr_t volatile *object, intptr_t volatile *expected,
intptr_t desired)
{
intptr_t old = *expected;
*expected = (intptr_t)InterlockedCompareExchangePointer(
(PVOID *)object, (PVOID)desired, (PVOID)old);
return *expected == old;
}
#define atomic_compare_exchange_strong_explicit(object, expected, desired, success, failure) \
atomic_compare_exchange_strong(object, expected, desired)
#define atomic_compare_exchange_weak(object, expected, desired) \
atomic_compare_exchange_strong(object, expected, desired)
#define atomic_compare_exchange_weak_explicit(object, expected, desired, success, failure) \
atomic_compare_exchange_weak(object, expected, desired)
#ifdef _WIN64
#define atomic_fetch_add(object, operand) \
InterlockedExchangeAdd64(object, operand)
#define atomic_fetch_sub(object, operand) \
InterlockedExchangeAdd64(object, -(operand))
#define atomic_fetch_or(object, operand) \
InterlockedOr64(object, operand)
#define atomic_fetch_xor(object, operand) \
InterlockedXor64(object, operand)
#define atomic_fetch_and(object, operand) \
InterlockedAnd64(object, operand)
#else
#define atomic_fetch_add(object, operand) \
InterlockedExchangeAdd(object, operand)
#define atomic_fetch_sub(object, operand) \
InterlockedExchangeAdd(object, -(operand))
#define atomic_fetch_or(object, operand) \
InterlockedOr(object, operand)
#define atomic_fetch_xor(object, operand) \
InterlockedXor(object, operand)
#define atomic_fetch_and(object, operand) \
InterlockedAnd(object, operand)
#endif /* _WIN64 */
/* specialized versions with explicit object size */
#define atomic_load_ptr atomic_load
#define atomic_store_ptr atomic_store
#define atomic_compare_exchange_weak_ptr atomic_compare_exchange_weak
#define atomic_compare_exchange_strong_ptr atomic_compare_exchange_strong
#define atomic_exchange_ptr atomic_exchange
#define atomic_fetch_add_ptr atomic_fetch_add
#define atomic_fetch_sub_ptr atomic_fetch_sub
#define atomic_fetch_and_ptr atomic_fetch_and
#define atomic_fetch_or_ptr atomic_fetch_or
#define atomic_fetch_xor_ptr atomic_fetch_xor
static inline void atomic_store_u64(unsigned long long volatile * object, unsigned long long desired) {
do {
MemoryBarrier();
*(object) = (desired);
MemoryBarrier();
} while (0);
}
static inline unsigned long long atomic_load_u64(unsigned long long volatile * object) {
return (MemoryBarrier(), *(object));
}
#define atomic_exchange_u64(object, desired) \
InterlockedExchange64(object, desired)
static inline int atomic_compare_exchange_strong_u64(unsigned long long volatile * object, unsigned long long volatile * expected,
unsigned long long desired)
{
unsigned long long old = *expected;
*expected = InterlockedCompareExchange64(object, desired, old);
return *expected == old;
}
#define atomic_compare_exchange_weak_u64(object, expected, desired) \
atomic_compare_exchange_strong_u64(object, expected, desired)
#define atomic_fetch_add_u64(object, operand) \
InterlockedExchangeAdd64(object, operand)
#define atomic_fetch_sub_u64(object, operand) \
InterlockedExchangeAdd64(object, -(operand))
#define atomic_fetch_or_u64(object, operand) \
InterlockedOr64(object, operand)
#define atomic_fetch_xor_u64(object, operand) \
InterlockedXor64(object, operand)
#define atomic_fetch_and_u64(object, operand) \
InterlockedAnd64(object, operand)
static inline void atomic_store_u32(unsigned volatile * object, unsigned desired) {
do {
MemoryBarrier();
*(object) = (desired);
MemoryBarrier();
} while (0);
}
static inline unsigned atomic_load_u32(unsigned volatile * object) {
return (MemoryBarrier(), *(object));
}
#define atomic_exchange_u32(object, desired) \
InterlockedExchange(object, desired)
static inline int atomic_compare_exchange_strong_u32(unsigned volatile * object, unsigned volatile * expected,
unsigned desired)
{
unsigned old = *expected;
*expected = InterlockedCompareExchange((void *)object, desired, old);
return *expected == old;
}
#define atomic_compare_exchange_weak_u32(object, expected, desired) \
atomic_compare_exchange_strong_u32(object, expected, desired)
#define atomic_fetch_add_u32(object, operand) \
InterlockedExchangeAdd(object, operand)
#define atomic_fetch_sub_u32(object, operand) \
InterlockedExchangeAdd(object, -(operand))
#define atomic_fetch_or_u32(object, operand) \
InterlockedOr(object, operand)
#define atomic_fetch_xor_u32(object, operand) \
InterlockedXor(object, operand)
#define atomic_fetch_and_u32(object, operand) \
InterlockedAnd(object, operand)
#ifdef _MSC_VER
#define InterlockedExchangeAdd16 _InterlockedExchangeAdd16
#else
#define InterlockedExchange16 ManualInterlockedExchange16
#define InterlockedExchangeAdd16 ManualInterlockedExchangeAdd16
static inline uint16_t ManualInterlockedExchange16(volatile uint16_t* object, uint16_t desired) {
__asm__ __volatile__ (
"xchgw %0, %1"
: "+r" (desired),
"+m" (*object)
:
: "memory"
);
return desired;
}
static inline unsigned short ManualInterlockedExchangeAdd16(unsigned short volatile* Addend, unsigned short Value) {
__asm__ __volatile__ (
"lock xaddw %w[value], %[mem]"
: [mem] "+m" (*Addend), [value] "+r" (Value)
: : "memory"
);
return Value;
}
#endif
static inline void atomic_store_u16(unsigned short volatile * object, unsigned short desired) {
do {
MemoryBarrier();
*(object) = (desired);
MemoryBarrier();
} while (0);
}
static inline unsigned short atomic_load_u16(unsigned short volatile * object) {
return (MemoryBarrier(), *(object));
}
#define atomic_exchange_u16(object, desired) \
InterlockedExchange16(object, desired)
static inline int atomic_compare_exchange_strong_u16(unsigned short volatile * object, unsigned short volatile * expected,
unsigned short desired)
{
unsigned short old = *expected;
*expected = InterlockedCompareExchange16(object, desired, old);
return *expected == old;
}
#define atomic_compare_exchange_weak_u16(object, expected, desired) \
atomic_compare_exchange_strong_u16((void*)object, expected, desired)
#define atomic_fetch_add_u16(object, operand) \
InterlockedExchangeAdd16(object, operand)
#define atomic_fetch_sub_u16(object, operand) \
InterlockedExchangeAdd16(object, -(operand))
#define atomic_fetch_or_u16(object, operand) \
InterlockedOr16(object, operand)
#define atomic_fetch_xor_u16(object, operand) \
InterlockedXor16(object, operand)
#define atomic_fetch_and_u16(object, operand) \
InterlockedAnd16(object, operand)
#define atomic_fetch_add_explicit(object, operand, order) \
atomic_fetch_add(object, operand)
#define atomic_fetch_sub_explicit(object, operand, order) \
atomic_fetch_sub(object, operand)
#define atomic_fetch_or_explicit(object, operand, order) \
atomic_fetch_or(object, operand)
#define atomic_fetch_xor_explicit(object, operand, order) \
atomic_fetch_xor(object, operand)
#define atomic_fetch_and_explicit(object, operand, order) \
atomic_fetch_and(object, operand)
#define atomic_flag_test_and_set(object) \
atomic_exchange(object, 1)
#define atomic_flag_test_and_set_explicit(object, order) \
atomic_flag_test_and_set(object)
#define atomic_flag_clear(object) \
atomic_store(object, 0)
#define atomic_flag_clear_explicit(object, order) \
atomic_flag_clear(object)
#ifdef _MSC_VER
#define InterlockedCompareExchange8 _InterlockedCompareExchange8
#define InterlockedExchangeAdd8 _InterlockedExchangeAdd8
#define InterlockedOr8 _InterlockedOr8
#define InterlockedXor8 _InterlockedXor8
#define InterlockedAnd8 _InterlockedAnd8
#else
#define InterlockedExchange8 ManualInterlockedExchange8
#define InterlockedCompareExchange8 ManualInterlockedCompareExchange8
#define InterlockedExchangeAdd8 ManualInterlockedExchangeAdd8
#define InterlockedOr8 ManualInterlockedOr8
#define InterlockedXor8 ManualInterlockedXor8
#define InterlockedAnd8 ManualInterlockedAnd8
static inline char ManualInterlockedExchange8(char volatile* object, char desired) {
__asm__ __volatile__ (
"xchgb %0, %1"
: "+q" (desired), "+m" (*object)
:
: "memory"
);
return desired;
}
static inline unsigned char ManualInterlockedCompareExchange8(unsigned char volatile * dest, unsigned char exchange, unsigned char comparand) {
unsigned char result;
__asm__ volatile (
"lock cmpxchgb %[exchange], %[dest]"
: "=a" (result), [dest] "+m" (*dest)
: [exchange] "q" (exchange), "a" (comparand)
: "memory"
);
return result;
}
static inline unsigned char ManualInterlockedExchangeAdd8(unsigned char volatile * dest, unsigned char value) {
unsigned char oldValue;
unsigned char newValue;
do {
oldValue = *dest;
} while (ManualInterlockedCompareExchange8(dest, oldValue + value, oldValue) != oldValue);
return oldValue;
}
static inline unsigned char ManualInterlockedOr8(unsigned char volatile * dest, unsigned char value) {
unsigned char oldValue;
do {
oldValue = *dest;
} while (ManualInterlockedCompareExchange8(dest, oldValue | value, oldValue) != oldValue);
return oldValue;
}
static inline unsigned char ManualInterlockedXor8(unsigned char volatile * dest, unsigned char value) {
unsigned char oldValue;
do {
oldValue = *dest;
} while (ManualInterlockedCompareExchange8(dest, oldValue ^ value, oldValue) != oldValue);
return oldValue;
}
static inline unsigned char ManualInterlockedAnd8(unsigned char volatile * dest, unsigned char value) {
unsigned char oldValue;
do {
oldValue = *dest;
} while (ManualInterlockedCompareExchange8(dest, oldValue & value, oldValue) != oldValue);
return oldValue;
}
#endif
static inline void atomic_store_byte(unsigned char volatile * object, unsigned char desired) {
do {
MemoryBarrier();
*(object) = (desired);
MemoryBarrier();
} while (0);
}
static inline unsigned char atomic_load_byte(unsigned char volatile * object) {
return (MemoryBarrier(), *(object));
}
#define atomic_exchange_byte(object, desired) \
InterlockedExchange8(object, desired)
static inline int atomic_compare_exchange_strong_byte(unsigned char volatile * object, unsigned char volatile * expected,
unsigned char desired)
{
unsigned char old = *expected;
*expected = InterlockedCompareExchange8(object, desired, old);
return *expected == old;
}
#define atomic_compare_exchange_weak_byte(object, expected, desired) \
atomic_compare_exchange_strong_byte(object, expected, desired)
#define atomic_fetch_add_byte(object, operand) \
InterlockedExchangeAdd8(object, operand)
#define atomic_fetch_sub_byte(object, operand) \
InterlockedExchangeAdd8(object, -(operand))
#define atomic_fetch_or_byte(object, operand) \
InterlockedOr8(object, operand)
#define atomic_fetch_xor_byte(object, operand) \
InterlockedXor8(object, operand)
#define atomic_fetch_and_byte(object, operand) \
InterlockedAnd8(object, operand)
#endif /* COMPAT_ATOMICS_WIN32_STDATOMIC_H */