Check waitThread rather than waitMutex during condvar timeouts

When a timeout occurs in `ConditionVariableWait`, we used to check `waitMutex` which is cleared by `MutexUnlock` but when we hit the CAS case in `ConditionVariableSignal` then we don't clear `waitMutex`. It's far more reliable to check `waitThread` as an indication for if the thread has already been unlocked as it's cleared at the start of `ConditionVariableWait` and would implicitly stay cleared in the CAS case while being set in `MutexLock` and being unset in `MutexUnlock`.
This commit is contained in:
PixelyIon 2022-11-30 03:13:39 +05:30 committed by Mark Collins
parent 2525bafe06
commit c4b4532222

View File

@ -221,6 +221,7 @@ namespace skyline::kernel::type {
{ {
// Update all waiter information // Update all waiter information
std::unique_lock lock{state.thread->waiterMutex}; std::unique_lock lock{state.thread->waiterMutex};
state.thread->waitThread = std::shared_ptr<KThread>{nullptr};
state.thread->waitMutex = mutex; state.thread->waitMutex = mutex;
state.thread->waitTag = tag; state.thread->waitTag = tag;
state.thread->waitConditionVariable = key; state.thread->waitConditionVariable = key;
@ -259,7 +260,7 @@ namespace skyline::kernel::type {
std::unique_lock lock{state.thread->waiterMutex}; std::unique_lock lock{state.thread->waiterMutex};
if (state.thread->waitSignalled) { if (state.thread->waitSignalled) {
if (state.thread->waitMutex) { if (state.thread->waitThread) {
auto waitThread{state.thread->waitThread}; auto waitThread{state.thread->waitThread};
std::unique_lock waitLock{waitThread->waiterMutex, std::try_to_lock}; std::unique_lock waitLock{waitThread->waiterMutex, std::try_to_lock};
if (!waitLock) { if (!waitLock) {
@ -284,7 +285,7 @@ namespace skyline::kernel::type {
shouldWait = true; shouldWait = true;
} }
} else { } else {
// If the waitMutex is null then we were signalled and are no longer waiting on the associated mutex // If the waitThread is null then we were signalled and are no longer waiting on the associated mutex
shouldWait = true; shouldWait = true;
} }
} else { } else {