From 7966bfa9f6822c5045f2efbab459cb23fe191d10 Mon Sep 17 00:00:00 2001 From: PixelyIon Date: Sun, 28 Aug 2022 20:15:08 +0530 Subject: [PATCH] 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. --- .../main/cpp/skyline/kernel/types/KThread.cpp | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/app/src/main/cpp/skyline/kernel/types/KThread.cpp b/app/src/main/cpp/skyline/kernel/types/KThread.cpp index d69d32a4..7d31bdba 100644 --- a/app/src/main/cpp/skyline/kernel/types/KThread.cpp +++ b/app/src/main/cpp/skyline/kernel/types/KThread.cpp @@ -296,7 +296,9 @@ namespace skyline::kernel::type { waitingOn->priority = ownerPriority; lock.unlock(); + waiterLock.lock(); + waiterLock.unlock(); lock.lock(); waitingOn = waitThread; @@ -307,7 +309,23 @@ namespace skyline::kernel::type { auto nextThread{waitingOn->waitThread}; if (nextThread) { // 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}; piWaiters.erase(std::find(piWaiters.begin(), piWaiters.end(), waitingOn)); piWaiters.insert(std::upper_bound(piWaiters.begin(), piWaiters.end(), currentPriority, KThread::IsHigherPriority), waitingOn);