aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei <bunneidev@gmail.com>2015-04-03 18:40:16 -0400
committerGravatar bunnei <bunneidev@gmail.com>2015-04-09 19:06:39 -0400
commit9c3419ebccf046e0a123e0516ea134547393e451 (patch)
tree24073b71ade88e5f99db439b824228bdc6b2737d /src
parent7b9f428b23e1761e7b6c177d2e8eb9219ac6b7f6 (diff)
Kernel: Implemented priority inheritance for mutexes.
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/kernel/mutex.cpp10
-rw-r--r--src/core/hle/kernel/thread.cpp10
-rw-r--r--src/core/hle/kernel/thread.h6
3 files changed, 22 insertions, 4 deletions
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp
index be2c4970..ebc9e79d 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -56,7 +56,15 @@ SharedPtr<Mutex> Mutex::Create(bool initial_locked, std::string name) {
}
bool Mutex::ShouldWait() {
- return lock_count > 0 && holding_thread != GetCurrentThread();;
+ auto thread = GetCurrentThread();
+ bool wait = lock_count > 0 && holding_thread != thread;
+
+ // If the holding thread of the mutex is lower priority than this thread, that thread should
+ // temporarily inherit this thread's priority
+ if (wait && thread->current_priority < holding_thread->current_priority)
+ holding_thread->BoostPriority(thread->current_priority);
+
+ return wait;
}
void Mutex::Acquire() {
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 3a1e15ac..33d66b98 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -156,9 +156,8 @@ static void PriorityBoostStarvedThreads() {
u64 delta = current_ticks - thread->last_running_ticks;
if (thread->status == THREADSTATUS_READY && delta > boost_timeout && !thread->idle) {
- const s32 boost_priority = std::max(ready_queue.get_first()->current_priority - 1, 0);
- ready_queue.move(thread, thread->current_priority, boost_priority);
- thread->current_priority = boost_priority;
+ const s32 priority = std::max(ready_queue.get_first()->current_priority - 1, 0);
+ thread->BoostPriority(priority);
}
}
}
@@ -435,6 +434,11 @@ void Thread::SetPriority(s32 priority) {
nominal_priority = current_priority = priority;
}
+void Thread::BoostPriority(s32 priority) {
+ ready_queue.move(this, current_priority, priority);
+ current_priority = priority;
+}
+
SharedPtr<Thread> SetupIdleThread() {
// We need to pass a few valid values to get around parameter checking in Thread::Create.
auto thread = Thread::Create("idle", Memory::KERNEL_MEMORY_VADDR, THREADPRIO_LOWEST, 0,
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index 92f2c423..233bcbdb 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -90,6 +90,12 @@ public:
void SetPriority(s32 priority);
/**
+ * Temporarily boosts the thread's priority until the next time it is scheduled
+ * @param priority The new priority
+ */
+ void BoostPriority(s32 priority);
+
+ /**
* Gets the thread's thread ID
* @return The thread's ID
*/