mirror of
https://github.com/cemu-project/Cemu.git
synced 2024-11-26 11:04:18 +01:00
coreinit: Tweak JD2019 workaround to avoid XCX softlock
This commit is contained in:
parent
aadd2f4a1a
commit
1ee9d5c78c
@ -310,7 +310,7 @@ namespace coreinit
|
|||||||
currentThread->mutexQueue.removeMutex(mutex);
|
currentThread->mutexQueue.removeMutex(mutex);
|
||||||
mutex->owner = nullptr;
|
mutex->owner = nullptr;
|
||||||
if (!mutex->threadQueue.isEmpty())
|
if (!mutex->threadQueue.isEmpty())
|
||||||
mutex->threadQueue.wakeupSingleThreadWaitQueue(true);
|
mutex->threadQueue.wakeupSingleThreadWaitQueue(true, true);
|
||||||
}
|
}
|
||||||
// currentThread->cancelState = currentThread->cancelState & ~0x10000;
|
// currentThread->cancelState = currentThread->cancelState & ~0x10000;
|
||||||
}
|
}
|
||||||
|
@ -758,14 +758,14 @@ namespace coreinit
|
|||||||
}
|
}
|
||||||
|
|
||||||
// returns true if thread runs on same core and has higher priority
|
// returns true if thread runs on same core and has higher priority
|
||||||
bool __OSCoreShouldSwitchToThread(OSThread_t* currentThread, OSThread_t* newThread)
|
bool __OSCoreShouldSwitchToThread(OSThread_t* currentThread, OSThread_t* newThread, bool sharedPriorityAndAffinityWorkaround)
|
||||||
{
|
{
|
||||||
uint32 coreIndex = OSGetCoreId();
|
uint32 coreIndex = OSGetCoreId();
|
||||||
if (!newThread->context.hasCoreAffinitySet(coreIndex))
|
if (!newThread->context.hasCoreAffinitySet(coreIndex))
|
||||||
return false;
|
return false;
|
||||||
// special case: if current and new thread are running only on the same core then reschedule even if priority is equal
|
// special case: if current and new thread are running only on the same core then reschedule even if priority is equal
|
||||||
// this resolves a deadlock in Just Dance 2019 where one thread would always reacquire the same mutex within it's timeslice, blocking another thread on the same core from acquiring it
|
// this resolves a deadlock in Just Dance 2019 where one thread would always reacquire the same mutex within it's timeslice, blocking another thread on the same core from acquiring it
|
||||||
if ((1<<coreIndex) == newThread->context.affinity && currentThread->context.affinity == newThread->context.affinity && currentThread->effectivePriority == newThread->effectivePriority)
|
if (sharedPriorityAndAffinityWorkaround && (1<<coreIndex) == newThread->context.affinity && currentThread->context.affinity == newThread->context.affinity && currentThread->effectivePriority == newThread->effectivePriority)
|
||||||
return true;
|
return true;
|
||||||
// otherwise reschedule if new thread has higher priority
|
// otherwise reschedule if new thread has higher priority
|
||||||
return newThread->effectivePriority < currentThread->effectivePriority;
|
return newThread->effectivePriority < currentThread->effectivePriority;
|
||||||
@ -791,7 +791,7 @@ namespace coreinit
|
|||||||
// todo - only set this once?
|
// todo - only set this once?
|
||||||
thread->wakeUpTime = PPCInterpreter_getMainCoreCycleCounter();
|
thread->wakeUpTime = PPCInterpreter_getMainCoreCycleCounter();
|
||||||
// reschedule if thread has higher priority
|
// reschedule if thread has higher priority
|
||||||
if (PPCInterpreter_getCurrentInstance() && __OSCoreShouldSwitchToThread(coreinit::OSGetCurrentThread(), thread))
|
if (PPCInterpreter_getCurrentInstance() && __OSCoreShouldSwitchToThread(coreinit::OSGetCurrentThread(), thread, false))
|
||||||
PPCCore_switchToSchedulerWithLock();
|
PPCCore_switchToSchedulerWithLock();
|
||||||
}
|
}
|
||||||
return previousSuspendCount;
|
return previousSuspendCount;
|
||||||
@ -948,7 +948,7 @@ namespace coreinit
|
|||||||
OSThread_t* currentThread = OSGetCurrentThread();
|
OSThread_t* currentThread = OSGetCurrentThread();
|
||||||
if (currentThread && currentThread != thread)
|
if (currentThread && currentThread != thread)
|
||||||
{
|
{
|
||||||
if (__OSCoreShouldSwitchToThread(currentThread, thread))
|
if (__OSCoreShouldSwitchToThread(currentThread, thread, false))
|
||||||
PPCCore_switchToSchedulerWithLock();
|
PPCCore_switchToSchedulerWithLock();
|
||||||
}
|
}
|
||||||
__OSUnlockScheduler();
|
__OSUnlockScheduler();
|
||||||
|
@ -126,8 +126,8 @@ namespace coreinit
|
|||||||
|
|
||||||
// counterparts for queueAndWait
|
// counterparts for queueAndWait
|
||||||
void cancelWait(OSThread_t* thread);
|
void cancelWait(OSThread_t* thread);
|
||||||
void wakeupEntireWaitQueue(bool reschedule);
|
void wakeupEntireWaitQueue(bool reschedule, bool sharedPriorityAndAffinityWorkaround = false);
|
||||||
void wakeupSingleThreadWaitQueue(bool reschedule);
|
void wakeupSingleThreadWaitQueue(bool reschedule, bool sharedPriorityAndAffinityWorkaround = false);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
OSThread_t* takeFirstFromQueue(size_t linkOffset)
|
OSThread_t* takeFirstFromQueue(size_t linkOffset)
|
||||||
@ -611,7 +611,7 @@ namespace coreinit
|
|||||||
|
|
||||||
// internal
|
// internal
|
||||||
void __OSAddReadyThreadToRunQueue(OSThread_t* thread);
|
void __OSAddReadyThreadToRunQueue(OSThread_t* thread);
|
||||||
bool __OSCoreShouldSwitchToThread(OSThread_t* currentThread, OSThread_t* newThread);
|
bool __OSCoreShouldSwitchToThread(OSThread_t* currentThread, OSThread_t* newThread, bool sharedPriorityAndAffinityWorkaround);
|
||||||
void __OSQueueThreadDeallocation(OSThread_t* thread);
|
void __OSQueueThreadDeallocation(OSThread_t* thread);
|
||||||
|
|
||||||
bool __OSIsThreadActive(OSThread_t* thread);
|
bool __OSIsThreadActive(OSThread_t* thread);
|
||||||
|
@ -128,7 +128,8 @@ namespace coreinit
|
|||||||
|
|
||||||
// counterpart for queueAndWait
|
// counterpart for queueAndWait
|
||||||
// if reschedule is true then scheduler will switch to woken up thread (if it is runnable on the same core)
|
// if reschedule is true then scheduler will switch to woken up thread (if it is runnable on the same core)
|
||||||
void OSThreadQueueInternal::wakeupEntireWaitQueue(bool reschedule)
|
// sharedPriorityAndAffinityWorkaround is currently a hack/placeholder for some special cases. A proper fix likely involves handling all the nuances of thread effective priority
|
||||||
|
void OSThreadQueueInternal::wakeupEntireWaitQueue(bool reschedule, bool sharedPriorityAndAffinityWorkaround)
|
||||||
{
|
{
|
||||||
cemu_assert_debug(__OSHasSchedulerLock());
|
cemu_assert_debug(__OSHasSchedulerLock());
|
||||||
bool shouldReschedule = false;
|
bool shouldReschedule = false;
|
||||||
@ -139,7 +140,7 @@ namespace coreinit
|
|||||||
thread->state = OSThread_t::THREAD_STATE::STATE_READY;
|
thread->state = OSThread_t::THREAD_STATE::STATE_READY;
|
||||||
thread->currentWaitQueue = nullptr;
|
thread->currentWaitQueue = nullptr;
|
||||||
coreinit::__OSAddReadyThreadToRunQueue(thread);
|
coreinit::__OSAddReadyThreadToRunQueue(thread);
|
||||||
if (reschedule && thread->suspendCounter == 0 && PPCInterpreter_getCurrentInstance() && __OSCoreShouldSwitchToThread(coreinit::OSGetCurrentThread(), thread))
|
if (reschedule && thread->suspendCounter == 0 && PPCInterpreter_getCurrentInstance() && __OSCoreShouldSwitchToThread(coreinit::OSGetCurrentThread(), thread, sharedPriorityAndAffinityWorkaround))
|
||||||
shouldReschedule = true;
|
shouldReschedule = true;
|
||||||
}
|
}
|
||||||
if (shouldReschedule)
|
if (shouldReschedule)
|
||||||
@ -148,7 +149,7 @@ namespace coreinit
|
|||||||
|
|
||||||
// counterpart for queueAndWait
|
// counterpart for queueAndWait
|
||||||
// if reschedule is true then scheduler will switch to woken up thread (if it is runnable on the same core)
|
// if reschedule is true then scheduler will switch to woken up thread (if it is runnable on the same core)
|
||||||
void OSThreadQueueInternal::wakeupSingleThreadWaitQueue(bool reschedule)
|
void OSThreadQueueInternal::wakeupSingleThreadWaitQueue(bool reschedule, bool sharedPriorityAndAffinityWorkaround)
|
||||||
{
|
{
|
||||||
cemu_assert_debug(__OSHasSchedulerLock());
|
cemu_assert_debug(__OSHasSchedulerLock());
|
||||||
OSThread_t* thread = takeFirstFromQueue(offsetof(OSThread_t, waitQueueLink));
|
OSThread_t* thread = takeFirstFromQueue(offsetof(OSThread_t, waitQueueLink));
|
||||||
@ -159,7 +160,7 @@ namespace coreinit
|
|||||||
thread->state = OSThread_t::THREAD_STATE::STATE_READY;
|
thread->state = OSThread_t::THREAD_STATE::STATE_READY;
|
||||||
thread->currentWaitQueue = nullptr;
|
thread->currentWaitQueue = nullptr;
|
||||||
coreinit::__OSAddReadyThreadToRunQueue(thread);
|
coreinit::__OSAddReadyThreadToRunQueue(thread);
|
||||||
if (reschedule && thread->suspendCounter == 0 && PPCInterpreter_getCurrentInstance() && __OSCoreShouldSwitchToThread(coreinit::OSGetCurrentThread(), thread))
|
if (reschedule && thread->suspendCounter == 0 && PPCInterpreter_getCurrentInstance() && __OSCoreShouldSwitchToThread(coreinit::OSGetCurrentThread(), thread, sharedPriorityAndAffinityWorkaround))
|
||||||
shouldReschedule = true;
|
shouldReschedule = true;
|
||||||
}
|
}
|
||||||
if (shouldReschedule)
|
if (shouldReschedule)
|
||||||
|
Loading…
Reference in New Issue
Block a user