Kernel/SVC: Signal the highest priority threads first in svcSignalProcessWideKey.

This commit is contained in:
Subv 2018-05-19 16:58:30 -05:00
parent c74f2555b6
commit 2a35a36251
1 changed files with 68 additions and 51 deletions

View File

@ -608,18 +608,43 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target
NGLOG_TRACE(Kernel_SVC, "called, condition_variable_addr=0x{:X}, target=0x{:08X}", NGLOG_TRACE(Kernel_SVC, "called, condition_variable_addr=0x{:X}, target=0x{:08X}",
condition_variable_addr, target); condition_variable_addr, target);
u32 processed = 0; auto RetrieveWaitingThreads =
[](size_t core_index, std::vector<SharedPtr<Thread>>& waiting_threads, VAddr condvar_addr) {
auto signal_process_wide_key = [&](size_t core_index) {
const auto& scheduler = Core::System::GetInstance().Scheduler(core_index); const auto& scheduler = Core::System::GetInstance().Scheduler(core_index);
for (auto& thread : scheduler->GetThreadList()) { auto& thread_list = scheduler->GetThreadList();
if (thread->condvar_wait_address != condition_variable_addr)
continue; for (auto& thread : thread_list) {
if (thread->condvar_wait_address == condvar_addr)
waiting_threads.push_back(thread);
}
};
// Retrieve a list of all threads that are waiting for this condition variable.
std::vector<SharedPtr<Thread>> waiting_threads;
RetrieveWaitingThreads(0, waiting_threads, condition_variable_addr);
RetrieveWaitingThreads(1, waiting_threads, condition_variable_addr);
RetrieveWaitingThreads(2, waiting_threads, condition_variable_addr);
RetrieveWaitingThreads(3, waiting_threads, condition_variable_addr);
// Sort them by priority, such that the highest priority ones come first.
std::sort(waiting_threads.begin(), waiting_threads.end(),
[](const SharedPtr<Thread>& lhs, const SharedPtr<Thread>& rhs) {
return lhs->current_priority < rhs->current_priority;
});
// Only process up to 'target' threads, unless 'target' is -1, in which case process // Only process up to 'target' threads, unless 'target' is -1, in which case process
// them all. // them all.
if (target != -1 && processed >= target) size_t last = waiting_threads.size();
break; if (target != -1)
last = target;
// If there are no threads waiting on this condition variable, just exit
if (last > waiting_threads.size())
return RESULT_SUCCESS;
for (size_t index = 0; index < last; ++index) {
auto& thread = waiting_threads[index];
ASSERT(thread->condvar_wait_address == condition_variable_addr);
// If the mutex is not yet acquired, acquire it. // If the mutex is not yet acquired, acquire it.
u32 mutex_val = Memory::Read32(thread->mutex_wait_address); u32 mutex_val = Memory::Read32(thread->mutex_wait_address);
@ -654,15 +679,7 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target
Core::System::GetInstance().CpuCore(thread->processor_id).PrepareReschedule(); Core::System::GetInstance().CpuCore(thread->processor_id).PrepareReschedule();
} }
++processed;
} }
};
signal_process_wide_key(0);
signal_process_wide_key(1);
signal_process_wide_key(2);
signal_process_wide_key(3);
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }