diff options
| author | 2019-11-23 13:24:39 -0500 | |
|---|---|---|
| committer | 2019-11-23 13:24:39 -0500 | |
| commit | 6a3fc5d2ff2732e0392db56b04ff0c4e2c167bf2 (patch) | |
| tree | 7d8189083964982abf5e48e3dd8e87e504ca7ab6 /src/core/hle/kernel/svc.cpp | |
| parent | Merge pull request #3141 from ReinUsesLisp/gl-position (diff) | |
| parent | Kernel: Optimize condition variable threads management. (diff) | |
| download | yuzu-6a3fc5d2ff2732e0392db56b04ff0c4e2c167bf2.tar.gz yuzu-6a3fc5d2ff2732e0392db56b04ff0c4e2c167bf2.tar.xz yuzu-6a3fc5d2ff2732e0392db56b04ff0c4e2c167bf2.zip | |
Merge pull request #3114 from FernandoS27/cond-var
Kernel: Correct behavior of Condition Variables to be more similar to real hardware.
Diffstat (limited to 'src/core/hle/kernel/svc.cpp')
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 28 |
1 files changed, 7 insertions, 21 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index b2cef3be9..8c67ada43 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -1631,6 +1631,7 @@ static ResultCode WaitProcessWideKeyAtomic(Core::System& system, VAddr mutex_add | |||
| 1631 | current_thread->SetWaitHandle(thread_handle); | 1631 | current_thread->SetWaitHandle(thread_handle); |
| 1632 | current_thread->SetStatus(ThreadStatus::WaitCondVar); | 1632 | current_thread->SetStatus(ThreadStatus::WaitCondVar); |
| 1633 | current_thread->InvalidateWakeupCallback(); | 1633 | current_thread->InvalidateWakeupCallback(); |
| 1634 | current_process->InsertConditionVariableThread(current_thread); | ||
| 1634 | 1635 | ||
| 1635 | current_thread->WakeAfterDelay(nano_seconds); | 1636 | current_thread->WakeAfterDelay(nano_seconds); |
| 1636 | 1637 | ||
| @@ -1649,38 +1650,23 @@ static ResultCode SignalProcessWideKey(Core::System& system, VAddr condition_var | |||
| 1649 | ASSERT(condition_variable_addr == Common::AlignDown(condition_variable_addr, 4)); | 1650 | ASSERT(condition_variable_addr == Common::AlignDown(condition_variable_addr, 4)); |
| 1650 | 1651 | ||
| 1651 | // Retrieve a list of all threads that are waiting for this condition variable. | 1652 | // Retrieve a list of all threads that are waiting for this condition variable. |
| 1652 | std::vector<SharedPtr<Thread>> waiting_threads; | 1653 | auto* const current_process = system.Kernel().CurrentProcess(); |
| 1653 | const auto& scheduler = system.GlobalScheduler(); | 1654 | std::vector<SharedPtr<Thread>> waiting_threads = |
| 1654 | const auto& thread_list = scheduler.GetThreadList(); | 1655 | current_process->GetConditionVariableThreads(condition_variable_addr); |
| 1655 | |||
| 1656 | for (const auto& thread : thread_list) { | ||
| 1657 | if (thread->GetCondVarWaitAddress() == condition_variable_addr) { | ||
| 1658 | waiting_threads.push_back(thread); | ||
| 1659 | } | ||
| 1660 | } | ||
| 1661 | |||
| 1662 | // Sort them by priority, such that the highest priority ones come first. | ||
| 1663 | std::sort(waiting_threads.begin(), waiting_threads.end(), | ||
| 1664 | [](const SharedPtr<Thread>& lhs, const SharedPtr<Thread>& rhs) { | ||
| 1665 | return lhs->GetPriority() < rhs->GetPriority(); | ||
| 1666 | }); | ||
| 1667 | 1656 | ||
| 1668 | // Only process up to 'target' threads, unless 'target' is -1, in which case process | 1657 | // Only process up to 'target' threads, unless 'target' is less equal 0, in which case process |
| 1669 | // them all. | 1658 | // them all. |
| 1670 | std::size_t last = waiting_threads.size(); | 1659 | std::size_t last = waiting_threads.size(); |
| 1671 | if (target != -1) | 1660 | if (target > 0) |
| 1672 | last = std::min(waiting_threads.size(), static_cast<std::size_t>(target)); | 1661 | last = std::min(waiting_threads.size(), static_cast<std::size_t>(target)); |
| 1673 | 1662 | ||
| 1674 | // If there are no threads waiting on this condition variable, just exit | ||
| 1675 | if (last == 0) | ||
| 1676 | return RESULT_SUCCESS; | ||
| 1677 | |||
| 1678 | for (std::size_t index = 0; index < last; ++index) { | 1663 | for (std::size_t index = 0; index < last; ++index) { |
| 1679 | auto& thread = waiting_threads[index]; | 1664 | auto& thread = waiting_threads[index]; |
| 1680 | 1665 | ||
| 1681 | ASSERT(thread->GetCondVarWaitAddress() == condition_variable_addr); | 1666 | ASSERT(thread->GetCondVarWaitAddress() == condition_variable_addr); |
| 1682 | 1667 | ||
| 1683 | // liberate Cond Var Thread. | 1668 | // liberate Cond Var Thread. |
| 1669 | current_process->RemoveConditionVariableThread(thread); | ||
| 1684 | thread->SetCondVarWaitAddress(0); | 1670 | thread->SetCondVarWaitAddress(0); |
| 1685 | 1671 | ||
| 1686 | const std::size_t current_core = system.CurrentCoreIndex(); | 1672 | const std::size_t current_core = system.CurrentCoreIndex(); |