Implement more atomic operations.
- atomic_*_p(). - atomic_cas_*(). - atomic_write_*().
This commit is contained in:
parent
8ddc93293c
commit
a55dfa4b0a
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#define atomic_read_uint64(p) atomic_add_uint64(p, 0)
|
#define atomic_read_uint64(p) atomic_add_uint64(p, 0)
|
||||||
#define atomic_read_uint32(p) atomic_add_uint32(p, 0)
|
#define atomic_read_uint32(p) atomic_add_uint32(p, 0)
|
||||||
|
#define atomic_read_p(p) atomic_add_p(p, NULL)
|
||||||
#define atomic_read_z(p) atomic_add_z(p, 0)
|
#define atomic_read_z(p) atomic_add_z(p, 0)
|
||||||
#define atomic_read_u(p) atomic_add_u(p, 0)
|
#define atomic_read_u(p) atomic_add_u(p, 0)
|
||||||
|
|
||||||
@ -19,88 +20,54 @@
|
|||||||
#ifdef JEMALLOC_H_INLINES
|
#ifdef JEMALLOC_H_INLINES
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* All functions return the arithmetic result of the atomic operation. Some
|
* All arithmetic functions return the arithmetic result of the atomic
|
||||||
* atomic operation APIs return the value prior to mutation, in which case the
|
* operation. Some atomic operation APIs return the value prior to mutation, in
|
||||||
* following functions must redundantly compute the result so that it can be
|
* which case the following functions must redundantly compute the result so
|
||||||
* returned. These functions are normally inlined, so the extra operations can
|
* that it can be returned. These functions are normally inlined, so the extra
|
||||||
* be optimized away if the return values aren't used by the callers.
|
* operations can be optimized away if the return values aren't used by the
|
||||||
|
* callers.
|
||||||
*
|
*
|
||||||
|
* <t> atomic_read_<t>(<t> *p) { return (*p); }
|
||||||
* <t> atomic_add_<t>(<t> *p, <t> x) { return (*p + x); }
|
* <t> atomic_add_<t>(<t> *p, <t> x) { return (*p + x); }
|
||||||
* <t> atomic_sub_<t>(<t> *p, <t> x) { return (*p - x); }
|
* <t> atomic_sub_<t>(<t> *p, <t> x) { return (*p - x); }
|
||||||
|
* bool atomic_cas_<t>(<t> *p, <t> c, <t> s)
|
||||||
|
* {
|
||||||
|
* if (*p != c)
|
||||||
|
* return (true);
|
||||||
|
* *p = s;
|
||||||
|
* return (false);
|
||||||
|
* }
|
||||||
|
* void atomic_write_<t>(<t> *p, <t> x) { *p = x; }
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef JEMALLOC_ENABLE_INLINE
|
#ifndef JEMALLOC_ENABLE_INLINE
|
||||||
uint64_t atomic_add_uint64(uint64_t *p, uint64_t x);
|
uint64_t atomic_add_uint64(uint64_t *p, uint64_t x);
|
||||||
uint64_t atomic_sub_uint64(uint64_t *p, uint64_t x);
|
uint64_t atomic_sub_uint64(uint64_t *p, uint64_t x);
|
||||||
|
bool atomic_cas_uint64(uint64_t *p, uint64_t c, uint64_t s);
|
||||||
|
void atomic_write_uint64(uint64_t *p, uint64_t x);
|
||||||
uint32_t atomic_add_uint32(uint32_t *p, uint32_t x);
|
uint32_t atomic_add_uint32(uint32_t *p, uint32_t x);
|
||||||
uint32_t atomic_sub_uint32(uint32_t *p, uint32_t x);
|
uint32_t atomic_sub_uint32(uint32_t *p, uint32_t x);
|
||||||
|
bool atomic_cas_uint32(uint32_t *p, uint32_t c, uint32_t s);
|
||||||
|
void atomic_write_uint32(uint32_t *p, uint32_t x);
|
||||||
|
void *atomic_add_p(void **p, void *x);
|
||||||
|
void *atomic_sub_p(void **p, void *x);
|
||||||
|
bool atomic_cas_p(void **p, void *c, void *s);
|
||||||
|
void atomic_write_p(void **p, void *x);
|
||||||
size_t atomic_add_z(size_t *p, size_t x);
|
size_t atomic_add_z(size_t *p, size_t x);
|
||||||
size_t atomic_sub_z(size_t *p, size_t x);
|
size_t atomic_sub_z(size_t *p, size_t x);
|
||||||
|
bool atomic_cas_z(size_t *p, size_t c, size_t s);
|
||||||
|
void atomic_write_z(size_t *p, size_t x);
|
||||||
unsigned atomic_add_u(unsigned *p, unsigned x);
|
unsigned atomic_add_u(unsigned *p, unsigned x);
|
||||||
unsigned atomic_sub_u(unsigned *p, unsigned x);
|
unsigned atomic_sub_u(unsigned *p, unsigned x);
|
||||||
|
bool atomic_cas_u(unsigned *p, unsigned c, unsigned s);
|
||||||
|
void atomic_write_u(unsigned *p, unsigned x);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_ATOMIC_C_))
|
#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_ATOMIC_C_))
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/* 64-bit operations. */
|
/* 64-bit operations. */
|
||||||
#if (LG_SIZEOF_PTR == 3 || LG_SIZEOF_INT == 3)
|
#if (LG_SIZEOF_PTR == 3 || LG_SIZEOF_INT == 3)
|
||||||
# ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
|
# if (defined(__amd64__) || defined(__x86_64__))
|
||||||
JEMALLOC_INLINE uint64_t
|
|
||||||
atomic_add_uint64(uint64_t *p, uint64_t x)
|
|
||||||
{
|
|
||||||
|
|
||||||
return (__sync_add_and_fetch(p, x));
|
|
||||||
}
|
|
||||||
|
|
||||||
JEMALLOC_INLINE uint64_t
|
|
||||||
atomic_sub_uint64(uint64_t *p, uint64_t x)
|
|
||||||
{
|
|
||||||
|
|
||||||
return (__sync_sub_and_fetch(p, x));
|
|
||||||
}
|
|
||||||
# elif (defined(_MSC_VER))
|
|
||||||
JEMALLOC_INLINE uint64_t
|
|
||||||
atomic_add_uint64(uint64_t *p, uint64_t x)
|
|
||||||
{
|
|
||||||
|
|
||||||
return (InterlockedExchangeAdd64(p, x) + x);
|
|
||||||
}
|
|
||||||
|
|
||||||
JEMALLOC_INLINE uint64_t
|
|
||||||
atomic_sub_uint64(uint64_t *p, uint64_t x)
|
|
||||||
{
|
|
||||||
|
|
||||||
return (InterlockedExchangeAdd64(p, -((int64_t)x)) - x);
|
|
||||||
}
|
|
||||||
# elif (defined(JEMALLOC_C11ATOMICS))
|
|
||||||
JEMALLOC_INLINE uint64_t
|
|
||||||
atomic_add_uint64(uint64_t *p, uint64_t x)
|
|
||||||
{
|
|
||||||
volatile atomic_uint_least64_t *a = (volatile atomic_uint_least64_t *)p;
|
|
||||||
return (atomic_fetch_add(a, x) + x);
|
|
||||||
}
|
|
||||||
|
|
||||||
JEMALLOC_INLINE uint64_t
|
|
||||||
atomic_sub_uint64(uint64_t *p, uint64_t x)
|
|
||||||
{
|
|
||||||
volatile atomic_uint_least64_t *a = (volatile atomic_uint_least64_t *)p;
|
|
||||||
return (atomic_fetch_sub(a, x) - x);
|
|
||||||
}
|
|
||||||
# elif (defined(JEMALLOC_OSATOMIC))
|
|
||||||
JEMALLOC_INLINE uint64_t
|
|
||||||
atomic_add_uint64(uint64_t *p, uint64_t x)
|
|
||||||
{
|
|
||||||
|
|
||||||
return (OSAtomicAdd64((int64_t)x, (int64_t *)p));
|
|
||||||
}
|
|
||||||
|
|
||||||
JEMALLOC_INLINE uint64_t
|
|
||||||
atomic_sub_uint64(uint64_t *p, uint64_t x)
|
|
||||||
{
|
|
||||||
|
|
||||||
return (OSAtomicAdd64(-((int64_t)x), (int64_t *)p));
|
|
||||||
}
|
|
||||||
# elif (defined(__amd64__) || defined(__x86_64__))
|
|
||||||
JEMALLOC_INLINE uint64_t
|
JEMALLOC_INLINE uint64_t
|
||||||
atomic_add_uint64(uint64_t *p, uint64_t x)
|
atomic_add_uint64(uint64_t *p, uint64_t x)
|
||||||
{
|
{
|
||||||
@ -130,6 +97,62 @@ atomic_sub_uint64(uint64_t *p, uint64_t x)
|
|||||||
|
|
||||||
return (t + x);
|
return (t + x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE bool
|
||||||
|
atomic_cas_uint64(uint64_t *p, uint64_t c, uint64_t s)
|
||||||
|
{
|
||||||
|
uint8_t success;
|
||||||
|
|
||||||
|
asm volatile (
|
||||||
|
"lock; cmpxchgq %4, %0;"
|
||||||
|
"sete %1;"
|
||||||
|
: "=m" (*p), "=a" (success) /* Outputs. */
|
||||||
|
: "m" (*p), "a" (c), "r" (s) /* Inputs. */
|
||||||
|
: "memory" /* Clobbers. */
|
||||||
|
);
|
||||||
|
|
||||||
|
return (!(bool)success);
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE void
|
||||||
|
atomic_write_uint64(uint64_t *p, uint64_t x)
|
||||||
|
{
|
||||||
|
|
||||||
|
asm volatile (
|
||||||
|
"lock; xchgq %1, %0;"
|
||||||
|
: "=m" (*p), "+r" (x) /* Outputs. */
|
||||||
|
: "m" (*p) /* Inputs. */
|
||||||
|
: "memory" /* Clobbers. */
|
||||||
|
);
|
||||||
|
}
|
||||||
|
# elif (defined(JEMALLOC_C11ATOMICS))
|
||||||
|
JEMALLOC_INLINE uint64_t
|
||||||
|
atomic_add_uint64(uint64_t *p, uint64_t x)
|
||||||
|
{
|
||||||
|
volatile atomic_uint_least64_t *a = (volatile atomic_uint_least64_t *)p;
|
||||||
|
return (atomic_fetch_add(a, x) + x);
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE uint64_t
|
||||||
|
atomic_sub_uint64(uint64_t *p, uint64_t x)
|
||||||
|
{
|
||||||
|
volatile atomic_uint_least64_t *a = (volatile atomic_uint_least64_t *)p;
|
||||||
|
return (atomic_fetch_sub(a, x) - x);
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE bool
|
||||||
|
atomic_cas_uint64(uint64_t *p, uint64_t c, uint64_t s)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (!atomic_compare_exchange_strong(p, &c, s));
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE void
|
||||||
|
atomic_write_uint64(uint64_t *p, uint64_t x)
|
||||||
|
{
|
||||||
|
|
||||||
|
atomic_store(p, x);
|
||||||
|
}
|
||||||
# elif (defined(JEMALLOC_ATOMIC9))
|
# elif (defined(JEMALLOC_ATOMIC9))
|
||||||
JEMALLOC_INLINE uint64_t
|
JEMALLOC_INLINE uint64_t
|
||||||
atomic_add_uint64(uint64_t *p, uint64_t x)
|
atomic_add_uint64(uint64_t *p, uint64_t x)
|
||||||
@ -152,7 +175,88 @@ atomic_sub_uint64(uint64_t *p, uint64_t x)
|
|||||||
|
|
||||||
return (atomic_fetchadd_long(p, (unsigned long)(-(long)x)) - x);
|
return (atomic_fetchadd_long(p, (unsigned long)(-(long)x)) - x);
|
||||||
}
|
}
|
||||||
# elif (defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_8))
|
|
||||||
|
JEMALLOC_INLINE bool
|
||||||
|
atomic_cas_uint64(uint64_t *p, uint64_t c, uint64_t s)
|
||||||
|
{
|
||||||
|
|
||||||
|
assert(sizeof(uint64_t) == sizeof(unsigned long));
|
||||||
|
|
||||||
|
return (!atomic_cmpset_long(p, (unsigned long)c, (unsigned long)s));
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE void
|
||||||
|
atomic_write_uint64(uint64_t *p, uint64_t x)
|
||||||
|
{
|
||||||
|
|
||||||
|
assert(sizeof(uint64_t) == sizeof(unsigned long));
|
||||||
|
|
||||||
|
atomic_store_rel_long(p, x);
|
||||||
|
}
|
||||||
|
# elif (defined(JEMALLOC_OSATOMIC))
|
||||||
|
JEMALLOC_INLINE uint64_t
|
||||||
|
atomic_add_uint64(uint64_t *p, uint64_t x)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (OSAtomicAdd64((int64_t)x, (int64_t *)p));
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE uint64_t
|
||||||
|
atomic_sub_uint64(uint64_t *p, uint64_t x)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (OSAtomicAdd64(-((int64_t)x), (int64_t *)p));
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE bool
|
||||||
|
atomic_cas_uint64(uint64_t *p, uint64_t c, uint64_t s)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (!OSAtomicCompareAndSwap64(c, s, (int64_t *)p));
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE void
|
||||||
|
atomic_write_uint64(uint64_t *p, uint64_t x)
|
||||||
|
{
|
||||||
|
uint64_t o;
|
||||||
|
|
||||||
|
/*The documented OSAtomic*() API does not expose an atomic exchange. */
|
||||||
|
do {
|
||||||
|
o = atomic_read_uint64(p);
|
||||||
|
} while (atomic_cas_uint64(p, o, x));
|
||||||
|
}
|
||||||
|
# elif (defined(_MSC_VER))
|
||||||
|
JEMALLOC_INLINE uint64_t
|
||||||
|
atomic_add_uint64(uint64_t *p, uint64_t x)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (InterlockedExchangeAdd64(p, x) + x);
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE uint64_t
|
||||||
|
atomic_sub_uint64(uint64_t *p, uint64_t x)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (InterlockedExchangeAdd64(p, -((int64_t)x)) - x);
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE bool
|
||||||
|
atomic_cas_uint64(uint64_t *p, uint64_t c, uint64_t s)
|
||||||
|
{
|
||||||
|
uint64_t o;
|
||||||
|
|
||||||
|
o = InterlockedCompareExchange64(p, s, c);
|
||||||
|
return (o != c);
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE void
|
||||||
|
atomic_write_uint64(uint64_t *p, uint64_t x)
|
||||||
|
{
|
||||||
|
|
||||||
|
InterlockedExchange64(p, x);
|
||||||
|
}
|
||||||
|
# elif (defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8) || \
|
||||||
|
defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_8))
|
||||||
JEMALLOC_INLINE uint64_t
|
JEMALLOC_INLINE uint64_t
|
||||||
atomic_add_uint64(uint64_t *p, uint64_t x)
|
atomic_add_uint64(uint64_t *p, uint64_t x)
|
||||||
{
|
{
|
||||||
@ -166,6 +270,20 @@ atomic_sub_uint64(uint64_t *p, uint64_t x)
|
|||||||
|
|
||||||
return (__sync_sub_and_fetch(p, x));
|
return (__sync_sub_and_fetch(p, x));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE bool
|
||||||
|
atomic_cas_uint64(uint64_t *p, uint64_t c, uint64_t s)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (!__sync_bool_compare_and_swap(p, c, s));
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE void
|
||||||
|
atomic_write_uint64(uint64_t *p, uint64_t x)
|
||||||
|
{
|
||||||
|
|
||||||
|
__sync_lock_test_and_set(p, x);
|
||||||
|
}
|
||||||
# else
|
# else
|
||||||
# error "Missing implementation for 64-bit atomic operations"
|
# error "Missing implementation for 64-bit atomic operations"
|
||||||
# endif
|
# endif
|
||||||
@ -173,63 +291,7 @@ atomic_sub_uint64(uint64_t *p, uint64_t x)
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/* 32-bit operations. */
|
/* 32-bit operations. */
|
||||||
#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
|
#if (defined(__i386__) || defined(__amd64__) || defined(__x86_64__))
|
||||||
JEMALLOC_INLINE uint32_t
|
|
||||||
atomic_add_uint32(uint32_t *p, uint32_t x)
|
|
||||||
{
|
|
||||||
|
|
||||||
return (__sync_add_and_fetch(p, x));
|
|
||||||
}
|
|
||||||
|
|
||||||
JEMALLOC_INLINE uint32_t
|
|
||||||
atomic_sub_uint32(uint32_t *p, uint32_t x)
|
|
||||||
{
|
|
||||||
|
|
||||||
return (__sync_sub_and_fetch(p, x));
|
|
||||||
}
|
|
||||||
#elif (defined(_MSC_VER))
|
|
||||||
JEMALLOC_INLINE uint32_t
|
|
||||||
atomic_add_uint32(uint32_t *p, uint32_t x)
|
|
||||||
{
|
|
||||||
|
|
||||||
return (InterlockedExchangeAdd(p, x) + x);
|
|
||||||
}
|
|
||||||
|
|
||||||
JEMALLOC_INLINE uint32_t
|
|
||||||
atomic_sub_uint32(uint32_t *p, uint32_t x)
|
|
||||||
{
|
|
||||||
|
|
||||||
return (InterlockedExchangeAdd(p, -((int32_t)x)) - x);
|
|
||||||
}
|
|
||||||
# elif (defined(JEMALLOC_C11ATOMICS))
|
|
||||||
JEMALLOC_INLINE uint32_t
|
|
||||||
atomic_add_uint32(uint32_t *p, uint32_t x)
|
|
||||||
{
|
|
||||||
volatile atomic_uint_least32_t *a = (volatile atomic_uint_least32_t *)p;
|
|
||||||
return (atomic_fetch_add(a, x) + x);
|
|
||||||
}
|
|
||||||
|
|
||||||
JEMALLOC_INLINE uint32_t
|
|
||||||
atomic_sub_uint32(uint32_t *p, uint32_t x)
|
|
||||||
{
|
|
||||||
volatile atomic_uint_least32_t *a = (volatile atomic_uint_least32_t *)p;
|
|
||||||
return (atomic_fetch_sub(a, x) - x);
|
|
||||||
}
|
|
||||||
#elif (defined(JEMALLOC_OSATOMIC))
|
|
||||||
JEMALLOC_INLINE uint32_t
|
|
||||||
atomic_add_uint32(uint32_t *p, uint32_t x)
|
|
||||||
{
|
|
||||||
|
|
||||||
return (OSAtomicAdd32((int32_t)x, (int32_t *)p));
|
|
||||||
}
|
|
||||||
|
|
||||||
JEMALLOC_INLINE uint32_t
|
|
||||||
atomic_sub_uint32(uint32_t *p, uint32_t x)
|
|
||||||
{
|
|
||||||
|
|
||||||
return (OSAtomicAdd32(-((int32_t)x), (int32_t *)p));
|
|
||||||
}
|
|
||||||
#elif (defined(__i386__) || defined(__amd64__) || defined(__x86_64__))
|
|
||||||
JEMALLOC_INLINE uint32_t
|
JEMALLOC_INLINE uint32_t
|
||||||
atomic_add_uint32(uint32_t *p, uint32_t x)
|
atomic_add_uint32(uint32_t *p, uint32_t x)
|
||||||
{
|
{
|
||||||
@ -259,6 +321,62 @@ atomic_sub_uint32(uint32_t *p, uint32_t x)
|
|||||||
|
|
||||||
return (t + x);
|
return (t + x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE bool
|
||||||
|
atomic_cas_uint32(uint32_t *p, uint32_t c, uint32_t s)
|
||||||
|
{
|
||||||
|
uint8_t success;
|
||||||
|
|
||||||
|
asm volatile (
|
||||||
|
"lock; cmpxchgl %4, %0;"
|
||||||
|
"sete %1;"
|
||||||
|
: "=m" (*p), "=a" (success) /* Outputs. */
|
||||||
|
: "m" (*p), "a" (c), "r" (s) /* Inputs. */
|
||||||
|
: "memory"
|
||||||
|
);
|
||||||
|
|
||||||
|
return (!(bool)success);
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE void
|
||||||
|
atomic_write_uint32(uint32_t *p, uint32_t x)
|
||||||
|
{
|
||||||
|
|
||||||
|
asm volatile (
|
||||||
|
"lock; xchgl %1, %0;"
|
||||||
|
: "=m" (*p), "+r" (x) /* Outputs. */
|
||||||
|
: "m" (*p) /* Inputs. */
|
||||||
|
: "memory" /* Clobbers. */
|
||||||
|
);
|
||||||
|
}
|
||||||
|
# elif (defined(JEMALLOC_C11ATOMICS))
|
||||||
|
JEMALLOC_INLINE uint32_t
|
||||||
|
atomic_add_uint32(uint32_t *p, uint32_t x)
|
||||||
|
{
|
||||||
|
volatile atomic_uint_least32_t *a = (volatile atomic_uint_least32_t *)p;
|
||||||
|
return (atomic_fetch_add(a, x) + x);
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE uint32_t
|
||||||
|
atomic_sub_uint32(uint32_t *p, uint32_t x)
|
||||||
|
{
|
||||||
|
volatile atomic_uint_least32_t *a = (volatile atomic_uint_least32_t *)p;
|
||||||
|
return (atomic_fetch_sub(a, x) - x);
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE bool
|
||||||
|
atomic_cas_uint32(uint32_t *p, uint32_t c, uint32_t s)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (!atomic_compare_exchange_strong(p, &c, s));
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE void
|
||||||
|
atomic_write_uint32(uint32_t *p, uint32_t x)
|
||||||
|
{
|
||||||
|
|
||||||
|
atomic_store(p, x);
|
||||||
|
}
|
||||||
#elif (defined(JEMALLOC_ATOMIC9))
|
#elif (defined(JEMALLOC_ATOMIC9))
|
||||||
JEMALLOC_INLINE uint32_t
|
JEMALLOC_INLINE uint32_t
|
||||||
atomic_add_uint32(uint32_t *p, uint32_t x)
|
atomic_add_uint32(uint32_t *p, uint32_t x)
|
||||||
@ -273,7 +391,84 @@ atomic_sub_uint32(uint32_t *p, uint32_t x)
|
|||||||
|
|
||||||
return (atomic_fetchadd_32(p, (uint32_t)(-(int32_t)x)) - x);
|
return (atomic_fetchadd_32(p, (uint32_t)(-(int32_t)x)) - x);
|
||||||
}
|
}
|
||||||
#elif (defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_4))
|
|
||||||
|
JEMALLOC_INLINE bool
|
||||||
|
atomic_cas_uint32(uint32_t *p, uint32_t c, uint32_t s)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (!atomic_cmpset_32(p, c, s));
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE void
|
||||||
|
atomic_write_uint32(uint32_t *p, uint32_t x)
|
||||||
|
{
|
||||||
|
|
||||||
|
atomic_store_rel_32(p, x);
|
||||||
|
}
|
||||||
|
#elif (defined(JEMALLOC_OSATOMIC))
|
||||||
|
JEMALLOC_INLINE uint32_t
|
||||||
|
atomic_add_uint32(uint32_t *p, uint32_t x)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (OSAtomicAdd32((int32_t)x, (int32_t *)p));
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE uint32_t
|
||||||
|
atomic_sub_uint32(uint32_t *p, uint32_t x)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (OSAtomicAdd32(-((int32_t)x), (int32_t *)p));
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE bool
|
||||||
|
atomic_cas_uint32(uint32_t *p, uint32_t c, uint32_t s)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (!OSAtomicCompareAndSwap32(c, s, (int32_t *)p));
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE void
|
||||||
|
atomic_write_uint32(uint32_t *p, uint32_t x)
|
||||||
|
{
|
||||||
|
uint32_t o;
|
||||||
|
|
||||||
|
/*The documented OSAtomic*() API does not expose an atomic exchange. */
|
||||||
|
do {
|
||||||
|
o = atomic_read_uint32(p);
|
||||||
|
} while (atomic_cas_uint32(p, o, x));
|
||||||
|
}
|
||||||
|
#elif (defined(_MSC_VER))
|
||||||
|
JEMALLOC_INLINE uint32_t
|
||||||
|
atomic_add_uint32(uint32_t *p, uint32_t x)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (InterlockedExchangeAdd(p, x) + x);
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE uint32_t
|
||||||
|
atomic_sub_uint32(uint32_t *p, uint32_t x)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (InterlockedExchangeAdd(p, -((int32_t)x)) - x);
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE bool
|
||||||
|
atomic_cas_uint32(uint32_t *p, uint32_t c, uint32_t s)
|
||||||
|
{
|
||||||
|
uint32_t o;
|
||||||
|
|
||||||
|
o = InterlockedCompareExchange32(p, s, c);
|
||||||
|
return (o != c);
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE void
|
||||||
|
atomic_write_uint32(uint32_t *p, uint32_t x)
|
||||||
|
{
|
||||||
|
|
||||||
|
InterlockedExchange(p, x);
|
||||||
|
}
|
||||||
|
#elif (defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) || \
|
||||||
|
defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_4))
|
||||||
JEMALLOC_INLINE uint32_t
|
JEMALLOC_INLINE uint32_t
|
||||||
atomic_add_uint32(uint32_t *p, uint32_t x)
|
atomic_add_uint32(uint32_t *p, uint32_t x)
|
||||||
{
|
{
|
||||||
@ -287,10 +482,72 @@ atomic_sub_uint32(uint32_t *p, uint32_t x)
|
|||||||
|
|
||||||
return (__sync_sub_and_fetch(p, x));
|
return (__sync_sub_and_fetch(p, x));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE bool
|
||||||
|
atomic_cas_uint32(uint32_t *p, uint32_t c, uint32_t s)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (!__sync_bool_compare_and_swap(p, c, s));
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE void
|
||||||
|
atomic_write_uint32(uint32_t *p, uint32_t x)
|
||||||
|
{
|
||||||
|
|
||||||
|
__sync_lock_test_and_set(p, x);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
# error "Missing implementation for 32-bit atomic operations"
|
# error "Missing implementation for 32-bit atomic operations"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
/* Pointer operations. */
|
||||||
|
JEMALLOC_INLINE void *
|
||||||
|
atomic_add_p(void **p, void *x)
|
||||||
|
{
|
||||||
|
|
||||||
|
#if (LG_SIZEOF_PTR == 3)
|
||||||
|
return ((void *)atomic_add_uint64((uint64_t *)p, (uint64_t)x));
|
||||||
|
#elif (LG_SIZEOF_PTR == 2)
|
||||||
|
return ((void *)atomic_add_uint32((uint32_t *)p, (uint32_t)x));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE void *
|
||||||
|
atomic_sub_p(void **p, void *x)
|
||||||
|
{
|
||||||
|
|
||||||
|
#if (LG_SIZEOF_PTR == 3)
|
||||||
|
return ((void *)atomic_add_uint64((uint64_t *)p,
|
||||||
|
(uint64_t)-((int64_t)x)));
|
||||||
|
#elif (LG_SIZEOF_PTR == 2)
|
||||||
|
return ((void *)atomic_add_uint32((uint32_t *)p,
|
||||||
|
(uint32_t)-((int32_t)x)));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE bool
|
||||||
|
atomic_cas_p(void **p, void *c, void *s)
|
||||||
|
{
|
||||||
|
|
||||||
|
#if (LG_SIZEOF_PTR == 3)
|
||||||
|
return (atomic_cas_uint64((uint64_t *)p, (uint64_t)c, (uint64_t)s));
|
||||||
|
#elif (LG_SIZEOF_PTR == 2)
|
||||||
|
return (atomic_cas_uint32((uint32_t *)p, (uint32_t)c, (uint32_t)s));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE void
|
||||||
|
atomic_write_p(void **p, void *x)
|
||||||
|
{
|
||||||
|
|
||||||
|
#if (LG_SIZEOF_PTR == 3)
|
||||||
|
atomic_write_uint64((uint64_t *)p, (uint64_t)x);
|
||||||
|
#elif (LG_SIZEOF_PTR == 2)
|
||||||
|
atomic_write_uint32((uint32_t *)p, (uint32_t)x);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/* size_t operations. */
|
/* size_t operations. */
|
||||||
JEMALLOC_INLINE size_t
|
JEMALLOC_INLINE size_t
|
||||||
@ -317,6 +574,28 @@ atomic_sub_z(size_t *p, size_t x)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE bool
|
||||||
|
atomic_cas_z(size_t *p, size_t c, size_t s)
|
||||||
|
{
|
||||||
|
|
||||||
|
#if (LG_SIZEOF_PTR == 3)
|
||||||
|
return (atomic_cas_uint64((uint64_t *)p, (uint64_t)c, (uint64_t)s));
|
||||||
|
#elif (LG_SIZEOF_PTR == 2)
|
||||||
|
return (atomic_cas_uint32((uint32_t *)p, (uint32_t)c, (uint32_t)s));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE void
|
||||||
|
atomic_write_z(size_t *p, size_t x)
|
||||||
|
{
|
||||||
|
|
||||||
|
#if (LG_SIZEOF_PTR == 3)
|
||||||
|
atomic_write_uint64((uint64_t *)p, (uint64_t)x);
|
||||||
|
#elif (LG_SIZEOF_PTR == 2)
|
||||||
|
atomic_write_uint32((uint32_t *)p, (uint32_t)x);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/* unsigned operations. */
|
/* unsigned operations. */
|
||||||
JEMALLOC_INLINE unsigned
|
JEMALLOC_INLINE unsigned
|
||||||
@ -342,6 +621,29 @@ atomic_sub_u(unsigned *p, unsigned x)
|
|||||||
(uint32_t)-((int32_t)x)));
|
(uint32_t)-((int32_t)x)));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE bool
|
||||||
|
atomic_cas_u(unsigned *p, unsigned c, unsigned s)
|
||||||
|
{
|
||||||
|
|
||||||
|
#if (LG_SIZEOF_INT == 3)
|
||||||
|
return (atomic_cas_uint64((uint64_t *)p, (uint64_t)c, (uint64_t)s));
|
||||||
|
#elif (LG_SIZEOF_INT == 2)
|
||||||
|
return (atomic_cas_uint32((uint32_t *)p, (uint32_t)c, (uint32_t)s));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
JEMALLOC_INLINE void
|
||||||
|
atomic_write_u(unsigned *p, unsigned x)
|
||||||
|
{
|
||||||
|
|
||||||
|
#if (LG_SIZEOF_INT == 3)
|
||||||
|
atomic_write_uint64((uint64_t *)p, (uint64_t)x);
|
||||||
|
#elif (LG_SIZEOF_INT == 2)
|
||||||
|
atomic_write_uint32((uint32_t *)p, (uint32_t)x);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -85,10 +85,17 @@ arena_stats_merge
|
|||||||
arena_tcache_fill_small
|
arena_tcache_fill_small
|
||||||
arenas_cache_bypass_cleanup
|
arenas_cache_bypass_cleanup
|
||||||
arenas_cache_cleanup
|
arenas_cache_cleanup
|
||||||
|
atomic_add_p
|
||||||
atomic_add_u
|
atomic_add_u
|
||||||
atomic_add_uint32
|
atomic_add_uint32
|
||||||
atomic_add_uint64
|
atomic_add_uint64
|
||||||
atomic_add_z
|
atomic_add_z
|
||||||
|
atomic_cas_p
|
||||||
|
atomic_cas_u
|
||||||
|
atomic_cas_uint32
|
||||||
|
atomic_cas_uint64
|
||||||
|
atomic_cas_z
|
||||||
|
atomic_sub_p
|
||||||
atomic_sub_u
|
atomic_sub_u
|
||||||
atomic_sub_uint32
|
atomic_sub_uint32
|
||||||
atomic_sub_uint64
|
atomic_sub_uint64
|
||||||
|
@ -4,48 +4,64 @@
|
|||||||
struct p##_test_s { \
|
struct p##_test_s { \
|
||||||
t accum0; \
|
t accum0; \
|
||||||
t x; \
|
t x; \
|
||||||
|
t s; \
|
||||||
}; \
|
}; \
|
||||||
typedef struct p##_test_s p##_test_t;
|
typedef struct p##_test_s p##_test_t;
|
||||||
|
|
||||||
#define TEST_BODY(p, t, PRI) do { \
|
#define TEST_BODY(p, t, tc, ta, PRI) do { \
|
||||||
const p##_test_t tests[] = { \
|
const p##_test_t tests[] = { \
|
||||||
{-1, -1}, \
|
{(t)-1, (t)-1, (t)-2}, \
|
||||||
{-1, 0}, \
|
{(t)-1, (t) 0, (t)-2}, \
|
||||||
{-1, 1}, \
|
{(t)-1, (t) 1, (t)-2}, \
|
||||||
\
|
\
|
||||||
{ 0, -1}, \
|
{(t) 0, (t)-1, (t)-2}, \
|
||||||
{ 0, 0}, \
|
{(t) 0, (t) 0, (t)-2}, \
|
||||||
{ 0, 1}, \
|
{(t) 0, (t) 1, (t)-2}, \
|
||||||
\
|
\
|
||||||
{ 1, -1}, \
|
{(t) 1, (t)-1, (t)-2}, \
|
||||||
{ 1, 0}, \
|
{(t) 1, (t) 0, (t)-2}, \
|
||||||
{ 1, 1}, \
|
{(t) 1, (t) 1, (t)-2}, \
|
||||||
\
|
\
|
||||||
{0, -(1 << 22)}, \
|
{(t)0, (t)-(1 << 22), (t)-2}, \
|
||||||
{0, (1 << 22)}, \
|
{(t)0, (t)(1 << 22), (t)-2}, \
|
||||||
{(1 << 22), -(1 << 22)}, \
|
{(t)(1 << 22), (t)-(1 << 22), (t)-2}, \
|
||||||
{(1 << 22), (1 << 22)} \
|
{(t)(1 << 22), (t)(1 << 22), (t)-2} \
|
||||||
}; \
|
}; \
|
||||||
unsigned i; \
|
unsigned i; \
|
||||||
\
|
\
|
||||||
for (i = 0; i < sizeof(tests)/sizeof(p##_test_t); i++) { \
|
for (i = 0; i < sizeof(tests)/sizeof(p##_test_t); i++) { \
|
||||||
|
bool err; \
|
||||||
t accum = tests[i].accum0; \
|
t accum = tests[i].accum0; \
|
||||||
assert_u64_eq(atomic_read_##p(&accum), tests[i].accum0, \
|
assert_##ta##_eq(atomic_read_##p(&accum), \
|
||||||
"i=%u", i); \
|
tests[i].accum0, \
|
||||||
assert_u64_eq(atomic_add_##p(&accum, tests[i].x), \
|
"Erroneous read, i=%u", i); \
|
||||||
tests[i].accum0 + tests[i].x, \
|
\
|
||||||
"i=%u, accum=%#"PRI", x=%#"PRI, \
|
assert_##ta##_eq(atomic_add_##p(&accum, tests[i].x), \
|
||||||
|
(t)((tc)tests[i].accum0 + (tc)tests[i].x), \
|
||||||
|
"i=%u, accum=%"PRI", x=%"PRI, \
|
||||||
i, tests[i].accum0, tests[i].x); \
|
i, tests[i].accum0, tests[i].x); \
|
||||||
assert_u64_eq(atomic_read_##p(&accum), accum, \
|
assert_##ta##_eq(atomic_read_##p(&accum), accum, \
|
||||||
"i=%u", i); \
|
"Erroneous add, i=%u", i); \
|
||||||
\
|
\
|
||||||
accum = tests[i].accum0; \
|
accum = tests[i].accum0; \
|
||||||
assert_u64_eq(atomic_sub_##p(&accum, tests[i].x), \
|
assert_##ta##_eq(atomic_sub_##p(&accum, tests[i].x), \
|
||||||
tests[i].accum0 - tests[i].x, \
|
(t)((tc)tests[i].accum0 - (tc)tests[i].x), \
|
||||||
"i=%u, accum=%#"PRI", x=%#"PRI, \
|
"i=%u, accum=%"PRI", x=%"PRI, \
|
||||||
i, tests[i].accum0, tests[i].x); \
|
i, tests[i].accum0, tests[i].x); \
|
||||||
assert_u64_eq(atomic_read_##p(&accum), accum, \
|
assert_##ta##_eq(atomic_read_##p(&accum), accum, \
|
||||||
"i=%u", i); \
|
"Erroneous sub, i=%u", i); \
|
||||||
|
\
|
||||||
|
accum = tests[i].accum0; \
|
||||||
|
err = atomic_cas_##p(&accum, tests[i].x, tests[i].s); \
|
||||||
|
assert_b_eq(err, tests[i].accum0 != tests[i].x, \
|
||||||
|
"Erroneous cas success/failure result"); \
|
||||||
|
assert_##ta##_eq(accum, err ? tests[i].accum0 : \
|
||||||
|
tests[i].s, "Erroneous cas effect, i=%u", i); \
|
||||||
|
\
|
||||||
|
accum = tests[i].accum0; \
|
||||||
|
atomic_write_##p(&accum, tests[i].s); \
|
||||||
|
assert_##ta##_eq(accum, tests[i].s, \
|
||||||
|
"Erroneous write, i=%u", i); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
@ -56,7 +72,7 @@ TEST_BEGIN(test_atomic_uint64)
|
|||||||
#if !(LG_SIZEOF_PTR == 3 || LG_SIZEOF_INT == 3)
|
#if !(LG_SIZEOF_PTR == 3 || LG_SIZEOF_INT == 3)
|
||||||
test_skip("64-bit atomic operations not supported");
|
test_skip("64-bit atomic operations not supported");
|
||||||
#else
|
#else
|
||||||
TEST_BODY(uint64, uint64_t, PRIx64);
|
TEST_BODY(uint64, uint64_t, uint64_t, u64, PRIx64);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
TEST_END
|
TEST_END
|
||||||
@ -65,7 +81,15 @@ TEST_STRUCT(uint32, uint32_t)
|
|||||||
TEST_BEGIN(test_atomic_uint32)
|
TEST_BEGIN(test_atomic_uint32)
|
||||||
{
|
{
|
||||||
|
|
||||||
TEST_BODY(uint32, uint32_t, PRIx32);
|
TEST_BODY(uint32, uint32_t, uint32_t, u32, "#"PRIx32);
|
||||||
|
}
|
||||||
|
TEST_END
|
||||||
|
|
||||||
|
TEST_STRUCT(p, void *)
|
||||||
|
TEST_BEGIN(test_atomic_p)
|
||||||
|
{
|
||||||
|
|
||||||
|
TEST_BODY(p, void *, uintptr_t, ptr, "p");
|
||||||
}
|
}
|
||||||
TEST_END
|
TEST_END
|
||||||
|
|
||||||
@ -73,7 +97,7 @@ TEST_STRUCT(z, size_t)
|
|||||||
TEST_BEGIN(test_atomic_z)
|
TEST_BEGIN(test_atomic_z)
|
||||||
{
|
{
|
||||||
|
|
||||||
TEST_BODY(z, size_t, "zx");
|
TEST_BODY(z, size_t, size_t, zu, "#zx");
|
||||||
}
|
}
|
||||||
TEST_END
|
TEST_END
|
||||||
|
|
||||||
@ -81,7 +105,7 @@ TEST_STRUCT(u, unsigned)
|
|||||||
TEST_BEGIN(test_atomic_u)
|
TEST_BEGIN(test_atomic_u)
|
||||||
{
|
{
|
||||||
|
|
||||||
TEST_BODY(u, unsigned, "x");
|
TEST_BODY(u, unsigned, unsigned, u, "#x");
|
||||||
}
|
}
|
||||||
TEST_END
|
TEST_END
|
||||||
|
|
||||||
@ -92,6 +116,7 @@ main(void)
|
|||||||
return (test(
|
return (test(
|
||||||
test_atomic_uint64,
|
test_atomic_uint64,
|
||||||
test_atomic_uint32,
|
test_atomic_uint32,
|
||||||
|
test_atomic_p,
|
||||||
test_atomic_z,
|
test_atomic_z,
|
||||||
test_atomic_u));
|
test_atomic_u));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user