summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/thread.cpp
diff options
context:
space:
mode:
authorGravatar David Marcec2018-04-26 14:28:54 -0700
committerGravatar David Marcec2018-04-26 14:28:54 -0700
commit7391741a204d6f25a06132eda214b2199b60a084 (patch)
treeaeeb723744c4563ad608361b82dd938b062a3e09 /src/core/hle/kernel/thread.cpp
parentAdded PREPO to logging backend, Removed comments from SaveReportWithUser (diff)
parentMerge pull request #403 from lioncash/common (diff)
downloadyuzu-7391741a204d6f25a06132eda214b2199b60a084.tar.gz
yuzu-7391741a204d6f25a06132eda214b2199b60a084.tar.xz
yuzu-7391741a204d6f25a06132eda214b2199b60a084.zip
Merge branch 'master' of https://github.com/yuzu-emu/yuzu into service-impl
Diffstat (limited to 'src/core/hle/kernel/thread.cpp')
-rw-r--r--src/core/hle/kernel/thread.cpp81
1 files changed, 59 insertions, 22 deletions
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index f3a8aa4aa..4cd57ab25 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 =
@@ -104,9 +101,10 @@ void ExitCurrentThread() {
104 * @param cycles_late The number of CPU cycles that have passed since the desired wakeup time 101 * @param cycles_late The number of CPU cycles that have passed since the desired wakeup time
105 */ 102 */
106static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) { 103static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) {
107 SharedPtr<Thread> thread = wakeup_callback_handle_table.Get<Thread>((Handle)thread_handle); 104 const auto proper_handle = static_cast<Handle>(thread_handle);
105 SharedPtr<Thread> thread = wakeup_callback_handle_table.Get<Thread>(proper_handle);
108 if (thread == nullptr) { 106 if (thread == nullptr) {
109 LOG_CRITICAL(Kernel, "Callback fired for invalid thread %08X", (Handle)thread_handle); 107 NGLOG_CRITICAL(Kernel, "Callback fired for invalid thread {:08X}", proper_handle);
110 return; 108 return;
111 } 109 }
112 110
@@ -126,6 +124,19 @@ static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) {
126 resume = thread->wakeup_callback(ThreadWakeupReason::Timeout, thread, nullptr, 0); 124 resume = thread->wakeup_callback(ThreadWakeupReason::Timeout, thread, nullptr, 0);
127 } 125 }
128 126
127 if (thread->mutex_wait_address != 0 || thread->condvar_wait_address != 0 ||
128 thread->wait_handle) {
129 ASSERT(thread->status == THREADSTATUS_WAIT_MUTEX);
130 thread->mutex_wait_address = 0;
131 thread->condvar_wait_address = 0;
132 thread->wait_handle = 0;
133
134 auto lock_owner = thread->lock_owner;
135 // Threads waking up by timeout from WaitProcessWideKey do not perform priority inheritance
136 // and don't have a lock owner.
137 ASSERT(lock_owner == nullptr);
138 }
139
129 if (resume) 140 if (resume)
130 thread->ResumeFromWait(); 141 thread->ResumeFromWait();
131} 142}
@@ -151,6 +162,7 @@ void Thread::ResumeFromWait() {
151 case THREADSTATUS_WAIT_HLE_EVENT: 162 case THREADSTATUS_WAIT_HLE_EVENT:
152 case THREADSTATUS_WAIT_SLEEP: 163 case THREADSTATUS_WAIT_SLEEP:
153 case THREADSTATUS_WAIT_IPC: 164 case THREADSTATUS_WAIT_IPC:
165 case THREADSTATUS_WAIT_MUTEX:
154 break; 166 break;
155 167
156 case THREADSTATUS_READY: 168 case THREADSTATUS_READY:
@@ -227,19 +239,19 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
227 SharedPtr<Process> owner_process) { 239 SharedPtr<Process> owner_process) {
228 // Check if priority is in ranged. Lowest priority -> highest priority id. 240 // Check if priority is in ranged. Lowest priority -> highest priority id.
229 if (priority > THREADPRIO_LOWEST) { 241 if (priority > THREADPRIO_LOWEST) {
230 LOG_ERROR(Kernel_SVC, "Invalid thread priority: %u", priority); 242 NGLOG_ERROR(Kernel_SVC, "Invalid thread priority: {}", priority);
231 return ERR_OUT_OF_RANGE; 243 return ERR_OUT_OF_RANGE;
232 } 244 }
233 245
234 if (processor_id > THREADPROCESSORID_MAX) { 246 if (processor_id > THREADPROCESSORID_MAX) {
235 LOG_ERROR(Kernel_SVC, "Invalid processor id: %d", processor_id); 247 NGLOG_ERROR(Kernel_SVC, "Invalid processor id: {}", processor_id);
236 return ERR_OUT_OF_RANGE_KERNEL; 248 return ERR_OUT_OF_RANGE_KERNEL;
237 } 249 }
238 250
239 // TODO(yuriks): Other checks, returning 0xD9001BEA 251 // TODO(yuriks): Other checks, returning 0xD9001BEA
240 252
241 if (!Memory::IsValidVirtualAddress(*owner_process, entry_point)) { 253 if (!Memory::IsValidVirtualAddress(*owner_process, entry_point)) {
242 LOG_ERROR(Kernel_SVC, "(name=%s): invalid entry %016" PRIx64, name.c_str(), entry_point); 254 NGLOG_ERROR(Kernel_SVC, "(name={}): invalid entry {:016X}", name, entry_point);
243 // TODO (bunnei): Find the correct error code to use here 255 // TODO (bunnei): Find the correct error code to use here
244 return ResultCode(-1); 256 return ResultCode(-1);
245 } 257 }
@@ -256,7 +268,9 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
256 thread->last_running_ticks = CoreTiming::GetTicks(); 268 thread->last_running_ticks = CoreTiming::GetTicks();
257 thread->processor_id = processor_id; 269 thread->processor_id = processor_id;
258 thread->wait_objects.clear(); 270 thread->wait_objects.clear();
259 thread->wait_address = 0; 271 thread->mutex_wait_address = 0;
272 thread->condvar_wait_address = 0;
273 thread->wait_handle = 0;
260 thread->name = std::move(name); 274 thread->name = std::move(name);
261 thread->callback_handle = wakeup_callback_handle_table.Create(thread).Unwrap(); 275 thread->callback_handle = wakeup_callback_handle_table.Create(thread).Unwrap();
262 thread->owner_process = owner_process; 276 thread->owner_process = owner_process;
@@ -276,8 +290,8 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
276 auto& linheap_memory = memory_region->linear_heap_memory; 290 auto& linheap_memory = memory_region->linear_heap_memory;
277 291
278 if (linheap_memory->size() + Memory::PAGE_SIZE > memory_region->size) { 292 if (linheap_memory->size() + Memory::PAGE_SIZE > memory_region->size) {
279 LOG_ERROR(Kernel_SVC, 293 NGLOG_ERROR(Kernel_SVC,
280 "Not enough space in region to allocate a new TLS page for thread"); 294 "Not enough space in region to allocate a new TLS page for thread");
281 return ERR_OUT_OF_MEMORY; 295 return ERR_OUT_OF_MEMORY;
282 } 296 }
283 297
@@ -317,17 +331,8 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
317void Thread::SetPriority(u32 priority) { 331void Thread::SetPriority(u32 priority) {
318 ASSERT_MSG(priority <= THREADPRIO_LOWEST && priority >= THREADPRIO_HIGHEST, 332 ASSERT_MSG(priority <= THREADPRIO_LOWEST && priority >= THREADPRIO_HIGHEST,
319 "Invalid priority value."); 333 "Invalid priority value.");
320 Core::System::GetInstance().Scheduler().SetThreadPriority(this, priority); 334 nominal_priority = priority;
321 nominal_priority = current_priority = priority; 335 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} 336}
332 337
333void Thread::BoostPriority(u32 priority) { 338void Thread::BoostPriority(u32 priority) {
@@ -377,6 +382,38 @@ VAddr Thread::GetCommandBufferAddress() const {
377 return GetTLSAddress() + CommandHeaderOffset; 382 return GetTLSAddress() + CommandHeaderOffset;
378} 383}
379 384
385void Thread::AddMutexWaiter(SharedPtr<Thread> thread) {
386 thread->lock_owner = this;
387 wait_mutex_threads.emplace_back(std::move(thread));
388 UpdatePriority();
389}
390
391void Thread::RemoveMutexWaiter(SharedPtr<Thread> thread) {
392 boost::remove_erase(wait_mutex_threads, thread);
393 thread->lock_owner = nullptr;
394 UpdatePriority();
395}
396
397void Thread::UpdatePriority() {
398 // Find the highest priority among all the threads that are waiting for this thread's lock
399 u32 new_priority = nominal_priority;
400 for (const auto& thread : wait_mutex_threads) {
401 if (thread->nominal_priority < new_priority)
402 new_priority = thread->nominal_priority;
403 }
404
405 if (new_priority == current_priority)
406 return;
407
408 Core::System::GetInstance().Scheduler().SetThreadPriority(this, new_priority);
409
410 current_priority = new_priority;
411
412 // Recursively update the priority of the thread that depends on the priority of this one.
413 if (lock_owner)
414 lock_owner->UpdatePriority();
415}
416
380//////////////////////////////////////////////////////////////////////////////////////////////////// 417////////////////////////////////////////////////////////////////////////////////////////////////////
381 418
382/** 419/**