#ifndef JEMALLOC_INTERNAL_ATOMIC_H #define JEMALLOC_INTERNAL_ATOMIC_H #include "jemalloc/internal/jemalloc_preamble.h" #define JEMALLOC_U8_ATOMICS #if defined(JEMALLOC_GCC_ATOMIC_ATOMICS) # include "jemalloc/internal/atomic_gcc_atomic.h" # if !defined(JEMALLOC_GCC_U8_ATOMIC_ATOMICS) # undef JEMALLOC_U8_ATOMICS # endif #elif defined(JEMALLOC_GCC_SYNC_ATOMICS) # include "jemalloc/internal/atomic_gcc_sync.h" # if !defined(JEMALLOC_GCC_U8_SYNC_ATOMICS) # undef JEMALLOC_U8_ATOMICS # endif #elif defined(_MSC_VER) # include "jemalloc/internal/atomic_msvc.h" #elif defined(JEMALLOC_C11_ATOMICS) # include "jemalloc/internal/atomic_c11.h" #else # error "Don't have atomics implemented on this platform." #endif #define ATOMIC_INLINE JEMALLOC_ALWAYS_INLINE /* * This header gives more or less a backport of C11 atomics. The user can write * JEMALLOC_GENERATE_ATOMICS(type, short_type, lg_sizeof_type); to generate * counterparts of the C11 atomic functions for type, as so: * JEMALLOC_GENERATE_ATOMICS(int *, pi, 3); * and then write things like: * int *some_ptr; * atomic_pi_t atomic_ptr_to_int; * atomic_store_pi(&atomic_ptr_to_int, some_ptr, ATOMIC_RELAXED); * int *prev_value = atomic_exchange_pi(&ptr_to_int, NULL, ATOMIC_ACQ_REL); * assert(some_ptr == prev_value); * and expect things to work in the obvious way. * * Also included (with naming differences to avoid conflicts with the standard * library): * atomic_fence(atomic_memory_order_t) (mimics C11's atomic_thread_fence). * ATOMIC_INIT (mimics C11's ATOMIC_VAR_INIT). */ /* * Pure convenience, so that we don't have to type "atomic_memory_order_" * quite so often. */ #define ATOMIC_RELAXED atomic_memory_order_relaxed #define ATOMIC_ACQUIRE atomic_memory_order_acquire #define ATOMIC_RELEASE atomic_memory_order_release #define ATOMIC_ACQ_REL atomic_memory_order_acq_rel #define ATOMIC_SEQ_CST atomic_memory_order_seq_cst /* * Another convenience -- simple atomic helper functions. */ #define JEMALLOC_GENERATE_EXPANDED_INT_ATOMICS(type, short_type, \ lg_size) \ JEMALLOC_GENERATE_INT_ATOMICS(type, short_type, lg_size) \ ATOMIC_INLINE void \ atomic_load_add_store_##short_type(atomic_##short_type##_t *a, \ type inc) { \ type oldval = atomic_load_##short_type(a, ATOMIC_RELAXED); \ type newval = oldval + inc; \ atomic_store_##short_type(a, newval, ATOMIC_RELAXED); \ } \ ATOMIC_INLINE void \ atomic_load_sub_store_##short_type(atomic_##short_type##_t *a, \ type inc) { \ type oldval = atomic_load_##short_type(a, ATOMIC_RELAXED); \ type newval = oldval - inc; \ atomic_store_##short_type(a, newval, ATOMIC_RELAXED); \ } /* * Not all platforms have 64-bit atomics. If we do, this #define exposes that * fact. */ #if (LG_SIZEOF_PTR == 3 || LG_SIZEOF_INT == 3) # define JEMALLOC_ATOMIC_U64 #endif JEMALLOC_GENERATE_ATOMICS(void *, p, LG_SIZEOF_PTR) /* * There's no actual guarantee that sizeof(bool) == 1, but it's true on the only * platform that actually needs to know the size, MSVC. */ JEMALLOC_GENERATE_ATOMICS(bool, b, 0) JEMALLOC_GENERATE_EXPANDED_INT_ATOMICS(unsigned, u, LG_SIZEOF_INT) JEMALLOC_GENERATE_EXPANDED_INT_ATOMICS(size_t, zu, LG_SIZEOF_PTR) JEMALLOC_GENERATE_EXPANDED_INT_ATOMICS(ssize_t, zd, LG_SIZEOF_PTR) JEMALLOC_GENERATE_EXPANDED_INT_ATOMICS(uint8_t, u8, 0) JEMALLOC_GENERATE_EXPANDED_INT_ATOMICS(uint32_t, u32, 2) #ifdef JEMALLOC_ATOMIC_U64 JEMALLOC_GENERATE_EXPANDED_INT_ATOMICS(uint64_t, u64, 3) #endif #undef ATOMIC_INLINE #endif /* JEMALLOC_INTERNAL_ATOMIC_H */