Migrating atomic ops to std::atomic where possible and poly.
This commit is contained in:
parent
bf882714d0
commit
9b78dd977b
|
@ -4020,16 +4020,16 @@ int Translate_UNPACK(TranslationContext& ctx, Instr* i) {
|
|||
}
|
||||
|
||||
uint32_t IntCode_ATOMIC_EXCHANGE_I32(IntCodeState& ics, const IntCode* i) {
|
||||
auto address = (uint8_t*)ics.rf[i->src1_reg].u64;
|
||||
auto address = (uint32_t*)ics.rf[i->src1_reg].u64;
|
||||
auto new_value = ics.rf[i->src2_reg].u32;
|
||||
auto old_value = xe_atomic_exchange_32(new_value, address);
|
||||
auto old_value = poly::atomic_exchange(new_value, address);
|
||||
ics.rf[i->dest_reg].u32 = old_value;
|
||||
return IA_NEXT;
|
||||
}
|
||||
uint32_t IntCode_ATOMIC_EXCHANGE_I64(IntCodeState& ics, const IntCode* i) {
|
||||
auto address = (uint8_t*)ics.rf[i->src1_reg].u64;
|
||||
auto address = (uint64_t*)ics.rf[i->src1_reg].u64;
|
||||
auto new_value = ics.rf[i->src2_reg].u64;
|
||||
auto old_value = xe_atomic_exchange_64(new_value, address);
|
||||
auto old_value = poly::atomic_exchange(new_value, address);
|
||||
ics.rf[i->dest_reg].u64 = old_value;
|
||||
return IA_NEXT;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#define ALLOY_CORE_H_
|
||||
|
||||
// TODO(benvanik): move the common stuff into here?
|
||||
#include <xenia/atomic.h>
|
||||
#include <xenia/byte_order.h>
|
||||
#include <xenia/config.h>
|
||||
#include <xenia/logging.h>
|
||||
|
|
|
@ -9,15 +9,17 @@
|
|||
|
||||
#include <alloy/tracing/tracer.h>
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#include <alloy/tracing/channel.h>
|
||||
|
||||
namespace alloy {
|
||||
namespace tracing {
|
||||
|
||||
volatile int next_thread_id_ = 0x10000000;
|
||||
std::atomic<int> next_thread_id_(0x10000000);
|
||||
|
||||
Tracer::Tracer(Channel* channel) : channel_(channel) {
|
||||
thread_id_ = xe_atomic_inc_32(&next_thread_id_);
|
||||
thread_id_ = ++next_thread_id_;
|
||||
}
|
||||
|
||||
Tracer::~Tracer() {}
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef POLY_ATOMIC_H_
|
||||
#define POLY_ATOMIC_H_
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include <poly/config.h>
|
||||
#include <poly/platform.h>
|
||||
|
||||
namespace poly {
|
||||
|
||||
// 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>
|
||||
|
||||
inline int32_t atomic_inc(volatile int32_t* value) {
|
||||
return OSAtomicIncrement32Barrier(reinterpret_cast<volatile LONG*>(value));
|
||||
}
|
||||
inline int32_t atomic_dec(volatile int32_t* value) {
|
||||
return OSAtomicDecrement32Barrier(reinterpret_cast<volatile LONG*>(value));
|
||||
}
|
||||
|
||||
inline int32_t atomic_exchange(int32_t new_value, volatile int32_t* value) {
|
||||
//
|
||||
}
|
||||
inline int64_t atomic_exchange(int64_t new_value, volatile int64_t* value) {
|
||||
//
|
||||
}
|
||||
|
||||
inline int32_t atomic_cas(int32_t old_value, int32_t new_value,
|
||||
volatile int32_t* value) {
|
||||
return OSAtomicCompareAndSwap32Barrier(
|
||||
old_value, new_value, reinterpret_cast<volatile LONG*>(value));
|
||||
}
|
||||
|
||||
#elif XE_LIKE_WIN32
|
||||
|
||||
inline int32_t atomic_inc(volatile int32_t* value) {
|
||||
return InterlockedIncrement(reinterpret_cast<volatile LONG*>(value));
|
||||
}
|
||||
inline int32_t atomic_dec(volatile int32_t* value) {
|
||||
return InterlockedDecrement(reinterpret_cast<volatile LONG*>(value));
|
||||
}
|
||||
|
||||
inline int32_t atomic_exchange(int32_t new_value, volatile int32_t* value) {
|
||||
return InterlockedExchange(reinterpret_cast<volatile LONG*>(value),
|
||||
new_value);
|
||||
}
|
||||
inline int64_t atomic_exchange(int64_t new_value, volatile int64_t* value) {
|
||||
return InterlockedExchange64(reinterpret_cast<volatile LONGLONG*>(value),
|
||||
new_value);
|
||||
}
|
||||
|
||||
inline int32_t atomic_cas(int32_t old_value, int32_t new_value,
|
||||
volatile int32_t* value) {
|
||||
return InterlockedCompareExchange(reinterpret_cast<volatile LONG*>(value),
|
||||
new_value, old_value) == old_value;
|
||||
}
|
||||
|
||||
#elif XE_LIKE_POSIX
|
||||
|
||||
inline int32_t atomic_inc(volatile int32_t* value) {
|
||||
return __sync_add_and_fetch(value, 1);
|
||||
}
|
||||
inline int32_t atomic_dec(volatile int32_t* value) {
|
||||
return __sync_sub_and_fetch(value, 1);
|
||||
}
|
||||
|
||||
inline int32_t atomic_exchange(int32_t new_value, volatile int32_t* value) {
|
||||
//
|
||||
}
|
||||
inline int64_t atomic_exchange(int64_t new_value, volatile int64_t* value) {
|
||||
//
|
||||
}
|
||||
|
||||
inline int32_t atomic_cas(int32_t old_value, int32_t new_value,
|
||||
volatile int32_t* value) {
|
||||
return __sync_bool_compare_and_swap(reinterpret_cast<volatile LONG*>(value),
|
||||
old_value, new_value);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#error No atomic primitives defined for this platform/cpu combination.
|
||||
|
||||
#endif // OSX
|
||||
|
||||
inline uint32_t atomic_inc(volatile uint32_t* value) {
|
||||
return static_cast<uint32_t>(
|
||||
atomic_inc(reinterpret_cast<volatile int32_t*>(value)));
|
||||
}
|
||||
inline uint32_t atomic_dec(volatile uint32_t* value) {
|
||||
return static_cast<uint32_t>(
|
||||
atomic_dec(reinterpret_cast<volatile int32_t*>(value)));
|
||||
}
|
||||
|
||||
inline uint32_t atomic_exchange(uint32_t new_value, volatile uint32_t* value) {
|
||||
return static_cast<uint32_t>(
|
||||
atomic_exchange(static_cast<int32_t>(new_value),
|
||||
reinterpret_cast<volatile int32_t*>(value)));
|
||||
}
|
||||
inline uint64_t atomic_exchange(uint64_t new_value, volatile uint64_t* value) {
|
||||
return static_cast<uint64_t>(
|
||||
atomic_exchange(static_cast<int64_t>(new_value),
|
||||
reinterpret_cast<volatile int64_t*>(value)));
|
||||
}
|
||||
|
||||
inline uint32_t atomic_cas(uint32_t old_value, uint32_t new_value,
|
||||
volatile uint32_t* value) {
|
||||
return static_cast<uint32_t>(atomic_cas(
|
||||
static_cast<int32_t>(old_value), static_cast<int32_t>(new_value),
|
||||
reinterpret_cast<volatile int32_t*>(value)));
|
||||
}
|
||||
|
||||
} // namespace poly
|
||||
|
||||
#endif // POLY_ATOMIC_H_
|
|
@ -11,6 +11,7 @@
|
|||
#define POLY_POLY_H_
|
||||
|
||||
#include <poly/assert.h>
|
||||
#include <poly/atomic.h>
|
||||
#include <poly/config.h>
|
||||
#include <poly/cxx_compat.h>
|
||||
#include <poly/math.h>
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
{
|
||||
'sources': [
|
||||
'assert.h',
|
||||
'atomic.h',
|
||||
'config.h',
|
||||
'cxx_compat.h',
|
||||
'math.h',
|
||||
|
|
|
@ -1,100 +0,0 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* 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 <cstdint>
|
||||
|
||||
#include <xenia/platform.h>
|
||||
#include <xenia/types.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_exchange_32(newValue, value) \
|
||||
TODOTODO
|
||||
#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_exchange_32(newValue, value) \
|
||||
InterlockedExchange((volatile LONG*)value, newValue)
|
||||
#define xe_atomic_exchange_64(newValue, value) \
|
||||
InterlockedExchange64((volatile LONGLONG*)value, newValue)
|
||||
#define xe_atomic_cas_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) {
|
||||
return (void*)(((uint8_t*)ptr) - offset);
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#elif XE_LIKE_POSIX
|
||||
|
||||
#define xe_atomic_inc_32(value) \
|
||||
__sync_add_and_fetch(value, 1)
|
||||
#define xe_atomic_dec_32(value) \
|
||||
__sync_sub_and_fetch(value, 1)
|
||||
#define xe_atomic_add_32(amount, value) \
|
||||
__sync_fetch_and_add(value, amount)
|
||||
#define xe_atomic_sub_32(amount, value) \
|
||||
__sync_fetch_and_sub(value, amount)
|
||||
#define xe_atomic_exchange_32(newValue, value) \
|
||||
TODOTODO
|
||||
#define xe_atomic_cas_32(oldValue, newValue, value) \
|
||||
__sync_bool_compare_and_swap(value, oldValue, newValue)
|
||||
|
||||
#else
|
||||
|
||||
#error No atomic primitives defined for this platform/cpu combination.
|
||||
|
||||
#endif // OSX
|
||||
|
||||
|
||||
#endif // XENIA_ATOMIC_H_
|
|
@ -11,8 +11,8 @@
|
|||
#define XENIA_COMMON_H_
|
||||
|
||||
#include <poly/assert.h>
|
||||
#include <poly/atomic.h>
|
||||
|
||||
#include <xenia/atomic.h>
|
||||
#include <xenia/byte_order.h>
|
||||
#include <xenia/config.h>
|
||||
#include <xenia/logging.h>
|
||||
|
|
|
@ -15,14 +15,14 @@ void xe_ref_init(xe_ref_t* ref) {
|
|||
}
|
||||
|
||||
void xe_ref_retain(xe_ref_t* ref) {
|
||||
xe_atomic_inc_32(&ref->count);
|
||||
poly::atomic_inc(&ref->count);
|
||||
}
|
||||
|
||||
void xe_ref_release(xe_ref_t* ref, xe_ref_dealloc_t dealloc) {
|
||||
if (!ref) {
|
||||
return;
|
||||
}
|
||||
if (!xe_atomic_dec_32(&ref->count)) {
|
||||
if (!poly::atomic_dec(&ref->count)) {
|
||||
if (dealloc) {
|
||||
dealloc(ref);
|
||||
}
|
||||
|
|
|
@ -76,7 +76,7 @@ volatile int* XenonThreadState::suspend_flag_address() const {
|
|||
int XenonThreadState::Suspend(uint32_t timeout_ms) {
|
||||
// Set suspend flag.
|
||||
// One of the checks should call in to OnSuspend() at some point.
|
||||
xe_atomic_inc_32(&context_->suspend_flag);
|
||||
poly::atomic_inc(&context_->suspend_flag);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -86,7 +86,7 @@ int XenonThreadState::Resume(bool force) {
|
|||
context_->suspend_flag = 0;
|
||||
SetEvent(debug_break_);
|
||||
} else {
|
||||
if (!xe_atomic_dec_32(&context_->suspend_flag)) {
|
||||
if (!poly::atomic_dec(&context_->suspend_flag)) {
|
||||
SetEvent(debug_break_);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -406,7 +406,7 @@ void XThread::LeaveCriticalRegion() {
|
|||
}
|
||||
|
||||
uint32_t XThread::RaiseIrql(uint32_t new_irql) {
|
||||
return xe_atomic_exchange_32(new_irql, &irql_);
|
||||
return irql_.exchange(new_irql);
|
||||
}
|
||||
|
||||
void XThread::LowerIrql(uint32_t new_irql) {
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#ifndef XENIA_KERNEL_XBOXKRNL_XTHREAD_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_XTHREAD_H_
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#include <xenia/kernel/xobject.h>
|
||||
|
||||
#include <xenia/xbox.h>
|
||||
|
@ -94,7 +96,7 @@ private:
|
|||
|
||||
char* name_;
|
||||
|
||||
uint32_t irql_;
|
||||
std::atomic<uint32_t> irql_;
|
||||
xe_mutex_t* apc_lock_;
|
||||
NativeList* apc_list_;
|
||||
|
||||
|
|
|
@ -606,13 +606,13 @@ void xeRtlEnterCriticalSection(uint32_t cs_ptr, uint32_t thread_id) {
|
|||
|
||||
uint32_t spin_wait_remaining = cs->spin_count_div_256 * 256;
|
||||
spin:
|
||||
if (xe_atomic_inc_32(&cs->lock_count) != 0) {
|
||||
if (poly::atomic_inc(&cs->lock_count) != 0) {
|
||||
// If this thread already owns the CS increment the recursion count.
|
||||
if (cs->owning_thread_id == thread_id) {
|
||||
cs->recursion_count++;
|
||||
return;
|
||||
}
|
||||
xe_atomic_dec_32(&cs->lock_count);
|
||||
poly::atomic_dec(&cs->lock_count);
|
||||
|
||||
// Thread was locked - spin wait.
|
||||
if (spin_wait_remaining) {
|
||||
|
@ -658,13 +658,13 @@ uint32_t xeRtlTryEnterCriticalSection(uint32_t cs_ptr, uint32_t thread_id) {
|
|||
|
||||
X_RTL_CRITICAL_SECTION* cs = (X_RTL_CRITICAL_SECTION*)IMPL_MEM_ADDR(cs_ptr);
|
||||
|
||||
if (xe_atomic_cas_32(-1, 0, &cs->lock_count)) {
|
||||
if (poly::atomic_cas(-1, 0, &cs->lock_count)) {
|
||||
// Able to steal the lock right away.
|
||||
cs->owning_thread_id = thread_id;
|
||||
cs->recursion_count = 1;
|
||||
return 1;
|
||||
} else if (cs->owning_thread_id == thread_id) {
|
||||
xe_atomic_inc_32(&cs->lock_count);
|
||||
poly::atomic_inc(&cs->lock_count);
|
||||
++cs->recursion_count;
|
||||
return 1;
|
||||
}
|
||||
|
@ -699,13 +699,13 @@ void xeRtlLeaveCriticalSection(uint32_t cs_ptr) {
|
|||
// Drop recursion count - if we are still not zero'ed return.
|
||||
uint32_t recursion_count = --cs->recursion_count;
|
||||
if (recursion_count) {
|
||||
xe_atomic_dec_32(&cs->lock_count);
|
||||
poly::atomic_dec(&cs->lock_count);
|
||||
return;
|
||||
}
|
||||
|
||||
// Unlock!
|
||||
cs->owning_thread_id = 0;
|
||||
if (xe_atomic_dec_32(&cs->lock_count) != -1) {
|
||||
if (poly::atomic_dec(&cs->lock_count) != -1) {
|
||||
// There were waiters - wake one of them.
|
||||
// TODO(benvanik): wake a waiter.
|
||||
XELOGE("RtlLeaveCriticalSection would have woken a waiter");
|
||||
|
|
|
@ -1258,9 +1258,9 @@ SHIM_CALL NtSignalAndWaitForSingleObjectEx_shim(
|
|||
}
|
||||
|
||||
|
||||
uint32_t xeKfAcquireSpinLock(void* lock_ptr) {
|
||||
uint32_t xeKfAcquireSpinLock(uint32_t* lock_ptr) {
|
||||
// Lock.
|
||||
while (!xe_atomic_cas_32(0, 1, lock_ptr)) {
|
||||
while (!poly::atomic_cas(0, 1, lock_ptr)) {
|
||||
// Spin!
|
||||
// TODO(benvanik): error on deadlock?
|
||||
}
|
||||
|
@ -1279,19 +1279,20 @@ SHIM_CALL KfAcquireSpinLock_shim(
|
|||
"KfAcquireSpinLock(%.8X)",
|
||||
lock_ptr);
|
||||
|
||||
uint32_t old_irql = xeKfAcquireSpinLock(SHIM_MEM_ADDR(lock_ptr));
|
||||
auto lock = reinterpret_cast<uint32_t*>(SHIM_MEM_ADDR(lock_ptr));
|
||||
uint32_t old_irql = xeKfAcquireSpinLock(lock);
|
||||
|
||||
SHIM_SET_RETURN_64(old_irql);
|
||||
}
|
||||
|
||||
|
||||
void xeKfReleaseSpinLock(void* lock_ptr, uint32_t old_irql) {
|
||||
void xeKfReleaseSpinLock(uint32_t* lock_ptr, uint32_t old_irql) {
|
||||
// Restore IRQL.
|
||||
XThread* thread = XThread::GetCurrentThread();
|
||||
thread->LowerIrql(old_irql);
|
||||
|
||||
// Unlock.
|
||||
xe_atomic_dec_32(lock_ptr);
|
||||
poly::atomic_dec(lock_ptr);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1305,7 +1306,8 @@ SHIM_CALL KfReleaseSpinLock_shim(
|
|||
lock_ptr,
|
||||
old_irql);
|
||||
|
||||
xeKfReleaseSpinLock(SHIM_MEM_ADDR(lock_ptr), old_irql);
|
||||
xeKfReleaseSpinLock(reinterpret_cast<uint32_t*>(SHIM_MEM_ADDR(lock_ptr)),
|
||||
old_irql);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1318,8 +1320,8 @@ SHIM_CALL KeAcquireSpinLockAtRaisedIrql_shim(
|
|||
lock_ptr);
|
||||
|
||||
// Lock.
|
||||
void* lock = SHIM_MEM_ADDR(lock_ptr);
|
||||
while (!xe_atomic_cas_32(0, 1, lock)) {
|
||||
auto lock = reinterpret_cast<uint32_t*>(SHIM_MEM_ADDR(lock_ptr));
|
||||
while (!poly::atomic_cas(0, 1, lock)) {
|
||||
// Spin!
|
||||
// TODO(benvanik): error on deadlock?
|
||||
}
|
||||
|
@ -1335,8 +1337,8 @@ SHIM_CALL KeReleaseSpinLockFromRaisedIrql_shim(
|
|||
lock_ptr);
|
||||
|
||||
// Unlock.
|
||||
void* lock = SHIM_MEM_ADDR(lock_ptr);
|
||||
xe_atomic_dec_32(lock);
|
||||
auto lock = reinterpret_cast<uint32_t*>(SHIM_MEM_ADDR(lock_ptr));
|
||||
poly::atomic_dec(lock);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -52,8 +52,8 @@ X_STATUS xeKeWaitForSingleObject(
|
|||
void* object_ptr, uint32_t wait_reason, uint32_t processor_mode,
|
||||
uint32_t alertable, uint64_t* opt_timeout);
|
||||
|
||||
uint32_t xeKfAcquireSpinLock(void* lock_ptr);
|
||||
void xeKfReleaseSpinLock(void* lock_ptr, uint32_t old_irql);
|
||||
uint32_t xeKfAcquireSpinLock(uint32_t* lock_ptr);
|
||||
void xeKfReleaseSpinLock(uint32_t* lock_ptr, uint32_t old_irql);
|
||||
|
||||
void xeKeEnterCriticalRegion();
|
||||
void xeKeLeaveCriticalRegion();
|
||||
|
|
|
@ -46,22 +46,22 @@ X_HANDLE XObject::handle() const {
|
|||
}
|
||||
|
||||
void XObject::RetainHandle() {
|
||||
xe_atomic_inc_32(&handle_ref_count_);
|
||||
++handle_ref_count_;
|
||||
}
|
||||
|
||||
bool XObject::ReleaseHandle() {
|
||||
if (!xe_atomic_dec_32(&handle_ref_count_)) {
|
||||
if (--handle_ref_count_ == 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void XObject::Retain() {
|
||||
xe_atomic_inc_32(&pointer_ref_count_);
|
||||
++pointer_ref_count_;
|
||||
}
|
||||
|
||||
void XObject::Release() {
|
||||
if (!xe_atomic_dec_32(&pointer_ref_count_)) {
|
||||
if (--pointer_ref_count_ == 0) {
|
||||
assert_true(pointer_ref_count_ >= handle_ref_count_);
|
||||
delete this;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#ifndef XENIA_KERNEL_XBOXKRNL_XOBJECT_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_XOBJECT_H_
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#include <xenia/kernel/kernel_state.h>
|
||||
|
||||
#include <xenia/xbox.h>
|
||||
|
@ -87,8 +89,8 @@ protected:
|
|||
KernelState* kernel_state_;
|
||||
|
||||
private:
|
||||
volatile int32_t handle_ref_count_;
|
||||
volatile int32_t pointer_ref_count_;
|
||||
std::atomic<int32_t> handle_ref_count_;
|
||||
std::atomic<int32_t> pointer_ref_count_;
|
||||
|
||||
Type type_;
|
||||
X_HANDLE handle_;
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
# Copyright 2013 Ben Vanik. All Rights Reserved.
|
||||
{
|
||||
'sources': [
|
||||
'atomic.h',
|
||||
'byte_order.h',
|
||||
'common.h',
|
||||
'config.h',
|
||||
|
|
Loading…
Reference in New Issue