diff options
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 3 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.cpp | 21 | 
2 files changed, 22 insertions, 2 deletions
| diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 5db2db687..5818cc06d 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -706,8 +706,7 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target              Handle owner_handle = static_cast<Handle>(mutex_val & Mutex::MutexOwnerMask);              auto owner = g_handle_table.Get<Thread>(owner_handle);              ASSERT(owner); -            ASSERT(thread->status != ThreadStatus::Running); -            thread->status = ThreadStatus::WaitMutex; +            ASSERT(thread->status == ThreadStatus::WaitMutex);              thread->wakeup_callback = nullptr;              owner->AddMutexWaiter(thread); diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index b9022feae..40918ca81 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -419,12 +419,33 @@ VAddr Thread::GetCommandBufferAddress() const {  }  void Thread::AddMutexWaiter(SharedPtr<Thread> thread) { +    if (thread->lock_owner == this) { +        // If the thread is already waiting for this thread to release the mutex, ensure that the +        // waiters list is consistent and return without doing anything. +        auto itr = std::find(wait_mutex_threads.begin(), wait_mutex_threads.end(), thread); +        ASSERT(itr != wait_mutex_threads.end()); +        return; +    } + +    // A thread can't wait on two different mutexes at the same time. +    ASSERT(thread->lock_owner == nullptr); + +    // Ensure that the thread is not already in the list of mutex waiters +    auto itr = std::find(wait_mutex_threads.begin(), wait_mutex_threads.end(), thread); +    ASSERT(itr == wait_mutex_threads.end()); +      thread->lock_owner = this;      wait_mutex_threads.emplace_back(std::move(thread));      UpdatePriority();  }  void Thread::RemoveMutexWaiter(SharedPtr<Thread> thread) { +    ASSERT(thread->lock_owner == this); + +    // Ensure that the thread is in the list of mutex waiters +    auto itr = std::find(wait_mutex_threads.begin(), wait_mutex_threads.end(), thread); +    ASSERT(itr != wait_mutex_threads.end()); +      boost::remove_erase(wait_mutex_threads, thread);      thread->lock_owner = nullptr;      UpdatePriority(); | 
