diff options
author | Fernando Sahmkow <fsahmkow27@gmail.com> | 2019-06-19 15:11:18 +0200 |
---|---|---|
committer | FernandoS27 <fsahmkow27@gmail.com> | 2019-10-15 17:55:12 +0200 |
commit | 82218c925af8bcbaa05ae9f39af2d2393de7681f (patch) | |
tree | e38d90c4838679ae59d58f51fff2904b16b1a155 /src/core | |
parent | Correct PrepareReschedule (diff) | |
download | yuzu-82218c925af8bcbaa05ae9f39af2d2393de7681f.tar yuzu-82218c925af8bcbaa05ae9f39af2d2393de7681f.tar.gz yuzu-82218c925af8bcbaa05ae9f39af2d2393de7681f.tar.bz2 yuzu-82218c925af8bcbaa05ae9f39af2d2393de7681f.tar.lz yuzu-82218c925af8bcbaa05ae9f39af2d2393de7681f.tar.xz yuzu-82218c925af8bcbaa05ae9f39af2d2393de7681f.tar.zst yuzu-82218c925af8bcbaa05ae9f39af2d2393de7681f.zip |
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/core.cpp | 5 | ||||
-rw-r--r-- | src/core/core.h | 4 | ||||
-rw-r--r-- | src/core/core_cpu.cpp | 2 | ||||
-rw-r--r-- | src/core/core_cpu.h | 2 | ||||
-rw-r--r-- | src/core/hle/kernel/address_arbiter.cpp | 1 | ||||
-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/scheduler.cpp | 78 | ||||
-rw-r--r-- | src/core/hle/kernel/scheduler.h | 53 | ||||
-rw-r--r-- | src/core/hle/kernel/svc.cpp | 15 | ||||
-rw-r--r-- | src/core/hle/kernel/thread.cpp | 54 | ||||
-rw-r--r-- | src/core/hle/kernel/thread.h | 15 |
12 files changed, 137 insertions, 96 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp index 4a95630bd..d79045eea 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -404,9 +404,10 @@ void System::PrepareReschedule() { CurrentCpuCore().PrepareReschedule(); } -void System::PrepareReschedule(s32 core_index) { - if (core_index >= 0) +void System::PrepareReschedule(const u32 core_index) { + if (core_index < GlobalScheduler().CpuCoresCount()) { CpuCore(core_index).PrepareReschedule(); + } } PerfStatsResults System::GetAndResetPerfStats() { diff --git a/src/core/core.h b/src/core/core.h index 0d1008895..984074ce3 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -24,10 +24,10 @@ class VfsFilesystem; } // namespace FileSys namespace Kernel { +class GlobalScheduler; class KernelCore; class Process; class Scheduler; -class GlobalScheduler; } // namespace Kernel namespace Loader { @@ -186,7 +186,7 @@ public: void PrepareReschedule(); /// Prepare the core emulation for a reschedule - void PrepareReschedule(s32 core_index); + void PrepareReschedule(u32 core_index); /// Gets and resets core performance statistics PerfStatsResults GetAndResetPerfStats(); diff --git a/src/core/core_cpu.cpp b/src/core/core_cpu.cpp index 2a7c3af24..a6f63e437 100644 --- a/src/core/core_cpu.cpp +++ b/src/core/core_cpu.cpp @@ -111,7 +111,7 @@ void Cpu::PrepareReschedule() { void Cpu::Reschedule() { // Lock the global kernel mutex when we manipulate the HLE state - std::lock_guard<std::recursive_mutex> lock(HLE::g_hle_lock); + std::lock_guard lock(HLE::g_hle_lock); global_scheduler.SelectThread(core_index); scheduler->TryDoContextSwitch(); diff --git a/src/core/core_cpu.h b/src/core/core_cpu.h index 0cde54787..80261daf7 100644 --- a/src/core/core_cpu.h +++ b/src/core/core_cpu.h @@ -12,8 +12,8 @@ #include "common/common_types.h" namespace Kernel { -class Scheduler; class GlobalScheduler; +class Scheduler; } // namespace Kernel namespace Core { diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp index c66cd16ef..4c1d3fd18 100644 --- a/src/core/hle/kernel/address_arbiter.cpp +++ b/src/core/hle/kernel/address_arbiter.cpp @@ -22,7 +22,6 @@ namespace Kernel { namespace { // Wake up num_to_wake (or all) threads in a vector. void WakeThreads(const std::vector<SharedPtr<Thread>>& waiting_threads, s32 num_to_wake) { - auto& system = Core::System::GetInstance(); // Only process up to 'target' threads, unless 'target' is <= 0, in which case process // them all. diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index b4fd1d3f3..600d6ec74 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -89,7 +89,7 @@ static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] s64 cycles_ } struct KernelCore::Impl { - explicit Impl(Core::System& system) : system{system} {} + explicit Impl(Core::System& system) : system{system}, global_scheduler{system} {} void Initialize(KernelCore& kernel) { Shutdown(); diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 57f2d8bf3..eb919246c 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -140,7 +140,7 @@ ResultCode Mutex::Release(VAddr address) { thread->SetMutexWaitAddress(0); thread->SetWaitHandle(0); - Core::System::GetInstance().PrepareReschedule(); + system.PrepareReschedule(); return RESULT_SUCCESS; } diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp index 537640152..df4e9b799 100644 --- a/src/core/hle/kernel/scheduler.cpp +++ b/src/core/hle/kernel/scheduler.cpp @@ -1,6 +1,9 @@ // Copyright 2018 yuzu emulator team // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +// +// SelectThreads, Yield functions originally by TuxSH. +// licensed under GPLv2 or later under exception provided by the author. #include <algorithm> #include <set> @@ -19,16 +22,15 @@ namespace Kernel { -/* - * SelectThreads, Yield functions originally by TuxSH. - * licensed under GPLv2 or later under exception provided by the author. - */ +GlobalScheduler::GlobalScheduler(Core::System& system) : system{system} { + reselection_pending = false; +} void GlobalScheduler::AddThread(SharedPtr<Thread> thread) { thread_list.push_back(std::move(thread)); } -void GlobalScheduler::RemoveThread(Thread* thread) { +void GlobalScheduler::RemoveThread(const Thread* thread) { thread_list.erase(std::remove(thread_list.begin(), thread_list.end(), thread), thread_list.end()); } @@ -37,7 +39,7 @@ void GlobalScheduler::RemoveThread(Thread* thread) { * UnloadThread selects a core and forces it to unload its current thread's context */ void GlobalScheduler::UnloadThread(s32 core) { - Scheduler& sched = Core::System::GetInstance().Scheduler(core); + Scheduler& sched = system.Scheduler(core); sched.UnloadThread(); } @@ -52,7 +54,7 @@ void GlobalScheduler::UnloadThread(s32 core) { * thread in another core and swap it with its current thread. */ void GlobalScheduler::SelectThread(u32 core) { - auto update_thread = [](Thread* thread, Scheduler& sched) { + const auto update_thread = [](Thread* thread, Scheduler& sched) { if (thread != sched.selected_thread) { if (thread == nullptr) { ++sched.idle_selection_count; @@ -62,7 +64,7 @@ void GlobalScheduler::SelectThread(u32 core) { sched.context_switch_pending = sched.selected_thread != sched.current_thread; std::atomic_thread_fence(std::memory_order_seq_cst); }; - Scheduler& sched = Core::System::GetInstance().Scheduler(core); + Scheduler& sched = system.Scheduler(core); Thread* current_thread = nullptr; // Step 1: Get top thread in schedule queue. current_thread = scheduled_queue[core].empty() ? nullptr : scheduled_queue[core].front(); @@ -118,8 +120,8 @@ void GlobalScheduler::SelectThread(u32 core) { */ void GlobalScheduler::YieldThread(Thread* yielding_thread) { // Note: caller should use critical section, etc. - u32 core_id = static_cast<u32>(yielding_thread->GetProcessorID()); - u32 priority = yielding_thread->GetPriority(); + const u32 core_id = static_cast<u32>(yielding_thread->GetProcessorID()); + const u32 priority = yielding_thread->GetPriority(); // Yield the thread ASSERT_MSG(yielding_thread == scheduled_queue[core_id].front(priority), @@ -139,8 +141,8 @@ void GlobalScheduler::YieldThread(Thread* yielding_thread) { void GlobalScheduler::YieldThreadAndBalanceLoad(Thread* yielding_thread) { // Note: caller should check if !thread.IsSchedulerOperationRedundant and use critical section, // etc. - u32 core_id = static_cast<u32>(yielding_thread->GetProcessorID()); - u32 priority = yielding_thread->GetPriority(); + const u32 core_id = static_cast<u32>(yielding_thread->GetProcessorID()); + const u32 priority = yielding_thread->GetPriority(); // Yield the thread ASSERT_MSG(yielding_thread == scheduled_queue[core_id].front(priority), @@ -155,12 +157,13 @@ void GlobalScheduler::YieldThreadAndBalanceLoad(Thread* yielding_thread) { Thread* next_thread = scheduled_queue[core_id].front(priority); Thread* winner = nullptr; for (auto& thread : suggested_queue[core_id]) { - s32 source_core = thread->GetProcessorID(); + const s32 source_core = thread->GetProcessorID(); if (source_core >= 0) { if (current_threads[source_core] != nullptr) { if (thread == current_threads[source_core] || - current_threads[source_core]->GetPriority() < min_regular_priority) + current_threads[source_core]->GetPriority() < min_regular_priority) { continue; + } } if (next_thread->GetLastRunningTicks() >= thread->GetLastRunningTicks() || next_thread->GetPriority() < thread->GetPriority()) { @@ -174,8 +177,9 @@ void GlobalScheduler::YieldThreadAndBalanceLoad(Thread* yielding_thread) { if (winner != nullptr) { if (winner != yielding_thread) { - if (winner->IsRunning()) + if (winner->IsRunning()) { UnloadThread(winner->GetProcessorID()); + } TransferToCore(winner->GetPriority(), core_id, winner); } } else { @@ -195,7 +199,7 @@ void GlobalScheduler::YieldThreadAndWaitForLoadBalancing(Thread* yielding_thread // Note: caller should check if !thread.IsSchedulerOperationRedundant and use critical section, // etc. Thread* winner = nullptr; - u32 core_id = static_cast<u32>(yielding_thread->GetProcessorID()); + const u32 core_id = static_cast<u32>(yielding_thread->GetProcessorID()); // Remove the thread from its scheduled mlq, put it on the corresponding "suggested" one instead TransferToCore(yielding_thread->GetPriority(), -1, yielding_thread); @@ -209,9 +213,10 @@ void GlobalScheduler::YieldThreadAndWaitForLoadBalancing(Thread* yielding_thread current_threads[i] = scheduled_queue[i].empty() ? nullptr : scheduled_queue[i].front(); } for (auto& thread : suggested_queue[core_id]) { - s32 source_core = thread->GetProcessorID(); - if (source_core < 0 || thread == current_threads[source_core]) + const s32 source_core = thread->GetProcessorID(); + if (source_core < 0 || thread == current_threads[source_core]) { continue; + } if (current_threads[source_core] == nullptr || current_threads[source_core]->GetPriority() >= min_regular_priority) { winner = thread; @@ -220,8 +225,9 @@ void GlobalScheduler::YieldThreadAndWaitForLoadBalancing(Thread* yielding_thread } if (winner != nullptr) { if (winner != yielding_thread) { - if (winner->IsRunning()) + if (winner->IsRunning()) { UnloadThread(winner->GetProcessorID()); + } TransferToCore(winner->GetPriority(), core_id, winner); } } else { @@ -232,6 +238,16 @@ void GlobalScheduler::YieldThreadAndWaitForLoadBalancing(Thread* yielding_thread AskForReselectionOrMarkRedundant(yielding_thread, winner); } +void GlobalScheduler::Schedule(u32 priority, u32 core, Thread* thread) { + ASSERT_MSG(thread->GetProcessorID() == core, "Thread must be assigned to this core."); + scheduled_queue[core].add(thread, priority); +} + +void GlobalScheduler::SchedulePrepend(u32 priority, u32 core, Thread* thread) { + ASSERT_MSG(thread->GetProcessorID() == core, "Thread must be assigned to this core."); + scheduled_queue[core].add(thread, priority, false); +} + void GlobalScheduler::AskForReselectionOrMarkRedundant(Thread* current_thread, Thread* winner) { if (current_thread == winner) { // TODO(blinkhawk): manage redundant operations, this is not implemented. @@ -244,13 +260,13 @@ void GlobalScheduler::AskForReselectionOrMarkRedundant(Thread* current_thread, T GlobalScheduler::~GlobalScheduler() = default; -Scheduler::Scheduler(Core::System& system, Core::ARM_Interface& cpu_core, u32 id) - : system(system), cpu_core(cpu_core), id(id) {} +Scheduler::Scheduler(Core::System& system, Core::ARM_Interface& cpu_core, u32 core_id) + : system(system), cpu_core(cpu_core), core_id(core_id) {} -Scheduler::~Scheduler() {} +Scheduler::~Scheduler() = default; bool Scheduler::HaveReadyThreads() const { - return system.GlobalScheduler().HaveReadyThreads(id); + return system.GlobalScheduler().HaveReadyThreads(core_id); } Thread* Scheduler::GetCurrentThread() const { @@ -262,7 +278,7 @@ Thread* Scheduler::GetSelectedThread() const { } void Scheduler::SelectThreads() { - system.GlobalScheduler().SelectThread(id); + system.GlobalScheduler().SelectThread(core_id); } u64 Scheduler::GetLastContextSwitchTicks() const { @@ -270,13 +286,14 @@ u64 Scheduler::GetLastContextSwitchTicks() const { } void Scheduler::TryDoContextSwitch() { - if (context_switch_pending) + if (context_switch_pending) { SwitchContext(); + } } void Scheduler::UnloadThread() { Thread* const previous_thread = GetCurrentThread(); - Process* const previous_process = Core::CurrentProcess(); + Process* const previous_process = system.Kernel().CurrentProcess(); UpdateLastContextSwitchTime(previous_thread, previous_process); @@ -301,10 +318,11 @@ void Scheduler::SwitchContext() { Thread* const new_thread = GetSelectedThread(); context_switch_pending = false; - if (new_thread == previous_thread) + if (new_thread == previous_thread) { return; + } - Process* const previous_process = Core::CurrentProcess(); + Process* const previous_process = system.Kernel().CurrentProcess(); UpdateLastContextSwitchTime(previous_thread, previous_process); @@ -324,7 +342,7 @@ void Scheduler::SwitchContext() { // Load context of new thread if (new_thread) { - ASSERT_MSG(new_thread->GetProcessorID() == this->id, + ASSERT_MSG(new_thread->GetProcessorID() == this->core_id, "Thread must be assigned to this core."); ASSERT_MSG(new_thread->GetStatus() == ThreadStatus::Ready, "Thread must be ready to become running."); @@ -353,7 +371,7 @@ void Scheduler::SwitchContext() { void Scheduler::UpdateLastContextSwitchTime(Thread* thread, Process* process) { const u64 prev_switch_ticks = last_context_switch_time; - const u64 most_recent_switch_ticks = Core::System::GetInstance().CoreTiming().GetTicks(); + const u64 most_recent_switch_ticks = system.CoreTiming().GetTicks(); const u64 update_ticks = most_recent_switch_ticks - prev_switch_ticks; if (thread != nullptr) { diff --git a/src/core/hle/kernel/scheduler.h b/src/core/hle/kernel/scheduler.h index 82ed64b55..1c9d8a30f 100644 --- a/src/core/hle/kernel/scheduler.h +++ b/src/core/hle/kernel/scheduler.h @@ -24,62 +24,70 @@ class GlobalScheduler final { public: static constexpr u32 NUM_CPU_CORES = 4; - GlobalScheduler() { - reselection_pending = false; - } + explicit GlobalScheduler(Core::System& system); ~GlobalScheduler(); /// Adds a new thread to the scheduler void AddThread(SharedPtr<Thread> thread); /// Removes a thread from the scheduler - void RemoveThread(Thread* thread); + void RemoveThread(const Thread* thread); /// Returns a list of all threads managed by the scheduler const std::vector<SharedPtr<Thread>>& GetThreadList() const { return thread_list; } + // Add a thread to the suggested queue of a cpu core. Suggested threads may be + // picked if no thread is scheduled to run on the core. void Suggest(u32 priority, u32 core, Thread* thread) { suggested_queue[core].add(thread, priority); } + // Remove a thread to the suggested queue of a cpu core. Suggested threads may be + // picked if no thread is scheduled to run on the core. void Unsuggest(u32 priority, u32 core, Thread* thread) { suggested_queue[core].remove(thread, priority); } - void Schedule(u32 priority, u32 core, Thread* thread) { - ASSERT_MSG(thread->GetProcessorID() == core, "Thread must be assigned to this core."); - scheduled_queue[core].add(thread, priority); - } + // Add a thread to the scheduling queue of a cpu core. The thread is added at the + // back the queue in its priority level + void Schedule(u32 priority, u32 core, Thread* thread); - void SchedulePrepend(u32 priority, u32 core, Thread* thread) { - ASSERT_MSG(thread->GetProcessorID() == core, "Thread must be assigned to this core."); - scheduled_queue[core].add(thread, priority, false); - } + // Add a thread to the scheduling queue of a cpu core. The thread is added at the + // front the queue in its priority level + void SchedulePrepend(u32 priority, u32 core, Thread* thread); + // Reschedule an already scheduled thread based on a new priority void Reschedule(u32 priority, u32 core, Thread* thread) { scheduled_queue[core].remove(thread, priority); scheduled_queue[core].add(thread, priority); } + // Unschedule a thread. void Unschedule(u32 priority, u32 core, Thread* thread) { scheduled_queue[core].remove(thread, priority); } + // Transfers a thread into an specific core. If the destination_core is -1 + // it will be unscheduled from its source code and added into its suggested + // queue. void TransferToCore(u32 priority, s32 destination_core, Thread* thread) { - bool schedulable = thread->GetPriority() < THREADPRIO_COUNT; - s32 source_core = thread->GetProcessorID(); - if (source_core == destination_core || !schedulable) + const bool schedulable = thread->GetPriority() < THREADPRIO_COUNT; + const s32 source_core = thread->GetProcessorID(); + if (source_core == destination_core || !schedulable) { return; + } thread->SetProcessorID(destination_core); - if (source_core >= 0) + if (source_core >= 0) { Unschedule(priority, source_core, thread); + } if (destination_core >= 0) { Unsuggest(priority, destination_core, thread); Schedule(priority, destination_core, thread); } - if (source_core >= 0) + if (source_core >= 0) { Suggest(priority, source_core, thread); + } } /* @@ -99,7 +107,7 @@ public: */ void SelectThread(u32 core); - bool HaveReadyThreads(u32 core_id) { + bool HaveReadyThreads(u32 core_id) const { return !scheduled_queue[core_id].empty(); } @@ -133,8 +141,8 @@ public: reselection_pending.store(true, std::memory_order_release); } - bool IsReselectionPending() { - return reselection_pending.load(std::memory_order_acquire); + bool IsReselectionPending() const { + return reselection_pending.load(); } private: @@ -147,11 +155,12 @@ private: /// Lists all thread ids that aren't deleted/etc. std::vector<SharedPtr<Thread>> thread_list; + Core::System& system; }; class Scheduler final { public: - explicit Scheduler(Core::System& system, Core::ARM_Interface& cpu_core, const u32 id); + explicit Scheduler(Core::System& system, Core::ARM_Interface& cpu_core, const u32 core_id); ~Scheduler(); /// Returns whether there are any threads that are ready to run. @@ -204,7 +213,7 @@ private: Core::ARM_Interface& cpu_core; u64 last_context_switch_time = 0; u64 idle_selection_count = 0; - const u32 id; + const u32 core_id; bool context_switch_pending = false; }; diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 560ac3945..d520ed033 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -1560,13 +1560,13 @@ static void SleepThread(Core::System& system, s64 nanoseconds) { if (nanoseconds <= 0) { switch (static_cast<SleepType>(nanoseconds)) { case SleepType::YieldWithoutLoadBalancing: - current_thread->YieldType0(); + current_thread->YieldSimple(); break; case SleepType::YieldWithLoadBalancing: - current_thread->YieldType1(); + current_thread->YieldAndBalanceLoad(); break; case SleepType::YieldAndWaitForLoadBalancing: - current_thread->YieldType2(); + current_thread->YieldAndWaitForLoadBalancing(); break; default: UNREACHABLE_MSG("Unimplemented sleep yield type '{:016X}'!", nanoseconds); @@ -1638,8 +1638,9 @@ static ResultCode SignalProcessWideKey(Core::System& system, VAddr condition_var const auto& thread_list = scheduler.GetThreadList(); for (const auto& thread : thread_list) { - if (thread->GetCondVarWaitAddress() == condition_variable_addr) + if (thread->GetCondVarWaitAddress() == condition_variable_addr) { waiting_threads.push_back(thread); + } } // Sort them by priority, such that the highest priority ones come first. @@ -1747,9 +1748,11 @@ static ResultCode WaitForAddress(Core::System& system, VAddr address, u32 type, const auto arbitration_type = static_cast<AddressArbiter::ArbitrationType>(type); auto& address_arbiter = system.Kernel().CurrentProcess()->GetAddressArbiter(); - ResultCode result = address_arbiter.WaitForAddress(address, arbitration_type, value, timeout); - if (result == RESULT_SUCCESS) + const ResultCode result = + address_arbiter.WaitForAddress(address, arbitration_type, value, timeout); + if (result == RESULT_SUCCESS) { system.PrepareReschedule(); + } return result; } diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index d0fa7b370..8cf0a7ec7 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -373,43 +373,44 @@ void Thread::Sleep(s64 nanoseconds) { WakeAfterDelay(nanoseconds); } -void Thread::YieldType0() { +void Thread::YieldSimple() { auto& scheduler = kernel.GlobalScheduler(); scheduler.YieldThread(this); } -void Thread::YieldType1() { +void Thread::YieldAndBalanceLoad() { auto& scheduler = kernel.GlobalScheduler(); scheduler.YieldThreadAndBalanceLoad(this); } -void Thread::YieldType2() { +void Thread::YieldAndWaitForLoadBalancing() { auto& scheduler = kernel.GlobalScheduler(); scheduler.YieldThreadAndWaitForLoadBalancing(this); } void Thread::SetSchedulingStatus(ThreadSchedStatus new_status) { - u32 old_flags = scheduling_state; + const u32 old_flags = scheduling_state; scheduling_state = (scheduling_state & ThreadSchedMasks::HighMask) | static_cast<u32>(new_status); AdjustSchedulingOnStatus(old_flags); } void Thread::SetCurrentPriority(u32 new_priority) { - u32 old_priority = current_priority; - current_priority = new_priority; + u32 old_priority = std::exchange(current_priority, new_priority); AdjustSchedulingOnPriority(old_priority); } ResultCode Thread::SetCoreAndAffinityMask(s32 new_core, u64 new_affinity_mask) { - auto HighestSetCore = [](u64 mask, u32 max_cores) { + const auto HighestSetCore = [](u64 mask, u32 max_cores) { for (s32 core = max_cores - 1; core >= 0; core--) { - if (((mask >> core) & 1) != 0) + if (((mask >> core) & 1) != 0) { return core; + } } return -1; }; - bool use_override = affinity_override_count != 0; + + const bool use_override = affinity_override_count != 0; // The value -3 is "do not change the ideal core". if (new_core == -3) { new_core = use_override ? ideal_core_override : ideal_core; @@ -421,11 +422,10 @@ ResultCode Thread::SetCoreAndAffinityMask(s32 new_core, u64 new_affinity_mask) { ideal_core_override = new_core; affinity_mask_override = new_affinity_mask; } else { - u64 old_affinity_mask = affinity_mask; + const u64 old_affinity_mask = std::exchange(affinity_mask, new_affinity_mask); ideal_core = new_core; - affinity_mask = new_affinity_mask; if (old_affinity_mask != new_affinity_mask) { - s32 old_core = processor_id; + const s32 old_core = processor_id; if (processor_id >= 0 && ((affinity_mask >> processor_id) & 1) == 0) { if (ideal_core < 0) { processor_id = HighestSetCore(affinity_mask, GlobalScheduler::NUM_CPU_CORES); @@ -440,28 +440,33 @@ ResultCode Thread::SetCoreAndAffinityMask(s32 new_core, u64 new_affinity_mask) { } void Thread::AdjustSchedulingOnStatus(u32 old_flags) { - if (old_flags == scheduling_state) + if (old_flags == scheduling_state) { return; + } auto& scheduler = kernel.GlobalScheduler(); if (static_cast<ThreadSchedStatus>(old_flags & ThreadSchedMasks::LowMask) == ThreadSchedStatus::Runnable) { // In this case the thread was running, now it's pausing/exitting - if (processor_id >= 0) + if (processor_id >= 0) { scheduler.Unschedule(current_priority, processor_id, this); + } - for (s32 core = 0; core < GlobalScheduler::NUM_CPU_CORES; core++) { - if (core != processor_id && ((affinity_mask >> core) & 1) != 0) + for (u32 core = 0; core < GlobalScheduler::NUM_CPU_CORES; core++) { + if (core != processor_id && ((affinity_mask >> core) & 1) != 0) { scheduler.Unsuggest(current_priority, core, this); + } } } else if (GetSchedulingStatus() == ThreadSchedStatus::Runnable) { // The thread is now set to running from being stopped - if (processor_id >= 0) + if (processor_id >= 0) { scheduler.Schedule(current_priority, processor_id, this); + } - for (s32 core = 0; core < GlobalScheduler::NUM_CPU_CORES; core++) { - if (core != processor_id && ((affinity_mask >> core) & 1) != 0) + for (u32 core = 0; core < GlobalScheduler::NUM_CPU_CORES; core++) { + if (core != processor_id && ((affinity_mask >> core) & 1) != 0) { scheduler.Suggest(current_priority, core, this); + } } } @@ -477,7 +482,7 @@ void Thread::AdjustSchedulingOnPriority(u32 old_priority) { scheduler.Unschedule(old_priority, processor_id, this); } - for (s32 core = 0; core < GlobalScheduler::NUM_CPU_CORES; core++) { + for (u32 core = 0; core < GlobalScheduler::NUM_CPU_CORES; core++) { if (core != processor_id && ((affinity_mask >> core) & 1) != 0) { scheduler.Unsuggest(old_priority, core, this); } @@ -494,7 +499,7 @@ void Thread::AdjustSchedulingOnPriority(u32 old_priority) { } } - for (s32 core = 0; core < GlobalScheduler::NUM_CPU_CORES; core++) { + for (u32 core = 0; core < GlobalScheduler::NUM_CPU_CORES; core++) { if (core != processor_id && ((affinity_mask >> core) & 1) != 0) { scheduler.Suggest(current_priority, core, this); } @@ -506,10 +511,11 @@ void Thread::AdjustSchedulingOnPriority(u32 old_priority) { void Thread::AdjustSchedulingOnAffinity(u64 old_affinity_mask, s32 old_core) { auto& scheduler = Core::System::GetInstance().GlobalScheduler(); if (GetSchedulingStatus() != ThreadSchedStatus::Runnable || - current_priority >= THREADPRIO_COUNT) + current_priority >= THREADPRIO_COUNT) { return; + } - for (s32 core = 0; core < GlobalScheduler::NUM_CPU_CORES; core++) { + for (u32 core = 0; core < GlobalScheduler::NUM_CPU_CORES; core++) { if (((old_affinity_mask >> core) & 1) != 0) { if (core == old_core) { scheduler.Unschedule(current_priority, core, this); @@ -519,7 +525,7 @@ void Thread::AdjustSchedulingOnAffinity(u64 old_affinity_mask, s32 old_core) { } } - for (s32 core = 0; core < GlobalScheduler::NUM_CPU_CORES; core++) { + for (u32 core = 0; core < GlobalScheduler::NUM_CPU_CORES; core++) { if (((affinity_mask >> core) & 1) != 0) { if (core == processor_id) { scheduler.Schedule(current_priority, core, this); diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index c426a7209..bf0cae959 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -75,7 +75,12 @@ enum class ThreadActivity : u32 { Paused = 1, }; -enum class ThreadSchedStatus : u32 { None = 0, Paused = 1, Runnable = 2, Exited = 3 }; +enum class ThreadSchedStatus : u32 { + None = 0, + Paused = 1, + Runnable = 2, + Exited = 3, +}; enum ThreadSchedFlags : u32 { ProcessPauseFlag = 1 << 4, @@ -403,15 +408,15 @@ public: void Sleep(s64 nanoseconds); /// Yields this thread without rebalancing loads. - void YieldType0(); + void YieldSimple(); /// Yields this thread and does a load rebalancing. - void YieldType1(); + void YieldAndBalanceLoad(); /// Yields this thread and if the core is left idle, loads are rebalanced - void YieldType2(); + void YieldAndWaitForLoadBalancing(); - ThreadSchedStatus GetSchedulingStatus() { + ThreadSchedStatus GetSchedulingStatus() const { return static_cast<ThreadSchedStatus>(scheduling_state & ThreadSchedMasks::LowMask); } |