Blame jemalloc/include/jemalloc/internal/atomic_msvc.h

Packit 345191
#ifndef JEMALLOC_INTERNAL_ATOMIC_MSVC_H
Packit 345191
#define JEMALLOC_INTERNAL_ATOMIC_MSVC_H
Packit 345191
Packit 345191
#define ATOMIC_INIT(...) {__VA_ARGS__}
Packit 345191
Packit 345191
typedef enum {
Packit 345191
	atomic_memory_order_relaxed,
Packit 345191
	atomic_memory_order_acquire,
Packit 345191
	atomic_memory_order_release,
Packit 345191
	atomic_memory_order_acq_rel,
Packit 345191
	atomic_memory_order_seq_cst
Packit 345191
} atomic_memory_order_t;
Packit 345191
Packit 345191
typedef char atomic_repr_0_t;
Packit 345191
typedef short atomic_repr_1_t;
Packit 345191
typedef long atomic_repr_2_t;
Packit 345191
typedef __int64 atomic_repr_3_t;
Packit 345191
Packit 345191
ATOMIC_INLINE void
Packit 345191
atomic_fence(atomic_memory_order_t mo) {
Packit 345191
	_ReadWriteBarrier();
Packit 345191
#  if defined(_M_ARM) || defined(_M_ARM64)
Packit 345191
	/* ARM needs a barrier for everything but relaxed. */
Packit 345191
	if (mo != atomic_memory_order_relaxed) {
Packit 345191
		MemoryBarrier();
Packit 345191
	}
Packit 345191
#  elif defined(_M_IX86) || defined (_M_X64)
Packit 345191
	/* x86 needs a barrier only for seq_cst. */
Packit 345191
	if (mo == atomic_memory_order_seq_cst) {
Packit 345191
		MemoryBarrier();
Packit 345191
	}
Packit 345191
#  else
Packit 345191
#  error "Don't know how to create atomics for this platform for MSVC."
Packit 345191
#  endif
Packit 345191
	_ReadWriteBarrier();
Packit 345191
}
Packit 345191
Packit 345191
#define ATOMIC_INTERLOCKED_REPR(lg_size) atomic_repr_ ## lg_size ## _t
Packit 345191
Packit 345191
#define ATOMIC_CONCAT(a, b) ATOMIC_RAW_CONCAT(a, b)
Packit 345191
#define ATOMIC_RAW_CONCAT(a, b) a ## b
Packit 345191
Packit 345191
#define ATOMIC_INTERLOCKED_NAME(base_name, lg_size) ATOMIC_CONCAT(	\
Packit 345191
    base_name, ATOMIC_INTERLOCKED_SUFFIX(lg_size))
Packit 345191
Packit 345191
#define ATOMIC_INTERLOCKED_SUFFIX(lg_size)				\
Packit 345191
    ATOMIC_CONCAT(ATOMIC_INTERLOCKED_SUFFIX_, lg_size)
Packit 345191
Packit 345191
#define ATOMIC_INTERLOCKED_SUFFIX_0 8
Packit 345191
#define ATOMIC_INTERLOCKED_SUFFIX_1 16
Packit 345191
#define ATOMIC_INTERLOCKED_SUFFIX_2
Packit 345191
#define ATOMIC_INTERLOCKED_SUFFIX_3 64
Packit 345191
Packit 345191
#define JEMALLOC_GENERATE_ATOMICS(type, short_type, lg_size)		\
Packit 345191
typedef struct {							\
Packit 345191
	ATOMIC_INTERLOCKED_REPR(lg_size) repr;				\
Packit 345191
} atomic_##short_type##_t;						\
Packit 345191
									\
Packit 345191
ATOMIC_INLINE type							\
Packit 345191
atomic_load_##short_type(const atomic_##short_type##_t *a,		\
Packit 345191
    atomic_memory_order_t mo) {						\
Packit 345191
	ATOMIC_INTERLOCKED_REPR(lg_size) ret = a->repr;			\
Packit 345191
	if (mo != atomic_memory_order_relaxed) {			\
Packit 345191
		atomic_fence(atomic_memory_order_acquire);		\
Packit 345191
	}								\
Packit 345191
	return (type) ret;						\
Packit 345191
}									\
Packit 345191
									\
Packit 345191
ATOMIC_INLINE void							\
Packit 345191
atomic_store_##short_type(atomic_##short_type##_t *a,			\
Packit 345191
    type val, atomic_memory_order_t mo) {				\
Packit 345191
	if (mo != atomic_memory_order_relaxed) {			\
Packit 345191
		atomic_fence(atomic_memory_order_release);		\
Packit 345191
	}								\
Packit 345191
	a->repr = (ATOMIC_INTERLOCKED_REPR(lg_size)) val;		\
Packit 345191
	if (mo == atomic_memory_order_seq_cst) {			\
Packit 345191
		atomic_fence(atomic_memory_order_seq_cst);		\
Packit 345191
	}								\
Packit 345191
}									\
Packit 345191
									\
Packit 345191
ATOMIC_INLINE type							\
Packit 345191
atomic_exchange_##short_type(atomic_##short_type##_t *a, type val,	\
Packit 345191
    atomic_memory_order_t mo) {						\
Packit 345191
	return (type)ATOMIC_INTERLOCKED_NAME(_InterlockedExchange,	\
Packit 345191
	    lg_size)(&a->repr, (ATOMIC_INTERLOCKED_REPR(lg_size))val);	\
Packit 345191
}									\
Packit 345191
									\
Packit 345191
ATOMIC_INLINE bool							\
Packit 345191
atomic_compare_exchange_weak_##short_type(atomic_##short_type##_t *a,	\
Packit 345191
    type *expected, type desired, atomic_memory_order_t success_mo,	\
Packit 345191
    atomic_memory_order_t failure_mo) {					\
Packit 345191
	ATOMIC_INTERLOCKED_REPR(lg_size) e =				\
Packit 345191
	    (ATOMIC_INTERLOCKED_REPR(lg_size))*expected;		\
Packit 345191
	ATOMIC_INTERLOCKED_REPR(lg_size) d =				\
Packit 345191
	    (ATOMIC_INTERLOCKED_REPR(lg_size))desired;			\
Packit 345191
	ATOMIC_INTERLOCKED_REPR(lg_size) old =				\
Packit 345191
	    ATOMIC_INTERLOCKED_NAME(_InterlockedCompareExchange, 	\
Packit 345191
		lg_size)(&a->repr, d, e);				\
Packit 345191
	if (old == e) {							\
Packit 345191
		return true;						\
Packit 345191
	} else {							\
Packit 345191
		*expected = (type)old;					\
Packit 345191
		return false;						\
Packit 345191
	}								\
Packit 345191
}									\
Packit 345191
									\
Packit 345191
ATOMIC_INLINE bool							\
Packit 345191
atomic_compare_exchange_strong_##short_type(atomic_##short_type##_t *a,	\
Packit 345191
    type *expected, type desired, atomic_memory_order_t success_mo,	\
Packit 345191
    atomic_memory_order_t failure_mo) {					\
Packit 345191
	/* We implement the weak version with strong semantics. */	\
Packit 345191
	return atomic_compare_exchange_weak_##short_type(a, expected,	\
Packit 345191
	    desired, success_mo, failure_mo);				\
Packit 345191
}
Packit 345191
Packit 345191
Packit 345191
#define JEMALLOC_GENERATE_INT_ATOMICS(type, short_type, lg_size)	\
Packit 345191
JEMALLOC_GENERATE_ATOMICS(type, short_type, lg_size)			\
Packit 345191
									\
Packit 345191
ATOMIC_INLINE type							\
Packit 345191
atomic_fetch_add_##short_type(atomic_##short_type##_t *a,		\
Packit 345191
    type val, atomic_memory_order_t mo) {				\
Packit 345191
	return (type)ATOMIC_INTERLOCKED_NAME(_InterlockedExchangeAdd,	\
Packit 345191
	    lg_size)(&a->repr, (ATOMIC_INTERLOCKED_REPR(lg_size))val);	\
Packit 345191
}									\
Packit 345191
									\
Packit 345191
ATOMIC_INLINE type							\
Packit 345191
atomic_fetch_sub_##short_type(atomic_##short_type##_t *a,		\
Packit 345191
    type val, atomic_memory_order_t mo) {				\
Packit 345191
	/*								\
Packit 345191
	 * MSVC warns on negation of unsigned operands, but for us it	\
Packit 345191
	 * gives exactly the right semantics (MAX_TYPE + 1 - operand).	\
Packit 345191
	 */								\
Packit 345191
	__pragma(warning(push))						\
Packit 345191
	__pragma(warning(disable: 4146))				\
Packit 345191
	return atomic_fetch_add_##short_type(a, -val, mo);		\
Packit 345191
	__pragma(warning(pop))						\
Packit 345191
}									\
Packit 345191
ATOMIC_INLINE type							\
Packit 345191
atomic_fetch_and_##short_type(atomic_##short_type##_t *a,		\
Packit 345191
    type val, atomic_memory_order_t mo) {				\
Packit 345191
	return (type)ATOMIC_INTERLOCKED_NAME(_InterlockedAnd, lg_size)(	\
Packit 345191
	    &a->repr, (ATOMIC_INTERLOCKED_REPR(lg_size))val);		\
Packit 345191
}									\
Packit 345191
ATOMIC_INLINE type							\
Packit 345191
atomic_fetch_or_##short_type(atomic_##short_type##_t *a,		\
Packit 345191
    type val, atomic_memory_order_t mo) {				\
Packit 345191
	return (type)ATOMIC_INTERLOCKED_NAME(_InterlockedOr, lg_size)(	\
Packit 345191
	    &a->repr, (ATOMIC_INTERLOCKED_REPR(lg_size))val);		\
Packit 345191
}									\
Packit 345191
ATOMIC_INLINE type							\
Packit 345191
atomic_fetch_xor_##short_type(atomic_##short_type##_t *a,		\
Packit 345191
    type val, atomic_memory_order_t mo) {				\
Packit 345191
	return (type)ATOMIC_INTERLOCKED_NAME(_InterlockedXor, lg_size)(	\
Packit 345191
	    &a->repr, (ATOMIC_INTERLOCKED_REPR(lg_size))val);		\
Packit 345191
}
Packit 345191
Packit 345191
#endif /* JEMALLOC_INTERNAL_ATOMIC_MSVC_H */