summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/svc.cpp
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2019-11-14 20:13:18 -0400
committerGravatar FernandoS272019-11-21 10:46:55 -0400
commit2d16507f9fa06e868349d6f57a78585aec8628fd (patch)
tree7931e2bb9db6d55e7be760f1a1dcff14de09db78 /src/core/hle/kernel/svc.cpp
parentMerge pull request #3142 from ReinUsesLisp/depbar-log (diff)
downloadyuzu-2d16507f9fa06e868349d6f57a78585aec8628fd.tar.gz
yuzu-2d16507f9fa06e868349d6f57a78585aec8628fd.tar.xz
yuzu-2d16507f9fa06e868349d6f57a78585aec8628fd.zip
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.
Diffstat (limited to 'src/core/hle/kernel/svc.cpp')
-rw-r--r--src/core/hle/kernel/svc.cpp20
1 files changed, 5 insertions, 15 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index c63a9ba8b..c27529f4d 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -1626,6 +1626,7 @@ static ResultCode WaitProcessWideKeyAtomic(Core::System& system, VAddr mutex_add
1626 current_thread->SetWaitHandle(thread_handle); 1626 current_thread->SetWaitHandle(thread_handle);
1627 current_thread->SetStatus(ThreadStatus::WaitCondVar); 1627 current_thread->SetStatus(ThreadStatus::WaitCondVar);
1628 current_thread->InvalidateWakeupCallback(); 1628 current_thread->InvalidateWakeupCallback();
1629 current_process->InsertConditionVariableThread(current_thread);
1629 1630
1630 current_thread->WakeAfterDelay(nano_seconds); 1631 current_thread->WakeAfterDelay(nano_seconds);
1631 1632
@@ -1644,21 +1645,9 @@ static ResultCode SignalProcessWideKey(Core::System& system, VAddr condition_var
1644 ASSERT(condition_variable_addr == Common::AlignDown(condition_variable_addr, 4)); 1645 ASSERT(condition_variable_addr == Common::AlignDown(condition_variable_addr, 4));
1645 1646
1646 // Retrieve a list of all threads that are waiting for this condition variable. 1647 // Retrieve a list of all threads that are waiting for this condition variable.
1647 std::vector<SharedPtr<Thread>> waiting_threads; 1648 auto* const current_process = system.Kernel().CurrentProcess();
1648 const auto& scheduler = system.GlobalScheduler(); 1649 std::vector<SharedPtr<Thread>> waiting_threads =
1649 const auto& thread_list = scheduler.GetThreadList(); 1650 current_process->GetConditionVariableThreads(condition_variable_addr);
1650
1651 for (const auto& thread : thread_list) {
1652 if (thread->GetCondVarWaitAddress() == condition_variable_addr) {
1653 waiting_threads.push_back(thread);
1654 }
1655 }
1656
1657 // Sort them by priority, such that the highest priority ones come first.
1658 std::sort(waiting_threads.begin(), waiting_threads.end(),
1659 [](const SharedPtr<Thread>& lhs, const SharedPtr<Thread>& rhs) {
1660 return lhs->GetPriority() < rhs->GetPriority();
1661 });
1662 1651
1663 // Only process up to 'target' threads, unless 'target' is -1, in which case process 1652 // Only process up to 'target' threads, unless 'target' is -1, in which case process
1664 // them all. 1653 // them all.
@@ -1677,6 +1666,7 @@ static ResultCode SignalProcessWideKey(Core::System& system, VAddr condition_var
1677 1666
1678 // liberate Cond Var Thread. 1667 // liberate Cond Var Thread.
1679 thread->SetCondVarWaitAddress(0); 1668 thread->SetCondVarWaitAddress(0);
1669 current_process->RemoveConditionVariableThread(thread);
1680 1670
1681 const std::size_t current_core = system.CurrentCoreIndex(); 1671 const std::size_t current_core = system.CurrentCoreIndex();
1682 auto& monitor = system.Monitor(); 1672 auto& monitor = system.Monitor();