SharedPtr<Thread> AddressArbiter::ResumeHighestPriorityThread(VAddr address) { // Determine which threads are waiting on this address, those should be considered for wakeup. auto matches_start = std::stable_partition( waiting_threads.begin(), waiting_threads.end(), [address](const auto& thread) { ASSERT_MSG(thread->status == ThreadStatus::WaitArb, "Inconsistent AddressArbiter state"); return thread->wait_address != address; }); // Iterate through threads, find highest priority thread that is waiting to be arbitrated. // Note: The real kernel will pick the first thread in the list if more than one have the // same highest priority value. Lower priority values mean higher priority. auto itr = std::min_element(matches_start, waiting_threads.end(), [](const auto& lhs, const auto& rhs) { return lhs->current_priority < rhs->current_priority; }); if (itr == waiting_threads.end()) return nullptr; auto thread = *itr; thread->ResumeFromWait(); waiting_threads.erase(itr); return thread; }
void Thread::ReleaseWaitObject(WaitObject* wait_object) { if (status != THREADSTATUS_WAIT_SYNCH || wait_objects.empty()) { LOG_CRITICAL(Kernel, "thread is not waiting on any objects!"); return; } // Remove this thread from the waiting object's thread list wait_object->RemoveWaitingThread(this); unsigned index = 0; bool wait_all_failed = false; // Will be set to true if any object is unavailable // Iterate through all waiting objects to check availability... for (auto itr = wait_objects.begin(); itr != wait_objects.end(); ++itr) { if ((*itr)->ShouldWait()) wait_all_failed = true; // The output should be the last index of wait_object if (*itr == wait_object) index = itr - wait_objects.begin(); } // If we are waiting on all objects... if (wait_all) { // Resume the thread only if all are available... if (!wait_all_failed) { SetWaitSynchronizationResult(RESULT_SUCCESS); SetWaitSynchronizationOutput(-1); ResumeFromWait(); } } else { // Otherwise, resume SetWaitSynchronizationResult(RESULT_SUCCESS); if (wait_set_output) SetWaitSynchronizationOutput(index); ResumeFromWait(); } }