diff options
Diffstat (limited to 'src/core/hle/kernel')
| -rw-r--r-- | src/core/hle/kernel/address_arbiter.cpp | 4 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_scheduler.cpp | 32 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_scheduler.h | 4 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_synchronization_object.cpp | 6 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/mutex.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/process.cpp | 4 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 11 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.cpp | 81 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.h | 75 | ||||
| -rw-r--r-- | src/core/hle/kernel/time_manager.cpp | 3 |
11 files changed, 97 insertions, 127 deletions
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp index 23e1ef032..fe8675186 100644 --- a/src/core/hle/kernel/address_arbiter.cpp +++ b/src/core/hle/kernel/address_arbiter.cpp | |||
| @@ -201,7 +201,7 @@ ResultCode AddressArbiter::WaitForAddressIfLessThan(VAddr address, s32 value, s6 | |||
| 201 | 201 | ||
| 202 | current_thread->SetArbiterWaitAddress(address); | 202 | current_thread->SetArbiterWaitAddress(address); |
| 203 | InsertThread(SharedFrom(current_thread)); | 203 | InsertThread(SharedFrom(current_thread)); |
| 204 | current_thread->SetState(ThreadStatus::WaitArb); | 204 | current_thread->SetState(ThreadState::Waiting); |
| 205 | current_thread->WaitForArbitration(true); | 205 | current_thread->WaitForArbitration(true); |
| 206 | } | 206 | } |
| 207 | 207 | ||
| @@ -256,7 +256,7 @@ ResultCode AddressArbiter::WaitForAddressIfEqual(VAddr address, s32 value, s64 t | |||
| 256 | current_thread->SetSynchronizationResults(nullptr, RESULT_TIMEOUT); | 256 | current_thread->SetSynchronizationResults(nullptr, RESULT_TIMEOUT); |
| 257 | current_thread->SetArbiterWaitAddress(address); | 257 | current_thread->SetArbiterWaitAddress(address); |
| 258 | InsertThread(SharedFrom(current_thread)); | 258 | InsertThread(SharedFrom(current_thread)); |
| 259 | current_thread->SetState(ThreadStatus::WaitArb); | 259 | current_thread->SetState(ThreadState::Waiting); |
| 260 | current_thread->WaitForArbitration(true); | 260 | current_thread->WaitForArbitration(true); |
| 261 | } | 261 | } |
| 262 | 262 | ||
diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp index f44d31992..cdcb89f68 100644 --- a/src/core/hle/kernel/k_scheduler.cpp +++ b/src/core/hle/kernel/k_scheduler.cpp | |||
| @@ -180,22 +180,22 @@ u64 KScheduler::UpdateHighestPriorityThreadsImpl(KernelCore& kernel) { | |||
| 180 | return cores_needing_scheduling; | 180 | return cores_needing_scheduling; |
| 181 | } | 181 | } |
| 182 | 182 | ||
| 183 | void KScheduler::OnThreadStateChanged(KernelCore& kernel, Thread* thread, u32 old_state) { | 183 | void KScheduler::OnThreadStateChanged(KernelCore& kernel, Thread* thread, ThreadState old_state) { |
| 184 | ASSERT(kernel.GlobalSchedulerContext().IsLocked()); | 184 | ASSERT(kernel.GlobalSchedulerContext().IsLocked()); |
| 185 | 185 | ||
| 186 | // Check if the state has changed, because if it hasn't there's nothing to do. | 186 | // Check if the state has changed, because if it hasn't there's nothing to do. |
| 187 | const auto cur_state = thread->scheduling_state; | 187 | const auto cur_state = thread->GetRawState(); |
| 188 | if (cur_state == old_state) { | 188 | if (cur_state == old_state) { |
| 189 | return; | 189 | return; |
| 190 | } | 190 | } |
| 191 | 191 | ||
| 192 | // Update the priority queues. | 192 | // Update the priority queues. |
| 193 | if (old_state == static_cast<u32>(ThreadSchedStatus::Runnable)) { | 193 | if (old_state == ThreadState::Runnable) { |
| 194 | // If we were previously runnable, then we're not runnable now, and we should remove. | 194 | // If we were previously runnable, then we're not runnable now, and we should remove. |
| 195 | GetPriorityQueue(kernel).Remove(thread); | 195 | GetPriorityQueue(kernel).Remove(thread); |
| 196 | IncrementScheduledCount(thread); | 196 | IncrementScheduledCount(thread); |
| 197 | SetSchedulerUpdateNeeded(kernel); | 197 | SetSchedulerUpdateNeeded(kernel); |
| 198 | } else if (cur_state == static_cast<u32>(ThreadSchedStatus::Runnable)) { | 198 | } else if (cur_state == ThreadState::Runnable) { |
| 199 | // If we're now runnable, then we weren't previously, and we should add. | 199 | // If we're now runnable, then we weren't previously, and we should add. |
| 200 | GetPriorityQueue(kernel).PushBack(thread); | 200 | GetPriorityQueue(kernel).PushBack(thread); |
| 201 | IncrementScheduledCount(thread); | 201 | IncrementScheduledCount(thread); |
| @@ -204,12 +204,12 @@ void KScheduler::OnThreadStateChanged(KernelCore& kernel, Thread* thread, u32 ol | |||
| 204 | } | 204 | } |
| 205 | 205 | ||
| 206 | void KScheduler::OnThreadPriorityChanged(KernelCore& kernel, Thread* thread, Thread* current_thread, | 206 | void KScheduler::OnThreadPriorityChanged(KernelCore& kernel, Thread* thread, Thread* current_thread, |
| 207 | u32 old_priority) { | 207 | s32 old_priority) { |
| 208 | 208 | ||
| 209 | ASSERT(kernel.GlobalSchedulerContext().IsLocked()); | 209 | ASSERT(kernel.GlobalSchedulerContext().IsLocked()); |
| 210 | 210 | ||
| 211 | // If the thread is runnable, we want to change its priority in the queue. | 211 | // If the thread is runnable, we want to change its priority in the queue. |
| 212 | if (thread->scheduling_state == static_cast<u32>(ThreadSchedStatus::Runnable)) { | 212 | if (thread->GetRawState() == ThreadState::Runnable) { |
| 213 | GetPriorityQueue(kernel).ChangePriority( | 213 | GetPriorityQueue(kernel).ChangePriority( |
| 214 | old_priority, thread == kernel.CurrentScheduler()->GetCurrentThread(), thread); | 214 | old_priority, thread == kernel.CurrentScheduler()->GetCurrentThread(), thread); |
| 215 | IncrementScheduledCount(thread); | 215 | IncrementScheduledCount(thread); |
| @@ -222,7 +222,7 @@ void KScheduler::OnThreadAffinityMaskChanged(KernelCore& kernel, Thread* thread, | |||
| 222 | ASSERT(kernel.GlobalSchedulerContext().IsLocked()); | 222 | ASSERT(kernel.GlobalSchedulerContext().IsLocked()); |
| 223 | 223 | ||
| 224 | // If the thread is runnable, we want to change its affinity in the queue. | 224 | // If the thread is runnable, we want to change its affinity in the queue. |
| 225 | if (thread->scheduling_state == static_cast<u32>(ThreadSchedStatus::Runnable)) { | 225 | if (thread->GetRawState() == ThreadState::Runnable) { |
| 226 | GetPriorityQueue(kernel).ChangeAffinityMask(old_core, old_affinity, thread); | 226 | GetPriorityQueue(kernel).ChangeAffinityMask(old_core, old_affinity, thread); |
| 227 | IncrementScheduledCount(thread); | 227 | IncrementScheduledCount(thread); |
| 228 | SetSchedulerUpdateNeeded(kernel); | 228 | SetSchedulerUpdateNeeded(kernel); |
| @@ -395,8 +395,8 @@ void KScheduler::YieldWithoutCoreMigration() { | |||
| 395 | { | 395 | { |
| 396 | KScopedSchedulerLock lock(kernel); | 396 | KScopedSchedulerLock lock(kernel); |
| 397 | 397 | ||
| 398 | const auto cur_state = cur_thread.scheduling_state; | 398 | const auto cur_state = cur_thread.GetRawState(); |
| 399 | if (cur_state == static_cast<u32>(ThreadSchedStatus::Runnable)) { | 399 | if (cur_state == ThreadState::Runnable) { |
| 400 | // Put the current thread at the back of the queue. | 400 | // Put the current thread at the back of the queue. |
| 401 | Thread* next_thread = priority_queue.MoveToScheduledBack(std::addressof(cur_thread)); | 401 | Thread* next_thread = priority_queue.MoveToScheduledBack(std::addressof(cur_thread)); |
| 402 | IncrementScheduledCount(std::addressof(cur_thread)); | 402 | IncrementScheduledCount(std::addressof(cur_thread)); |
| @@ -436,8 +436,8 @@ void KScheduler::YieldWithCoreMigration() { | |||
| 436 | { | 436 | { |
| 437 | KScopedSchedulerLock lock(kernel); | 437 | KScopedSchedulerLock lock(kernel); |
| 438 | 438 | ||
| 439 | const auto cur_state = cur_thread.scheduling_state; | 439 | const auto cur_state = cur_thread.GetRawState(); |
| 440 | if (cur_state == static_cast<u32>(ThreadSchedStatus::Runnable)) { | 440 | if (cur_state == ThreadState::Runnable) { |
| 441 | // Get the current active core. | 441 | // Get the current active core. |
| 442 | const s32 core_id = cur_thread.GetActiveCore(); | 442 | const s32 core_id = cur_thread.GetActiveCore(); |
| 443 | 443 | ||
| @@ -526,8 +526,8 @@ void KScheduler::YieldToAnyThread() { | |||
| 526 | { | 526 | { |
| 527 | KScopedSchedulerLock lock(kernel); | 527 | KScopedSchedulerLock lock(kernel); |
| 528 | 528 | ||
| 529 | const auto cur_state = cur_thread.scheduling_state; | 529 | const auto cur_state = cur_thread.GetRawState(); |
| 530 | if (cur_state == static_cast<u32>(ThreadSchedStatus::Runnable)) { | 530 | if (cur_state == ThreadState::Runnable) { |
| 531 | // Get the current active core. | 531 | // Get the current active core. |
| 532 | const s32 core_id = cur_thread.GetActiveCore(); | 532 | const s32 core_id = cur_thread.GetActiveCore(); |
| 533 | 533 | ||
| @@ -645,7 +645,7 @@ void KScheduler::Unload(Thread* thread) { | |||
| 645 | 645 | ||
| 646 | void KScheduler::Reload(Thread* thread) { | 646 | void KScheduler::Reload(Thread* thread) { |
| 647 | if (thread) { | 647 | if (thread) { |
| 648 | ASSERT_MSG(thread->GetState() == ThreadSchedStatus::Runnable, "Thread must be runnable."); | 648 | ASSERT_MSG(thread->GetState() == ThreadState::Runnable, "Thread must be runnable."); |
| 649 | 649 | ||
| 650 | // Cancel any outstanding wakeup events for this thread | 650 | // Cancel any outstanding wakeup events for this thread |
| 651 | thread->SetIsRunning(true); | 651 | thread->SetIsRunning(true); |
| @@ -724,7 +724,7 @@ void KScheduler::SwitchToCurrent() { | |||
| 724 | do { | 724 | do { |
| 725 | if (current_thread != nullptr && !current_thread->IsHLEThread()) { | 725 | if (current_thread != nullptr && !current_thread->IsHLEThread()) { |
| 726 | current_thread->context_guard.lock(); | 726 | current_thread->context_guard.lock(); |
| 727 | if (!current_thread->IsRunnable()) { | 727 | if (current_thread->GetRawState() != ThreadState::Runnable) { |
| 728 | current_thread->context_guard.unlock(); | 728 | current_thread->context_guard.unlock(); |
| 729 | break; | 729 | break; |
| 730 | } | 730 | } |
| @@ -771,7 +771,7 @@ void KScheduler::Initialize() { | |||
| 771 | 771 | ||
| 772 | { | 772 | { |
| 773 | KScopedSchedulerLock lock{system.Kernel()}; | 773 | KScopedSchedulerLock lock{system.Kernel()}; |
| 774 | idle_thread->SetState(ThreadStatus::Ready); | 774 | idle_thread->SetState(ThreadState::Runnable); |
| 775 | } | 775 | } |
| 776 | } | 776 | } |
| 777 | 777 | ||
diff --git a/src/core/hle/kernel/k_scheduler.h b/src/core/hle/kernel/k_scheduler.h index e84abc84c..677375d1a 100644 --- a/src/core/hle/kernel/k_scheduler.h +++ b/src/core/hle/kernel/k_scheduler.h | |||
| @@ -100,11 +100,11 @@ public: | |||
| 100 | void YieldToAnyThread(); | 100 | void YieldToAnyThread(); |
| 101 | 101 | ||
| 102 | /// Notify the scheduler a thread's status has changed. | 102 | /// Notify the scheduler a thread's status has changed. |
| 103 | static void OnThreadStateChanged(KernelCore& kernel, Thread* thread, u32 old_state); | 103 | static void OnThreadStateChanged(KernelCore& kernel, Thread* thread, ThreadState old_state); |
| 104 | 104 | ||
| 105 | /// Notify the scheduler a thread's priority has changed. | 105 | /// Notify the scheduler a thread's priority has changed. |
| 106 | static void OnThreadPriorityChanged(KernelCore& kernel, Thread* thread, Thread* current_thread, | 106 | static void OnThreadPriorityChanged(KernelCore& kernel, Thread* thread, Thread* current_thread, |
| 107 | u32 old_priority); | 107 | s32 old_priority); |
| 108 | 108 | ||
| 109 | /// Notify the scheduler a thread's core and/or affinity mask has changed. | 109 | /// Notify the scheduler a thread's core and/or affinity mask has changed. |
| 110 | static void OnThreadAffinityMaskChanged(KernelCore& kernel, Thread* thread, | 110 | static void OnThreadAffinityMaskChanged(KernelCore& kernel, Thread* thread, |
diff --git a/src/core/hle/kernel/k_synchronization_object.cpp b/src/core/hle/kernel/k_synchronization_object.cpp index e7fd119d8..64c566caa 100644 --- a/src/core/hle/kernel/k_synchronization_object.cpp +++ b/src/core/hle/kernel/k_synchronization_object.cpp | |||
| @@ -77,7 +77,7 @@ ResultCode KSynchronizationObject::Wait(KernelCore& kernel, s32* out_index, | |||
| 77 | // Mark the thread as waiting. | 77 | // Mark the thread as waiting. |
| 78 | thread->SetCancellable(); | 78 | thread->SetCancellable(); |
| 79 | thread->SetSyncedObject(nullptr, Svc::ResultTimedOut); | 79 | thread->SetSyncedObject(nullptr, Svc::ResultTimedOut); |
| 80 | thread->SetState(ThreadState::WaitSynch); | 80 | thread->SetState(ThreadState::Waiting); |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | // The lock/sleep is done, so we should be able to get our result. | 83 | // The lock/sleep is done, so we should be able to get our result. |
| @@ -148,9 +148,9 @@ void KSynchronizationObject::NotifyAvailable(ResultCode result) { | |||
| 148 | // Iterate over each thread. | 148 | // Iterate over each thread. |
| 149 | for (auto* cur_node = thread_list_head; cur_node != nullptr; cur_node = cur_node->next) { | 149 | for (auto* cur_node = thread_list_head; cur_node != nullptr; cur_node = cur_node->next) { |
| 150 | Thread* thread = cur_node->thread; | 150 | Thread* thread = cur_node->thread; |
| 151 | if (thread->GetState() == ThreadSchedStatus::Paused) { | 151 | if (thread->GetState() == ThreadState::Waiting) { |
| 152 | thread->SetSyncedObject(this, result); | 152 | thread->SetSyncedObject(this, result); |
| 153 | thread->SetState(ThreadStatus::Ready); | 153 | thread->SetState(ThreadState::Runnable); |
| 154 | } | 154 | } |
| 155 | } | 155 | } |
| 156 | } | 156 | } |
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index f1dcbe2eb..af4a5e33d 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -602,7 +602,7 @@ void KernelCore::Suspend(bool in_suspention) { | |||
| 602 | const bool should_suspend = exception_exited || in_suspention; | 602 | const bool should_suspend = exception_exited || in_suspention; |
| 603 | { | 603 | { |
| 604 | KScopedSchedulerLock lock(*this); | 604 | KScopedSchedulerLock lock(*this); |
| 605 | ThreadStatus status = should_suspend ? ThreadStatus::Ready : ThreadStatus::WaitSleep; | 605 | const auto status = should_suspend ? ThreadState::Runnable : ThreadState::Waiting; |
| 606 | for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { | 606 | for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { |
| 607 | impl->suspend_threads[i]->SetState(status); | 607 | impl->suspend_threads[i]->SetState(status); |
| 608 | } | 608 | } |
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index badd883aa..8a0faacf8 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp | |||
| @@ -107,7 +107,7 @@ ResultCode Mutex::TryAcquire(VAddr address, Handle holding_thread_handle, | |||
| 107 | current_thread->SetMutexWaitAddress(address); | 107 | current_thread->SetMutexWaitAddress(address); |
| 108 | current_thread->SetWaitHandle(requesting_thread_handle); | 108 | current_thread->SetWaitHandle(requesting_thread_handle); |
| 109 | 109 | ||
| 110 | current_thread->SetState(ThreadStatus::WaitMutex); | 110 | current_thread->SetState(ThreadState::Waiting); |
| 111 | 111 | ||
| 112 | // Update the lock holder thread's priority to prevent priority inversion. | 112 | // Update the lock holder thread's priority to prevent priority inversion. |
| 113 | holding_thread->AddMutexWaiter(current_thread); | 113 | holding_thread->AddMutexWaiter(current_thread); |
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 92e877c3e..a306c7c73 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp | |||
| @@ -55,7 +55,7 @@ void SetupMainThread(Core::System& system, Process& owner_process, u32 priority, | |||
| 55 | // Threads by default are dormant, wake up the main thread so it runs when the scheduler fires | 55 | // Threads by default are dormant, wake up the main thread so it runs when the scheduler fires |
| 56 | { | 56 | { |
| 57 | KScopedSchedulerLock lock{kernel}; | 57 | KScopedSchedulerLock lock{kernel}; |
| 58 | thread->SetState(ThreadStatus::Ready); | 58 | thread->SetState(ThreadState::Runnable); |
| 59 | } | 59 | } |
| 60 | } | 60 | } |
| 61 | } // Anonymous namespace | 61 | } // Anonymous namespace |
| @@ -318,7 +318,7 @@ void Process::PrepareForTermination() { | |||
| 318 | continue; | 318 | continue; |
| 319 | 319 | ||
| 320 | // TODO(Subv): When are the other running/ready threads terminated? | 320 | // TODO(Subv): When are the other running/ready threads terminated? |
| 321 | ASSERT_MSG(thread->GetStatus() == ThreadStatus::WaitSynch, | 321 | ASSERT_MSG(thread->GetState() == ThreadState::Waiting, |
| 322 | "Exiting processes with non-waiting threads is currently unimplemented"); | 322 | "Exiting processes with non-waiting threads is currently unimplemented"); |
| 323 | 323 | ||
| 324 | thread->Stop(); | 324 | thread->Stop(); |
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 0a3064c7d..304b8727d 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -343,7 +343,7 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) { | |||
| 343 | auto thread = kernel.CurrentScheduler()->GetCurrentThread(); | 343 | auto thread = kernel.CurrentScheduler()->GetCurrentThread(); |
| 344 | { | 344 | { |
| 345 | KScopedSchedulerLock lock(kernel); | 345 | KScopedSchedulerLock lock(kernel); |
| 346 | thread->SetState(ThreadStatus::WaitIPC); | 346 | thread->SetState(ThreadState::Waiting); |
| 347 | session->SendSyncRequest(SharedFrom(thread), system.Memory(), system.CoreTiming()); | 347 | session->SendSyncRequest(SharedFrom(thread), system.Memory(), system.CoreTiming()); |
| 348 | } | 348 | } |
| 349 | 349 | ||
| @@ -1546,7 +1546,7 @@ static ResultCode StartThread(Core::System& system, Handle thread_handle) { | |||
| 1546 | return ERR_INVALID_HANDLE; | 1546 | return ERR_INVALID_HANDLE; |
| 1547 | } | 1547 | } |
| 1548 | 1548 | ||
| 1549 | ASSERT(thread->GetStatus() == ThreadStatus::Dormant); | 1549 | ASSERT(thread->GetState() == ThreadState::Initialized); |
| 1550 | 1550 | ||
| 1551 | return thread->Start(); | 1551 | return thread->Start(); |
| 1552 | } | 1552 | } |
| @@ -1661,7 +1661,8 @@ static ResultCode WaitProcessWideKeyAtomic(Core::System& system, VAddr mutex_add | |||
| 1661 | current_thread->SetCondVarWaitAddress(condition_variable_addr); | 1661 | current_thread->SetCondVarWaitAddress(condition_variable_addr); |
| 1662 | current_thread->SetMutexWaitAddress(mutex_addr); | 1662 | current_thread->SetMutexWaitAddress(mutex_addr); |
| 1663 | current_thread->SetWaitHandle(thread_handle); | 1663 | current_thread->SetWaitHandle(thread_handle); |
| 1664 | current_thread->SetState(ThreadStatus::WaitCondVar); | 1664 | current_thread->SetState(ThreadState::Waiting); |
| 1665 | current_thread->SetWaitingCondVar(true); | ||
| 1665 | current_process->InsertConditionVariableThread(SharedFrom(current_thread)); | 1666 | current_process->InsertConditionVariableThread(SharedFrom(current_thread)); |
| 1666 | } | 1667 | } |
| 1667 | 1668 | ||
| @@ -1755,9 +1756,7 @@ static void SignalProcessWideKey(Core::System& system, VAddr condition_variable_ | |||
| 1755 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | 1756 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); |
| 1756 | auto owner = handle_table.Get<Thread>(owner_handle); | 1757 | auto owner = handle_table.Get<Thread>(owner_handle); |
| 1757 | ASSERT(owner); | 1758 | ASSERT(owner); |
| 1758 | if (thread->GetStatus() == ThreadStatus::WaitCondVar) { | 1759 | thread->SetWaitingCondVar(false); |
| 1759 | thread->SetState(ThreadStatus::WaitMutex); | ||
| 1760 | } | ||
| 1761 | 1760 | ||
| 1762 | owner->AddMutexWaiter(thread); | 1761 | owner->AddMutexWaiter(thread); |
| 1763 | } | 1762 | } |
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index ac19e2997..33a4e1fa3 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp | |||
| @@ -44,7 +44,7 @@ Thread::~Thread() = default; | |||
| 44 | void Thread::Stop() { | 44 | void Thread::Stop() { |
| 45 | { | 45 | { |
| 46 | KScopedSchedulerLock lock(kernel); | 46 | KScopedSchedulerLock lock(kernel); |
| 47 | SetState(ThreadStatus::Dead); | 47 | SetState(ThreadState::Terminated); |
| 48 | signaled = true; | 48 | signaled = true; |
| 49 | NotifyAvailable(); | 49 | NotifyAvailable(); |
| 50 | kernel.GlobalHandleTable().Close(global_handle); | 50 | kernel.GlobalHandleTable().Close(global_handle); |
| @@ -62,54 +62,43 @@ void Thread::Stop() { | |||
| 62 | 62 | ||
| 63 | void Thread::Wakeup() { | 63 | void Thread::Wakeup() { |
| 64 | KScopedSchedulerLock lock(kernel); | 64 | KScopedSchedulerLock lock(kernel); |
| 65 | switch (status) { | 65 | switch (thread_state) { |
| 66 | case ThreadStatus::Paused: | 66 | case ThreadState::Runnable: |
| 67 | case ThreadStatus::WaitSynch: | ||
| 68 | case ThreadStatus::WaitHLEEvent: | ||
| 69 | case ThreadStatus::WaitSleep: | ||
| 70 | case ThreadStatus::WaitIPC: | ||
| 71 | case ThreadStatus::WaitMutex: | ||
| 72 | case ThreadStatus::WaitCondVar: | ||
| 73 | case ThreadStatus::WaitArb: | ||
| 74 | case ThreadStatus::Dormant: | ||
| 75 | break; | ||
| 76 | |||
| 77 | case ThreadStatus::Ready: | ||
| 78 | // If the thread is waiting on multiple wait objects, it might be awoken more than once | 67 | // If the thread is waiting on multiple wait objects, it might be awoken more than once |
| 79 | // before actually resuming. We can ignore subsequent wakeups if the thread status has | 68 | // before actually resuming. We can ignore subsequent wakeups if the thread status has |
| 80 | // already been set to ThreadStatus::Ready. | 69 | // already been set to ThreadStatus::Ready. |
| 81 | return; | 70 | return; |
| 82 | case ThreadStatus::Dead: | 71 | case ThreadState::Terminated: |
| 83 | // This should never happen, as threads must complete before being stopped. | 72 | // This should never happen, as threads must complete before being stopped. |
| 84 | DEBUG_ASSERT_MSG(false, "Thread with object id {} cannot be resumed because it's DEAD.", | 73 | DEBUG_ASSERT_MSG(false, "Thread with object id {} cannot be resumed because it's DEAD.", |
| 85 | GetObjectId()); | 74 | GetObjectId()); |
| 86 | return; | 75 | return; |
| 87 | } | 76 | } |
| 88 | 77 | ||
| 89 | SetState(ThreadStatus::Ready); | 78 | SetState(ThreadState::Runnable); |
| 90 | } | 79 | } |
| 91 | 80 | ||
| 92 | void Thread::OnWakeUp() { | 81 | void Thread::OnWakeUp() { |
| 93 | KScopedSchedulerLock lock(kernel); | 82 | KScopedSchedulerLock lock(kernel); |
| 94 | SetState(ThreadStatus::Ready); | 83 | SetState(ThreadState::Runnable); |
| 95 | } | 84 | } |
| 96 | 85 | ||
| 97 | ResultCode Thread::Start() { | 86 | ResultCode Thread::Start() { |
| 98 | KScopedSchedulerLock lock(kernel); | 87 | KScopedSchedulerLock lock(kernel); |
| 99 | SetState(ThreadStatus::Ready); | 88 | SetState(ThreadState::Runnable); |
| 100 | return RESULT_SUCCESS; | 89 | return RESULT_SUCCESS; |
| 101 | } | 90 | } |
| 102 | 91 | ||
| 103 | void Thread::CancelWait() { | 92 | void Thread::CancelWait() { |
| 104 | KScopedSchedulerLock lock(kernel); | 93 | KScopedSchedulerLock lock(kernel); |
| 105 | if (GetState() != ThreadSchedStatus::Paused || !is_cancellable) { | 94 | if (GetState() != ThreadState::Waiting || !is_cancellable) { |
| 106 | is_sync_cancelled = true; | 95 | is_sync_cancelled = true; |
| 107 | return; | 96 | return; |
| 108 | } | 97 | } |
| 109 | // TODO(Blinkhawk): Implement cancel of server session | 98 | // TODO(Blinkhawk): Implement cancel of server session |
| 110 | is_sync_cancelled = false; | 99 | is_sync_cancelled = false; |
| 111 | SetSynchronizationResults(nullptr, ERR_SYNCHRONIZATION_CANCELED); | 100 | SetSynchronizationResults(nullptr, ERR_SYNCHRONIZATION_CANCELED); |
| 112 | SetState(ThreadStatus::Ready); | 101 | SetState(ThreadState::Runnable); |
| 113 | } | 102 | } |
| 114 | 103 | ||
| 115 | static void ResetThreadContext32(Core::ARM_Interface::ThreadContext32& context, u32 stack_top, | 104 | static void ResetThreadContext32(Core::ARM_Interface::ThreadContext32& context, u32 stack_top, |
| @@ -173,7 +162,7 @@ ResultVal<std::shared_ptr<Thread>> Thread::Create(Core::System& system, ThreadTy | |||
| 173 | std::shared_ptr<Thread> thread = std::make_shared<Thread>(kernel); | 162 | std::shared_ptr<Thread> thread = std::make_shared<Thread>(kernel); |
| 174 | 163 | ||
| 175 | thread->thread_id = kernel.CreateNewThreadID(); | 164 | thread->thread_id = kernel.CreateNewThreadID(); |
| 176 | thread->status = ThreadStatus::Dormant; | 165 | thread->thread_state = ThreadState::Initialized; |
| 177 | thread->entry_point = entry_point; | 166 | thread->entry_point = entry_point; |
| 178 | thread->stack_top = stack_top; | 167 | thread->stack_top = stack_top; |
| 179 | thread->disable_count = 1; | 168 | thread->disable_count = 1; |
| @@ -235,27 +224,18 @@ VAddr Thread::GetCommandBufferAddress() const { | |||
| 235 | return GetTLSAddress() + command_header_offset; | 224 | return GetTLSAddress() + command_header_offset; |
| 236 | } | 225 | } |
| 237 | 226 | ||
| 238 | void Thread::SetState(ThreadStatus new_status) { | 227 | void Thread::SetState(ThreadState new_status) { |
| 239 | if (new_status == status) { | 228 | if (new_status == thread_state) { |
| 240 | return; | 229 | return; |
| 241 | } | 230 | } |
| 242 | 231 | ||
| 243 | switch (new_status) { | 232 | if (new_status != ThreadState::Waiting) { |
| 244 | case ThreadStatus::Ready: | 233 | SetWaitingCondVar(false); |
| 245 | SetSchedulingStatus(ThreadSchedStatus::Runnable); | ||
| 246 | break; | ||
| 247 | case ThreadStatus::Dormant: | ||
| 248 | SetSchedulingStatus(ThreadSchedStatus::None); | ||
| 249 | break; | ||
| 250 | case ThreadStatus::Dead: | ||
| 251 | SetSchedulingStatus(ThreadSchedStatus::Exited); | ||
| 252 | break; | ||
| 253 | default: | ||
| 254 | SetSchedulingStatus(ThreadSchedStatus::Paused); | ||
| 255 | break; | ||
| 256 | } | 234 | } |
| 257 | 235 | ||
| 258 | status = new_status; | 236 | SetSchedulingStatus(new_status); |
| 237 | |||
| 238 | thread_state = new_status; | ||
| 259 | } | 239 | } |
| 260 | 240 | ||
| 261 | void Thread::AddMutexWaiter(std::shared_ptr<Thread> thread) { | 241 | void Thread::AddMutexWaiter(std::shared_ptr<Thread> thread) { |
| @@ -312,13 +292,13 @@ void Thread::UpdatePriority() { | |||
| 312 | return; | 292 | return; |
| 313 | } | 293 | } |
| 314 | 294 | ||
| 315 | if (GetStatus() == ThreadStatus::WaitCondVar) { | 295 | if (GetState() == ThreadState::Waiting && is_waiting_on_condvar) { |
| 316 | owner_process->RemoveConditionVariableThread(SharedFrom(this)); | 296 | owner_process->RemoveConditionVariableThread(SharedFrom(this)); |
| 317 | } | 297 | } |
| 318 | 298 | ||
| 319 | SetCurrentPriority(new_priority); | 299 | SetCurrentPriority(new_priority); |
| 320 | 300 | ||
| 321 | if (GetStatus() == ThreadStatus::WaitCondVar) { | 301 | if (GetState() == ThreadState::Waiting && is_waiting_on_condvar) { |
| 322 | owner_process->InsertConditionVariableThread(SharedFrom(this)); | 302 | owner_process->InsertConditionVariableThread(SharedFrom(this)); |
| 323 | } | 303 | } |
| 324 | 304 | ||
| @@ -340,7 +320,7 @@ ResultCode Thread::SetActivity(ThreadActivity value) { | |||
| 340 | 320 | ||
| 341 | auto sched_status = GetState(); | 321 | auto sched_status = GetState(); |
| 342 | 322 | ||
| 343 | if (sched_status != ThreadSchedStatus::Runnable && sched_status != ThreadSchedStatus::Paused) { | 323 | if (sched_status != ThreadState::Runnable && sched_status != ThreadState::Waiting) { |
| 344 | return ERR_INVALID_STATE; | 324 | return ERR_INVALID_STATE; |
| 345 | } | 325 | } |
| 346 | 326 | ||
| @@ -366,7 +346,7 @@ ResultCode Thread::Sleep(s64 nanoseconds) { | |||
| 366 | Handle event_handle{}; | 346 | Handle event_handle{}; |
| 367 | { | 347 | { |
| 368 | KScopedSchedulerLockAndSleep lock(kernel, event_handle, this, nanoseconds); | 348 | KScopedSchedulerLockAndSleep lock(kernel, event_handle, this, nanoseconds); |
| 369 | SetState(ThreadStatus::WaitSleep); | 349 | SetState(ThreadState::Waiting); |
| 370 | } | 350 | } |
| 371 | 351 | ||
| 372 | if (event_handle != InvalidHandle) { | 352 | if (event_handle != InvalidHandle) { |
| @@ -377,25 +357,24 @@ ResultCode Thread::Sleep(s64 nanoseconds) { | |||
| 377 | } | 357 | } |
| 378 | 358 | ||
| 379 | void Thread::AddSchedulingFlag(ThreadSchedFlags flag) { | 359 | void Thread::AddSchedulingFlag(ThreadSchedFlags flag) { |
| 380 | const u32 old_state = scheduling_state; | 360 | const auto old_state = GetRawState(); |
| 381 | pausing_state |= static_cast<u32>(flag); | 361 | pausing_state |= static_cast<u32>(flag); |
| 382 | const u32 base_scheduling = static_cast<u32>(GetState()); | 362 | const auto base_scheduling = GetState(); |
| 383 | scheduling_state = base_scheduling | pausing_state; | 363 | thread_state = base_scheduling | static_cast<ThreadState>(pausing_state); |
| 384 | KScheduler::OnThreadStateChanged(kernel, this, old_state); | 364 | KScheduler::OnThreadStateChanged(kernel, this, old_state); |
| 385 | } | 365 | } |
| 386 | 366 | ||
| 387 | void Thread::RemoveSchedulingFlag(ThreadSchedFlags flag) { | 367 | void Thread::RemoveSchedulingFlag(ThreadSchedFlags flag) { |
| 388 | const u32 old_state = scheduling_state; | 368 | const auto old_state = GetRawState(); |
| 389 | pausing_state &= ~static_cast<u32>(flag); | 369 | pausing_state &= ~static_cast<u32>(flag); |
| 390 | const u32 base_scheduling = static_cast<u32>(GetState()); | 370 | const auto base_scheduling = GetState(); |
| 391 | scheduling_state = base_scheduling | pausing_state; | 371 | thread_state = base_scheduling | static_cast<ThreadState>(pausing_state); |
| 392 | KScheduler::OnThreadStateChanged(kernel, this, old_state); | 372 | KScheduler::OnThreadStateChanged(kernel, this, old_state); |
| 393 | } | 373 | } |
| 394 | 374 | ||
| 395 | void Thread::SetSchedulingStatus(ThreadSchedStatus new_status) { | 375 | void Thread::SetSchedulingStatus(ThreadState new_status) { |
| 396 | const u32 old_state = scheduling_state; | 376 | const auto old_state = GetRawState(); |
| 397 | scheduling_state = (scheduling_state & static_cast<u32>(ThreadSchedMasks::HighMask)) | | 377 | thread_state = (thread_state & ThreadState::HighMask) | new_status; |
| 398 | static_cast<u32>(new_status); | ||
| 399 | KScheduler::OnThreadStateChanged(kernel, this, old_state); | 378 | KScheduler::OnThreadStateChanged(kernel, this, old_state); |
| 400 | } | 379 | } |
| 401 | 380 | ||
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 69458548b..06dd2ef2d 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h | |||
| @@ -73,19 +73,26 @@ enum ThreadProcessorId : s32 { | |||
| 73 | (1 << THREADPROCESSORID_2) | (1 << THREADPROCESSORID_3) | 73 | (1 << THREADPROCESSORID_2) | (1 << THREADPROCESSORID_3) |
| 74 | }; | 74 | }; |
| 75 | 75 | ||
| 76 | enum class ThreadStatus { | 76 | enum class ThreadState : u16 { |
| 77 | Ready, ///< Ready to run | 77 | Initialized = 0, |
| 78 | Paused, ///< Paused by SetThreadActivity or debug | 78 | Waiting = 1, |
| 79 | WaitHLEEvent, ///< Waiting for hle event to finish | 79 | Runnable = 2, |
| 80 | WaitSleep, ///< Waiting due to a SleepThread SVC | 80 | Terminated = 3, |
| 81 | WaitIPC, ///< Waiting for the reply from an IPC request | 81 | |
| 82 | WaitSynch, ///< Waiting due to WaitSynchronization | 82 | SuspendShift = 4, |
| 83 | WaitMutex, ///< Waiting due to an ArbitrateLock svc | 83 | Mask = (1 << SuspendShift) - 1, |
| 84 | WaitCondVar, ///< Waiting due to an WaitProcessWideKey svc | 84 | |
| 85 | WaitArb, ///< Waiting due to a SignalToAddress/WaitForAddress svc | 85 | ProcessSuspended = (1 << (0 + SuspendShift)), |
| 86 | Dormant, ///< Created but not yet made ready | 86 | ThreadSuspended = (1 << (1 + SuspendShift)), |
| 87 | Dead ///< Run to completion, or forcefully terminated | 87 | DebugSuspended = (1 << (2 + SuspendShift)), |
| 88 | BacktraceSuspended = (1 << (3 + SuspendShift)), | ||
| 89 | InitSuspended = (1 << (4 + SuspendShift)), | ||
| 90 | |||
| 91 | SuspendFlagMask = ((1 << 5) - 1) << SuspendShift, | ||
| 92 | |||
| 93 | HighMask = 0xfff0, | ||
| 88 | }; | 94 | }; |
| 95 | DECLARE_ENUM_FLAG_OPERATORS(ThreadState); | ||
| 89 | 96 | ||
| 90 | enum class ThreadWakeupReason { | 97 | enum class ThreadWakeupReason { |
| 91 | Signal, // The thread was woken up by WakeupAllWaitingThreads due to an object signal. | 98 | Signal, // The thread was woken up by WakeupAllWaitingThreads due to an object signal. |
| @@ -97,13 +104,6 @@ enum class ThreadActivity : u32 { | |||
| 97 | Paused = 1, | 104 | Paused = 1, |
| 98 | }; | 105 | }; |
| 99 | 106 | ||
| 100 | enum class ThreadSchedStatus : u32 { | ||
| 101 | None = 0, | ||
| 102 | Paused = 1, | ||
| 103 | Runnable = 2, | ||
| 104 | Exited = 3, | ||
| 105 | }; | ||
| 106 | |||
| 107 | enum class ThreadSchedFlags : u32 { | 107 | enum class ThreadSchedFlags : u32 { |
| 108 | ProcessPauseFlag = 1 << 4, | 108 | ProcessPauseFlag = 1 << 4, |
| 109 | ThreadPauseFlag = 1 << 5, | 109 | ThreadPauseFlag = 1 << 5, |
| @@ -111,12 +111,6 @@ enum class ThreadSchedFlags : u32 { | |||
| 111 | KernelInitPauseFlag = 1 << 8, | 111 | KernelInitPauseFlag = 1 << 8, |
| 112 | }; | 112 | }; |
| 113 | 113 | ||
| 114 | enum class ThreadSchedMasks : u32 { | ||
| 115 | LowMask = 0x000f, | ||
| 116 | HighMask = 0xfff0, | ||
| 117 | ForcePauseMask = 0x0070, | ||
| 118 | }; | ||
| 119 | |||
| 120 | class Thread final : public KSynchronizationObject { | 114 | class Thread final : public KSynchronizationObject { |
| 121 | public: | 115 | public: |
| 122 | explicit Thread(KernelCore& kernel); | 116 | explicit Thread(KernelCore& kernel); |
| @@ -326,11 +320,19 @@ public: | |||
| 326 | 320 | ||
| 327 | std::shared_ptr<Common::Fiber>& GetHostContext(); | 321 | std::shared_ptr<Common::Fiber>& GetHostContext(); |
| 328 | 322 | ||
| 329 | ThreadStatus GetStatus() const { | 323 | ThreadState GetState() const { |
| 330 | return status; | 324 | return thread_state & ThreadState::Mask; |
| 331 | } | 325 | } |
| 332 | 326 | ||
| 333 | void SetState(ThreadStatus new_status); | 327 | ThreadState GetRawState() const { |
| 328 | return thread_state; | ||
| 329 | } | ||
| 330 | |||
| 331 | void SetState(ThreadState new_state); | ||
| 332 | |||
| 333 | void SetWaitingCondVar(bool value) { | ||
| 334 | is_waiting_on_condvar = value; | ||
| 335 | } | ||
| 334 | 336 | ||
| 335 | s64 GetLastScheduledTick() const { | 337 | s64 GetLastScheduledTick() const { |
| 336 | return this->last_scheduled_tick; | 338 | return this->last_scheduled_tick; |
| @@ -447,15 +449,6 @@ public: | |||
| 447 | this->schedule_count = count; | 449 | this->schedule_count = count; |
| 448 | } | 450 | } |
| 449 | 451 | ||
| 450 | ThreadSchedStatus GetState() const { | ||
| 451 | return static_cast<ThreadSchedStatus>(scheduling_state & | ||
| 452 | static_cast<u32>(ThreadSchedMasks::LowMask)); | ||
| 453 | } | ||
| 454 | |||
| 455 | bool IsRunnable() const { | ||
| 456 | return scheduling_state == static_cast<u32>(ThreadSchedStatus::Runnable); | ||
| 457 | } | ||
| 458 | |||
| 459 | bool IsRunning() const { | 452 | bool IsRunning() const { |
| 460 | return is_running; | 453 | return is_running; |
| 461 | } | 454 | } |
| @@ -497,7 +490,7 @@ public: | |||
| 497 | } | 490 | } |
| 498 | 491 | ||
| 499 | bool IsTerminationRequested() const { | 492 | bool IsTerminationRequested() const { |
| 500 | return will_be_terminated || GetState() == ThreadSchedStatus::Exited; | 493 | return will_be_terminated || GetState() == ThreadState::Terminated; |
| 501 | } | 494 | } |
| 502 | 495 | ||
| 503 | bool IsPaused() const { | 496 | bool IsPaused() const { |
| @@ -590,7 +583,7 @@ private: | |||
| 590 | friend class KScheduler; | 583 | friend class KScheduler; |
| 591 | friend class Process; | 584 | friend class Process; |
| 592 | 585 | ||
| 593 | void SetSchedulingStatus(ThreadSchedStatus new_status); | 586 | void SetSchedulingStatus(ThreadState new_status); |
| 594 | void AddSchedulingFlag(ThreadSchedFlags flag); | 587 | void AddSchedulingFlag(ThreadSchedFlags flag); |
| 595 | void RemoveSchedulingFlag(ThreadSchedFlags flag); | 588 | void RemoveSchedulingFlag(ThreadSchedFlags flag); |
| 596 | void SetCurrentPriority(u32 new_priority); | 589 | void SetCurrentPriority(u32 new_priority); |
| @@ -600,8 +593,7 @@ private: | |||
| 600 | ThreadContext64 context_64{}; | 593 | ThreadContext64 context_64{}; |
| 601 | std::shared_ptr<Common::Fiber> host_context{}; | 594 | std::shared_ptr<Common::Fiber> host_context{}; |
| 602 | 595 | ||
| 603 | ThreadStatus status = ThreadStatus::Dormant; | 596 | ThreadState thread_state = ThreadState::Initialized; |
| 604 | u32 scheduling_state = 0; | ||
| 605 | 597 | ||
| 606 | u64 thread_id = 0; | 598 | u64 thread_id = 0; |
| 607 | 599 | ||
| @@ -647,6 +639,7 @@ private: | |||
| 647 | 639 | ||
| 648 | /// If waiting on a ConditionVariable, this is the ConditionVariable address | 640 | /// If waiting on a ConditionVariable, this is the ConditionVariable address |
| 649 | VAddr condvar_wait_address = 0; | 641 | VAddr condvar_wait_address = 0; |
| 642 | bool is_waiting_on_condvar{}; | ||
| 650 | /// If waiting on a Mutex, this is the mutex address | 643 | /// If waiting on a Mutex, this is the mutex address |
| 651 | VAddr mutex_wait_address = 0; | 644 | VAddr mutex_wait_address = 0; |
| 652 | /// The handle used to wait for the mutex. | 645 | /// The handle used to wait for the mutex. |
diff --git a/src/core/hle/kernel/time_manager.cpp b/src/core/hle/kernel/time_manager.cpp index 79628e2b4..b58a76dba 100644 --- a/src/core/hle/kernel/time_manager.cpp +++ b/src/core/hle/kernel/time_manager.cpp | |||
| @@ -42,8 +42,7 @@ void TimeManager::ScheduleTimeEvent(Handle& event_handle, Thread* timetask, s64 | |||
| 42 | event_handle = timetask->GetGlobalHandle(); | 42 | event_handle = timetask->GetGlobalHandle(); |
| 43 | if (nanoseconds > 0) { | 43 | if (nanoseconds > 0) { |
| 44 | ASSERT(timetask); | 44 | ASSERT(timetask); |
| 45 | ASSERT(timetask->GetStatus() != ThreadStatus::Ready); | 45 | ASSERT(timetask->GetState() != ThreadState::Runnable); |
| 46 | ASSERT(timetask->GetStatus() != ThreadStatus::WaitMutex); | ||
| 47 | system.CoreTiming().ScheduleEvent(std::chrono::nanoseconds{nanoseconds}, | 46 | system.CoreTiming().ScheduleEvent(std::chrono::nanoseconds{nanoseconds}, |
| 48 | time_manager_event_type, event_handle); | 47 | time_manager_event_type, event_handle); |
| 49 | } else { | 48 | } else { |