aboutsummaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/svc.cpp
diff options
context:
space:
mode:
authorSubv <subv2112@gmail.com>2018-04-20 20:15:16 -0500
committerSubv <subv2112@gmail.com>2018-04-23 11:23:44 -0500
commit46572d027dc9620ed2b2a50277e6afd2a115ab81 (patch)
tree72562a37575252e8f4c0160a3067b415027fdf4b /src/core/hle/kernel/svc.cpp
parenta70ed9c8ae034a1035d1b099161ad740840c5a94 (diff)
Kernel: Implemented mutex priority inheritance.
Verified with a hwtest and implemented based on reverse engineering. Thread A's priority will get bumped to the highest priority among all the threads that are waiting for a mutex that A holds. Once A releases the mutex and ownership is transferred to B, A's priority will return to normal and B's priority will be bumped.
Diffstat (limited to 'src/core/hle/kernel/svc.cpp')
-rw-r--r--src/core/hle/kernel/svc.cpp9
1 files changed, 9 insertions, 0 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 082c36caf..a3015cf7a 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -621,6 +621,8 @@ static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr condition_var
current_thread->WakeAfterDelay(nano_seconds);
+ // Note: Deliberately don't attempt to inherit the lock owner's priority.
+
Core::System::GetInstance().PrepareReschedule();
return RESULT_SUCCESS;
}
@@ -651,6 +653,11 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target
ASSERT(thread->status == THREADSTATUS_WAIT_MUTEX);
thread->ResumeFromWait();
+ auto lock_owner = thread->lock_owner;
+ if (lock_owner)
+ lock_owner->RemoveMutexWaiter(thread);
+
+ thread->lock_owner = nullptr;
thread->mutex_wait_address = 0;
thread->condvar_wait_address = 0;
thread->wait_handle = 0;
@@ -666,6 +673,8 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target
// Signal that the mutex now has a waiting thread.
Memory::Write32(thread->mutex_wait_address, mutex_val | Mutex::MutexHasWaitersFlag);
+ owner->AddMutexWaiter(thread);
+
Core::System::GetInstance().PrepareReschedule();
}