yuzu-emu
/
yuzu-android
Archived
1
0
Fork 0

kernel/thread: Maintain priority ordering of added mutex waiting threads

The kernel keeps the internal waiting list ordered by priority. This is
trivial to do with std::find_if followed by an insertion.
This commit is contained in:
Lioncash 2019-03-15 01:02:13 -04:00
parent 3bfd199497
commit 0b78cfcc53
1 changed files with 23 additions and 13 deletions

View File

@ -7,8 +7,6 @@
#include <optional> #include <optional>
#include <vector> #include <vector>
#include <boost/range/algorithm_ext/erase.hpp>
#include "common/assert.h" #include "common/assert.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "common/logging/log.h" #include "common/logging/log.h"
@ -269,8 +267,8 @@ void Thread::AddMutexWaiter(SharedPtr<Thread> thread) {
if (thread->lock_owner == this) { if (thread->lock_owner == this) {
// If the thread is already waiting for this thread to release the mutex, ensure that the // If the thread is already waiting for this thread to release the mutex, ensure that the
// waiters list is consistent and return without doing anything. // waiters list is consistent and return without doing anything.
auto itr = std::find(wait_mutex_threads.begin(), wait_mutex_threads.end(), thread); const auto iter = std::find(wait_mutex_threads.begin(), wait_mutex_threads.end(), thread);
ASSERT(itr != wait_mutex_threads.end()); ASSERT(iter != wait_mutex_threads.end());
return; return;
} }
@ -278,11 +276,16 @@ void Thread::AddMutexWaiter(SharedPtr<Thread> thread) {
ASSERT(thread->lock_owner == nullptr); ASSERT(thread->lock_owner == nullptr);
// Ensure that the thread is not already in the list of mutex waiters // Ensure that the thread is not already in the list of mutex waiters
auto itr = std::find(wait_mutex_threads.begin(), wait_mutex_threads.end(), thread); const auto iter = std::find(wait_mutex_threads.begin(), wait_mutex_threads.end(), thread);
ASSERT(itr == wait_mutex_threads.end()); ASSERT(iter == wait_mutex_threads.end());
// Keep the list in an ordered fashion
const auto insertion_point = std::find_if(
wait_mutex_threads.begin(), wait_mutex_threads.end(),
[&thread](const auto& entry) { return entry->GetPriority() > thread->GetPriority(); });
wait_mutex_threads.insert(insertion_point, thread);
thread->lock_owner = this; thread->lock_owner = this;
wait_mutex_threads.emplace_back(std::move(thread));
UpdatePriority(); UpdatePriority();
} }
@ -290,10 +293,11 @@ void Thread::RemoveMutexWaiter(SharedPtr<Thread> thread) {
ASSERT(thread->lock_owner == this); ASSERT(thread->lock_owner == this);
// Ensure that the thread is in the list of mutex waiters // Ensure that the thread is in the list of mutex waiters
auto itr = std::find(wait_mutex_threads.begin(), wait_mutex_threads.end(), thread); const auto iter = std::find(wait_mutex_threads.begin(), wait_mutex_threads.end(), thread);
ASSERT(itr != wait_mutex_threads.end()); ASSERT(iter != wait_mutex_threads.end());
wait_mutex_threads.erase(iter);
boost::remove_erase(wait_mutex_threads, thread);
thread->lock_owner = nullptr; thread->lock_owner = nullptr;
UpdatePriority(); UpdatePriority();
} }
@ -310,11 +314,17 @@ void Thread::UpdatePriority() {
return; return;
scheduler->SetThreadPriority(this, new_priority); scheduler->SetThreadPriority(this, new_priority);
current_priority = new_priority; current_priority = new_priority;
if (!lock_owner) {
return;
}
// Ensure that the thread is within the correct location in the waiting list.
lock_owner->RemoveMutexWaiter(this);
lock_owner->AddMutexWaiter(this);
// Recursively update the priority of the thread that depends on the priority of this one. // Recursively update the priority of the thread that depends on the priority of this one.
if (lock_owner)
lock_owner->UpdatePriority(); lock_owner->UpdatePriority();
} }