mirror of
https://github.com/hedge-dev/UnleashedRecomp.git
synced 2026-04-27 04:41:39 +00:00
Cross-platform atomic operations. (#44)
* Cross-platform spin lock implementation. * Cross-platform reference counting.
This commit is contained in:
parent
5642576cea
commit
4770e85573
4 changed files with 41 additions and 13 deletions
|
|
@ -44,22 +44,26 @@ namespace Hedgehog::Base
|
||||||
|
|
||||||
inline void SStringHolder::AddRef()
|
inline void SStringHolder::AddRef()
|
||||||
{
|
{
|
||||||
|
std::atomic_ref atomicRef(RefCountAndLength.value);
|
||||||
|
|
||||||
uint32_t originalValue, incrementedValue;
|
uint32_t originalValue, incrementedValue;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
originalValue = RefCountAndLength.value;
|
originalValue = RefCountAndLength.value;
|
||||||
incrementedValue = ByteSwap(ByteSwap(originalValue) + 1);
|
incrementedValue = ByteSwap(ByteSwap(originalValue) + 1);
|
||||||
} while (InterlockedCompareExchange(reinterpret_cast<LONG*>(&RefCountAndLength), incrementedValue, originalValue) != originalValue);
|
} while (!atomicRef.compare_exchange_weak(originalValue, incrementedValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void SStringHolder::Release()
|
inline void SStringHolder::Release()
|
||||||
{
|
{
|
||||||
|
std::atomic_ref atomicRef(RefCountAndLength.value);
|
||||||
|
|
||||||
uint32_t originalValue, decrementedValue;
|
uint32_t originalValue, decrementedValue;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
originalValue = RefCountAndLength.value;
|
originalValue = RefCountAndLength.value;
|
||||||
decrementedValue = ByteSwap(ByteSwap(originalValue) - 1);
|
decrementedValue = ByteSwap(ByteSwap(originalValue) - 1);
|
||||||
} while (InterlockedCompareExchange(reinterpret_cast<LONG*>(&RefCountAndLength), decrementedValue, originalValue) != originalValue);
|
} while (!atomicRef.compare_exchange_weak(originalValue, decrementedValue));
|
||||||
|
|
||||||
if (RefCountAndLength == 0)
|
if (RefCountAndLength == 0)
|
||||||
__HH_FREE(this);
|
__HH_FREE(this);
|
||||||
|
|
|
||||||
|
|
@ -28,22 +28,26 @@ namespace boost
|
||||||
|
|
||||||
void add_ref()
|
void add_ref()
|
||||||
{
|
{
|
||||||
|
std::atomic_ref useCount(use_count_.value);
|
||||||
|
|
||||||
be<uint32_t> original, incremented;
|
be<uint32_t> original, incremented;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
original = use_count_;
|
original = use_count_;
|
||||||
incremented = original + 1;
|
incremented = original + 1;
|
||||||
} while (InterlockedCompareExchange((unsigned long*)&use_count_, incremented.value, original.value) != original.value);
|
} while (!useCount.compare_exchange_weak(original.value, incremented.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
void release()
|
void release()
|
||||||
{
|
{
|
||||||
|
std::atomic_ref useCount(use_count_.value);
|
||||||
|
|
||||||
be<uint32_t> original, decremented;
|
be<uint32_t> original, decremented;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
original = use_count_;
|
original = use_count_;
|
||||||
decremented = original - 1;
|
decremented = original - 1;
|
||||||
} while (InterlockedCompareExchange((unsigned long*)&use_count_, decremented.value, original.value) != original.value);
|
} while (!useCount.compare_exchange_weak(original.value, decremented.value));
|
||||||
|
|
||||||
if (decremented == 0)
|
if (decremented == 0)
|
||||||
{
|
{
|
||||||
|
|
@ -54,12 +58,14 @@ namespace boost
|
||||||
|
|
||||||
void weak_release()
|
void weak_release()
|
||||||
{
|
{
|
||||||
|
std::atomic_ref weakCount(weak_count_.value);
|
||||||
|
|
||||||
be<uint32_t> original, decremented;
|
be<uint32_t> original, decremented;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
original = weak_count_;
|
original = weak_count_;
|
||||||
decremented = original - 1;
|
decremented = original - 1;
|
||||||
} while (InterlockedCompareExchange((unsigned long*)&weak_count_, decremented.value, original.value) != original.value);
|
} while (!weakCount.compare_exchange_weak(original.value, decremented.value));
|
||||||
|
|
||||||
if (decremented == 0)
|
if (decremented == 0)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -84,22 +84,26 @@ struct GuestResource
|
||||||
|
|
||||||
void AddRef()
|
void AddRef()
|
||||||
{
|
{
|
||||||
|
std::atomic_ref atomicRef(refCount.value);
|
||||||
|
|
||||||
uint32_t originalValue, incrementedValue;
|
uint32_t originalValue, incrementedValue;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
originalValue = refCount.value;
|
originalValue = refCount.value;
|
||||||
incrementedValue = ByteSwap(ByteSwap(originalValue) + 1);
|
incrementedValue = ByteSwap(ByteSwap(originalValue) + 1);
|
||||||
} while (InterlockedCompareExchange(reinterpret_cast<LONG*>(&refCount), incrementedValue, originalValue) != originalValue);
|
} while (!atomicRef.compare_exchange_weak(originalValue, incrementedValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Release()
|
void Release()
|
||||||
{
|
{
|
||||||
|
std::atomic_ref atomicRef(refCount.value);
|
||||||
|
|
||||||
uint32_t originalValue, decrementedValue;
|
uint32_t originalValue, decrementedValue;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
originalValue = refCount.value;
|
originalValue = refCount.value;
|
||||||
decrementedValue = ByteSwap(ByteSwap(originalValue) - 1);
|
decrementedValue = ByteSwap(ByteSwap(originalValue) - 1);
|
||||||
} while (InterlockedCompareExchange(reinterpret_cast<LONG*>(&refCount), decrementedValue, originalValue) != originalValue);
|
} while (!atomicRef.compare_exchange_weak(originalValue, decrementedValue));
|
||||||
|
|
||||||
// Normally we are supposed to release here, so only use this
|
// Normally we are supposed to release here, so only use this
|
||||||
// function when you know you won't be the one destructing it.
|
// function when you know you won't be the one destructing it.
|
||||||
|
|
|
||||||
|
|
@ -695,15 +695,22 @@ void RtlRaiseException_x()
|
||||||
|
|
||||||
void KfReleaseSpinLock(uint32_t* spinLock)
|
void KfReleaseSpinLock(uint32_t* spinLock)
|
||||||
{
|
{
|
||||||
InterlockedExchange((volatile long*)spinLock, 0);
|
std::atomic_ref spinLockRef(*spinLock);
|
||||||
|
spinLockRef = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KfAcquireSpinLock(uint32_t* spinLock)
|
void KfAcquireSpinLock(uint32_t* spinLock)
|
||||||
{
|
{
|
||||||
const auto ctx = GetPPCContext();
|
std::atomic_ref spinLockRef(*spinLock);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
uint32_t expected = 0;
|
||||||
|
if (spinLockRef.compare_exchange_weak(expected, g_ppcContext->r13.u32))
|
||||||
|
break;
|
||||||
|
|
||||||
while (InterlockedCompareExchange((volatile long*)spinLock, ByteSwap(*(uint32_t*)(g_memory.Translate(ctx->r13.u32 + 0x110))), 0) != 0)
|
|
||||||
std::this_thread::yield();
|
std::this_thread::yield();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t KeQueryPerformanceFrequency()
|
uint64_t KeQueryPerformanceFrequency()
|
||||||
|
|
@ -735,15 +742,22 @@ void VdGetSystemCommandBuffer()
|
||||||
|
|
||||||
void KeReleaseSpinLockFromRaisedIrql(uint32_t* spinLock)
|
void KeReleaseSpinLockFromRaisedIrql(uint32_t* spinLock)
|
||||||
{
|
{
|
||||||
InterlockedExchange((volatile long*)spinLock, 0);
|
std::atomic_ref spinLockRef(*spinLock);
|
||||||
|
spinLockRef = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeAcquireSpinLockAtRaisedIrql(uint32_t* spinLock)
|
void KeAcquireSpinLockAtRaisedIrql(uint32_t* spinLock)
|
||||||
{
|
{
|
||||||
const auto ctx = GetPPCContext();
|
std::atomic_ref spinLockRef(*spinLock);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
uint32_t expected = 0;
|
||||||
|
if (spinLockRef.compare_exchange_weak(expected, g_ppcContext->r13.u32))
|
||||||
|
break;
|
||||||
|
|
||||||
while (InterlockedCompareExchange((volatile long*)spinLock, ByteSwap(*(uint32_t*)(g_memory.Translate(ctx->r13.u32 + 0x110))), 0) != 0)
|
|
||||||
std::this_thread::yield();
|
std::this_thread::yield();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t KiApcNormalRoutineNop()
|
uint32_t KiApcNormalRoutineNop()
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue