xref: /freebsd/contrib/jemalloc/include/jemalloc/internal/atomic.h (revision c43cad87172039ccf38172129c79755ea79e6102)
1b7eaed25SJason Evans #ifndef JEMALLOC_INTERNAL_ATOMIC_H
2b7eaed25SJason Evans #define JEMALLOC_INTERNAL_ATOMIC_H
3a4bd5210SJason Evans 
4c5ad8142SEric van Gyzen #define ATOMIC_INLINE JEMALLOC_ALWAYS_INLINE
5a4bd5210SJason Evans 
6c5ad8142SEric van Gyzen #define JEMALLOC_U8_ATOMICS
7b7eaed25SJason Evans #if defined(JEMALLOC_GCC_ATOMIC_ATOMICS)
8b7eaed25SJason Evans #  include "jemalloc/internal/atomic_gcc_atomic.h"
9c5ad8142SEric van Gyzen #  if !defined(JEMALLOC_GCC_U8_ATOMIC_ATOMICS)
10c5ad8142SEric van Gyzen #    undef JEMALLOC_U8_ATOMICS
11c5ad8142SEric van Gyzen #  endif
12b7eaed25SJason Evans #elif defined(JEMALLOC_GCC_SYNC_ATOMICS)
13b7eaed25SJason Evans #  include "jemalloc/internal/atomic_gcc_sync.h"
14c5ad8142SEric van Gyzen #  if !defined(JEMALLOC_GCC_U8_SYNC_ATOMICS)
15c5ad8142SEric van Gyzen #    undef JEMALLOC_U8_ATOMICS
16c5ad8142SEric van Gyzen #  endif
17b7eaed25SJason Evans #elif defined(_MSC_VER)
18b7eaed25SJason Evans #  include "jemalloc/internal/atomic_msvc.h"
19b7eaed25SJason Evans #elif defined(JEMALLOC_C11_ATOMICS)
20b7eaed25SJason Evans #  include "jemalloc/internal/atomic_c11.h"
21b7eaed25SJason Evans #else
22b7eaed25SJason Evans #  error "Don't have atomics implemented on this platform."
23b7eaed25SJason Evans #endif
24a4bd5210SJason Evans 
25d0e79aa3SJason Evans /*
26b7eaed25SJason Evans  * This header gives more or less a backport of C11 atomics. The user can write
27b7eaed25SJason Evans  * JEMALLOC_GENERATE_ATOMICS(type, short_type, lg_sizeof_type); to generate
28b7eaed25SJason Evans  * counterparts of the C11 atomic functions for type, as so:
29b7eaed25SJason Evans  *   JEMALLOC_GENERATE_ATOMICS(int *, pi, 3);
30b7eaed25SJason Evans  * and then write things like:
31b7eaed25SJason Evans  *   int *some_ptr;
32b7eaed25SJason Evans  *   atomic_pi_t atomic_ptr_to_int;
33b7eaed25SJason Evans  *   atomic_store_pi(&atomic_ptr_to_int, some_ptr, ATOMIC_RELAXED);
34b7eaed25SJason Evans  *   int *prev_value = atomic_exchange_pi(&ptr_to_int, NULL, ATOMIC_ACQ_REL);
35b7eaed25SJason Evans  *   assert(some_ptr == prev_value);
36b7eaed25SJason Evans  * and expect things to work in the obvious way.
37d0e79aa3SJason Evans  *
38b7eaed25SJason Evans  * Also included (with naming differences to avoid conflicts with the standard
39b7eaed25SJason Evans  * library):
40b7eaed25SJason Evans  *   atomic_fence(atomic_memory_order_t) (mimics C11's atomic_thread_fence).
41b7eaed25SJason Evans  *   ATOMIC_INIT (mimics C11's ATOMIC_VAR_INIT).
42d0e79aa3SJason Evans  */
43d0e79aa3SJason Evans 
44c92c6224SJason Evans /*
45b7eaed25SJason Evans  * Pure convenience, so that we don't have to type "atomic_memory_order_"
46b7eaed25SJason Evans  * quite so often.
47c92c6224SJason Evans  */
48b7eaed25SJason Evans #define ATOMIC_RELAXED atomic_memory_order_relaxed
49b7eaed25SJason Evans #define ATOMIC_ACQUIRE atomic_memory_order_acquire
50b7eaed25SJason Evans #define ATOMIC_RELEASE atomic_memory_order_release
51b7eaed25SJason Evans #define ATOMIC_ACQ_REL atomic_memory_order_acq_rel
52b7eaed25SJason Evans #define ATOMIC_SEQ_CST atomic_memory_order_seq_cst
53c92c6224SJason Evans 
54b7eaed25SJason Evans /*
55*c43cad87SWarner Losh  * Another convenience -- simple atomic helper functions.
56*c43cad87SWarner Losh  */
57*c43cad87SWarner Losh #define JEMALLOC_GENERATE_EXPANDED_INT_ATOMICS(type, short_type,	\
58*c43cad87SWarner Losh     lg_size)								\
59*c43cad87SWarner Losh     JEMALLOC_GENERATE_INT_ATOMICS(type, short_type, lg_size)		\
60*c43cad87SWarner Losh     ATOMIC_INLINE void							\
61*c43cad87SWarner Losh     atomic_load_add_store_##short_type(atomic_##short_type##_t *a,	\
62*c43cad87SWarner Losh 	type inc) {							\
63*c43cad87SWarner Losh 	    type oldval = atomic_load_##short_type(a, ATOMIC_RELAXED);	\
64*c43cad87SWarner Losh 	    type newval = oldval + inc;					\
65*c43cad87SWarner Losh 	    atomic_store_##short_type(a, newval, ATOMIC_RELAXED);	\
66*c43cad87SWarner Losh 	}								\
67*c43cad87SWarner Losh     ATOMIC_INLINE void							\
68*c43cad87SWarner Losh     atomic_load_sub_store_##short_type(atomic_##short_type##_t *a,	\
69*c43cad87SWarner Losh 	type inc) {							\
70*c43cad87SWarner Losh 	    type oldval = atomic_load_##short_type(a, ATOMIC_RELAXED);	\
71*c43cad87SWarner Losh 	    type newval = oldval - inc;					\
72*c43cad87SWarner Losh 	    atomic_store_##short_type(a, newval, ATOMIC_RELAXED);	\
73*c43cad87SWarner Losh 	}
74*c43cad87SWarner Losh 
75*c43cad87SWarner Losh /*
76b7eaed25SJason Evans  * Not all platforms have 64-bit atomics.  If we do, this #define exposes that
77b7eaed25SJason Evans  * fact.
78b7eaed25SJason Evans  */
79b7eaed25SJason Evans #if (LG_SIZEOF_PTR == 3 || LG_SIZEOF_INT == 3)
80b7eaed25SJason Evans #  define JEMALLOC_ATOMIC_U64
81a4bd5210SJason Evans #endif
82a4bd5210SJason Evans 
83b7eaed25SJason Evans JEMALLOC_GENERATE_ATOMICS(void *, p, LG_SIZEOF_PTR)
84a4bd5210SJason Evans 
85b7eaed25SJason Evans /*
86b7eaed25SJason Evans  * There's no actual guarantee that sizeof(bool) == 1, but it's true on the only
87b7eaed25SJason Evans  * platform that actually needs to know the size, MSVC.
88b7eaed25SJason Evans  */
89b7eaed25SJason Evans JEMALLOC_GENERATE_ATOMICS(bool, b, 0)
90a4bd5210SJason Evans 
91*c43cad87SWarner Losh JEMALLOC_GENERATE_EXPANDED_INT_ATOMICS(unsigned, u, LG_SIZEOF_INT)
92a4bd5210SJason Evans 
93*c43cad87SWarner Losh JEMALLOC_GENERATE_EXPANDED_INT_ATOMICS(size_t, zu, LG_SIZEOF_PTR)
94a4bd5210SJason Evans 
95*c43cad87SWarner Losh JEMALLOC_GENERATE_EXPANDED_INT_ATOMICS(ssize_t, zd, LG_SIZEOF_PTR)
96a4bd5210SJason Evans 
97*c43cad87SWarner Losh JEMALLOC_GENERATE_EXPANDED_INT_ATOMICS(uint8_t, u8, 0)
98c5ad8142SEric van Gyzen 
99*c43cad87SWarner Losh JEMALLOC_GENERATE_EXPANDED_INT_ATOMICS(uint32_t, u32, 2)
100d0e79aa3SJason Evans 
101b7eaed25SJason Evans #ifdef JEMALLOC_ATOMIC_U64
102*c43cad87SWarner Losh JEMALLOC_GENERATE_EXPANDED_INT_ATOMICS(uint64_t, u64, 3)
103a4bd5210SJason Evans #endif
104a4bd5210SJason Evans 
105b7eaed25SJason Evans #undef ATOMIC_INLINE
106d0e79aa3SJason Evans 
107b7eaed25SJason Evans #endif /* JEMALLOC_INTERNAL_ATOMIC_H */
108