1#ifndef JEMALLOC_INTERNAL_ATOMIC_C11_H
2#define JEMALLOC_INTERNAL_ATOMIC_C11_H
3
4#include <stdatomic.h>
5
6#define ATOMIC_INIT(...) ATOMIC_VAR_INIT(__VA_ARGS__)
7
8#define atomic_memory_order_t memory_order
9#define atomic_memory_order_relaxed memory_order_relaxed
10#define atomic_memory_order_acquire memory_order_acquire
11#define atomic_memory_order_release memory_order_release
12#define atomic_memory_order_acq_rel memory_order_acq_rel
13#define atomic_memory_order_seq_cst memory_order_seq_cst
14
15#define atomic_fence atomic_thread_fence
16
17#define JEMALLOC_GENERATE_ATOMICS(type, short_type,			\
18    /* unused */ lg_size)						\
19typedef _Atomic(type) atomic_##short_type##_t;				\
20									\
21ATOMIC_INLINE type							\
22atomic_load_##short_type(const atomic_##short_type##_t *a,		\
23    atomic_memory_order_t mo) {						\
24	/*								\
25	 * A strict interpretation of the C standard prevents		\
26	 * atomic_load from taking a const argument, but it's		\
27	 * convenient for our purposes. This cast is a workaround.	\
28	 */								\
29	atomic_##short_type##_t* a_nonconst =				\
30	    (atomic_##short_type##_t*)(_Atomic void *)(_Atomic uintptr_t)(a);			\
31	return atomic_load_explicit(a_nonconst, mo);			\
32}									\
33									\
34ATOMIC_INLINE void							\
35atomic_store_##short_type(atomic_##short_type##_t *a,			\
36    type val, atomic_memory_order_t mo) {				\
37	atomic_store_explicit(a, val, mo);				\
38}									\
39									\
40ATOMIC_INLINE type							\
41atomic_exchange_##short_type(atomic_##short_type##_t *a, type val,	\
42    atomic_memory_order_t mo) {						\
43	return atomic_exchange_explicit(a, val, mo);			\
44}									\
45									\
46ATOMIC_INLINE bool							\
47atomic_compare_exchange_weak_##short_type(atomic_##short_type##_t *a,	\
48    type *expected, type desired, atomic_memory_order_t success_mo,	\
49    atomic_memory_order_t failure_mo) {					\
50	return atomic_compare_exchange_weak_explicit(a, expected,	\
51	    desired, success_mo, failure_mo);				\
52}									\
53									\
54ATOMIC_INLINE bool							\
55atomic_compare_exchange_strong_##short_type(atomic_##short_type##_t *a,	\
56    type *expected, type desired, atomic_memory_order_t success_mo,	\
57    atomic_memory_order_t failure_mo) {					\
58	return atomic_compare_exchange_strong_explicit(a, expected,	\
59	    desired, success_mo, failure_mo);				\
60}
61
62/*
63 * Integral types have some special operations available that non-integral ones
64 * lack.
65 */
66#define JEMALLOC_GENERATE_INT_ATOMICS(type, short_type, 		\
67    /* unused */ lg_size)						\
68JEMALLOC_GENERATE_ATOMICS(type, short_type, /* unused */ lg_size)	\
69									\
70ATOMIC_INLINE type							\
71atomic_fetch_add_##short_type(atomic_##short_type##_t *a,		\
72    type val, atomic_memory_order_t mo) {				\
73	return atomic_fetch_add_explicit(a, val, mo);			\
74}									\
75									\
76ATOMIC_INLINE type							\
77atomic_fetch_sub_##short_type(atomic_##short_type##_t *a,		\
78    type val, atomic_memory_order_t mo) {				\
79	return atomic_fetch_sub_explicit(a, val, mo);			\
80}									\
81ATOMIC_INLINE type							\
82atomic_fetch_and_##short_type(atomic_##short_type##_t *a,		\
83    type val, atomic_memory_order_t mo) {				\
84	return atomic_fetch_and_explicit(a, val, mo);			\
85}									\
86ATOMIC_INLINE type							\
87atomic_fetch_or_##short_type(atomic_##short_type##_t *a,		\
88    type val, atomic_memory_order_t mo) {				\
89	return atomic_fetch_or_explicit(a, val, mo);			\
90}									\
91ATOMIC_INLINE type							\
92atomic_fetch_xor_##short_type(atomic_##short_type##_t *a,		\
93    type val, atomic_memory_order_t mo) {				\
94	return atomic_fetch_xor_explicit(a, val, mo);			\
95}
96
97#endif /* JEMALLOC_INTERNAL_ATOMIC_C11_H */
98