summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2020-03-07 12:44:35 -0400
committerGravatar Fernando Sahmkow2020-06-27 11:35:33 -0400
commit83c7ba1ef700eff17f30b6c2782db77710dc322e (patch)
tree63b5901d96afa6a823a8a14859db84d6c74a283d /src/core
parentSCC: Small corrections to CancelSynchronization (diff)
downloadyuzu-83c7ba1ef700eff17f30b6c2782db77710dc322e.tar.gz
yuzu-83c7ba1ef700eff17f30b6c2782db77710dc322e.tar.xz
yuzu-83c7ba1ef700eff17f30b6c2782db77710dc322e.zip
SVC: Correct SetThreadActivity.
Diffstat (limited to 'src/core')
-rw-r--r--src/core/hle/kernel/scheduler.cpp9
-rw-r--r--src/core/hle/kernel/svc.cpp5
-rw-r--r--src/core/hle/kernel/thread.cpp61
-rw-r--r--src/core/hle/kernel/thread.h22
4 files changed, 59 insertions, 38 deletions
diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp
index f020438fb..a37b992ec 100644
--- a/src/core/hle/kernel/scheduler.cpp
+++ b/src/core/hle/kernel/scheduler.cpp
@@ -417,8 +417,7 @@ void GlobalScheduler::AdjustSchedulingOnStatus(Thread* thread, u32 old_flags) {
417 } 417 }
418 ASSERT(is_locked); 418 ASSERT(is_locked);
419 419
420 if (static_cast<ThreadSchedStatus>(old_flags & static_cast<u32>(ThreadSchedMasks::LowMask)) == 420 if (old_flags == static_cast<u32>(ThreadSchedStatus::Runnable)) {
421 ThreadSchedStatus::Runnable) {
422 // In this case the thread was running, now it's pausing/exitting 421 // In this case the thread was running, now it's pausing/exitting
423 if (thread->processor_id >= 0) { 422 if (thread->processor_id >= 0) {
424 Unschedule(thread->current_priority, static_cast<u32>(thread->processor_id), thread); 423 Unschedule(thread->current_priority, static_cast<u32>(thread->processor_id), thread);
@@ -430,7 +429,7 @@ void GlobalScheduler::AdjustSchedulingOnStatus(Thread* thread, u32 old_flags) {
430 Unsuggest(thread->current_priority, core, thread); 429 Unsuggest(thread->current_priority, core, thread);
431 } 430 }
432 } 431 }
433 } else if (thread->GetSchedulingStatus() == ThreadSchedStatus::Runnable) { 432 } else if (thread->scheduling_state == static_cast<u32>(ThreadSchedStatus::Runnable)) {
434 // The thread is now set to running from being stopped 433 // The thread is now set to running from being stopped
435 if (thread->processor_id >= 0) { 434 if (thread->processor_id >= 0) {
436 Schedule(thread->current_priority, static_cast<u32>(thread->processor_id), thread); 435 Schedule(thread->current_priority, static_cast<u32>(thread->processor_id), thread);
@@ -448,7 +447,7 @@ void GlobalScheduler::AdjustSchedulingOnStatus(Thread* thread, u32 old_flags) {
448} 447}
449 448
450void GlobalScheduler::AdjustSchedulingOnPriority(Thread* thread, u32 old_priority) { 449void GlobalScheduler::AdjustSchedulingOnPriority(Thread* thread, u32 old_priority) {
451 if (thread->GetSchedulingStatus() != ThreadSchedStatus::Runnable) { 450 if (thread->scheduling_state != static_cast<u32>(ThreadSchedStatus::Runnable)) {
452 return; 451 return;
453 } 452 }
454 ASSERT(is_locked); 453 ASSERT(is_locked);
@@ -486,7 +485,7 @@ void GlobalScheduler::AdjustSchedulingOnPriority(Thread* thread, u32 old_priorit
486 485
487void GlobalScheduler::AdjustSchedulingOnAffinity(Thread* thread, u64 old_affinity_mask, 486void GlobalScheduler::AdjustSchedulingOnAffinity(Thread* thread, u64 old_affinity_mask,
488 s32 old_core) { 487 s32 old_core) {
489 if (thread->GetSchedulingStatus() != ThreadSchedStatus::Runnable || 488 if (thread->scheduling_state != static_cast<u32>(ThreadSchedStatus::Runnable) ||
490 thread->current_priority >= THREADPRIO_COUNT) { 489 thread->current_priority >= THREADPRIO_COUNT) {
491 return; 490 return;
492 } 491 }
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 718462b2b..da2f90a1d 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -1012,7 +1012,6 @@ static ResultCode UnmapPhysicalMemory(Core::System& system, VAddr addr, u64 size
1012/// Sets the thread activity 1012/// Sets the thread activity
1013static ResultCode SetThreadActivity(Core::System& system, Handle handle, u32 activity) { 1013static ResultCode SetThreadActivity(Core::System& system, Handle handle, u32 activity) {
1014 LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, activity=0x{:08X}", handle, activity); 1014 LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, activity=0x{:08X}", handle, activity);
1015 UNIMPLEMENTED();
1016 if (activity > static_cast<u32>(ThreadActivity::Paused)) { 1015 if (activity > static_cast<u32>(ThreadActivity::Paused)) {
1017 return ERR_INVALID_ENUM_VALUE; 1016 return ERR_INVALID_ENUM_VALUE;
1018 } 1017 }
@@ -1039,9 +1038,7 @@ static ResultCode SetThreadActivity(Core::System& system, Handle handle, u32 act
1039 return ERR_BUSY; 1038 return ERR_BUSY;
1040 } 1039 }
1041 1040
1042 thread->SetActivity(static_cast<ThreadActivity>(activity)); 1041 return thread->SetActivity(static_cast<ThreadActivity>(activity));
1043
1044 return RESULT_SUCCESS;
1045} 1042}
1046 1043
1047/// Gets the thread context 1044/// Gets the thread context
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) {
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index d8a983200..0a8f7bb65 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -497,11 +497,7 @@ public:
497 return affinity_mask; 497 return affinity_mask;
498 } 498 }
499 499
500 ThreadActivity GetActivity() const { 500 ResultCode SetActivity(ThreadActivity value);
501 return activity;
502 }
503
504 void SetActivity(ThreadActivity value);
505 501
506 /// Sleeps this thread for the given amount of nanoseconds. 502 /// Sleeps this thread for the given amount of nanoseconds.
507 ResultCode Sleep(s64 nanoseconds); 503 ResultCode Sleep(s64 nanoseconds);
@@ -564,11 +560,22 @@ public:
564 is_waiting_on_sync = is_waiting; 560 is_waiting_on_sync = is_waiting;
565 } 561 }
566 562
563 bool IsPendingTermination() const {
564 return will_be_terminated || GetSchedulingStatus() == ThreadSchedStatus::Exited;
565 }
566
567 bool IsPaused() const {
568 return pausing_state != 0;
569 }
570
567private: 571private:
568 friend class GlobalScheduler; 572 friend class GlobalScheduler;
569 friend class Scheduler; 573 friend class Scheduler;
570 574
571 void SetSchedulingStatus(ThreadSchedStatus new_status); 575 void SetSchedulingStatus(ThreadSchedStatus new_status);
576 void AddSchedulingFlag(ThreadSchedFlags flag);
577 void RemoveSchedulingFlag(ThreadSchedFlags flag);
578
572 void SetCurrentPriority(u32 new_priority); 579 void SetCurrentPriority(u32 new_priority);
573 580
574 void AdjustSchedulingOnAffinity(u64 old_affinity_mask, s32 old_core); 581 void AdjustSchedulingOnAffinity(u64 old_affinity_mask, s32 old_core);
@@ -650,18 +657,17 @@ private:
650 u32 ideal_core{0xFFFFFFFF}; 657 u32 ideal_core{0xFFFFFFFF};
651 u64 affinity_mask{0x1}; 658 u64 affinity_mask{0x1};
652 659
653 ThreadActivity activity = ThreadActivity::Normal;
654
655 s32 ideal_core_override = -1; 660 s32 ideal_core_override = -1;
656 u64 affinity_mask_override = 0x1; 661 u64 affinity_mask_override = 0x1;
657 u32 affinity_override_count = 0; 662 u32 affinity_override_count = 0;
658 663
659 u32 scheduling_state = 0; 664 u32 scheduling_state = 0;
665 u32 pausing_state = 0;
660 bool is_running = false; 666 bool is_running = false;
661 bool is_waiting_on_sync = false; 667 bool is_waiting_on_sync = false;
662 bool is_sync_cancelled = false; 668 bool is_sync_cancelled = false;
663 669
664 bool will_be_terminated{}; 670 bool will_be_terminated = false;
665 671
666 std::string name; 672 std::string name;
667}; 673};