coreinit: Dont yield uninterruptible threads in spinlock

This commit is contained in:
Exzap 2023-01-27 09:15:27 +01:00
parent 387b712959
commit 859dc78e90
3 changed files with 23 additions and 2 deletions

View File

@ -128,11 +128,25 @@ namespace coreinit
else
{
// loop until lock acquired
if (coreinit::__CemuIsMulticoreMode())
{
while (!spinlock->ownerThread.atomic_compare_exchange(nullptr, currentThread))
{
_mm_pause();
}
}
else
{
// we are in single-core mode and the lock will never be released unless we let other threads resume work
// to avoid an infinite loop we have no choice but to yield the thread even it is in an uninterruptible state
if( !OSIsInterruptEnabled() )
cemuLog_log(LogType::APIErrors, "OSUninterruptibleSpinLock_Acquire(): Lock is occupied which requires a wait but current thread is already in an uninterruptible state (Avoid cascaded OSDisableInterrupts and/or OSUninterruptibleSpinLock)");
while (!spinlock->ownerThread.atomic_compare_exchange(nullptr, currentThread))
{
OSYieldThread();
}
}
}
__OSBoostThread(currentThread);
spinlock->interruptMask = OSDisableInterrupts();
cemu_assert_debug(spinlock->ownerThread == currentThread);

View File

@ -66,6 +66,11 @@ namespace coreinit
std::unordered_map<OSThread_t*, OSHostThread*> s_threadToFiber;
bool __CemuIsMulticoreMode()
{
return g_isMulticoreMode;
}
// create host thread (fiber) that will be used to run the PPC instance
// note that host threads are fibers and not actual threads
void __OSCreateHostThread(OSThread_t* thread)

View File

@ -488,6 +488,8 @@ namespace coreinit
void InitializeThread();
void InitializeConcurrency();
bool __CemuIsMulticoreMode();
OSThread_t* OSGetDefaultThread(sint32 coreIndex);
void* OSGetDefaultThreadStack(sint32 coreIndex, uint32& size);