summaryrefslogtreecommitdiffstats
path: root/src/core/hle/kernel/mutex.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/core/hle/kernel/mutex.cpp60
1 files changed, 22 insertions, 38 deletions
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp
index 84ff65150..cef961289 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -13,38 +13,6 @@
namespace Kernel {
-/**
- * Boost's a thread's priority to the best priority among the thread's held mutexes.
- * This prevents priority inversion via priority inheritance.
- */
-static void UpdateThreadPriority(Thread* thread) {
- s32 best_priority = THREADPRIO_LOWEST;
- for (auto& mutex : thread->held_mutexes) {
- if (mutex->priority < best_priority)
- best_priority = mutex->priority;
- }
-
- best_priority = std::min(best_priority, thread->nominal_priority);
- 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;
@@ -83,9 +51,7 @@ void Mutex::Acquire(Thread* thread) {
priority = thread->current_priority;
thread->held_mutexes.insert(this);
holding_thread = thread;
-
- UpdateThreadPriority(thread);
-
+ thread->UpdatePriority();
Core::System::GetInstance().PrepareReschedule();
}
@@ -100,7 +66,7 @@ void Mutex::Release() {
// Yield to the next thread only if we've fully released the mutex
if (lock_count == 0) {
holding_thread->held_mutexes.erase(this);
- UpdateThreadPriority(holding_thread.get());
+ holding_thread->UpdatePriority();
holding_thread = nullptr;
WakeupAllWaitingThreads();
Core::System::GetInstance().PrepareReschedule();
@@ -110,12 +76,30 @@ void Mutex::Release() {
void Mutex::AddWaitingThread(SharedPtr<Thread> thread) {
WaitObject::AddWaitingThread(thread);
- UpdateMutexPriority(this);
+ thread->pending_mutexes.insert(this);
+ UpdatePriority();
}
void Mutex::RemoveWaitingThread(Thread* thread) {
WaitObject::RemoveWaitingThread(thread);
- UpdateMutexPriority(this);
+ thread->pending_mutexes.erase(this);
+ UpdatePriority();
+}
+
+void Mutex::UpdatePriority() {
+ if (!holding_thread)
+ return;
+
+ 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;
+ holding_thread->UpdatePriority();
+ }
}
} // namespace