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) {
|
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 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;
|
ics.rf[i->dest_reg].u32 = old_value;
|
||||||
return IA_NEXT;
|
return IA_NEXT;
|
||||||
}
|
}
|
||||||
uint32_t IntCode_ATOMIC_EXCHANGE_I64(IntCodeState& ics, const IntCode* i) {
|
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 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;
|
ics.rf[i->dest_reg].u64 = old_value;
|
||||||
return IA_NEXT;
|
return IA_NEXT;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
#define ALLOY_CORE_H_
|
#define ALLOY_CORE_H_
|
||||||
|
|
||||||
// TODO(benvanik): move the common stuff into here?
|
// TODO(benvanik): move the common stuff into here?
|
||||||
#include <xenia/atomic.h>
|
|
||||||
#include <xenia/byte_order.h>
|
#include <xenia/byte_order.h>
|
||||||
#include <xenia/config.h>
|
#include <xenia/config.h>
|
||||||
#include <xenia/logging.h>
|
#include <xenia/logging.h>
|
||||||
|
|
|
@ -9,15 +9,17 @@
|
||||||
|
|
||||||
#include <alloy/tracing/tracer.h>
|
#include <alloy/tracing/tracer.h>
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
#include <alloy/tracing/channel.h>
|
#include <alloy/tracing/channel.h>
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
namespace tracing {
|
namespace tracing {
|
||||||
|
|
||||||
volatile int next_thread_id_ = 0x10000000;
|
std::atomic<int> next_thread_id_(0x10000000);
|
||||||
|
|
||||||
Tracer::Tracer(Channel* channel) : channel_(channel) {
|
Tracer::Tracer(Channel* channel) : channel_(channel) {
|
||||||
thread_id_ = xe_atomic_inc_32(&next_thread_id_);
|
thread_id_ = ++next_thread_id_;
|
||||||
}
|
}
|
||||||
|
|
||||||
Tracer::~Tracer() {}
|
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_
|
#define POLY_POLY_H_
|
||||||
|
|
||||||
#include <poly/assert.h>
|
#include <poly/assert.h>
|
||||||
|
#include <poly/atomic.h>
|
||||||
#include <poly/config.h>
|
#include <poly/config.h>
|
||||||
#include <poly/cxx_compat.h>
|
#include <poly/cxx_compat.h>
|
||||||
#include <poly/math.h>
|
#include <poly/math.h>
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
{
|
{
|
||||||
'sources': [
|
'sources': [
|
||||||
'assert.h',
|
'assert.h',
|
||||||
|
'atomic.h',
|
||||||
'config.h',
|
'config.h',
|
||||||
'cxx_compat.h',
|
'cxx_compat.h',
|
||||||
'math.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_
|
#define XENIA_COMMON_H_
|
||||||
|
|
||||||
#include <poly/assert.h>
|
#include <poly/assert.h>
|
||||||
|
#include <poly/atomic.h>
|
||||||
|
|
||||||
#include <xenia/atomic.h>
|
|
||||||
#include <xenia/byte_order.h>
|
#include <xenia/byte_order.h>
|
||||||
#include <xenia/config.h>
|
#include <xenia/config.h>
|
||||||
#include <xenia/logging.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) {
|
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) {
|
void xe_ref_release(xe_ref_t* ref, xe_ref_dealloc_t dealloc) {
|
||||||
if (!ref) {
|
if (!ref) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!xe_atomic_dec_32(&ref->count)) {
|
if (!poly::atomic_dec(&ref->count)) {
|
||||||
if (dealloc) {
|
if (dealloc) {
|
||||||
dealloc(ref);
|
dealloc(ref);
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,7 +76,7 @@ volatile int* XenonThreadState::suspend_flag_address() const {
|
||||||
int XenonThreadState::Suspend(uint32_t timeout_ms) {
|
int XenonThreadState::Suspend(uint32_t timeout_ms) {
|
||||||
// Set suspend flag.
|
// Set suspend flag.
|
||||||
// One of the checks should call in to OnSuspend() at some point.
|
// 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ int XenonThreadState::Resume(bool force) {
|
||||||
context_->suspend_flag = 0;
|
context_->suspend_flag = 0;
|
||||||
SetEvent(debug_break_);
|
SetEvent(debug_break_);
|
||||||
} else {
|
} else {
|
||||||
if (!xe_atomic_dec_32(&context_->suspend_flag)) {
|
if (!poly::atomic_dec(&context_->suspend_flag)) {
|
||||||
SetEvent(debug_break_);
|
SetEvent(debug_break_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -406,7 +406,7 @@ void XThread::LeaveCriticalRegion() {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t XThread::RaiseIrql(uint32_t new_irql) {
|
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) {
|
void XThread::LowerIrql(uint32_t new_irql) {
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
#ifndef XENIA_KERNEL_XBOXKRNL_XTHREAD_H_
|
#ifndef XENIA_KERNEL_XBOXKRNL_XTHREAD_H_
|
||||||
#define XENIA_KERNEL_XBOXKRNL_XTHREAD_H_
|
#define XENIA_KERNEL_XBOXKRNL_XTHREAD_H_
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
#include <xenia/kernel/xobject.h>
|
#include <xenia/kernel/xobject.h>
|
||||||
|
|
||||||
#include <xenia/xbox.h>
|
#include <xenia/xbox.h>
|
||||||
|
@ -94,7 +96,7 @@ private:
|
||||||
|
|
||||||
char* name_;
|
char* name_;
|
||||||
|
|
||||||
uint32_t irql_;
|
std::atomic<uint32_t> irql_;
|
||||||
xe_mutex_t* apc_lock_;
|
xe_mutex_t* apc_lock_;
|
||||||
NativeList* apc_list_;
|
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;
|
uint32_t spin_wait_remaining = cs->spin_count_div_256 * 256;
|
||||||
spin:
|
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 this thread already owns the CS increment the recursion count.
|
||||||
if (cs->owning_thread_id == thread_id) {
|
if (cs->owning_thread_id == thread_id) {
|
||||||
cs->recursion_count++;
|
cs->recursion_count++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
xe_atomic_dec_32(&cs->lock_count);
|
poly::atomic_dec(&cs->lock_count);
|
||||||
|
|
||||||
// Thread was locked - spin wait.
|
// Thread was locked - spin wait.
|
||||||
if (spin_wait_remaining) {
|
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);
|
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.
|
// Able to steal the lock right away.
|
||||||
cs->owning_thread_id = thread_id;
|
cs->owning_thread_id = thread_id;
|
||||||
cs->recursion_count = 1;
|
cs->recursion_count = 1;
|
||||||
return 1;
|
return 1;
|
||||||
} else if (cs->owning_thread_id == thread_id) {
|
} else if (cs->owning_thread_id == thread_id) {
|
||||||
xe_atomic_inc_32(&cs->lock_count);
|
poly::atomic_inc(&cs->lock_count);
|
||||||
++cs->recursion_count;
|
++cs->recursion_count;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -699,13 +699,13 @@ void xeRtlLeaveCriticalSection(uint32_t cs_ptr) {
|
||||||
// Drop recursion count - if we are still not zero'ed return.
|
// Drop recursion count - if we are still not zero'ed return.
|
||||||
uint32_t recursion_count = --cs->recursion_count;
|
uint32_t recursion_count = --cs->recursion_count;
|
||||||
if (recursion_count) {
|
if (recursion_count) {
|
||||||
xe_atomic_dec_32(&cs->lock_count);
|
poly::atomic_dec(&cs->lock_count);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unlock!
|
// Unlock!
|
||||||
cs->owning_thread_id = 0;
|
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.
|
// There were waiters - wake one of them.
|
||||||
// TODO(benvanik): wake a waiter.
|
// TODO(benvanik): wake a waiter.
|
||||||
XELOGE("RtlLeaveCriticalSection would have woken 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.
|
// Lock.
|
||||||
while (!xe_atomic_cas_32(0, 1, lock_ptr)) {
|
while (!poly::atomic_cas(0, 1, lock_ptr)) {
|
||||||
// Spin!
|
// Spin!
|
||||||
// TODO(benvanik): error on deadlock?
|
// TODO(benvanik): error on deadlock?
|
||||||
}
|
}
|
||||||
|
@ -1279,19 +1279,20 @@ SHIM_CALL KfAcquireSpinLock_shim(
|
||||||
"KfAcquireSpinLock(%.8X)",
|
"KfAcquireSpinLock(%.8X)",
|
||||||
lock_ptr);
|
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);
|
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.
|
// Restore IRQL.
|
||||||
XThread* thread = XThread::GetCurrentThread();
|
XThread* thread = XThread::GetCurrentThread();
|
||||||
thread->LowerIrql(old_irql);
|
thread->LowerIrql(old_irql);
|
||||||
|
|
||||||
// Unlock.
|
// Unlock.
|
||||||
xe_atomic_dec_32(lock_ptr);
|
poly::atomic_dec(lock_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1305,7 +1306,8 @@ SHIM_CALL KfReleaseSpinLock_shim(
|
||||||
lock_ptr,
|
lock_ptr,
|
||||||
old_irql);
|
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_ptr);
|
||||||
|
|
||||||
// Lock.
|
// Lock.
|
||||||
void* lock = SHIM_MEM_ADDR(lock_ptr);
|
auto lock = reinterpret_cast<uint32_t*>(SHIM_MEM_ADDR(lock_ptr));
|
||||||
while (!xe_atomic_cas_32(0, 1, lock)) {
|
while (!poly::atomic_cas(0, 1, lock)) {
|
||||||
// Spin!
|
// Spin!
|
||||||
// TODO(benvanik): error on deadlock?
|
// TODO(benvanik): error on deadlock?
|
||||||
}
|
}
|
||||||
|
@ -1335,8 +1337,8 @@ SHIM_CALL KeReleaseSpinLockFromRaisedIrql_shim(
|
||||||
lock_ptr);
|
lock_ptr);
|
||||||
|
|
||||||
// Unlock.
|
// Unlock.
|
||||||
void* lock = SHIM_MEM_ADDR(lock_ptr);
|
auto lock = reinterpret_cast<uint32_t*>(SHIM_MEM_ADDR(lock_ptr));
|
||||||
xe_atomic_dec_32(lock);
|
poly::atomic_dec(lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -52,8 +52,8 @@ X_STATUS xeKeWaitForSingleObject(
|
||||||
void* object_ptr, uint32_t wait_reason, uint32_t processor_mode,
|
void* object_ptr, uint32_t wait_reason, uint32_t processor_mode,
|
||||||
uint32_t alertable, uint64_t* opt_timeout);
|
uint32_t alertable, uint64_t* opt_timeout);
|
||||||
|
|
||||||
uint32_t xeKfAcquireSpinLock(void* lock_ptr);
|
uint32_t xeKfAcquireSpinLock(uint32_t* lock_ptr);
|
||||||
void xeKfReleaseSpinLock(void* lock_ptr, uint32_t old_irql);
|
void xeKfReleaseSpinLock(uint32_t* lock_ptr, uint32_t old_irql);
|
||||||
|
|
||||||
void xeKeEnterCriticalRegion();
|
void xeKeEnterCriticalRegion();
|
||||||
void xeKeLeaveCriticalRegion();
|
void xeKeLeaveCriticalRegion();
|
||||||
|
|
|
@ -46,22 +46,22 @@ X_HANDLE XObject::handle() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void XObject::RetainHandle() {
|
void XObject::RetainHandle() {
|
||||||
xe_atomic_inc_32(&handle_ref_count_);
|
++handle_ref_count_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool XObject::ReleaseHandle() {
|
bool XObject::ReleaseHandle() {
|
||||||
if (!xe_atomic_dec_32(&handle_ref_count_)) {
|
if (--handle_ref_count_ == 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void XObject::Retain() {
|
void XObject::Retain() {
|
||||||
xe_atomic_inc_32(&pointer_ref_count_);
|
++pointer_ref_count_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void XObject::Release() {
|
void XObject::Release() {
|
||||||
if (!xe_atomic_dec_32(&pointer_ref_count_)) {
|
if (--pointer_ref_count_ == 0) {
|
||||||
assert_true(pointer_ref_count_ >= handle_ref_count_);
|
assert_true(pointer_ref_count_ >= handle_ref_count_);
|
||||||
delete this;
|
delete this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
#ifndef XENIA_KERNEL_XBOXKRNL_XOBJECT_H_
|
#ifndef XENIA_KERNEL_XBOXKRNL_XOBJECT_H_
|
||||||
#define XENIA_KERNEL_XBOXKRNL_XOBJECT_H_
|
#define XENIA_KERNEL_XBOXKRNL_XOBJECT_H_
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
#include <xenia/kernel/kernel_state.h>
|
#include <xenia/kernel/kernel_state.h>
|
||||||
|
|
||||||
#include <xenia/xbox.h>
|
#include <xenia/xbox.h>
|
||||||
|
@ -87,8 +89,8 @@ protected:
|
||||||
KernelState* kernel_state_;
|
KernelState* kernel_state_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
volatile int32_t handle_ref_count_;
|
std::atomic<int32_t> handle_ref_count_;
|
||||||
volatile int32_t pointer_ref_count_;
|
std::atomic<int32_t> pointer_ref_count_;
|
||||||
|
|
||||||
Type type_;
|
Type type_;
|
||||||
X_HANDLE handle_;
|
X_HANDLE handle_;
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
# Copyright 2013 Ben Vanik. All Rights Reserved.
|
# Copyright 2013 Ben Vanik. All Rights Reserved.
|
||||||
{
|
{
|
||||||
'sources': [
|
'sources': [
|
||||||
'atomic.h',
|
|
||||||
'byte_order.h',
|
'byte_order.h',
|
||||||
'common.h',
|
'common.h',
|
||||||
'config.h',
|
'config.h',
|
||||||
|
|
Loading…
Reference in New Issue