svc: SignalProcessWideKey should apply to all cores.

This commit is contained in:
bunnei 2018-05-05 22:00:34 -04:00
parent 6a890023e9
commit 1c36f2a798

View file

@ -635,53 +635,60 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target
condition_variable_addr, target); condition_variable_addr, target);
u32 processed = 0; u32 processed = 0;
auto& thread_list = Core::System::GetInstance().CurrentScheduler().GetThreadList();
for (auto& thread : thread_list) { auto signal_process_wide_key = [&](size_t core_index) {
if (thread->condvar_wait_address != condition_variable_addr) const auto& scheduler = Core::System::GetInstance().Scheduler(core_index);
continue; for (auto& thread : scheduler->GetThreadList()) {
if (thread->condvar_wait_address != condition_variable_addr)
continue;
// 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) if (target != -1 && processed >= target)
break; break;
// 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);
if (mutex_val == 0) { if (mutex_val == 0) {
// We were able to acquire the mutex, resume this thread. // We were able to acquire the mutex, resume this thread.
Memory::Write32(thread->mutex_wait_address, thread->wait_handle); Memory::Write32(thread->mutex_wait_address, thread->wait_handle);
ASSERT(thread->status == THREADSTATUS_WAIT_MUTEX); ASSERT(thread->status == THREADSTATUS_WAIT_MUTEX);
thread->ResumeFromWait(); thread->ResumeFromWait();
auto lock_owner = thread->lock_owner; auto lock_owner = thread->lock_owner;
if (lock_owner) if (lock_owner)
lock_owner->RemoveMutexWaiter(thread); lock_owner->RemoveMutexWaiter(thread);
thread->lock_owner = nullptr; thread->lock_owner = nullptr;
thread->mutex_wait_address = 0; thread->mutex_wait_address = 0;
thread->condvar_wait_address = 0; thread->condvar_wait_address = 0;
thread->wait_handle = 0; thread->wait_handle = 0;
} else { } else {
// Couldn't acquire the mutex, block the thread. // Couldn't acquire the mutex, block the thread.
Handle owner_handle = static_cast<Handle>(mutex_val & Mutex::MutexOwnerMask); Handle owner_handle = static_cast<Handle>(mutex_val & Mutex::MutexOwnerMask);
auto owner = g_handle_table.Get<Thread>(owner_handle); auto owner = g_handle_table.Get<Thread>(owner_handle);
ASSERT(owner); ASSERT(owner);
ASSERT(thread->status != THREADSTATUS_RUNNING); ASSERT(thread->status != THREADSTATUS_RUNNING);
thread->status = THREADSTATUS_WAIT_MUTEX; thread->status = THREADSTATUS_WAIT_MUTEX;
thread->wakeup_callback = nullptr; thread->wakeup_callback = nullptr;
// Signal that the mutex now has a waiting thread. // Signal that the mutex now has a waiting thread.
Memory::Write32(thread->mutex_wait_address, mutex_val | Mutex::MutexHasWaitersFlag); Memory::Write32(thread->mutex_wait_address, mutex_val | Mutex::MutexHasWaitersFlag);
owner->AddMutexWaiter(thread); owner->AddMutexWaiter(thread);
Core::System::GetInstance().PrepareReschedule(); Core::System::GetInstance().PrepareReschedule();
}
++processed;
} }
};
++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;
} }