123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 |
- #ifndef JEMALLOC_INTERNAL_ATOMIC_H
- #define JEMALLOC_INTERNAL_ATOMIC_H
- #define ATOMIC_INLINE JEMALLOC_ALWAYS_INLINE
- #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
- /*
- * 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 */
|