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