v2 / thirdparty / stdatomic / nix / atomic.h
876 lines · 791 sloc · 33.87 KB · 0412ba36ee67b5b025187af0e7c6361fa71d438f
Raw
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
50typedef volatile long long atomic_llong;
51typedef volatile unsigned long long atomic_ullong;
52typedef volatile uintptr_t atomic_uintptr_t;
53
54extern void atomic_thread_fence (int memory_order);
55extern 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
66extern unsigned long long __atomic_load_8(unsigned long long* x, int mo);
67extern void __atomic_store_8(unsigned long long* x, unsigned long long y, int mo);
68extern _Bool __atomic_compare_exchange_8(unsigned long long* x, unsigned long long* expected, unsigned long long y, int mo, int mo2);
69extern unsigned long long __atomic_exchange_8(unsigned long long* x, unsigned long long y, int mo);
70extern unsigned long long __atomic_fetch_add_8(unsigned long long* x, unsigned long long y, int mo);
71extern unsigned long long __atomic_fetch_sub_8(unsigned long long* x, unsigned long long y, int mo);
72extern unsigned long long __atomic_fetch_and_8(unsigned long long* x, unsigned long long y, int mo);
73extern unsigned long long __atomic_fetch_or_8(unsigned long long* x, unsigned long long y, int mo);
74extern unsigned long long __atomic_fetch_xor_8(unsigned long long* x, unsigned long long y, int mo);
75
76extern unsigned int __atomic_load_4(unsigned int* x, int mo);
77extern void __atomic_store_4(unsigned int* x, unsigned int y, int mo);
78extern _Bool __atomic_compare_exchange_4(unsigned int* x, unsigned int* expected, unsigned int y, int mo, int mo2);
79extern unsigned int __atomic_exchange_4(unsigned int* x, unsigned int y, int mo);
80extern unsigned int __atomic_fetch_add_4(unsigned int* x, unsigned int y, int mo);
81extern unsigned int __atomic_fetch_sub_4(unsigned int* x, unsigned int y, int mo);
82extern unsigned int __atomic_fetch_and_4(unsigned int* x, unsigned int y, int mo);
83extern unsigned int __atomic_fetch_or_4(unsigned int* x, unsigned int y, int mo);
84extern unsigned int __atomic_fetch_xor_4(unsigned int* x, unsigned int y, int mo);
85
86extern unsigned short __atomic_load_2(unsigned short* x, int mo);
87extern void __atomic_store_2(unsigned short* x, unsigned short y, int mo);
88extern _Bool __atomic_compare_exchange_2(unsigned short* x, unsigned short* expected, unsigned short y, int mo, int mo2);
89extern unsigned short __atomic_exchange_2(unsigned short* x, unsigned short y, int mo);
90extern unsigned short __atomic_fetch_add_2(unsigned short* x, unsigned short y, int mo);
91extern unsigned short __atomic_fetch_sub_2(unsigned short* x, unsigned short y, int mo);
92extern unsigned short __atomic_fetch_and_2(unsigned short* x, unsigned short y, int mo);
93extern unsigned short __atomic_fetch_or_2(unsigned short* x, unsigned short y, int mo);
94extern unsigned short __atomic_fetch_xor_2(unsigned short* x, unsigned short y, int mo);
95
96extern unsigned char __atomic_load_1(unsigned char* x, int mo);
97extern void __atomic_store_1(unsigned char* x, unsigned char y, int mo);
98extern _Bool __atomic_compare_exchange_1(unsigned char* x, unsigned char* expected, unsigned char y, int mo, int mo2);
99extern unsigned char __atomic_exchange_1(unsigned char* x, unsigned char y, int mo);
100extern unsigned char __atomic_fetch_add_1(unsigned char* x, unsigned char y, int mo);
101extern unsigned char __atomic_fetch_sub_1(unsigned char* x, unsigned char y, int mo);
102extern unsigned char __atomic_fetch_and_1(unsigned char* x, unsigned char y, int mo);
103extern unsigned char __atomic_fetch_or_1(unsigned char* x, unsigned char y, int mo);
104extern 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
139static inline void** atomic_load(void** x) {
140 return (void**)atomic_load_explicit((unsigned long long*)x, memory_order_seq_cst);
141}
142static inline void atomic_store(void** x, void* y) {
143 atomic_store_explicit((unsigned long long*)x, (uintptr_t)y, memory_order_seq_cst);
144}
145static 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}
148static 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}
151static 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}
154static 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}
157static 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}
160static 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}
163static 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}
166static 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
183static inline unsigned long long atomic_load_u64(unsigned long long* x) {
184 return __atomic_load_8(x, memory_order_seq_cst);
185}
186static inline void atomic_store_u64(unsigned long long* x, unsigned long long y) {
187 __atomic_store_8(x, y, memory_order_seq_cst);
188}
189static 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}
192static 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}
195static 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}
198static 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}
201static 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}
204static 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}
207static 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}
210static 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
214static inline unsigned atomic_load_u32(unsigned* x) {
215 return __atomic_load_4(x, memory_order_seq_cst);
216}
217static inline void atomic_store_u32(unsigned* x, unsigned y) {
218 __atomic_store_4(x, y, memory_order_seq_cst);
219}
220static 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}
223static 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}
226static inline unsigned atomic_exchange_u32(unsigned* x, unsigned y) {
227 return __atomic_exchange_4(x, y, memory_order_seq_cst);
228}
229static inline unsigned atomic_fetch_add_u32(unsigned* x, unsigned y) {
230 return __atomic_fetch_add_4(x, y, memory_order_seq_cst);
231}
232static inline unsigned atomic_fetch_sub_u32(unsigned* x, unsigned y) {
233 return __atomic_fetch_sub_4(x, y, memory_order_seq_cst);
234}
235static inline unsigned atomic_fetch_and_u32(unsigned* x, unsigned y) {
236 return __atomic_fetch_and_4(x, y, memory_order_seq_cst);
237}
238static inline unsigned atomic_fetch_or_u32(unsigned* x, unsigned y) {
239 return __atomic_fetch_or_4(x, y, memory_order_seq_cst);
240}
241static inline unsigned atomic_fetch_xor_u32(unsigned* x, unsigned y) {
242 return __atomic_fetch_xor_4(x, y, memory_order_seq_cst);
243}
244
245static inline unsigned short atomic_load_u16(unsigned short* x) {
246 return __atomic_load_2(x, memory_order_seq_cst);
247}
248static inline void atomic_store_u16(void* x, unsigned short y) {
249 __atomic_store_2(x, y, memory_order_seq_cst);
250}
251static 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}
254static 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}
257static inline unsigned short atomic_exchange_u16(unsigned short* x, unsigned short y) {
258 return __atomic_exchange_2(x, y, memory_order_seq_cst);
259}
260static 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}
263static 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}
266static 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}
269static 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}
272static 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
276static inline unsigned char atomic_load_byte(unsigned char* x) {
277 return __atomic_load_1(x, memory_order_seq_cst);
278}
279static inline void atomic_store_byte(unsigned char* x, unsigned char y) {
280 __atomic_store_1(x, y, memory_order_seq_cst);
281}
282static 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}
285static 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}
288static inline unsigned char atomic_exchange_byte(unsigned char* x, unsigned char y) {
289 return __atomic_exchange_1(x, y, memory_order_seq_cst);
290}
291static 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}
294static 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}
297static 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}
300static 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}
303static 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
311extern 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
321extern 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
331extern 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
341extern 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
351extern 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
359extern 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
367extern 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
375extern 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
383extern 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
391extern 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
399extern 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
407extern 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
415extern 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
423extern 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
431extern 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
439extern 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
447extern 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
455extern 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
463extern 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
471extern 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
479extern 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
487extern 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
495extern 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
503extern 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
512extern 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
522extern 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
532extern 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
542extern 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
552extern 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
560extern 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
568extern 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
576extern 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
584extern 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
592extern 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
600extern 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
608extern 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
616extern 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
624extern 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
632extern 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
640extern 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
648extern 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
656extern 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
664extern 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
672extern 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
680extern 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
688extern 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
696extern 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
704extern 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
718static inline unsigned long long atomic_load_u64(uint64_t* x) {
719 return atomic_load_explicit((_Atomic (uint64_t)*)x, memory_order_seq_cst);
720}
721static 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}
724static 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}
727static 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}
730static 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}
733static 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}
736static 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}
739static 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}
742static 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}
745static 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
750static inline void* atomic_load_ptr(void** x) {
751 return (void*)atomic_load_explicit((_Atomic(uintptr_t)*)x, memory_order_seq_cst);
752}
753static 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}
756static 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}
759static 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}
762static 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}
765static 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}
768static 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}
771static 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}
774static 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}
777static 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
782static inline unsigned atomic_load_u32(unsigned* x) {
783 return atomic_load_explicit((_Atomic(unsigned)*)x, memory_order_seq_cst);
784}
785static inline void atomic_store_u32(unsigned* x, unsigned y) {
786 atomic_store_explicit((_Atomic(unsigned)*)x, y, memory_order_seq_cst);
787}
788static 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}
791static 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}
794static inline unsigned atomic_exchange_u32(unsigned* x, unsigned y) {
795 return atomic_exchange_explicit((_Atomic(unsigned)*)x, y, memory_order_seq_cst);
796}
797static 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}
800static 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}
803static 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}
806static 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}
809static 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
813static inline unsigned short atomic_load_u16(unsigned short* x) {
814 return atomic_load_explicit((_Atomic(unsigned short)*)x, memory_order_seq_cst);
815}
816static inline void atomic_store_u16(void* x, unsigned short y) {
817 atomic_store_explicit((_Atomic(unsigned short)*)x, y, memory_order_seq_cst);
818}
819static 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}
822static 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}
825static 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}
828static 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}
831static 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}
834static 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}
837static 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}
840static 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
844static inline unsigned char atomic_load_byte(unsigned char* x) {
845 return atomic_load_explicit((_Atomic(unsigned char)*)x, memory_order_seq_cst);
846}
847static 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}
850static 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}
853static 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}
856static 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}
859static 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}
862static 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}
865static 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}
868static 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}
871static 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