summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/kernel/thread.cpp52
-rw-r--r--src/core/hle/kernel/thread.h10
2 files changed, 41 insertions, 21 deletions
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 89f180bd9..d9ffebc3f 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -7,8 +7,6 @@
7#include <optional> 7#include <optional>
8#include <vector> 8#include <vector>
9 9
10#include <boost/range/algorithm_ext/erase.hpp>
11
12#include "common/assert.h" 10#include "common/assert.h"
13#include "common/common_types.h" 11#include "common/common_types.h"
14#include "common/logging/log.h" 12#include "common/logging/log.h"
@@ -258,8 +256,8 @@ void Thread::AddMutexWaiter(SharedPtr<Thread> thread) {
258 if (thread->lock_owner == this) { 256 if (thread->lock_owner == this) {
259 // If the thread is already waiting for this thread to release the mutex, ensure that the 257 // If the thread is already waiting for this thread to release the mutex, ensure that the
260 // waiters list is consistent and return without doing anything. 258 // waiters list is consistent and return without doing anything.
261 auto itr = std::find(wait_mutex_threads.begin(), wait_mutex_threads.end(), thread); 259 const auto iter = std::find(wait_mutex_threads.begin(), wait_mutex_threads.end(), thread);
262 ASSERT(itr != wait_mutex_threads.end()); 260 ASSERT(iter != wait_mutex_threads.end());
263 return; 261 return;
264 } 262 }
265 263
@@ -267,11 +265,16 @@ void Thread::AddMutexWaiter(SharedPtr<Thread> thread) {
267 ASSERT(thread->lock_owner == nullptr); 265 ASSERT(thread->lock_owner == nullptr);
268 266
269 // Ensure that the thread is not already in the list of mutex waiters 267 // Ensure that the thread is not already in the list of mutex waiters
270 auto itr = std::find(wait_mutex_threads.begin(), wait_mutex_threads.end(), thread); 268 const auto iter = std::find(wait_mutex_threads.begin(), wait_mutex_threads.end(), thread);
271 ASSERT(itr == wait_mutex_threads.end()); 269 ASSERT(iter == wait_mutex_threads.end());
272 270
271 // Keep the list in an ordered fashion
272 const auto insertion_point = std::find_if(
273 wait_mutex_threads.begin(), wait_mutex_threads.end(),
274 [&thread](const auto& entry) { return entry->GetPriority() > thread->GetPriority(); });
275 wait_mutex_threads.insert(insertion_point, thread);
273 thread->lock_owner = this; 276 thread->lock_owner = this;
274 wait_mutex_threads.emplace_back(std::move(thread)); 277
275 UpdatePriority(); 278 UpdatePriority();
276} 279}
277 280
@@ -279,32 +282,43 @@ void Thread::RemoveMutexWaiter(SharedPtr<Thread> thread) {
279 ASSERT(thread->lock_owner == this); 282 ASSERT(thread->lock_owner == this);
280 283
281 // Ensure that the thread is in the list of mutex waiters 284 // Ensure that the thread is in the list of mutex waiters
282 auto itr = std::find(wait_mutex_threads.begin(), wait_mutex_threads.end(), thread); 285 const auto iter = std::find(wait_mutex_threads.begin(), wait_mutex_threads.end(), thread);
283 ASSERT(itr != wait_mutex_threads.end()); 286 ASSERT(iter != wait_mutex_threads.end());
287
288 wait_mutex_threads.erase(iter);
284 289
285 boost::remove_erase(wait_mutex_threads, thread);
286 thread->lock_owner = nullptr; 290 thread->lock_owner = nullptr;
287 UpdatePriority(); 291 UpdatePriority();
288} 292}
289 293
290void Thread::UpdatePriority() { 294void Thread::UpdatePriority() {
291 // Find the highest priority among all the threads that are waiting for this thread's lock 295 // If any of the threads waiting on the mutex have a higher priority
296 // (taking into account priority inheritance), then this thread inherits
297 // that thread's priority.
292 u32 new_priority = nominal_priority; 298 u32 new_priority = nominal_priority;
293 for (const auto& thread : wait_mutex_threads) { 299 if (!wait_mutex_threads.empty()) {
294 if (thread->nominal_priority < new_priority) 300 if (wait_mutex_threads.front()->current_priority < new_priority) {
295 new_priority = thread->nominal_priority; 301 new_priority = wait_mutex_threads.front()->current_priority;
302 }
296 } 303 }
297 304
298 if (new_priority == current_priority) 305 if (new_priority == current_priority) {
299 return; 306 return;
307 }
300 308
301 scheduler->SetThreadPriority(this, new_priority); 309 scheduler->SetThreadPriority(this, new_priority);
302
303 current_priority = new_priority; 310 current_priority = new_priority;
304 311
312 if (!lock_owner) {
313 return;
314 }
315
316 // Ensure that the thread is within the correct location in the waiting list.
317 lock_owner->RemoveMutexWaiter(this);
318 lock_owner->AddMutexWaiter(this);
319
305 // Recursively update the priority of the thread that depends on the priority of this one. 320 // Recursively update the priority of the thread that depends on the priority of this one.
306 if (lock_owner) 321 lock_owner->UpdatePriority();
307 lock_owner->UpdatePriority();
308} 322}
309 323
310void Thread::ChangeCore(u32 core, u64 mask) { 324void Thread::ChangeCore(u32 core, u64 mask) {
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index ccdefeecc..faad5f391 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -401,8 +401,14 @@ private:
401 VAddr entry_point = 0; 401 VAddr entry_point = 0;
402 VAddr stack_top = 0; 402 VAddr stack_top = 0;
403 403
404 u32 nominal_priority = 0; ///< Nominal thread priority, as set by the emulated application 404 /// Nominal thread priority, as set by the emulated application.
405 u32 current_priority = 0; ///< Current thread priority, can be temporarily changed 405 /// The nominal priority is the thread priority without priority
406 /// inheritance taken into account.
407 u32 nominal_priority = 0;
408
409 /// Current thread priority. This may change over the course of the
410 /// thread's lifetime in order to facilitate priority inheritance.
411 u32 current_priority = 0;
406 412
407 u64 total_cpu_time_ticks = 0; ///< Total CPU running ticks. 413 u64 total_cpu_time_ticks = 0; ///< Total CPU running ticks.
408 u64 last_running_ticks = 0; ///< CPU tick when thread was last running 414 u64 last_running_ticks = 0; ///< CPU tick when thread was last running