diff options
| author | 2020-03-07 12:44:35 -0400 | |
|---|---|---|
| committer | 2020-06-27 11:35:33 -0400 | |
| commit | 83c7ba1ef700eff17f30b6c2782db77710dc322e (patch) | |
| tree | 63b5901d96afa6a823a8a14859db84d6c74a283d /src/core/hle/kernel | |
| parent | SCC: Small corrections to CancelSynchronization (diff) | |
| download | yuzu-83c7ba1ef700eff17f30b6c2782db77710dc322e.tar.gz yuzu-83c7ba1ef700eff17f30b6c2782db77710dc322e.tar.xz yuzu-83c7ba1ef700eff17f30b6c2782db77710dc322e.zip | |
SVC: Correct SetThreadActivity.
Diffstat (limited to 'src/core/hle/kernel')
| -rw-r--r-- | src/core/hle/kernel/scheduler.cpp | 9 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 5 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.cpp | 61 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.h | 22 |
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 | ||
| 450 | void GlobalScheduler::AdjustSchedulingOnPriority(Thread* thread, u32 old_priority) { | 449 | void 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 | ||
| 487 | void GlobalScheduler::AdjustSchedulingOnAffinity(Thread* thread, u64 old_affinity_mask, | 486 | void 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 |
| 1013 | static ResultCode SetThreadActivity(Core::System& system, Handle handle, u32 activity) { | 1013 | static 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 | ||
| 124 | void Thread::OnWakeUp() { | 119 | void 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 | ||
| 410 | void Thread::SetActivity(ThreadActivity value) { | 401 | ResultCode 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 | ||
| 425 | ResultCode Thread::Sleep(s64 nanoseconds) { | 428 | ResultCode Thread::Sleep(s64 nanoseconds) { |
| @@ -460,11 +463,27 @@ ResultCode Thread::YieldAndWaitForLoadBalancing() { | |||
| 460 | return RESULT_SUCCESS; | 463 | return RESULT_SUCCESS; |
| 461 | } | 464 | } |
| 462 | 465 | ||
| 466 | void 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 | |||
| 474 | void 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 | |||
| 463 | void Thread::SetSchedulingStatus(ThreadSchedStatus new_status) { | 482 | void 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 | ||
| 470 | void Thread::SetCurrentPriority(u32 new_priority) { | 489 | void 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 | |||
| 567 | private: | 571 | private: |
| 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 | }; |