Skip to content

Commit

Permalink
atomics update
Browse files Browse the repository at this point in the history
  • Loading branch information
peterino2 committed Jul 10, 2023
1 parent 93bd80a commit 530d7b5
Showing 1 changed file with 121 additions and 25 deletions.
146 changes: 121 additions & 25 deletions src/atomics.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,31 @@ struct SoundIoAtomicULong {
std::atomic<unsigned long> x;
};

#define SOUNDIO_ATOMIC_LOAD(a) (a.x.load())
#define SOUNDIO_ATOMIC_FETCH_ADD(a, delta) (a.x.fetch_add(delta))
#define SOUNDIO_ATOMIC_STORE(a, value) (a.x.store(value))
#define SOUNDIO_ATOMIC_EXCHANGE(a, value) (a.x.exchange(value))
#define SOUNDIO_ATOMIC_LOAD_(a) (a.x.load())
#define SOUNDIO_ATOMIC_FETCH_ADD_(a, delta) (a.x.fetch_add(delta))
#define SOUNDIO_ATOMIC_STORE_(a, value) (a.x.store(value))
#define SOUNDIO_ATOMIC_EXCHANGE_(a, value) (a.x.exchange(value))

#define SOUNDIO_ATOMIC_LOAD_BOOL SOUNDIO_ATOMIC_LOAD_
#define SOUNDIO_ATOMIC_STORE_BOOL SOUNDIO_ATOMIC_STORE_
#define SOUNDIO_ATOMIC_FETCH_ADD_BOOL SOUNDIO_ATOMIC_FETCH_ADD_
#define SOUNDIO_ATOMIC_EXCHANGE_BOOL SOUNDIO_ATOMIC_EXCHANGE_

#define SOUNDIO_ATOMIC_LOAD_INT SOUNDIO_ATOMIC_LOAD_
#define SOUNDIO_ATOMIC_STORE_INT SOUNDIO_ATOMIC_STORE_
#define SOUNDIO_ATOMIC_FETCH_ADD_INT SOUNDIO_ATOMIC_FETCH_ADD_
#define SOUNDIO_ATOMIC_EXCHANGE_INT SOUNDIO_ATOMIC_EXCHANGE_

#define SOUNDIO_ATOMIC_LOAD_LONG SOUNDIO_ATOMIC_LOAD_
#define SOUNDIO_ATOMIC_STORE_LONG SOUNDIO_ATOMIC_STORE_
#define SOUNDIO_ATOMIC_FETCH_ADD_LONG SOUNDIO_ATOMIC_FETCH_ADD_
#define SOUNDIO_ATOMIC_EXCHANGE_LONG SOUNDIO_ATOMIC_EXCHANGE_

#define SOUNDIO_ATOMIC_LOAD_ULONG SOUNDIO_ATOMIC_LOAD_
#define SOUNDIO_ATOMIC_STORE_ULONG SOUNDIO_ATOMIC_STORE_
#define SOUNDIO_ATOMIC_FETCH_ADD_ULONG SOUNDIO_ATOMIC_FETCH_ADD_
#define SOUNDIO_ATOMIC_EXCHANGE_ULONG SOUNDIO_ATOMIC_EXCHANGE_

#define SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(a) (a.x.test_and_set())
#define SOUNDIO_ATOMIC_FLAG_CLEAR(a) (a.x.clear())
#define SOUNDIO_ATOMIC_FLAG_INIT ATOMIC_FLAG_INIT
Expand Down Expand Up @@ -82,19 +103,45 @@ struct SoundIoAtomicULong {
atomic_ulong x;
};

#define SOUNDIO_ATOMIC_LOAD(a) atomic_load(&a.x)
#define SOUNDIO_ATOMIC_FETCH_ADD(a, delta) atomic_fetch_add(&a.x, delta)
#define SOUNDIO_ATOMIC_STORE(a, value) atomic_store(&a.x, value)
#define SOUNDIO_ATOMIC_EXCHANGE(a, value) atomic_exchange(&a.x, value)
#define SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(a) atomic_flag_test_and_set(&a.x)
#define SOUNDIO_ATOMIC_FLAG_CLEAR(a) atomic_flag_clear(&a.x)
#define SOUNDIO_ATOMIC_LOAD_(a) atomic_load(&a.x)
#define SOUNDIO_ATOMIC_FETCH_ADD_(a, delta) atomic_fetch_add(&a.x, delta)
#define SOUNDIO_ATOMIC_STORE_(a, value) atomic_store(&a.x, value)
#define SOUNDIO_ATOMIC_EXCHANGE_(a, value) atomic_exchange(&a.x, value)
#define SOUNDIO_ATOMIC_FLAG_TEST_AND_SET_(a) atomic_flag_test_and_set(&a.x)
#define SOUNDIO_ATOMIC_FLAG_CLEAR_(a) atomic_flag_clear(&a.x)
#define SOUNDIO_ATOMIC_FLAG_INIT ATOMIC_FLAG_INIT

#define SOUNDIO_ATOMIC_LOAD_BOOL SOUNDIO_ATOMIC_LOAD_
#define SOUNDIO_ATOMIC_STORE_BOOL SOUNDIO_ATOMIC_STORE_
#define SOUNDIO_ATOMIC_FETCH_ADD_BOOL SOUNDIO_ATOMIC_FETCH_ADD_
#define SOUNDIO_ATOMIC_EXCHANGE_BOOL SOUNDIO_ATOMIC_EXCHANGE_

#define SOUNDIO_ATOMIC_LOAD_INT SOUNDIO_ATOMIC_LOAD_
#define SOUNDIO_ATOMIC_STORE_INT SOUNDIO_ATOMIC_STORE_
#define SOUNDIO_ATOMIC_FETCH_ADD_INT SOUNDIO_ATOMIC_FETCH_ADD_
#define SOUNDIO_ATOMIC_EXCHANGE_INT SOUNDIO_ATOMIC_EXCHANGE_

#define SOUNDIO_ATOMIC_LOAD_LONG SOUNDIO_ATOMIC_LOAD_
#define SOUNDIO_ATOMIC_STORE_LONG SOUNDIO_ATOMIC_STORE_
#define SOUNDIO_ATOMIC_FETCH_ADD_LONG SOUNDIO_ATOMIC_FETCH_ADD_
#define SOUNDIO_ATOMIC_EXCHANGE_LONG SOUNDIO_ATOMIC_EXCHANGE_

#define SOUNDIO_ATOMIC_LOAD_ULONG SOUNDIO_ATOMIC_LOAD_
#define SOUNDIO_ATOMIC_STORE_ULONG SOUNDIO_ATOMIC_STORE_
#define SOUNDIO_ATOMIC_FETCH_ADD_ULONG SOUNDIO_ATOMIC_FETCH_ADD_
#define SOUNDIO_ATOMIC_EXCHANGE_ULONG SOUNDIO_ATOMIC_EXCHANGE_

#endif

#ifdef SOUNDIO_USE_MSVC_NATIVE_C_ATOMICS
// When building for native msvc, we can leverage builtin atomics.

#ifdef _WIN64
#define SOUNDIO_MSVC_POINTER_SIZE 8
#else
#define SOUNDIO_MSVC_POINTER_SIZE 4
#endif

struct SoundIoAtomicLong {
long x;
};
Expand All @@ -115,26 +162,75 @@ struct SoundIoAtomicULong {
unsigned long x;
};

// When sticking to raw C and msvc. need to call different
// When sticking to raw C and msvc, we rely on MSVC compiler intrinsics and are unable to
// Automatically deduce types at compile time. Must use the correct macro for the correct function.
//
// No headers needed. We use _Interlocked* family of compiler intrinsics.
// Implementation referenced from the fantastic turf library's `atomic_msvc.h`

// How the living hell is it that to this day and age. msvc does not support typeof which both clang
// and gcc support.
//
// guess this is why c11 in msvc can't implement stdatomic.h right now
#define SOUNDIO_ATOMIC_LOAD_BOOL(a) *((volatile char*) &(a.x))
#define SOUNDIO_ATOMIC_FETCH_ADD_BOOL(a, delta) _InterlockedExchangeAdd8()
#define SOUNDIO_ATOMIC_STORE_BOOL(a, value) (*((volatile char*) &(a.x))) = value
#define SOUNDIO_ATOMIC_EXCHANGE_BOOL(a, value) _InterlockedExchange8((char*) a, value)

#define SOUNDIO_ATOMIC_LOAD_BOOL(a)
#define SOUNDIO_ATOMIC_FETCH_ADD_BOOL(a, delta)
#define SOUNDIO_ATOMIC_STORE_BOOL(a, value)
#define SOUNDIO_ATOMIC_EXCHANGE_BOOL(a, value)
#define SOUNDIO_ATOMIC_FETCH_ADD_BOOL(a, delta) _InterlockedExchangeAdd8((char*) (&a.x), delta)
#define SOUNDIO_ATOMIC_EXCHANGE_BOOL(a, value) _InterlockedExchange8((char*) (&a.x), value)

#define SOUNDIO_ATOMIC_LOAD_INT(a) *((volatile int*) &(a.x))
#define SOUNDIO_ATOMIC_STORE_INT(a, value) *((volatile int*) &(a.x)) = value
#define SOUNDIO_ATOMIC_FETCH_ADD_INT(a, delta) _InterlockedExchangeAdd32((int*) (&a.x), delta)
#define SOUNDIO_ATOMIC_EXCHANGE_INT(a, value) _InterlockedExchange32((int*) (&a.x), value)

#define SOUNDIO_ATOMIC_LOAD_LONG(a) SoundIoMSVCLoadLong(&a)
#define SOUNDIO_ATOMIC_STORE_LONG(a, value) SoundIoMSVCStoreLong(&a, value)
#define SOUNDIO_ATOMIC_FETCH_ADD_LONG(a, delta) _InterlockedExchange32Add((long*) (&a.x), delta)
#define SOUNDIO_ATOMIC_EXCHANGE_LONG(a, value) _InterlockedExchange32((long*) (&a.x), delta)

#define SOUNDIO_ATOMIC_LOAD_ULONG(a) SoundIoMSVCLoadLong((unsigned long*)&a)
#define SOUNDIO_ATOMIC_STORE_ULONG(a, value) SoundIoMSVCStoreLong((unsigned long) &a, value)
#define SOUNDIO_ATOMIC_FETCH_ADD_ULONG(a, delta) _InterlockedExchange64Add((long*) (&a.x), delta)
#define SOUNDIO_ATOMIC_EXCHANGE_ULONG(a, value) _InterlockedExchange64((long*) (&a.x), delta)

#define SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(a) _interlockedbittestandset(a, 1)
#define SOUNDIO_ATOMIC_FLAG_CLEAR(a) _interlockedbittestandset(a, 0)
#define SOUNDIO_ATOMIC_FLAG_INIT 1

long SoundIoMSVCLoadLong(SoundIoAtomicLong* a)
{
#if SOUNDIO_MSVC_POINTER_SIZE == 8
return ((volatile long*) a)->x;
#else

#define SOUNDIO_ATOMIC_LOAD_LONG(a)
#define SOUNDIO_ATOMIC_FETCH_ADD_LONG(a, delta)
#define SOUNDIO_ATOMIC_STORE_LONG(a, value)
#define SOUNDIO_ATOMIC_EXCHANGE_LONG(a, value)
uint64_t result;
__asm {
mov esi, object;
mov ebx, eax;
mov ecx, edx;
lock cmpxchg8b [esi];
mov dword ptr result, eax;
mov dword ptr result[4], edx;
}
return result;

#define SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(a)
#define SOUNDIO_ATOMIC_FLAG_CLEAR(a)
#define SOUNDIO_ATOMIC_FLAG_INIT false
#endif
}

void SoundIoMSVCStoreLong(SoundIoAtomicLong* a, long value)
{
#if SOUNDIO_MSVC_POINTER_SIZE == 8
((volatile long*) a)->x = value;
#else
__asm {
mov esi, object;
mov ebx, dword ptr value;
mov ecx, dword ptr value[4];
retry:
cmpxchg8b [esi];
jne retry;
}
#endif
}

#endif

Expand Down

0 comments on commit 530d7b5

Please sign in to comment.