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,9 +128,23 @@ namespace coreinit
else else
{ {
// loop until lock acquired // loop until lock acquired
while (!spinlock->ownerThread.atomic_compare_exchange(nullptr, currentThread)) if (coreinit::__CemuIsMulticoreMode())
{ {
OSYieldThread(); 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); __OSBoostThread(currentThread);

View File

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

View File

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