Exemple #1
0
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;
}
Exemple #2
0
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();
    }
}