Emulate 64-bit atomic ops if hardware doesn't support them

Signed-off-by: Erik Boasson <eb@ilities.com>
This commit is contained in:
Erik Boasson 2019-06-12 14:40:49 +02:00 committed by eboasson
parent 6ad99463ce
commit 559c325307
4 changed files with 243 additions and 0 deletions

View file

@ -59,6 +59,34 @@ typedef ddsrt_atomic_uintptr_t ddsrt_atomic_voidp_t;
#error "Atomic operations are not supported"
#endif
#if ! DDSRT_HAVE_ATOMIC64
/* 64-bit atomics are not supported by all hardware, but it would be a shame not to use them when
they are available. That necessitates an alternative implementation when they are not, either in
the form of a different implementation where it is used, or as an emulation using a mutex in
ddsrt. It seems that the places where they'd be used end up adding a mutex, so an emulation in
ddsrt while being able to check whether it is supported by hardware is a sensible approach. */
DDS_EXPORT uint64_t ddsrt_atomic_ld64 (const volatile ddsrt_atomic_uint64_t *x);
DDS_EXPORT void ddsrt_atomic_st64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
DDS_EXPORT void ddsrt_atomic_inc64 (volatile ddsrt_atomic_uint64_t *x);
DDS_EXPORT uint64_t ddsrt_atomic_inc64_nv (volatile ddsrt_atomic_uint64_t *x);
DDS_EXPORT void ddsrt_atomic_dec64 (volatile ddsrt_atomic_uint64_t *x);
DDS_EXPORT uint64_t ddsrt_atomic_dec64_nv (volatile ddsrt_atomic_uint64_t *x);
DDS_EXPORT void ddsrt_atomic_add64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
DDS_EXPORT uint64_t ddsrt_atomic_add64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
DDS_EXPORT void ddsrt_atomic_sub64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
DDS_EXPORT uint64_t ddsrt_atomic_sub64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
DDS_EXPORT void ddsrt_atomic_and64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
DDS_EXPORT uint64_t ddsrt_atomic_and64_ov (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
DDS_EXPORT uint64_t ddsrt_atomic_and64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
DDS_EXPORT void ddsrt_atomic_or64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
DDS_EXPORT uint64_t ddsrt_atomic_or64_ov (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
DDS_EXPORT uint64_t ddsrt_atomic_or64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
DDS_EXPORT int ddsrt_atomic_cas64 (volatile ddsrt_atomic_uint64_t *x, uint64_t exp, uint64_t des);
#endif
void ddsrt_atomics_init (void);
void ddsrt_atomics_fini (void);
#if defined(__cplusplus)
}
#endif

View file

@ -318,10 +318,18 @@ inline void ddsrt_atomic_fence_ldld (void) {
#endif
}
inline void ddsrt_atomic_fence_acq (void) {
#if !(defined __i386__ || defined __x86_64__ || defined _M_IX86 || defined _M_X64)
ddsrt_atomic_fence ();
#else
asm volatile ("" ::: "memory");
#endif
}
inline void ddsrt_atomic_fence_rel (void) {
#if !(defined __i386__ || defined __x86_64__ || defined _M_IX86 || defined _M_X64)
ddsrt_atomic_fence ();
#else
asm volatile ("" ::: "memory");
#endif
}
#if defined (__cplusplus)