diff --git a/src/hl.h b/src/hl.h index 75ddcb8b1..b24925f37 100644 --- a/src/hl.h +++ b/src/hl.h @@ -211,6 +211,12 @@ typedef unsigned long long uint64; #define HL_API IMPORT #endif +#if defined(HL_VCC) +#define HL_INLINE __inline +#else +#define HL_INLINE inline +#endif + // -------------- UNICODE ----------------------------------- #if defined(HL_WIN) && !defined(HL_LLVM) diff --git a/src/std/thread.c b/src/std/thread.c index e95c69192..986d48dda 100644 --- a/src/std/thread.c +++ b/src/std/thread.c @@ -962,3 +962,162 @@ HL_PRIM void hl_thread_set_name( hl_thread *t, const char *name ) { DEFINE_PRIM(_THREAD, thread_current, _NO_ARG); DEFINE_PRIM(_THREAD, thread_create, _FUN(_VOID,_NO_ARG)); DEFINE_PRIM(_VOID, thread_set_name, _THREAD _BYTES); + +// ----------------- ATOMICS + +// Assumptions made: +// Everyone uses GCC, Clang or MSVC +// People are not using 8 year old versions of GCC. + +#if defined(HL_GCC) || defined(HL_CLANG) +#define HL_GCC_ATOMICS +#elif defined(HL_VCC) +#define HL_VCC_ATOMICS +#include +#else // Nearly everyone uses GCC, Clang or MSVC, right? +#error \ + "Neither GCC, clang or MSVC is being used. Please contribute the relevant atomic instrinsics for your compiler." +#endif + +HL_PRIM int hl_atomic_add32(int *a, int b) { +#if defined(HL_GCC_ATOMICS) + return __atomic_fetch_add(a, b, __ATOMIC_SEQ_CST); +#elif defined(HL_VCC_ATOMICS) + return _InterlockedExchangeAdd((LONG volatile *)a, b); +#endif +} + +HL_PRIM int hl_atomic_sub32(int *a, int b) { +#if defined(HL_GCC_ATOMICS) + return __atomic_fetch_sub(a, b, __ATOMIC_SEQ_CST); +#elif defined(HL_VCC_ATOMICS) + return _InterlockedExchangeAdd((LONG volatile *)a, -b); +#endif +} + +HL_PRIM int hl_atomic_and32(int *a, int b) { +#if defined(HL_GCC_ATOMICS) + return __atomic_fetch_and(a, b, __ATOMIC_SEQ_CST); +#elif defined(HL_VCC_ATOMICS) + return _InterlockedAnd((LONG volatile *)a, b); +#endif +} + +HL_PRIM int hl_atomic_or32(int *a, int b) { +#if defined(HL_GCC_ATOMICS) + return __atomic_fetch_or(a, b, __ATOMIC_SEQ_CST); +#elif defined(HL_VCC_ATOMICS) + return _InterlockedOr((LONG volatile *)a, b); +#endif +} + +HL_PRIM int hl_atomic_xor32(int *a, int b) { +#if defined(HL_GCC_ATOMICS) + return __atomic_fetch_xor(a, b, __ATOMIC_SEQ_CST); +#elif defined(HL_VCC_ATOMICS) + return _InterlockedXor((LONG volatile *)a, b); +#endif +} + +HL_PRIM int hl_atomic_compare_exchange32(int *a, int expected, + int replacement) { +#if defined(HL_GCC_ATOMICS) + int _expected = expected; + __atomic_compare_exchange(a, &_expected, &replacement, false, + __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); + return _expected; +#elif defined(HL_VCC_ATOMICS) + return _InterlockedCompareExchange((LONG volatile *)a, replacement, expected); +#endif +} + +HL_PRIM void *hl_atomic_compare_exchange_ptr(void **a, void *expected, + void *replacement) { +#if defined(HL_GCC_ATOMICS) + void *_expected = expected; + __atomic_compare_exchange(a, &_expected, &replacement, false, + __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); + return _expected; +#elif defined(HL_VCC_ATOMICS) + return _InterlockedCompareExchangePointer((void *volatile *)a, replacement, + expected); +#endif +} + +HL_PRIM int hl_atomic_exchange32(int *a, int replacement) { +#if defined(HL_GCC_ATOMICS) + int ret = 0; + __atomic_exchange(a, &replacement, &ret, __ATOMIC_SEQ_CST); + return ret; +#elif defined(HL_VCC_ATOMICS) + return _InterlockedExchange((LONG volatile *)a, replacement); +#endif +} + +HL_PRIM void *hl_atomic_exchange_ptr(void **a, void *replacement) { +#if defined(HL_GCC_ATOMICS) + void *ret = 0; + __atomic_exchange(a, &replacement, &ret, __ATOMIC_SEQ_CST); + return ret; +#elif defined(HL_VCC_ATOMICS) + return _InterlockedExchangePointer((void *volatile *)a, replacement); +#endif +} + +HL_PRIM int hl_atomic_load32(int *a) { +#if defined(HL_GCC_ATOMICS) + int ret = 0; + __atomic_load(a, &ret, __ATOMIC_SEQ_CST); + return ret; +#elif defined(HL_VCC_ATOMICS) + return _InterlockedXor((LONG volatile *)a, 0); +#endif +} + +HL_PRIM void *hl_atomic_load_ptr(void **a) { +#if defined(HL_GCC_ATOMICS) + void *ret = 0; + __atomic_load(a, &ret, __ATOMIC_SEQ_CST); + return ret; +#elif defined(HL_VCC_ATOMICS) +#ifdef HL_64 + return (void *)_InterlockedXor64((__int64 volatile *)a, 0); +#else + return (void *)_InterlockedXor((LONG volatile *)a, 0); +#endif +#endif +} + +HL_PRIM int hl_atomic_store32(int *a, int value) { +#if defined(HL_GCC_ATOMICS) + __atomic_store(a, &value, __ATOMIC_SEQ_CST); + return value; +#elif defined(HL_VCC_ATOMICS) + _InterlockedExchange((LONG volatile *)a, value); + return value; +#endif +} + +HL_PRIM void *hl_atomic_store_ptr(void **a, void *value) { +#if defined(HL_GCC_ATOMICS) + __atomic_store(a, &value, __ATOMIC_SEQ_CST); + return value; +#elif defined(HL_VCC_ATOMICS) + _InterlockedExchangePointer((void *volatile *)a, value); + return value; +#endif +} + +DEFINE_PRIM(_I32, atomic_add32, _REF(_I32) _I32) +DEFINE_PRIM(_I32, atomic_sub32, _REF(_I32) _I32) +DEFINE_PRIM(_I32, atomic_and32, _REF(_I32) _I32) +DEFINE_PRIM(_I32, atomic_or32, _REF(_I32) _I32) +DEFINE_PRIM(_I32, atomic_xor32, _REF(_I32) _I32) +DEFINE_PRIM(_I32, atomic_compare_exchange32, _REF(_I32) _I32 _I32) +DEFINE_PRIM(_DYN, atomic_compare_exchange_ptr, _REF(_DYN) _DYN _DYN) +DEFINE_PRIM(_I32, atomic_exchange32, _REF(_I32) _I32) +DEFINE_PRIM(_DYN, atomic_exchange_ptr, _REF(_DYN) _DYN) +DEFINE_PRIM(_I32, atomic_load32, _REF(_I32)) +DEFINE_PRIM(_DYN, atomic_load_ptr, _REF(_DYN)) +DEFINE_PRIM(_I32, atomic_store32, _REF(_I32) _I32) +DEFINE_PRIM(_DYN, atomic_store_ptr, _REF(_DYN) _DYN)