From b021fa33b98ea659c0593eb9528c572e76c425ab Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Thu, 14 Nov 2019 20:13:18 -0400 Subject: Kernel: Correct behavior of Condition Variables to be more similar to real hardware. This commit ensures cond var threads act exactly as they do in the real console. The original implementation uses an RBTree and the behavior of cond var threads is that at the same priority level they act like a FIFO. --- src/core/hle/kernel/kernel.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/core/hle/kernel/kernel.cpp') diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index f94ac150d0..cdf7944f78 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -66,6 +66,9 @@ static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] s64 cycles_ thread->SetMutexWaitAddress(0); thread->SetCondVarWaitAddress(0); thread->SetWaitHandle(0); + if (thread->GetStatus() == ThreadStatus::WaitCondVar) { + thread->GetOwnerProcess()->RemoveConditionVariableThread(thread); + } auto* const lock_owner = thread->GetLockOwner(); // Threads waking up by timeout from WaitProcessWideKey do not perform priority inheritance -- cgit v1.2.3 From eb0376720627f3e9231fa939b38409d8793795d6 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Thu, 21 Nov 2019 11:03:37 -0400 Subject: Kernel: Optimize condition variable threads management. --- src/core/hle/kernel/kernel.cpp | 2 +- src/core/hle/kernel/process.cpp | 38 +++++++++++++++++--------------------- src/core/hle/kernel/process.h | 3 ++- src/core/hle/kernel/svc.cpp | 2 +- 4 files changed, 21 insertions(+), 24 deletions(-) (limited to 'src/core/hle/kernel/kernel.cpp') diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index cdf7944f78..9d3b309b3e 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -64,10 +64,10 @@ static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] s64 cycles_ } else if (thread->GetStatus() == ThreadStatus::WaitMutex || thread->GetStatus() == ThreadStatus::WaitCondVar) { thread->SetMutexWaitAddress(0); - thread->SetCondVarWaitAddress(0); thread->SetWaitHandle(0); if (thread->GetStatus() == ThreadStatus::WaitCondVar) { thread->GetOwnerProcess()->RemoveConditionVariableThread(thread); + thread->SetCondVarWaitAddress(0); } auto* const lock_owner = thread->GetLockOwner(); diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 43576c6abc..a4e0dd3857 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -143,31 +143,28 @@ u64 Process::GetTotalPhysicalMemoryUsedWithoutSystemResource() const { } void Process::InsertConditionVariableThread(SharedPtr thread) { - auto it = cond_var_threads.begin(); - while (it != cond_var_threads.end()) { + VAddr cond_var_addr = thread->GetCondVarWaitAddress(); + std::list>& thread_list = cond_var_threads[cond_var_addr]; + auto it = thread_list.begin(); + while (it != thread_list.end()) { const SharedPtr current_thread = *it; - if (current_thread->GetCondVarWaitAddress() < thread->GetCondVarWaitAddress()) { - if (current_thread->GetCondVarWaitAddress() == thread->GetCondVarWaitAddress()) { - if (current_thread->GetPriority() > thread->GetPriority()) { - cond_var_threads.insert(it, thread); - return; - } - } else { - cond_var_threads.insert(it, thread); - return; - } + if (current_thread->GetPriority() > thread->GetPriority()) { + thread_list.insert(it, thread); + return; } ++it; } - cond_var_threads.push_back(thread); + thread_list.push_back(thread); } void Process::RemoveConditionVariableThread(SharedPtr thread) { - auto it = cond_var_threads.begin(); - while (it != cond_var_threads.end()) { + VAddr cond_var_addr = thread->GetCondVarWaitAddress(); + std::list>& thread_list = cond_var_threads[cond_var_addr]; + auto it = thread_list.begin(); + while (it != thread_list.end()) { const SharedPtr current_thread = *it; if (current_thread.get() == thread.get()) { - cond_var_threads.erase(it); + thread_list.erase(it); return; } ++it; @@ -177,12 +174,11 @@ void Process::RemoveConditionVariableThread(SharedPtr thread) { std::vector> Process::GetConditionVariableThreads(const VAddr cond_var_addr) { std::vector> result{}; - auto it = cond_var_threads.begin(); - while (it != cond_var_threads.end()) { + std::list>& thread_list = cond_var_threads[cond_var_addr]; + auto it = thread_list.begin(); + while (it != thread_list.end()) { SharedPtr current_thread = *it; - if (current_thread->GetCondVarWaitAddress() == cond_var_addr) { - result.push_back(current_thread); - } + result.push_back(current_thread); ++it; } return result; diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h index e8bff709bb..e2eda26b90 100644 --- a/src/core/hle/kernel/process.h +++ b/src/core/hle/kernel/process.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include "common/common_types.h" #include "core/hle/kernel/address_arbiter.h" @@ -385,7 +386,7 @@ private: std::list thread_list; /// List of threads waiting for a condition variable - std::list> cond_var_threads; + std::unordered_map>> cond_var_threads; /// System context Core::System& system; diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 4fdb6d429e..e2cf846243 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -1661,8 +1661,8 @@ static ResultCode SignalProcessWideKey(Core::System& system, VAddr condition_var ASSERT(thread->GetCondVarWaitAddress() == condition_variable_addr); // liberate Cond Var Thread. - thread->SetCondVarWaitAddress(0); current_process->RemoveConditionVariableThread(thread); + thread->SetCondVarWaitAddress(0); const std::size_t current_core = system.CurrentCoreIndex(); auto& monitor = system.Monitor(); -- cgit v1.2.3