summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/thread.cpp
diff options
context:
space:
mode:
authorGravatar bunnei2020-12-28 13:16:43 -0800
committerGravatar bunnei2021-01-11 14:23:16 -0800
commitc3c43e32fcf198444acb493483e03fcb193156df (patch)
treea516e116d7dbb9309b0adbfa2e3660861ff4e6b7 /src/core/hle/kernel/thread.cpp
parentcore: hle: kernel: Add some useful functions for checking kernel addresses. (diff)
downloadyuzu-c3c43e32fcf198444acb493483e03fcb193156df.tar.gz
yuzu-c3c43e32fcf198444acb493483e03fcb193156df.tar.xz
yuzu-c3c43e32fcf198444acb493483e03fcb193156df.zip
hle: kernel: thread: Replace ThreadStatus/ThreadSchedStatus with a single ThreadState.
- This is how the real kernel works, and is more accurate and simpler.
Diffstat (limited to 'src/core/hle/kernel/thread.cpp')
-rw-r--r--src/core/hle/kernel/thread.cpp81
1 files changed, 30 insertions, 51 deletions
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;
44void Thread::Stop() { 44void 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
63void Thread::Wakeup() { 63void 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
92void Thread::OnWakeUp() { 81void Thread::OnWakeUp() {
93 KScopedSchedulerLock lock(kernel); 82 KScopedSchedulerLock lock(kernel);
94 SetState(ThreadStatus::Ready); 83 SetState(ThreadState::Runnable);
95} 84}
96 85
97ResultCode Thread::Start() { 86ResultCode 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
103void Thread::CancelWait() { 92void 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
115static void ResetThreadContext32(Core::ARM_Interface::ThreadContext32& context, u32 stack_top, 104static 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
238void Thread::SetState(ThreadStatus new_status) { 227void 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
261void Thread::AddMutexWaiter(std::shared_ptr<Thread> thread) { 241void 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
379void Thread::AddSchedulingFlag(ThreadSchedFlags flag) { 359void 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
387void Thread::RemoveSchedulingFlag(ThreadSchedFlags flag) { 367void 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
395void Thread::SetSchedulingStatus(ThreadSchedStatus new_status) { 375void 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