summaryrefslogtreecommitdiffstats
path: root/src/core/hle/kernel
diff options
context:
space:
mode:
authorSubv <subv2112@gmail.com>2017-01-02 19:53:10 +0100
committerSubv <subv2112@gmail.com>2017-01-04 21:58:47 +0100
commitb6a0355568ee327bef8957b9a2498897b96e1278 (patch)
treec2b4ac0c55ecfc2c60495e85e88e64c0f2bb6d8f /src/core/hle/kernel
parentKernel/Mutex: Implemented priority inheritance. (diff)
downloadyuzu-b6a0355568ee327bef8957b9a2498897b96e1278.tar
yuzu-b6a0355568ee327bef8957b9a2498897b96e1278.tar.gz
yuzu-b6a0355568ee327bef8957b9a2498897b96e1278.tar.bz2
yuzu-b6a0355568ee327bef8957b9a2498897b96e1278.tar.lz
yuzu-b6a0355568ee327bef8957b9a2498897b96e1278.tar.xz
yuzu-b6a0355568ee327bef8957b9a2498897b96e1278.tar.zst
yuzu-b6a0355568ee327bef8957b9a2498897b96e1278.zip
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r--src/core/hle/kernel/kernel.cpp23
-rw-r--r--src/core/hle/kernel/kernel.h2
-rw-r--r--src/core/hle/kernel/mutex.cpp35
-rw-r--r--src/core/hle/kernel/mutex.h1
4 files changed, 39 insertions, 22 deletions
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index ef9dbafa5..6f61d526a 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -3,7 +3,6 @@
// Refer to the license.txt file included.
#include <algorithm>
-#include <boost/range/algorithm_ext/erase.hpp>
#include "common/assert.h"
#include "common/logging/log.h"
#include "core/hle/config_mem.h"
@@ -34,10 +33,17 @@ void WaitObject::RemoveWaitingThread(Thread* thread) {
SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() {
// Remove the threads that are ready or already running from our waitlist
- boost::range::remove_erase_if(waiting_threads, [](const SharedPtr<Thread>& thread) {
- return thread->status == THREADSTATUS_RUNNING || thread->status == THREADSTATUS_READY ||
- thread->status == THREADSTATUS_DEAD;
- });
+ auto to_remove = waiting_threads.end();
+ do {
+ to_remove = std::find_if(waiting_threads.begin(), waiting_threads.end(),
+ [](const SharedPtr<Thread>& thread) {
+ return thread->status == THREADSTATUS_RUNNING ||
+ thread->status == THREADSTATUS_READY ||
+ thread->status == THREADSTATUS_DEAD;
+ });
+ // Call RemoveWaitingThread so that child classes can override the behavior.
+ RemoveWaitingThread(to_remove->get());
+ } while (to_remove != waiting_threads.end());
Thread* candidate = nullptr;
s32 candidate_priority = THREADPRIO_LOWEST + 1;
@@ -49,9 +55,10 @@ SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() {
if (ShouldWait(thread.get()))
continue;
- bool ready_to_run =
- std::none_of(thread->wait_objects.begin(), thread->wait_objects.end(),
- [&thread](const SharedPtr<WaitObject>& object) { return object->ShouldWait(thread.get()); });
+ bool ready_to_run = std::none_of(thread->wait_objects.begin(), thread->wait_objects.end(),
+ [&thread](const SharedPtr<WaitObject>& object) {
+ return object->ShouldWait(thread.get());
+ });
if (ready_to_run) {
candidate = thread.get();
candidate_priority = thread->current_priority;
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 2680f89c9..05097824b 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -151,7 +151,7 @@ public:
* Removes a thread from waiting on this object (e.g. if it was resumed already)
* @param thread Pointer to thread to remove
*/
- void RemoveWaitingThread(Thread* thread);
+ virtual void RemoveWaitingThread(Thread* thread);
/**
* Wake up all threads waiting on this object that can be awoken, in priority order,
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp
index e83717e80..84ff65150 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -28,6 +28,23 @@ static void UpdateThreadPriority(Thread* thread) {
thread->SetPriority(best_priority);
}
+/**
+ * Elevate the mutex priority to the best priority
+ * among the priorities of all its waiting threads.
+ */
+static void UpdateMutexPriority(Mutex* mutex) {
+ s32 best_priority = THREADPRIO_LOWEST;
+ for (auto& waiter : mutex->GetWaitingThreads()) {
+ if (waiter->current_priority < best_priority)
+ best_priority = waiter->current_priority;
+ }
+
+ if (best_priority != mutex->priority) {
+ mutex->priority = best_priority;
+ UpdateThreadPriority(mutex->holding_thread.get());
+ }
+}
+
void ReleaseThreadMutexes(Thread* thread) {
for (auto& mtx : thread->held_mutexes) {
mtx->lock_count = 0;
@@ -93,20 +110,12 @@ void Mutex::Release() {
void Mutex::AddWaitingThread(SharedPtr<Thread> thread) {
WaitObject::AddWaitingThread(thread);
+ UpdateMutexPriority(this);
+}
- // Elevate the mutex priority to the best priority
- // among the priorities of all its waiting threads.
-
- s32 best_priority = THREADPRIO_LOWEST;
- for (auto& waiter : GetWaitingThreads()) {
- if (waiter->current_priority < best_priority)
- best_priority = waiter->current_priority;
- }
-
- if (best_priority != priority) {
- priority = best_priority;
- UpdateThreadPriority(holding_thread.get());
- }
+void Mutex::RemoveWaitingThread(Thread* thread) {
+ WaitObject::RemoveWaitingThread(thread);
+ UpdateMutexPriority(this);
}
} // namespace
diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h
index 3e6adeb17..31f920516 100644
--- a/src/core/hle/kernel/mutex.h
+++ b/src/core/hle/kernel/mutex.h
@@ -43,6 +43,7 @@ public:
void Acquire(Thread* thread) override;
void AddWaitingThread(SharedPtr<Thread> thread) override;
+ void RemoveWaitingThread(Thread* thread) override;
void Release();