mirror of
https://github.com/hedge-dev/UnleashedRecomp.git
synced 2026-04-27 12:51:42 +00:00
Implement guest critical sections using std::atomic.
This commit is contained in:
parent
7f45cb942d
commit
c4b21bde8b
3 changed files with 26 additions and 41 deletions
|
|
@ -1,13 +1,13 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
inline thread_local PPCContext* gPPCContext;
|
inline thread_local PPCContext* g_ppcContext;
|
||||||
|
|
||||||
inline PPCContext* GetPPCContext()
|
inline PPCContext* GetPPCContext()
|
||||||
{
|
{
|
||||||
return gPPCContext;
|
return g_ppcContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void SetPPCContext(PPCContext& ctx)
|
inline void SetPPCContext(PPCContext& ctx)
|
||||||
{
|
{
|
||||||
gPPCContext = &ctx;
|
g_ppcContext = &ctx;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4821,40 +4821,18 @@ struct PipelineStateQueueItem
|
||||||
|
|
||||||
static moodycamel::BlockingConcurrentQueue<PipelineStateQueueItem> g_pipelineStateQueue;
|
static moodycamel::BlockingConcurrentQueue<PipelineStateQueueItem> g_pipelineStateQueue;
|
||||||
|
|
||||||
struct MinimalGuestThreadContext
|
|
||||||
{
|
|
||||||
uint8_t* stack = nullptr;
|
|
||||||
PPCContext ppcContext{};
|
|
||||||
|
|
||||||
~MinimalGuestThreadContext()
|
|
||||||
{
|
|
||||||
if (stack != nullptr)
|
|
||||||
g_userHeap.Free(stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ensureValid()
|
|
||||||
{
|
|
||||||
if (stack == nullptr)
|
|
||||||
{
|
|
||||||
stack = reinterpret_cast<uint8_t*>(g_userHeap.Alloc(0x4000));
|
|
||||||
ppcContext.fn = (uint8_t*)g_codeCache.bucket;
|
|
||||||
ppcContext.r1.u64 = g_memory.MapVirtual(stack + 0x4000);
|
|
||||||
SetPPCContext(ppcContext);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static void PipelineCompilerThread()
|
static void PipelineCompilerThread()
|
||||||
{
|
{
|
||||||
GuestThread::SetThreadName(GetCurrentThreadId(), "Pipeline Compiler Thread");
|
GuestThread::SetThreadName(GetCurrentThreadId(), "Pipeline Compiler Thread");
|
||||||
MinimalGuestThreadContext ctx;
|
std::unique_ptr<GuestThreadContext> ctx;
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
PipelineStateQueueItem queueItem;
|
PipelineStateQueueItem queueItem;
|
||||||
g_pipelineStateQueue.wait_dequeue(queueItem);
|
g_pipelineStateQueue.wait_dequeue(queueItem);
|
||||||
|
|
||||||
ctx.ensureValid();
|
if (ctx == nullptr)
|
||||||
|
ctx = std::make_unique<GuestThreadContext>(0);
|
||||||
|
|
||||||
auto pipeline = CreateGraphicsPipeline(queueItem.pipelineState);
|
auto pipeline = CreateGraphicsPipeline(queueItem.pipelineState);
|
||||||
#ifdef ASYNC_PSO_DEBUG
|
#ifdef ASYNC_PSO_DEBUG
|
||||||
|
|
@ -5499,7 +5477,7 @@ static void ModelConsumerThread()
|
||||||
GuestThread::SetThreadName(GetCurrentThreadId(), "Model Consumer Thread");
|
GuestThread::SetThreadName(GetCurrentThreadId(), "Model Consumer Thread");
|
||||||
|
|
||||||
std::vector<boost::shared_ptr<Hedgehog::Database::CDatabaseData>> localPendingDataQueue;
|
std::vector<boost::shared_ptr<Hedgehog::Database::CDatabaseData>> localPendingDataQueue;
|
||||||
MinimalGuestThreadContext ctx;
|
std::unique_ptr<GuestThreadContext> ctx;
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
|
@ -5508,7 +5486,8 @@ static void ModelConsumerThread()
|
||||||
while ((pendingDataCount = g_pendingDataCount.load()) == 0)
|
while ((pendingDataCount = g_pendingDataCount.load()) == 0)
|
||||||
g_pendingDataCount.wait(pendingDataCount);
|
g_pendingDataCount.wait(pendingDataCount);
|
||||||
|
|
||||||
ctx.ensureValid();
|
if (ctx == nullptr)
|
||||||
|
ctx = std::make_unique<GuestThreadContext>(0);
|
||||||
|
|
||||||
if (g_pendingPipelineStateCache)
|
if (g_pendingPipelineStateCache)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -561,8 +561,6 @@ struct Semaphore : KernelObject, HostObject<XKSEMAPHORE>
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// https://devblogs.microsoft.com/oldnewthing/20160825-00/?p=94165
|
|
||||||
|
|
||||||
void RtlLeaveCriticalSection(XRTL_CRITICAL_SECTION* cs)
|
void RtlLeaveCriticalSection(XRTL_CRITICAL_SECTION* cs)
|
||||||
{
|
{
|
||||||
cs->RecursionCount--;
|
cs->RecursionCount--;
|
||||||
|
|
@ -570,25 +568,29 @@ void RtlLeaveCriticalSection(XRTL_CRITICAL_SECTION* cs)
|
||||||
if (cs->RecursionCount != 0)
|
if (cs->RecursionCount != 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
InterlockedExchange(&cs->OwningThread, 0);
|
std::atomic_ref owningThread(cs->OwningThread);
|
||||||
WakeByAddressSingle(&cs->OwningThread);
|
owningThread.store(0);
|
||||||
|
owningThread.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RtlEnterCriticalSection(XRTL_CRITICAL_SECTION* cs)
|
void RtlEnterCriticalSection(XRTL_CRITICAL_SECTION* cs)
|
||||||
{
|
{
|
||||||
DWORD thisThread = GetCurrentThreadId();
|
uint32_t thisThread = g_ppcContext->r13.u32;
|
||||||
|
assert(thisThread != NULL);
|
||||||
|
|
||||||
|
std::atomic_ref owningThread(cs->OwningThread);
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
DWORD previousOwner = InterlockedCompareExchangeAcquire(&cs->OwningThread, thisThread, 0);
|
uint32_t previousOwner = 0;
|
||||||
|
|
||||||
if (previousOwner == 0 || previousOwner == thisThread)
|
if (owningThread.compare_exchange_weak(previousOwner, thisThread) || previousOwner == thisThread)
|
||||||
{
|
{
|
||||||
cs->RecursionCount++;
|
cs->RecursionCount++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
WaitOnAddress(&cs->OwningThread, &previousOwner, sizeof(previousOwner), INFINITE);
|
owningThread.wait(previousOwner);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1036,10 +1038,14 @@ void XexGetModuleHandle()
|
||||||
|
|
||||||
bool RtlTryEnterCriticalSection(XRTL_CRITICAL_SECTION* cs)
|
bool RtlTryEnterCriticalSection(XRTL_CRITICAL_SECTION* cs)
|
||||||
{
|
{
|
||||||
DWORD thisThread = GetCurrentThreadId();
|
uint32_t thisThread = g_ppcContext->r13.u32;
|
||||||
DWORD previousOwner = InterlockedCompareExchangeAcquire(&cs->OwningThread, thisThread, 0);
|
assert(thisThread != NULL);
|
||||||
|
|
||||||
if (previousOwner == 0 || previousOwner == thisThread)
|
std::atomic_ref owningThread(cs->OwningThread);
|
||||||
|
|
||||||
|
uint32_t previousOwner = 0;
|
||||||
|
|
||||||
|
if (owningThread.compare_exchange_weak(previousOwner, thisThread) || previousOwner == thisThread)
|
||||||
{
|
{
|
||||||
cs->RecursionCount++;
|
cs->RecursionCount++;
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue