2013-01-13 07:25:41 +00:00
|
|
|
/**
|
|
|
|
******************************************************************************
|
|
|
|
* Xenia : Xbox 360 Emulator Research Project *
|
|
|
|
******************************************************************************
|
|
|
|
* Copyright 2013 Ben Vanik. All rights reserved. *
|
|
|
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
|
|
|
******************************************************************************
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef XENIA_ATOMIC_H_
|
|
|
|
#define XENIA_ATOMIC_H_
|
|
|
|
|
|
|
|
#include <xenia/platform.h>
|
|
|
|
#include <xenia/platform_includes.h>
|
|
|
|
|
|
|
|
|
|
|
|
// These functions are modeled off of the Apple OSAtomic routines
|
|
|
|
// http://developer.apple.com/library/mac/#documentation/DriversKernelHardware/Reference/libkern_ref/OSAtomic_h/
|
|
|
|
|
|
|
|
#if XE_LIKE(OSX)
|
|
|
|
#include <libkern/OSAtomic.h>
|
|
|
|
|
|
|
|
#define xe_atomic_inc_32(value) \
|
|
|
|
OSAtomicIncrement32Barrier(value)
|
|
|
|
#define xe_atomic_dec_32(value) \
|
|
|
|
OSAtomicDecrement32Barrier(value)
|
|
|
|
#define xe_atomic_add_32(amount, value) \
|
|
|
|
((void)OSAtomicAdd32Barrier(amount, value))
|
|
|
|
#define xe_atomic_sub_32(amount, value) \
|
|
|
|
((void)OSAtomicAdd32Barrier(-amount, value))
|
|
|
|
#define xe_atomic_cas_32(oldValue, newValue, value) \
|
|
|
|
OSAtomicCompareAndSwap32Barrier(oldValue, newValue, value)
|
|
|
|
|
|
|
|
typedef OSQueueHead xe_atomic_stack_t;
|
|
|
|
#define xe_atomic_stack_init(stack) \
|
|
|
|
*(stack) = (OSQueueHead)OS_ATOMIC_QUEUE_INIT
|
|
|
|
#define xe_atomic_stack_enqueue(stack, item, offset) \
|
|
|
|
OSAtomicEnqueue((OSQueueHead*)stack, item, offset)
|
|
|
|
#define xe_atomic_stack_dequeue(stack, offset) \
|
|
|
|
OSAtomicDequeue((OSQueueHead*)stack, offset)
|
|
|
|
|
|
|
|
#elif XE_LIKE(WIN32)
|
|
|
|
|
|
|
|
#define xe_atomic_inc_32(value) \
|
|
|
|
InterlockedIncrement((volatile LONG*)value)
|
|
|
|
#define xe_atomic_dec_32(value) \
|
|
|
|
InterlockedDecrement((volatile LONG*)value)
|
|
|
|
#define xe_atomic_add_32(amount, value) \
|
|
|
|
((void)InterlockedExchangeAdd((volatile LONG*)value, amount))
|
|
|
|
#define xe_atomic_sub_32(amount, value) \
|
|
|
|
((void)InterlockedExchangeSubtract((volatile unsigned*)value, amount))
|
|
|
|
#define xe_atomic_vas_32(oldValue, newValue, value) \
|
|
|
|
(InterlockedCompareExchange((volatile LONG*)value, newValue, oldValue) == oldValue)
|
|
|
|
|
|
|
|
typedef SLIST_HEADER xe_atomic_stack_t;
|
|
|
|
#define xe_atomic_stack_init(stack) \
|
|
|
|
InitializeSListHead((PSLIST_HEADER)stack)
|
|
|
|
#define xe_atomic_stack_enqueue(stack, item, offset) \
|
|
|
|
XEIGNORE(InterlockedPushEntrySList((PSLIST_HEADER)stack, (PSLIST_ENTRY)((byte*)item + offset)))
|
|
|
|
XEFORCEINLINE void* xe_atomic_stack_dequeue(xe_atomic_stack_t* stack,
|
|
|
|
const size_t offset) {
|
|
|
|
void* ptr = (void*)InterlockedPopEntrySList((PSLIST_HEADER)stack);
|
|
|
|
if (ptr) {
|
2013-01-30 09:35:08 +00:00
|
|
|
return (void*)(((uint8_t*)ptr) - offset);
|
2013-01-13 07:25:41 +00:00
|
|
|
} else {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#elif XE_LIKE(POSIX)
|
|
|
|
|
|
|
|
#error TODO(benvanik): POSIX atomic primitives
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
#error No atomic primitives defined for this platform/cpu combination.
|
|
|
|
|
|
|
|
#endif // OSX
|
|
|
|
|
|
|
|
|
|
|
|
#endif // XENIA_ATOMIC_H_
|