summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/thread.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel/thread.cpp')
-rw-r--r--src/core/hle/kernel/thread.cpp61
1 files changed, 40 insertions, 21 deletions
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index e8962a0d8..b99e3b7a5 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -113,20 +113,11 @@ void Thread::ResumeFromWait() {
113 return; 113 return;
114 } 114 }
115 115
116 if (activity == ThreadActivity::Paused) {
117 SetStatus(ThreadStatus::Paused);
118 return;
119 }
120
121 SetStatus(ThreadStatus::Ready); 116 SetStatus(ThreadStatus::Ready);
122} 117}
123 118
124void Thread::OnWakeUp() { 119void Thread::OnWakeUp() {
125 SchedulerLock lock(kernel); 120 SchedulerLock lock(kernel);
126 if (activity == ThreadActivity::Paused) {
127 SetStatus(ThreadStatus::Paused);
128 return;
129 }
130 121
131 SetStatus(ThreadStatus::Ready); 122 SetStatus(ThreadStatus::Ready);
132} 123}
@@ -143,7 +134,7 @@ void Thread::CancelWait() {
143 is_sync_cancelled = true; 134 is_sync_cancelled = true;
144 return; 135 return;
145 } 136 }
146 //TODO(Blinkhawk): Implement cancel of server session 137 // TODO(Blinkhawk): Implement cancel of server session
147 is_sync_cancelled = false; 138 is_sync_cancelled = false;
148 SetSynchronizationResults(nullptr, ERR_SYNCHRONIZATION_CANCELED); 139 SetSynchronizationResults(nullptr, ERR_SYNCHRONIZATION_CANCELED);
149 SetStatus(ThreadStatus::Ready); 140 SetStatus(ThreadStatus::Ready);
@@ -407,19 +398,31 @@ bool Thread::InvokeHLECallback(std::shared_ptr<Thread> thread) {
407 return hle_callback(std::move(thread)); 398 return hle_callback(std::move(thread));
408} 399}
409 400
410void Thread::SetActivity(ThreadActivity value) { 401ResultCode Thread::SetActivity(ThreadActivity value) {
411 activity = value; 402 SchedulerLock lock(kernel);
403
404 auto sched_status = GetSchedulingStatus();
405
406 if (sched_status != ThreadSchedStatus::Runnable && sched_status != ThreadSchedStatus::Paused) {
407 return ERR_INVALID_STATE;
408 }
409
410 if (IsPendingTermination()) {
411 return RESULT_SUCCESS;
412 }
412 413
413 if (value == ThreadActivity::Paused) { 414 if (value == ThreadActivity::Paused) {
414 // Set status if not waiting 415 if (pausing_state & static_cast<u32>(ThreadSchedFlags::ThreadPauseFlag) != 0) {
415 if (status == ThreadStatus::Ready || status == ThreadStatus::Running) { 416 return ERR_INVALID_STATE;
416 SetStatus(ThreadStatus::Paused);
417 kernel.PrepareReschedule(processor_id);
418 } 417 }
419 } else if (status == ThreadStatus::Paused) { 418 AddSchedulingFlag(ThreadSchedFlags::ThreadPauseFlag);
420 // Ready to reschedule 419 } else {
421 ResumeFromWait(); 420 if (pausing_state & static_cast<u32>(ThreadSchedFlags::ThreadPauseFlag) == 0) {
421 return ERR_INVALID_STATE;
422 }
423 RemoveSchedulingFlag(ThreadSchedFlags::ThreadPauseFlag);
422 } 424 }
425 return RESULT_SUCCESS;
423} 426}
424 427
425ResultCode Thread::Sleep(s64 nanoseconds) { 428ResultCode Thread::Sleep(s64 nanoseconds) {
@@ -460,11 +463,27 @@ ResultCode Thread::YieldAndWaitForLoadBalancing() {
460 return RESULT_SUCCESS; 463 return RESULT_SUCCESS;
461} 464}
462 465
466void Thread::AddSchedulingFlag(ThreadSchedFlags flag) {
467 const u32 old_state = scheduling_state;
468 pausing_state |= static_cast<u32>(flag);
469 const u32 base_scheduling = static_cast<u32>(GetSchedulingStatus());
470 scheduling_state = base_scheduling | pausing_state;
471 kernel.GlobalScheduler().AdjustSchedulingOnStatus(this, old_state);
472}
473
474void Thread::RemoveSchedulingFlag(ThreadSchedFlags flag) {
475 const u32 old_state = scheduling_state;
476 pausing_state &= ~static_cast<u32>(flag);
477 const u32 base_scheduling = static_cast<u32>(GetSchedulingStatus());
478 scheduling_state = base_scheduling | pausing_state;
479 kernel.GlobalScheduler().AdjustSchedulingOnStatus(this, old_state);
480}
481
463void Thread::SetSchedulingStatus(ThreadSchedStatus new_status) { 482void Thread::SetSchedulingStatus(ThreadSchedStatus new_status) {
464 const u32 old_flags = scheduling_state; 483 const u32 old_state = scheduling_state;
465 scheduling_state = (scheduling_state & static_cast<u32>(ThreadSchedMasks::HighMask)) | 484 scheduling_state = (scheduling_state & static_cast<u32>(ThreadSchedMasks::HighMask)) |
466 static_cast<u32>(new_status); 485 static_cast<u32>(new_status);
467 kernel.GlobalScheduler().AdjustSchedulingOnStatus(this, old_flags); 486 kernel.GlobalScheduler().AdjustSchedulingOnStatus(this, old_state);
468} 487}
469 488
470void Thread::SetCurrentPriority(u32 new_priority) { 489void Thread::SetCurrentPriority(u32 new_priority) {