From 2d16507f9fa06e868349d6f57a78585aec8628fd 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/process.cpp | 46 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'src/core/hle/kernel/process.cpp') diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 12a900bcc..43576c6ab 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -142,6 +142,52 @@ u64 Process::GetTotalPhysicalMemoryUsedWithoutSystemResource() const { return GetTotalPhysicalMemoryUsed() - GetSystemResourceUsage(); } +void Process::InsertConditionVariableThread(SharedPtr thread) { + auto it = cond_var_threads.begin(); + while (it != cond_var_threads.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; + } + } + ++it; + } + cond_var_threads.push_back(thread); +} + +void Process::RemoveConditionVariableThread(SharedPtr thread) { + auto it = cond_var_threads.begin(); + while (it != cond_var_threads.end()) { + const SharedPtr current_thread = *it; + if (current_thread.get() == thread.get()) { + cond_var_threads.erase(it); + return; + } + ++it; + } + UNREACHABLE(); +} + +std::vector> Process::GetConditionVariableThreads(const VAddr cond_var_addr) { + std::vector> result{}; + auto it = cond_var_threads.begin(); + while (it != cond_var_threads.end()) { + SharedPtr current_thread = *it; + if (current_thread->GetCondVarWaitAddress() == cond_var_addr) { + result.push_back(current_thread); + } + ++it; + } + return result; +} + void Process::RegisterThread(const Thread* thread) { thread_list.push_back(thread); } -- cgit v1.2.3