summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/thread.cpp
diff options
context:
space:
mode:
authorGravatar bunnei2018-04-23 16:33:00 -0400
committerGravatar GitHub2018-04-23 16:33:00 -0400
commit0214351f4f0e9377792f8ceb657e3a47aba334d1 (patch)
treef772d4dbaf3d804497740c6c67d1110f20fd010f /src/core/hle/kernel/thread.cpp
parentMerge pull request #384 from Subv/nvhost-remap (diff)
parentKernel: Implemented mutex priority inheritance. (diff)
downloadyuzu-0214351f4f0e9377792f8ceb657e3a47aba334d1.tar.gz
yuzu-0214351f4f0e9377792f8ceb657e3a47aba334d1.tar.xz
yuzu-0214351f4f0e9377792f8ceb657e3a47aba334d1.zip
Merge pull request #370 from Subv/sync_primitives
Kernel: Reworked the new kernel synchronization primitives.
Diffstat (limited to 'src/core/hle/kernel/thread.cpp')
-rw-r--r--src/core/hle/kernel/thread.cpp66
1 files changed, 51 insertions, 15 deletions
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index f3a8aa4aa..36222d45f 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -77,9 +77,6 @@ void Thread::Stop() {
77 } 77 }
78 wait_objects.clear(); 78 wait_objects.clear();
79 79
80 // Release all the mutexes that this thread holds
81 ReleaseThreadMutexes(this);
82
83 // Mark the TLS slot in the thread's page as free. 80 // Mark the TLS slot in the thread's page as free.
84 u64 tls_page = (tls_address - Memory::TLS_AREA_VADDR) / Memory::PAGE_SIZE; 81 u64 tls_page = (tls_address - Memory::TLS_AREA_VADDR) / Memory::PAGE_SIZE;
85 u64 tls_slot = 82 u64 tls_slot =
@@ -126,6 +123,19 @@ static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) {
126 resume = thread->wakeup_callback(ThreadWakeupReason::Timeout, thread, nullptr, 0); 123 resume = thread->wakeup_callback(ThreadWakeupReason::Timeout, thread, nullptr, 0);
127 } 124 }
128 125
126 if (thread->mutex_wait_address != 0 || thread->condvar_wait_address != 0 ||
127 thread->wait_handle) {
128 ASSERT(thread->status == THREADSTATUS_WAIT_MUTEX);
129 thread->mutex_wait_address = 0;
130 thread->condvar_wait_address = 0;
131 thread->wait_handle = 0;
132
133 auto lock_owner = thread->lock_owner;
134 // Threads waking up by timeout from WaitProcessWideKey do not perform priority inheritance
135 // and don't have a lock owner.
136 ASSERT(lock_owner == nullptr);
137 }
138
129 if (resume) 139 if (resume)
130 thread->ResumeFromWait(); 140 thread->ResumeFromWait();
131} 141}
@@ -151,6 +161,7 @@ void Thread::ResumeFromWait() {
151 case THREADSTATUS_WAIT_HLE_EVENT: 161 case THREADSTATUS_WAIT_HLE_EVENT:
152 case THREADSTATUS_WAIT_SLEEP: 162 case THREADSTATUS_WAIT_SLEEP:
153 case THREADSTATUS_WAIT_IPC: 163 case THREADSTATUS_WAIT_IPC:
164 case THREADSTATUS_WAIT_MUTEX:
154 break; 165 break;
155 166
156 case THREADSTATUS_READY: 167 case THREADSTATUS_READY:
@@ -256,7 +267,9 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
256 thread->last_running_ticks = CoreTiming::GetTicks(); 267 thread->last_running_ticks = CoreTiming::GetTicks();
257 thread->processor_id = processor_id; 268 thread->processor_id = processor_id;
258 thread->wait_objects.clear(); 269 thread->wait_objects.clear();
259 thread->wait_address = 0; 270 thread->mutex_wait_address = 0;
271 thread->condvar_wait_address = 0;
272 thread->wait_handle = 0;
260 thread->name = std::move(name); 273 thread->name = std::move(name);
261 thread->callback_handle = wakeup_callback_handle_table.Create(thread).Unwrap(); 274 thread->callback_handle = wakeup_callback_handle_table.Create(thread).Unwrap();
262 thread->owner_process = owner_process; 275 thread->owner_process = owner_process;
@@ -317,17 +330,8 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
317void Thread::SetPriority(u32 priority) { 330void Thread::SetPriority(u32 priority) {
318 ASSERT_MSG(priority <= THREADPRIO_LOWEST && priority >= THREADPRIO_HIGHEST, 331 ASSERT_MSG(priority <= THREADPRIO_LOWEST && priority >= THREADPRIO_HIGHEST,
319 "Invalid priority value."); 332 "Invalid priority value.");
320 Core::System::GetInstance().Scheduler().SetThreadPriority(this, priority); 333 nominal_priority = priority;
321 nominal_priority = current_priority = priority; 334 UpdatePriority();
322}
323
324void Thread::UpdatePriority() {
325 u32 best_priority = nominal_priority;
326 for (auto& mutex : held_mutexes) {
327 if (mutex->priority < best_priority)
328 best_priority = mutex->priority;
329 }
330 BoostPriority(best_priority);
331} 335}
332 336
333void Thread::BoostPriority(u32 priority) { 337void Thread::BoostPriority(u32 priority) {
@@ -377,6 +381,38 @@ VAddr Thread::GetCommandBufferAddress() const {
377 return GetTLSAddress() + CommandHeaderOffset; 381 return GetTLSAddress() + CommandHeaderOffset;
378} 382}
379 383
384void Thread::AddMutexWaiter(SharedPtr<Thread> thread) {
385 thread->lock_owner = this;
386 wait_mutex_threads.emplace_back(std::move(thread));
387 UpdatePriority();
388}
389
390void Thread::RemoveMutexWaiter(SharedPtr<Thread> thread) {
391 boost::remove_erase(wait_mutex_threads, thread);
392 thread->lock_owner = nullptr;
393 UpdatePriority();
394}
395
396void Thread::UpdatePriority() {
397 // Find the highest priority among all the threads that are waiting for this thread's lock
398 u32 new_priority = nominal_priority;
399 for (const auto& thread : wait_mutex_threads) {
400 if (thread->nominal_priority < new_priority)
401 new_priority = thread->nominal_priority;
402 }
403
404 if (new_priority == current_priority)
405 return;
406
407 Core::System::GetInstance().Scheduler().SetThreadPriority(this, new_priority);
408
409 current_priority = new_priority;
410
411 // Recursively update the priority of the thread that depends on the priority of this one.
412 if (lock_owner)
413 lock_owner->UpdatePriority();
414}
415
380//////////////////////////////////////////////////////////////////////////////////////////////////// 416////////////////////////////////////////////////////////////////////////////////////////////////////
381 417
382/** 418/**