mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-02 14:14:15 +01:00
Fix PI update KThread::waiterMutex
deadlock
It was determined that deadlocks inside `KThread::UpdatePriorityInheritance` would not only arise from the first level of locking with `waitingOn->waiterMutex` but also the second level of locking with `nextThread->waiterMutex` which has now also been fixed to fallback when facing contention.
This commit is contained in:
parent
86f6fc510e
commit
7966bfa9f6
@ -296,7 +296,9 @@ namespace skyline::kernel::type {
|
|||||||
waitingOn->priority = ownerPriority;
|
waitingOn->priority = ownerPriority;
|
||||||
|
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
|
|
||||||
waiterLock.lock();
|
waiterLock.lock();
|
||||||
|
waiterLock.unlock();
|
||||||
|
|
||||||
lock.lock();
|
lock.lock();
|
||||||
waitingOn = waitThread;
|
waitingOn = waitThread;
|
||||||
@ -307,7 +309,23 @@ namespace skyline::kernel::type {
|
|||||||
auto nextThread{waitingOn->waitThread};
|
auto nextThread{waitingOn->waitThread};
|
||||||
if (nextThread) {
|
if (nextThread) {
|
||||||
// We need to update the location of the owner thread in the waiter queue of the thread it's waiting on
|
// We need to update the location of the owner thread in the waiter queue of the thread it's waiting on
|
||||||
std::scoped_lock nextWaiterLock{nextThread->waiterMutex};
|
std::unique_lock nextWaiterLock{nextThread->waiterMutex, std::try_to_lock};
|
||||||
|
if (!nextWaiterLock) {
|
||||||
|
// We want to avoid a deadlock here from the thread holding nextThread->waiterMutex waiting for waiterMutex or waitingOn->waiterMutex
|
||||||
|
waitingOn->priority = ownerPriority;
|
||||||
|
|
||||||
|
lock.unlock();
|
||||||
|
waiterLock.unlock();
|
||||||
|
|
||||||
|
nextWaiterLock.lock();
|
||||||
|
nextWaiterLock.unlock();
|
||||||
|
|
||||||
|
lock.lock();
|
||||||
|
waitingOn = waitThread;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
auto &piWaiters{nextThread->waiters};
|
auto &piWaiters{nextThread->waiters};
|
||||||
piWaiters.erase(std::find(piWaiters.begin(), piWaiters.end(), waitingOn));
|
piWaiters.erase(std::find(piWaiters.begin(), piWaiters.end(), waitingOn));
|
||||||
piWaiters.insert(std::upper_bound(piWaiters.begin(), piWaiters.end(), currentPriority, KThread::IsHigherPriority), waitingOn);
|
piWaiters.insert(std::upper_bound(piWaiters.begin(), piWaiters.end(), currentPriority, KThread::IsHigherPriority), waitingOn);
|
||||||
|
Loading…
Reference in New Issue
Block a user