| 1 | /* |
| 2 | Compatibility header for stdatomic.h that works for all compilers supported by V. |
| 3 | For TCC, we use libatomic from the OS. |
| 4 | */ |
| 5 | #ifndef __ATOMIC_H |
| 6 | #define __ATOMIC_H |
| 7 | |
| 8 | #ifndef __cplusplus |
| 9 | // If C just use stdatomic.h |
| 10 | #ifndef __TINYC__ |
| 11 | #include <stdatomic.h> |
| 12 | #endif |
| 13 | #else |
| 14 | // CPP wrapper for atomic operations that are compatible with C |
| 15 | #include "atomic_cpp.h" |
| 16 | #endif |
| 17 | |
| 18 | #if defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || defined(_M_IX86) |
| 19 | /* x86 architecture: uses PAUSE instruction for efficient spinning */ |
| 20 | #define cpu_relax() __asm__ __volatile__ ("pause") |
| 21 | #elif defined(__aarch64__) || defined(_M_ARM64) || defined(__arm__) || defined(_M_ARM) |
| 22 | #ifdef __TINYC__ |
| 23 | /* TCC compiler limitation: assembly not supported on ARM */ |
| 24 | #define cpu_relax() |
| 25 | #else |
| 26 | /* ARM architecture: uses YIELD instruction for power-efficient spinning */ |
| 27 | #define cpu_relax() __asm__ __volatile__ ("yield" ::: "memory") |
| 28 | #endif |
| 29 | #elif defined(__riscv) && __riscv_xlen == 64 |
| 30 | /* RISC-V 64-bit: no dedicated pause instruction, using alternative sequence */ |
| 31 | #define cpu_relax() __asm__ __volatile__ ( \ |
| 32 | "fence rw, rw\n\t" /* Full memory barrier (read-write ordering) */ \ |
| 33 | "andi a0, a0, 0\n\t" /* Dummy arithmetic instruction (always sets a0 = 0) */ \ |
| 34 | ::: "memory", "a0") /* Clobbers memory and a0 register to prevent optimizations */ |
| 35 | #elif defined(__powerpc64__) || defined(__ppc64__) |
| 36 | /* PowerPC 64-bit: use OR instruction for synchronization */ |
| 37 | #define cpu_relax() __asm__ __volatile__ ("or 1,1,1\n\t" ::: "memory") |
| 38 | #elif defined(__mips64) |
| 39 | /* MIPS 64-bit: use series of super-scalar NOPs */ |
| 40 | #define cpu_relax() __asm__ __volatile__ ("ssnop\n\tssnop\n\tssnop\n\t" ::: "memory") |
| 41 | #else |
| 42 | /* Fallback implementation for unsupported architectures */ |
| 43 | #define cpu_relax() __asm__ __volatile__ ( \ |
| 44 | "nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t" /* Series of no-operation instructions */ \ |
| 45 | ::: "memory") /* Memory clobber to prevent instruction reordering */ |
| 46 | #endif |
| 47 | |
| 48 | #ifdef __TINYC__ |
| 49 | |
| 50 | typedef volatile long long atomic_llong; |
| 51 | typedef volatile unsigned long long atomic_ullong; |
| 52 | typedef volatile uintptr_t atomic_uintptr_t; |
| 53 | |
| 54 | extern void atomic_thread_fence (int memory_order); |
| 55 | extern void __atomic_thread_fence (int memory_order); |
| 56 | |
| 57 | // TinyCC relies on its runtime atomics support for thread fences. |
| 58 | #if !defined(__APPLE__) |
| 59 | #define atomic_thread_fence(order) __atomic_thread_fence(order) |
| 60 | #endif |
| 61 | |
| 62 | // use functions for 64, 32 and 8 bit from libatomic directly |
| 63 | // since tcc is not capible to use "generic" C functions |
| 64 | // there is no header file for libatomic so we provide function declarations here |
| 65 | |
| 66 | extern unsigned long long __atomic_load_8(unsigned long long* x, int mo); |
| 67 | extern void __atomic_store_8(unsigned long long* x, unsigned long long y, int mo); |
| 68 | extern _Bool __atomic_compare_exchange_8(unsigned long long* x, unsigned long long* expected, unsigned long long y, int mo, int mo2); |
| 69 | extern unsigned long long __atomic_exchange_8(unsigned long long* x, unsigned long long y, int mo); |
| 70 | extern unsigned long long __atomic_fetch_add_8(unsigned long long* x, unsigned long long y, int mo); |
| 71 | extern unsigned long long __atomic_fetch_sub_8(unsigned long long* x, unsigned long long y, int mo); |
| 72 | extern unsigned long long __atomic_fetch_and_8(unsigned long long* x, unsigned long long y, int mo); |
| 73 | extern unsigned long long __atomic_fetch_or_8(unsigned long long* x, unsigned long long y, int mo); |
| 74 | extern unsigned long long __atomic_fetch_xor_8(unsigned long long* x, unsigned long long y, int mo); |
| 75 | |
| 76 | extern unsigned int __atomic_load_4(unsigned int* x, int mo); |
| 77 | extern void __atomic_store_4(unsigned int* x, unsigned int y, int mo); |
| 78 | extern _Bool __atomic_compare_exchange_4(unsigned int* x, unsigned int* expected, unsigned int y, int mo, int mo2); |
| 79 | extern unsigned int __atomic_exchange_4(unsigned int* x, unsigned int y, int mo); |
| 80 | extern unsigned int __atomic_fetch_add_4(unsigned int* x, unsigned int y, int mo); |
| 81 | extern unsigned int __atomic_fetch_sub_4(unsigned int* x, unsigned int y, int mo); |
| 82 | extern unsigned int __atomic_fetch_and_4(unsigned int* x, unsigned int y, int mo); |
| 83 | extern unsigned int __atomic_fetch_or_4(unsigned int* x, unsigned int y, int mo); |
| 84 | extern unsigned int __atomic_fetch_xor_4(unsigned int* x, unsigned int y, int mo); |
| 85 | |
| 86 | extern unsigned short __atomic_load_2(unsigned short* x, int mo); |
| 87 | extern void __atomic_store_2(unsigned short* x, unsigned short y, int mo); |
| 88 | extern _Bool __atomic_compare_exchange_2(unsigned short* x, unsigned short* expected, unsigned short y, int mo, int mo2); |
| 89 | extern unsigned short __atomic_exchange_2(unsigned short* x, unsigned short y, int mo); |
| 90 | extern unsigned short __atomic_fetch_add_2(unsigned short* x, unsigned short y, int mo); |
| 91 | extern unsigned short __atomic_fetch_sub_2(unsigned short* x, unsigned short y, int mo); |
| 92 | extern unsigned short __atomic_fetch_and_2(unsigned short* x, unsigned short y, int mo); |
| 93 | extern unsigned short __atomic_fetch_or_2(unsigned short* x, unsigned short y, int mo); |
| 94 | extern unsigned short __atomic_fetch_xor_2(unsigned short* x, unsigned short y, int mo); |
| 95 | |
| 96 | extern unsigned char __atomic_load_1(unsigned char* x, int mo); |
| 97 | extern void __atomic_store_1(unsigned char* x, unsigned char y, int mo); |
| 98 | extern _Bool __atomic_compare_exchange_1(unsigned char* x, unsigned char* expected, unsigned char y, int mo, int mo2); |
| 99 | extern unsigned char __atomic_exchange_1(unsigned char* x, unsigned char y, int mo); |
| 100 | extern unsigned char __atomic_fetch_add_1(unsigned char* x, unsigned char y, int mo); |
| 101 | extern unsigned char __atomic_fetch_sub_1(unsigned char* x, unsigned char y, int mo); |
| 102 | extern unsigned char __atomic_fetch_and_1(unsigned char* x, unsigned char y, int mo); |
| 103 | extern unsigned char __atomic_fetch_or_1(unsigned char* x, unsigned char y, int mo); |
| 104 | extern unsigned char __atomic_fetch_xor_1(unsigned char* x, unsigned char y, int mo); |
| 105 | |
| 106 | // The default functions should work with pointers so we have to decide based on pointer size |
| 107 | #if UINTPTR_MAX == 0xFFFFFFFF |
| 108 | |
| 109 | #define atomic_load_explicit __atomic_load_4 |
| 110 | #define atomic_store_explicit __atomic_store_4 |
| 111 | #define atomic_compare_exchange_weak_explicit __atomic_compare_exchange_4 |
| 112 | #define atomic_compare_exchange_strong_explicit __atomic_compare_exchange_4 |
| 113 | #define atomic_exchange_explicit __atomic_exchange_4 |
| 114 | #define atomic_fetch_add_explicit __atomic_fetch_add_4 |
| 115 | #define atomic_fetch_sub_explicit __atomic_sub_fetch_4 |
| 116 | |
| 117 | |
| 118 | #else |
| 119 | |
| 120 | #define atomic_load_explicit __atomic_load_8 |
| 121 | #define atomic_store_explicit __atomic_store_8 |
| 122 | #define atomic_compare_exchange_weak_explicit __atomic_compare_exchange_8 |
| 123 | #define atomic_compare_exchange_strong_explicit __atomic_compare_exchange_8 |
| 124 | #define atomic_exchange_explicit __atomic_exchange_8 |
| 125 | #define atomic_fetch_add_explicit __atomic_fetch_add_8 |
| 126 | #define atomic_fetch_sub_explicit __atomic_sub_fetch_8 |
| 127 | |
| 128 | #endif |
| 129 | |
| 130 | // memory order policies - we use "sequentially consistent" by default |
| 131 | |
| 132 | #define memory_order_relaxed 0 |
| 133 | #define memory_order_consume 1 |
| 134 | #define memory_order_acquire 2 |
| 135 | #define memory_order_release 3 |
| 136 | #define memory_order_acq_rel 4 |
| 137 | #define memory_order_seq_cst 5 |
| 138 | |
| 139 | static inline void** atomic_load(void** x) { |
| 140 | return (void**)atomic_load_explicit((unsigned long long*)x, memory_order_seq_cst); |
| 141 | } |
| 142 | static inline void atomic_store(void** x, void* y) { |
| 143 | atomic_store_explicit((unsigned long long*)x, (uintptr_t)y, memory_order_seq_cst); |
| 144 | } |
| 145 | static inline int atomic_compare_exchange_weak(void** x, void** expected, intptr_t y) { |
| 146 | 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); |
| 147 | } |
| 148 | static inline int atomic_compare_exchange_strong(void** x, void** expected, intptr_t y) { |
| 149 | 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); |
| 150 | } |
| 151 | static inline uintptr_t atomic_exchange(void** x, void* y) { |
| 152 | return atomic_exchange_explicit((unsigned long long*)x, (uintptr_t)y, memory_order_seq_cst); |
| 153 | } |
| 154 | static inline uintptr_t atomic_fetch_add(uintptr_t* x, uintptr_t y) { |
| 155 | return atomic_fetch_add_explicit(x, y, memory_order_seq_cst); |
| 156 | } |
| 157 | static inline uintptr_t atomic_fetch_sub(uintptr_t* x, uintptr_t y) { |
| 158 | return atomic_fetch_sub_explicit(x, y, memory_order_seq_cst); |
| 159 | } |
| 160 | static inline uintptr_t atomic_fetch_and(uintptr_t* x, uintptr_t y) { |
| 161 | return atomic_fetch_and_explicit(x, y, memory_order_seq_cst); |
| 162 | } |
| 163 | static inline uintptr_t atomic_fetch_or(uintptr_t* x, uintptr_t y) { |
| 164 | return atomic_fetch_or_explicit(x, y, memory_order_seq_cst); |
| 165 | } |
| 166 | static inline uintptr_t atomic_fetch_xor(uintptr_t* x, uintptr_t y) { |
| 167 | return atomic_fetch_xor_explicit(x, y, memory_order_seq_cst); |
| 168 | } |
| 169 | |
| 170 | #define atomic_load_ptr atomic_load |
| 171 | #define atomic_store_ptr atomic_store |
| 172 | #define atomic_compare_exchange_weak_ptr atomic_compare_exchange_weak |
| 173 | #define atomic_compare_exchange_strong_ptr atomic_compare_exchange_strong |
| 174 | #define atomic_exchange_ptr atomic_exchange |
| 175 | #define atomic_fetch_add_ptr atomic_fetch_add |
| 176 | #define atomic_fetch_sub_ptr atomic_fetch_sub |
| 177 | #define atomic_fetch_and_ptr atomic_fetch_and |
| 178 | #define atomic_fetch_or_ptr atomic_fetch_or |
| 179 | #define atomic_fetch_xor_ptr atomic_fetch_xor |
| 180 | |
| 181 | // specialized versions for 64 bit |
| 182 | |
| 183 | static inline unsigned long long atomic_load_u64(unsigned long long* x) { |
| 184 | return __atomic_load_8(x, memory_order_seq_cst); |
| 185 | } |
| 186 | static inline void atomic_store_u64(unsigned long long* x, unsigned long long y) { |
| 187 | __atomic_store_8(x, y, memory_order_seq_cst); |
| 188 | } |
| 189 | static inline int atomic_compare_exchange_weak_u64(unsigned long long* x, unsigned long long* expected, unsigned long long y) { |
| 190 | return (int)__atomic_compare_exchange_8(x, expected, y, memory_order_seq_cst, memory_order_seq_cst); |
| 191 | } |
| 192 | static inline int atomic_compare_exchange_strong_u64(unsigned long long* x, unsigned long long* expected, unsigned long long y) { |
| 193 | return (int)__atomic_compare_exchange_8(x, expected, y, memory_order_seq_cst, memory_order_seq_cst); |
| 194 | } |
| 195 | static inline unsigned long long atomic_exchange_u64(unsigned long long* x, unsigned long long y) { |
| 196 | return __atomic_exchange_8(x, y, memory_order_seq_cst); |
| 197 | } |
| 198 | static inline unsigned long long atomic_fetch_add_u64(unsigned long long* x, unsigned long long y) { |
| 199 | return __atomic_fetch_add_8(x, y, memory_order_seq_cst); |
| 200 | } |
| 201 | static inline unsigned long long atomic_fetch_sub_u64(unsigned long long* x, unsigned long long y) { |
| 202 | return __atomic_fetch_sub_8(x, y, memory_order_seq_cst); |
| 203 | } |
| 204 | static inline unsigned long long atomic_fetch_and_u64(unsigned long long* x, unsigned long long y) { |
| 205 | return __atomic_fetch_and_8(x, y, memory_order_seq_cst); |
| 206 | } |
| 207 | static inline unsigned long long atomic_fetch_or_u64(unsigned long long* x, unsigned long long y) { |
| 208 | return __atomic_fetch_or_8(x, y, memory_order_seq_cst); |
| 209 | } |
| 210 | static inline unsigned long long atomic_fetch_xor_u64(unsigned long long* x, unsigned long long y) { |
| 211 | return __atomic_fetch_xor_8(x, y, memory_order_seq_cst); |
| 212 | } |
| 213 | |
| 214 | static inline unsigned atomic_load_u32(unsigned* x) { |
| 215 | return __atomic_load_4(x, memory_order_seq_cst); |
| 216 | } |
| 217 | static inline void atomic_store_u32(unsigned* x, unsigned y) { |
| 218 | __atomic_store_4(x, y, memory_order_seq_cst); |
| 219 | } |
| 220 | static inline int atomic_compare_exchange_weak_u32(unsigned* x, unsigned* expected, unsigned y) { |
| 221 | return (int)__atomic_compare_exchange_4(x, expected, y, memory_order_seq_cst, memory_order_seq_cst); |
| 222 | } |
| 223 | static inline int atomic_compare_exchange_strong_u32(unsigned* x, unsigned* expected, unsigned y) { |
| 224 | return (int)__atomic_compare_exchange_4(x, expected, y, memory_order_seq_cst, memory_order_seq_cst); |
| 225 | } |
| 226 | static inline unsigned atomic_exchange_u32(unsigned* x, unsigned y) { |
| 227 | return __atomic_exchange_4(x, y, memory_order_seq_cst); |
| 228 | } |
| 229 | static inline unsigned atomic_fetch_add_u32(unsigned* x, unsigned y) { |
| 230 | return __atomic_fetch_add_4(x, y, memory_order_seq_cst); |
| 231 | } |
| 232 | static inline unsigned atomic_fetch_sub_u32(unsigned* x, unsigned y) { |
| 233 | return __atomic_fetch_sub_4(x, y, memory_order_seq_cst); |
| 234 | } |
| 235 | static inline unsigned atomic_fetch_and_u32(unsigned* x, unsigned y) { |
| 236 | return __atomic_fetch_and_4(x, y, memory_order_seq_cst); |
| 237 | } |
| 238 | static inline unsigned atomic_fetch_or_u32(unsigned* x, unsigned y) { |
| 239 | return __atomic_fetch_or_4(x, y, memory_order_seq_cst); |
| 240 | } |
| 241 | static inline unsigned atomic_fetch_xor_u32(unsigned* x, unsigned y) { |
| 242 | return __atomic_fetch_xor_4(x, y, memory_order_seq_cst); |
| 243 | } |
| 244 | |
| 245 | static inline unsigned short atomic_load_u16(unsigned short* x) { |
| 246 | return __atomic_load_2(x, memory_order_seq_cst); |
| 247 | } |
| 248 | static inline void atomic_store_u16(void* x, unsigned short y) { |
| 249 | __atomic_store_2(x, y, memory_order_seq_cst); |
| 250 | } |
| 251 | static inline int atomic_compare_exchange_weak_u16(void* x, unsigned short* expected, unsigned short y) { |
| 252 | return (int)__atomic_compare_exchange_2(x, expected, y, memory_order_seq_cst, memory_order_seq_cst); |
| 253 | } |
| 254 | static inline int atomic_compare_exchange_strong_u16(unsigned short* x, unsigned short* expected, unsigned short y) { |
| 255 | return (int)__atomic_compare_exchange_2(x, expected, y, memory_order_seq_cst, memory_order_seq_cst); |
| 256 | } |
| 257 | static inline unsigned short atomic_exchange_u16(unsigned short* x, unsigned short y) { |
| 258 | return __atomic_exchange_2(x, y, memory_order_seq_cst); |
| 259 | } |
| 260 | static inline unsigned short atomic_fetch_add_u16(unsigned short* x, unsigned short y) { |
| 261 | return __atomic_fetch_add_2(x, y, memory_order_seq_cst); |
| 262 | } |
| 263 | static inline unsigned short atomic_fetch_sub_u16(unsigned short* x, unsigned short y) { |
| 264 | return __atomic_fetch_sub_2(x, y, memory_order_seq_cst); |
| 265 | } |
| 266 | static inline unsigned short atomic_fetch_and_u16(unsigned short* x, unsigned short y) { |
| 267 | return __atomic_fetch_and_2(x, y, memory_order_seq_cst); |
| 268 | } |
| 269 | static inline unsigned short atomic_fetch_or_u16(unsigned short* x, unsigned short y) { |
| 270 | return __atomic_fetch_or_2(x, y, memory_order_seq_cst); |
| 271 | } |
| 272 | static inline unsigned short atomic_fetch_xor_u16(unsigned short* x, unsigned short y) { |
| 273 | return __atomic_fetch_xor_2(x, y, memory_order_seq_cst); |
| 274 | } |
| 275 | |
| 276 | static inline unsigned char atomic_load_byte(unsigned char* x) { |
| 277 | return __atomic_load_1(x, memory_order_seq_cst); |
| 278 | } |
| 279 | static inline void atomic_store_byte(unsigned char* x, unsigned char y) { |
| 280 | __atomic_store_1(x, y, memory_order_seq_cst); |
| 281 | } |
| 282 | static inline int atomic_compare_exchange_weak_byte(unsigned char* x, unsigned char* expected, unsigned char y) { |
| 283 | return __atomic_compare_exchange_1(x, expected, y, memory_order_seq_cst, memory_order_seq_cst); |
| 284 | } |
| 285 | static inline int atomic_compare_exchange_strong_byte(unsigned char* x, unsigned char* expected, unsigned char y) { |
| 286 | return __atomic_compare_exchange_1(x, expected, y, memory_order_seq_cst, memory_order_seq_cst); |
| 287 | } |
| 288 | static inline unsigned char atomic_exchange_byte(unsigned char* x, unsigned char y) { |
| 289 | return __atomic_exchange_1(x, y, memory_order_seq_cst); |
| 290 | } |
| 291 | static inline unsigned char atomic_fetch_add_byte(unsigned char* x, unsigned char y) { |
| 292 | return __atomic_fetch_add_1(x, y, memory_order_seq_cst); |
| 293 | } |
| 294 | static inline unsigned char atomic_fetch_sub_byte(unsigned char* x, unsigned char y) { |
| 295 | return __atomic_fetch_sub_1(x, y, memory_order_seq_cst); |
| 296 | } |
| 297 | static inline unsigned char atomic_fetch_and_byte(unsigned char* x, unsigned char y) { |
| 298 | return __atomic_fetch_and_1(x, y, memory_order_seq_cst); |
| 299 | } |
| 300 | static inline unsigned char atomic_fetch_or_byte(unsigned char* x, unsigned char y) { |
| 301 | return __atomic_fetch_or_1(x, y, memory_order_seq_cst); |
| 302 | } |
| 303 | static inline unsigned char atomic_fetch_xor_byte(unsigned char* x, unsigned char y) { |
| 304 | return __atomic_fetch_xor_1(x, y, memory_order_seq_cst); |
| 305 | } |
| 306 | |
| 307 | #ifdef __aarch64__ |
| 308 | // must has an `extern` to link with libatomic.a |
| 309 | |
| 310 | // acq_rel version |
| 311 | extern inline _Bool __aarch64_cas1_acq_rel(unsigned char*ptr, unsigned char*expected, unsigned char desired) { |
| 312 | return __atomic_compare_exchange_1( |
| 313 | ptr, |
| 314 | expected, |
| 315 | desired, |
| 316 | memory_order_acq_rel, |
| 317 | memory_order_acquire |
| 318 | ); |
| 319 | } |
| 320 | |
| 321 | extern inline _Bool __aarch64_cas2_acq_rel(unsigned short*ptr, unsigned short*expected, unsigned short desired) { |
| 322 | return __atomic_compare_exchange_2( |
| 323 | ptr, |
| 324 | expected, |
| 325 | desired, |
| 326 | memory_order_acq_rel, |
| 327 | memory_order_acquire |
| 328 | ); |
| 329 | } |
| 330 | |
| 331 | extern inline _Bool __aarch64_cas4_acq_rel(unsigned int*ptr, unsigned int*expected, unsigned int desired) { |
| 332 | return __atomic_compare_exchange_4( |
| 333 | ptr, |
| 334 | expected, |
| 335 | desired, |
| 336 | memory_order_acq_rel, |
| 337 | memory_order_acquire |
| 338 | ); |
| 339 | } |
| 340 | |
| 341 | extern inline _Bool __aarch64_cas8_acq_rel(unsigned long long*ptr, unsigned long long*expected, unsigned long long desired) { |
| 342 | return __atomic_compare_exchange_8( |
| 343 | ptr, |
| 344 | expected, |
| 345 | desired, |
| 346 | memory_order_acq_rel, |
| 347 | memory_order_acquire |
| 348 | ); |
| 349 | } |
| 350 | |
| 351 | extern inline char __aarch64_ldadd1_acq_rel(char*ptr, char value) { |
| 352 | return __atomic_fetch_add_1( |
| 353 | (unsigned char*)ptr, |
| 354 | (unsigned char)value, |
| 355 | memory_order_acq_rel |
| 356 | ); |
| 357 | } |
| 358 | |
| 359 | extern inline short __aarch64_ldadd2_acq_rel(short*ptr, short value) { |
| 360 | return __atomic_fetch_add_2( |
| 361 | (unsigned short*)ptr, |
| 362 | (unsigned short)value, |
| 363 | memory_order_acq_rel |
| 364 | ); |
| 365 | } |
| 366 | |
| 367 | extern inline int __aarch64_ldadd4_acq_rel(int*ptr, int value) { |
| 368 | return __atomic_fetch_add_4( |
| 369 | (unsigned int*)ptr, |
| 370 | (unsigned int)value, |
| 371 | memory_order_acq_rel |
| 372 | ); |
| 373 | } |
| 374 | |
| 375 | extern inline long long __aarch64_ldadd8_acq_rel(long long*ptr, long long value) { |
| 376 | return __atomic_fetch_add_8( |
| 377 | (unsigned long long*)ptr, |
| 378 | (unsigned long long)value, |
| 379 | memory_order_acq_rel |
| 380 | ); |
| 381 | } |
| 382 | |
| 383 | extern inline unsigned char __aarch64_swp1_acq_rel(unsigned char*ptr, unsigned char newval) { |
| 384 | return __atomic_exchange_1( |
| 385 | ptr, |
| 386 | newval, |
| 387 | memory_order_acq_rel |
| 388 | ); |
| 389 | } |
| 390 | |
| 391 | extern inline unsigned short __aarch64_swp2_acq_rel(unsigned short*ptr, unsigned short newval) { |
| 392 | return __atomic_exchange_2( |
| 393 | ptr, |
| 394 | newval, |
| 395 | memory_order_acq_rel |
| 396 | ); |
| 397 | } |
| 398 | |
| 399 | extern inline unsigned int __aarch64_swp4_acq_rel(unsigned int*ptr, unsigned int newval) { |
| 400 | return __atomic_exchange_4( |
| 401 | ptr, |
| 402 | newval, |
| 403 | memory_order_acq_rel |
| 404 | ); |
| 405 | } |
| 406 | |
| 407 | extern inline unsigned long long __aarch64_swp8_acq_rel(unsigned long long*ptr, unsigned long long newval) { |
| 408 | return __atomic_exchange_8( |
| 409 | ptr, |
| 410 | newval, |
| 411 | memory_order_acq_rel |
| 412 | ); |
| 413 | } |
| 414 | |
| 415 | extern inline unsigned char __aarch64_ldclr1_acq_rel(unsigned char*ptr, unsigned char mask) { |
| 416 | return __atomic_fetch_and_1( |
| 417 | ptr, |
| 418 | ~mask, |
| 419 | memory_order_acq_rel |
| 420 | ); |
| 421 | } |
| 422 | |
| 423 | extern inline unsigned short __aarch64_ldclr2_acq_rel(unsigned short*ptr, unsigned short mask) { |
| 424 | return __atomic_fetch_and_2( |
| 425 | ptr, |
| 426 | ~mask, |
| 427 | memory_order_acq_rel |
| 428 | ); |
| 429 | } |
| 430 | |
| 431 | extern inline unsigned int __aarch64_ldclr4_acq_rel(unsigned int*ptr, unsigned int mask) { |
| 432 | return __atomic_fetch_and_4( |
| 433 | ptr, |
| 434 | ~mask, |
| 435 | memory_order_acq_rel |
| 436 | ); |
| 437 | } |
| 438 | |
| 439 | extern inline unsigned long long __aarch64_ldclr8_acq_rel(unsigned long long*ptr, unsigned long long mask) { |
| 440 | return __atomic_fetch_and_8( |
| 441 | ptr, |
| 442 | ~mask, |
| 443 | memory_order_acq_rel |
| 444 | ); |
| 445 | } |
| 446 | |
| 447 | extern inline unsigned char __aarch64_ldset1_acq_rel(unsigned char*ptr, unsigned char mask) { |
| 448 | return __atomic_fetch_or_1( |
| 449 | ptr, |
| 450 | mask, |
| 451 | memory_order_acq_rel |
| 452 | ); |
| 453 | } |
| 454 | |
| 455 | extern inline unsigned short __aarch64_ldset2_acq_rel(unsigned short*ptr, unsigned short mask) { |
| 456 | return __atomic_fetch_or_2( |
| 457 | ptr, |
| 458 | mask, |
| 459 | memory_order_acq_rel |
| 460 | ); |
| 461 | } |
| 462 | |
| 463 | extern inline unsigned int __aarch64_ldset4_acq_rel(unsigned int*ptr, unsigned int mask) { |
| 464 | return __atomic_fetch_or_4( |
| 465 | ptr, |
| 466 | mask, |
| 467 | memory_order_acq_rel |
| 468 | ); |
| 469 | } |
| 470 | |
| 471 | extern inline unsigned long long __aarch64_ldset8_acq_rel(unsigned long long*ptr, unsigned long long mask) { |
| 472 | return __atomic_fetch_or_8( |
| 473 | ptr, |
| 474 | mask, |
| 475 | memory_order_acq_rel |
| 476 | ); |
| 477 | } |
| 478 | |
| 479 | extern inline unsigned char __aarch64_ldeor1_acq_rel(unsigned char*ptr, unsigned char mask) { |
| 480 | return __atomic_fetch_xor_1( |
| 481 | ptr, |
| 482 | mask, |
| 483 | memory_order_acq_rel |
| 484 | ); |
| 485 | } |
| 486 | |
| 487 | extern inline unsigned short __aarch64_ldeor2_acq_rel(unsigned short*ptr, unsigned short mask) { |
| 488 | return __atomic_fetch_xor_2( |
| 489 | ptr, |
| 490 | mask, |
| 491 | memory_order_acq_rel |
| 492 | ); |
| 493 | } |
| 494 | |
| 495 | extern inline unsigned int __aarch64_ldeor4_acq_rel(unsigned int*ptr, unsigned int mask) { |
| 496 | return __atomic_fetch_xor_4( |
| 497 | ptr, |
| 498 | mask, |
| 499 | memory_order_acq_rel |
| 500 | ); |
| 501 | } |
| 502 | |
| 503 | extern inline unsigned long long __aarch64_ldeor8_acq_rel(unsigned long long*ptr, unsigned long long mask) { |
| 504 | return __atomic_fetch_xor_8( |
| 505 | ptr, |
| 506 | mask, |
| 507 | memory_order_acq_rel |
| 508 | ); |
| 509 | } |
| 510 | |
| 511 | // relax version |
| 512 | extern inline _Bool __aarch64_cas1_relax(unsigned char*ptr, unsigned char*expected, unsigned char desired) { |
| 513 | return __atomic_compare_exchange_1( |
| 514 | ptr, |
| 515 | expected, |
| 516 | desired, |
| 517 | memory_order_relaxed, |
| 518 | memory_order_relaxed |
| 519 | ); |
| 520 | } |
| 521 | |
| 522 | extern inline _Bool __aarch64_cas2_relax(unsigned short*ptr, unsigned short*expected, unsigned short desired) { |
| 523 | return __atomic_compare_exchange_2( |
| 524 | ptr, |
| 525 | expected, |
| 526 | desired, |
| 527 | memory_order_relaxed, |
| 528 | memory_order_relaxed |
| 529 | ); |
| 530 | } |
| 531 | |
| 532 | extern inline _Bool __aarch64_cas4_relax(unsigned int*ptr, unsigned int*expected, unsigned int desired) { |
| 533 | return __atomic_compare_exchange_4( |
| 534 | ptr, |
| 535 | expected, |
| 536 | desired, |
| 537 | memory_order_relaxed, |
| 538 | memory_order_relaxed |
| 539 | ); |
| 540 | } |
| 541 | |
| 542 | extern inline _Bool __aarch64_cas8_relax(unsigned long long*ptr, unsigned long long*expected, unsigned long long desired) { |
| 543 | return __atomic_compare_exchange_8( |
| 544 | ptr, |
| 545 | expected, |
| 546 | desired, |
| 547 | memory_order_relaxed, |
| 548 | memory_order_relaxed |
| 549 | ); |
| 550 | } |
| 551 | |
| 552 | extern inline char __aarch64_ldadd1_relax(char*ptr, char value) { |
| 553 | return __atomic_fetch_add_1( |
| 554 | (unsigned char*)ptr, |
| 555 | (unsigned char)value, |
| 556 | memory_order_relaxed |
| 557 | ); |
| 558 | } |
| 559 | |
| 560 | extern inline short __aarch64_ldadd2_relax(short*ptr, short value) { |
| 561 | return __atomic_fetch_add_2( |
| 562 | (unsigned short*)ptr, |
| 563 | (unsigned short)value, |
| 564 | memory_order_relaxed |
| 565 | ); |
| 566 | } |
| 567 | |
| 568 | extern inline int __aarch64_ldadd4_relax(int*ptr, int value) { |
| 569 | return __atomic_fetch_add_4( |
| 570 | (unsigned int*)ptr, |
| 571 | (unsigned int)value, |
| 572 | memory_order_relaxed |
| 573 | ); |
| 574 | } |
| 575 | |
| 576 | extern inline long long __aarch64_ldadd8_relax(long long*ptr, long long value) { |
| 577 | return __atomic_fetch_add_8( |
| 578 | (unsigned long long*)ptr, |
| 579 | (unsigned long long)value, |
| 580 | memory_order_relaxed |
| 581 | ); |
| 582 | } |
| 583 | |
| 584 | extern inline unsigned char __aarch64_swp1_relax(unsigned char*ptr, unsigned char newval) { |
| 585 | return __atomic_exchange_1( |
| 586 | ptr, |
| 587 | newval, |
| 588 | memory_order_relaxed |
| 589 | ); |
| 590 | } |
| 591 | |
| 592 | extern inline unsigned short __aarch64_swp2_relax(unsigned short*ptr, unsigned short newval) { |
| 593 | return __atomic_exchange_2( |
| 594 | ptr, |
| 595 | newval, |
| 596 | memory_order_relaxed |
| 597 | ); |
| 598 | } |
| 599 | |
| 600 | extern inline unsigned int __aarch64_swp4_relax(unsigned int*ptr, unsigned int newval) { |
| 601 | return __atomic_exchange_4( |
| 602 | ptr, |
| 603 | newval, |
| 604 | memory_order_relaxed |
| 605 | ); |
| 606 | } |
| 607 | |
| 608 | extern inline unsigned long long __aarch64_swp8_relax(unsigned long long*ptr, unsigned long long newval) { |
| 609 | return __atomic_exchange_8( |
| 610 | ptr, |
| 611 | newval, |
| 612 | memory_order_relaxed |
| 613 | ); |
| 614 | } |
| 615 | |
| 616 | extern inline unsigned char __aarch64_ldclr1_relax(unsigned char*ptr, unsigned char mask) { |
| 617 | return __atomic_fetch_and_1( |
| 618 | ptr, |
| 619 | ~mask, |
| 620 | memory_order_relaxed |
| 621 | ); |
| 622 | } |
| 623 | |
| 624 | extern inline unsigned short __aarch64_ldclr2_relax(unsigned short*ptr, unsigned short mask) { |
| 625 | return __atomic_fetch_and_2( |
| 626 | ptr, |
| 627 | ~mask, |
| 628 | memory_order_relaxed |
| 629 | ); |
| 630 | } |
| 631 | |
| 632 | extern inline unsigned int __aarch64_ldclr4_relax(unsigned int*ptr, unsigned int mask) { |
| 633 | return __atomic_fetch_and_4( |
| 634 | ptr, |
| 635 | ~mask, |
| 636 | memory_order_relaxed |
| 637 | ); |
| 638 | } |
| 639 | |
| 640 | extern inline unsigned long long __aarch64_ldclr8_relax(unsigned long long*ptr, unsigned long long mask) { |
| 641 | return __atomic_fetch_and_8( |
| 642 | ptr, |
| 643 | ~mask, |
| 644 | memory_order_relaxed |
| 645 | ); |
| 646 | } |
| 647 | |
| 648 | extern inline unsigned char __aarch64_ldset1_relax(unsigned char*ptr, unsigned char mask) { |
| 649 | return __atomic_fetch_or_1( |
| 650 | ptr, |
| 651 | mask, |
| 652 | memory_order_relaxed |
| 653 | ); |
| 654 | } |
| 655 | |
| 656 | extern inline unsigned short __aarch64_ldset2_relax(unsigned short*ptr, unsigned short mask) { |
| 657 | return __atomic_fetch_or_2( |
| 658 | ptr, |
| 659 | mask, |
| 660 | memory_order_relaxed |
| 661 | ); |
| 662 | } |
| 663 | |
| 664 | extern inline unsigned int __aarch64_ldset4_relax(unsigned int*ptr, unsigned int mask) { |
| 665 | return __atomic_fetch_or_4( |
| 666 | ptr, |
| 667 | mask, |
| 668 | memory_order_relaxed |
| 669 | ); |
| 670 | } |
| 671 | |
| 672 | extern inline unsigned long long __aarch64_ldset8_relax(unsigned long long*ptr, unsigned long long mask) { |
| 673 | return __atomic_fetch_or_8( |
| 674 | ptr, |
| 675 | mask, |
| 676 | memory_order_relaxed |
| 677 | ); |
| 678 | } |
| 679 | |
| 680 | extern inline unsigned char __aarch64_ldeor1_relax(unsigned char*ptr, unsigned char mask) { |
| 681 | return __atomic_fetch_xor_1( |
| 682 | ptr, |
| 683 | mask, |
| 684 | memory_order_relaxed |
| 685 | ); |
| 686 | } |
| 687 | |
| 688 | extern inline unsigned short __aarch64_ldeor2_relax(unsigned short*ptr, unsigned short mask) { |
| 689 | return __atomic_fetch_xor_2( |
| 690 | ptr, |
| 691 | mask, |
| 692 | memory_order_relaxed |
| 693 | ); |
| 694 | } |
| 695 | |
| 696 | extern inline unsigned int __aarch64_ldeor4_relax(unsigned int*ptr, unsigned int mask) { |
| 697 | return __atomic_fetch_xor_4( |
| 698 | ptr, |
| 699 | mask, |
| 700 | memory_order_relaxed |
| 701 | ); |
| 702 | } |
| 703 | |
| 704 | extern inline unsigned long long __aarch64_ldeor8_relax(unsigned long long*ptr, unsigned long long mask) { |
| 705 | return __atomic_fetch_xor_8( |
| 706 | ptr, |
| 707 | mask, |
| 708 | memory_order_relaxed |
| 709 | ); |
| 710 | } |
| 711 | |
| 712 | #endif // __aarch64__ |
| 713 | |
| 714 | #else |
| 715 | |
| 716 | // Since V might be confused with "generic" C functions either we provide special versions |
| 717 | // for gcc/clang, too |
| 718 | static inline unsigned long long atomic_load_u64(uint64_t* x) { |
| 719 | return atomic_load_explicit((_Atomic (uint64_t)*)x, memory_order_seq_cst); |
| 720 | } |
| 721 | static inline void atomic_store_u64(uint64_t* x, uint64_t y) { |
| 722 | atomic_store_explicit((_Atomic(uint64_t)*)x, y, memory_order_seq_cst); |
| 723 | } |
| 724 | static inline int atomic_compare_exchange_weak_u64(uint64_t* x, uint64_t* expected, uint64_t y) { |
| 725 | return (int)atomic_compare_exchange_weak_explicit((_Atomic(uint64_t)*)x, expected, y, memory_order_seq_cst, memory_order_seq_cst); |
| 726 | } |
| 727 | static inline int atomic_compare_exchange_strong_u64(uint64_t* x, uint64_t* expected, uint64_t y) { |
| 728 | return (int)atomic_compare_exchange_strong_explicit((_Atomic(uint64_t)*)x, expected, y, memory_order_seq_cst, memory_order_seq_cst); |
| 729 | } |
| 730 | static inline unsigned long long atomic_exchange_u64(uint64_t* x, uint64_t y) { |
| 731 | return atomic_exchange_explicit((_Atomic(uint64_t)*)x, y, memory_order_seq_cst); |
| 732 | } |
| 733 | static inline unsigned long long atomic_fetch_add_u64(uint64_t* x, uint64_t y) { |
| 734 | return atomic_fetch_add_explicit((_Atomic(uint64_t)*)x, y, memory_order_seq_cst); |
| 735 | } |
| 736 | static inline unsigned long long atomic_fetch_sub_u64(uint64_t* x, uint64_t y) { |
| 737 | return atomic_fetch_sub_explicit((_Atomic(uint64_t)*)x, y, memory_order_seq_cst); |
| 738 | } |
| 739 | static inline unsigned long long atomic_fetch_and_u64(uint64_t* x, uint64_t y) { |
| 740 | return atomic_fetch_and_explicit((_Atomic(uint64_t)*)x, y, memory_order_seq_cst); |
| 741 | } |
| 742 | static inline unsigned long long atomic_fetch_or_u64(uint64_t* x, uint64_t y) { |
| 743 | return atomic_fetch_or_explicit((_Atomic(uint64_t)*)x, y, memory_order_seq_cst); |
| 744 | } |
| 745 | static inline unsigned long long atomic_fetch_xor_u64(uint64_t* x, uint64_t y) { |
| 746 | return atomic_fetch_xor_explicit((_Atomic(uint64_t)*)x, y, memory_order_seq_cst); |
| 747 | } |
| 748 | |
| 749 | |
| 750 | static inline void* atomic_load_ptr(void** x) { |
| 751 | return (void*)atomic_load_explicit((_Atomic(uintptr_t)*)x, memory_order_seq_cst); |
| 752 | } |
| 753 | static inline void atomic_store_ptr(void** x, void* y) { |
| 754 | atomic_store_explicit((_Atomic(uintptr_t)*)x, (uintptr_t)y, memory_order_seq_cst); |
| 755 | } |
| 756 | static inline int atomic_compare_exchange_weak_ptr(void** x, void** expected, intptr_t y) { |
| 757 | 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); |
| 758 | } |
| 759 | static inline int atomic_compare_exchange_strong_ptr(void** x, void** expected, intptr_t y) { |
| 760 | 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); |
| 761 | } |
| 762 | static inline void* atomic_exchange_ptr(void** x, void* y) { |
| 763 | return (void*)atomic_exchange_explicit((_Atomic(uintptr_t)*)x, (uintptr_t)y, memory_order_seq_cst); |
| 764 | } |
| 765 | static inline void* atomic_fetch_add_ptr(void** x, void* y) { |
| 766 | return (void*)atomic_fetch_add_explicit((_Atomic(uintptr_t)*)x, (uintptr_t)y, memory_order_seq_cst); |
| 767 | } |
| 768 | static inline void* atomic_fetch_sub_ptr(void** x, void* y) { |
| 769 | return (void*)atomic_fetch_sub_explicit((_Atomic(uintptr_t)*)x, (uintptr_t)y, memory_order_seq_cst); |
| 770 | } |
| 771 | static inline void* atomic_fetch_and_ptr(void** x, void* y) { |
| 772 | return (void*)atomic_fetch_and_explicit((_Atomic(uintptr_t)*)x, (uintptr_t)y, memory_order_seq_cst); |
| 773 | } |
| 774 | static inline void* atomic_fetch_or_ptr(void** x, void* y) { |
| 775 | return (void*)atomic_fetch_or_explicit((_Atomic(uintptr_t)*)x, (uintptr_t)y, memory_order_seq_cst); |
| 776 | } |
| 777 | static inline void* atomic_fetch_xor_ptr(void** x, void* y) { |
| 778 | return (void*)atomic_fetch_xor_explicit((_Atomic(uintptr_t)*)x, (uintptr_t)y, memory_order_seq_cst); |
| 779 | } |
| 780 | |
| 781 | |
| 782 | static inline unsigned atomic_load_u32(unsigned* x) { |
| 783 | return atomic_load_explicit((_Atomic(unsigned)*)x, memory_order_seq_cst); |
| 784 | } |
| 785 | static inline void atomic_store_u32(unsigned* x, unsigned y) { |
| 786 | atomic_store_explicit((_Atomic(unsigned)*)x, y, memory_order_seq_cst); |
| 787 | } |
| 788 | static inline int atomic_compare_exchange_weak_u32(unsigned* x, unsigned* expected, unsigned y) { |
| 789 | return (int)atomic_compare_exchange_weak_explicit((_Atomic(unsigned)*)x, expected, y, memory_order_seq_cst, memory_order_seq_cst); |
| 790 | } |
| 791 | static inline int atomic_compare_exchange_strong_u32(unsigned* x, unsigned* expected, unsigned y) { |
| 792 | return (int)atomic_compare_exchange_strong_explicit((_Atomic(unsigned)*)x, expected, y, memory_order_seq_cst, memory_order_seq_cst); |
| 793 | } |
| 794 | static inline unsigned atomic_exchange_u32(unsigned* x, unsigned y) { |
| 795 | return atomic_exchange_explicit((_Atomic(unsigned)*)x, y, memory_order_seq_cst); |
| 796 | } |
| 797 | static inline unsigned atomic_fetch_add_u32(unsigned* x, unsigned y) { |
| 798 | return atomic_fetch_add_explicit((_Atomic(unsigned)*)x, y, memory_order_seq_cst); |
| 799 | } |
| 800 | static inline unsigned atomic_fetch_sub_u32(unsigned* x, unsigned y) { |
| 801 | return atomic_fetch_sub_explicit((_Atomic(unsigned)*)x, y, memory_order_seq_cst); |
| 802 | } |
| 803 | static inline unsigned atomic_fetch_and_u32(unsigned* x, unsigned y) { |
| 804 | return atomic_fetch_and_explicit((_Atomic(unsigned)*)x, y, memory_order_seq_cst); |
| 805 | } |
| 806 | static inline unsigned atomic_fetch_or_u32(unsigned* x, unsigned y) { |
| 807 | return atomic_fetch_or_explicit((_Atomic(unsigned)*)x, y, memory_order_seq_cst); |
| 808 | } |
| 809 | static inline unsigned atomic_fetch_xor_u32(unsigned* x, unsigned y) { |
| 810 | return atomic_fetch_xor_explicit((_Atomic(unsigned)*)x, y, memory_order_seq_cst); |
| 811 | } |
| 812 | |
| 813 | static inline unsigned short atomic_load_u16(unsigned short* x) { |
| 814 | return atomic_load_explicit((_Atomic(unsigned short)*)x, memory_order_seq_cst); |
| 815 | } |
| 816 | static inline void atomic_store_u16(void* x, unsigned short y) { |
| 817 | atomic_store_explicit((_Atomic(unsigned short)*)x, y, memory_order_seq_cst); |
| 818 | } |
| 819 | static inline int atomic_compare_exchange_weak_u16(void* x, unsigned short* expected, unsigned short y) { |
| 820 | return (int)atomic_compare_exchange_weak_explicit((_Atomic(unsigned short)*)x, expected, y, memory_order_seq_cst, memory_order_seq_cst); |
| 821 | } |
| 822 | static inline int atomic_compare_exchange_strong_u16(unsigned short* x, unsigned short* expected, unsigned short y) { |
| 823 | return (int)atomic_compare_exchange_strong_explicit((_Atomic(unsigned short)*)x, expected, y, memory_order_seq_cst, memory_order_seq_cst); |
| 824 | } |
| 825 | static inline unsigned short atomic_exchange_u16(unsigned short* x, unsigned short y) { |
| 826 | return atomic_exchange_explicit((_Atomic(unsigned short)*)x, y, memory_order_seq_cst); |
| 827 | } |
| 828 | static inline unsigned short atomic_fetch_add_u16(unsigned short* x, unsigned short y) { |
| 829 | return atomic_fetch_add_explicit((_Atomic(unsigned short)*)x, y, memory_order_seq_cst); |
| 830 | } |
| 831 | static inline unsigned short atomic_fetch_sub_u16(unsigned short* x, unsigned short y) { |
| 832 | return atomic_fetch_sub_explicit((_Atomic(unsigned short)*)x, y, memory_order_seq_cst); |
| 833 | } |
| 834 | static inline unsigned short atomic_fetch_and_u16(unsigned short* x, unsigned short y) { |
| 835 | return atomic_fetch_and_explicit((_Atomic(unsigned short)*)x, y, memory_order_seq_cst); |
| 836 | } |
| 837 | static inline unsigned short atomic_fetch_or_u16(unsigned short* x, unsigned short y) { |
| 838 | return atomic_fetch_or_explicit((_Atomic(unsigned short)*)x, y, memory_order_seq_cst); |
| 839 | } |
| 840 | static inline unsigned short atomic_fetch_xor_u16(unsigned short* x, unsigned short y) { |
| 841 | return atomic_fetch_xor_explicit((_Atomic(unsigned short)*)x, y, memory_order_seq_cst); |
| 842 | } |
| 843 | |
| 844 | static inline unsigned char atomic_load_byte(unsigned char* x) { |
| 845 | return atomic_load_explicit((_Atomic(unsigned char)*)x, memory_order_seq_cst); |
| 846 | } |
| 847 | static inline void atomic_store_byte(unsigned char* x, unsigned char y) { |
| 848 | atomic_store_explicit((_Atomic(unsigned char)*)x, y, memory_order_seq_cst); |
| 849 | } |
| 850 | static inline int atomic_compare_exchange_weak_byte(unsigned char* x, unsigned char* expected, unsigned char y) { |
| 851 | return (int)atomic_compare_exchange_weak_explicit((_Atomic(unsigned char)*)x, expected, y, memory_order_seq_cst, memory_order_seq_cst); |
| 852 | } |
| 853 | static inline int atomic_compare_exchange_strong_byte(unsigned char* x, unsigned char* expected, unsigned char y) { |
| 854 | return (int)atomic_compare_exchange_strong_explicit((_Atomic(unsigned char)*)x, expected, y, memory_order_seq_cst, memory_order_seq_cst); |
| 855 | } |
| 856 | static inline unsigned char atomic_exchange_byte(unsigned char* x, unsigned char y) { |
| 857 | return atomic_exchange_explicit((_Atomic(unsigned char)*)x, y, memory_order_seq_cst); |
| 858 | } |
| 859 | static inline unsigned char atomic_fetch_add_byte(unsigned char* x, unsigned char y) { |
| 860 | return atomic_fetch_add_explicit((_Atomic(unsigned char)*)x, y, memory_order_seq_cst); |
| 861 | } |
| 862 | static inline unsigned char atomic_fetch_sub_byte(unsigned char* x, unsigned char y) { |
| 863 | return atomic_fetch_sub_explicit((_Atomic(unsigned char)*)x, y, memory_order_seq_cst); |
| 864 | } |
| 865 | static inline unsigned char atomic_fetch_and_byte(unsigned char* x, unsigned char y) { |
| 866 | return atomic_fetch_and_explicit((_Atomic(unsigned char)*)x, y, memory_order_seq_cst); |
| 867 | } |
| 868 | static inline unsigned char atomic_fetch_or_byte(unsigned char* x, unsigned char y) { |
| 869 | return atomic_fetch_or_explicit((_Atomic(unsigned char)*)x, y, memory_order_seq_cst); |
| 870 | } |
| 871 | static inline unsigned char atomic_fetch_xor_byte(unsigned char* x, unsigned char y) { |
| 872 | return atomic_fetch_xor_explicit((_Atomic(unsigned char)*)x, y, memory_order_seq_cst); |
| 873 | } |
| 874 | |
| 875 | #endif |
| 876 | #endif |
| 877 | |