From 07524b63e8c55585e108f2b5d95d4db2ebda8ce4 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Fri, 29 Mar 2019 17:02:57 -0400 Subject: Add interfacing to the Global Scheduler --- src/core/hle/kernel/kernel.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/core/hle/kernel/kernel.cpp') diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 799e5e0d85..b4fd1d3f32 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -18,6 +18,7 @@ #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/process.h" #include "core/hle/kernel/resource_limit.h" +#include "core/hle/kernel/scheduler.h" #include "core/hle/kernel/thread.h" #include "core/hle/lock.h" #include "core/hle/result.h" @@ -140,6 +141,7 @@ struct KernelCore::Impl { // Lists all processes that exist in the current session. std::vector> process_list; Process* current_process = nullptr; + Kernel::GlobalScheduler global_scheduler; SharedPtr system_resource_limit; @@ -203,6 +205,14 @@ const std::vector>& KernelCore::GetProcessList() const { return impl->process_list; } +Kernel::GlobalScheduler& KernelCore::GlobalScheduler() { + return impl->global_scheduler; +} + +const Kernel::GlobalScheduler& KernelCore::GlobalScheduler() const { + return impl->global_scheduler; +} + void KernelCore::AddNamedPort(std::string name, SharedPtr port) { impl->named_ports.emplace(std::move(name), std::move(port)); } -- cgit v1.2.3 From 5130168171d67075b2d64566d6d41bf17985c272 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Wed, 19 Jun 2019 09:11:18 -0400 Subject: Kernel: Style and Corrections --- src/core/core.cpp | 5 ++- src/core/core.h | 4 +- src/core/core_cpu.cpp | 2 +- src/core/core_cpu.h | 2 +- src/core/hle/kernel/address_arbiter.cpp | 1 - src/core/hle/kernel/kernel.cpp | 2 +- src/core/hle/kernel/mutex.cpp | 2 +- src/core/hle/kernel/scheduler.cpp | 78 ++++++++++++++++++++------------- src/core/hle/kernel/scheduler.h | 53 ++++++++++++---------- src/core/hle/kernel/svc.cpp | 15 ++++--- src/core/hle/kernel/thread.cpp | 54 +++++++++++++---------- src/core/hle/kernel/thread.h | 15 ++++--- 12 files changed, 137 insertions(+), 96 deletions(-) (limited to 'src/core/hle/kernel/kernel.cpp') diff --git a/src/core/core.cpp b/src/core/core.cpp index 4a95630bd0..d79045eeaa 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 0d1008895d..984074ce35 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 2a7c3af240..a6f63e437a 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 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 0cde547878..80261daf75 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 c66cd16ef3..4c1d3fd180 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>& 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 b4fd1d3f32..600d6ec742 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 57f2d8bf30..eb919246cd 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 5376401526..df4e9b7994 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 #include @@ -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_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(yielding_thread->GetProcessorID()); - u32 priority = yielding_thread->GetPriority(); + const u32 core_id = static_cast(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(yielding_thread->GetProcessorID()); - u32 priority = yielding_thread->GetPriority(); + const u32 core_id = static_cast(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(yielding_thread->GetProcessorID()); + const u32 core_id = static_cast(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 82ed64b556..1c9d8a30f8 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); /// 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>& 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> 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 560ac39455..d520ed0332 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(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(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 d0fa7b3702..8cf0a7ec77 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(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(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 c426a72096..bf0cae959a 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(scheduling_state & ThreadSchedMasks::LowMask); } -- cgit v1.2.3 From 68325300aef4c932e78cec41fa90dc835a10f938 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Tue, 10 Sep 2019 11:04:40 -0400 Subject: Kernel: Initial implementation of thread preemption. --- src/core/hle/kernel/kernel.cpp | 16 ++++++++++++++++ src/core/hle/kernel/scheduler.cpp | 10 ++++++++++ src/core/hle/kernel/scheduler.h | 4 ++++ 3 files changed, 30 insertions(+) (limited to 'src/core/hle/kernel/kernel.cpp') diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 600d6ec742..7a913520dc 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -12,6 +12,7 @@ #include "core/core.h" #include "core/core_timing.h" +#include "core/core_timing_util.h" #include "core/hle/kernel/address_arbiter.h" #include "core/hle/kernel/client_port.h" #include "core/hle/kernel/handle_table.h" @@ -96,6 +97,7 @@ struct KernelCore::Impl { InitializeSystemResourceLimit(kernel); InitializeThreads(); + InitializePreemption(); } void Shutdown() { @@ -111,6 +113,7 @@ struct KernelCore::Impl { thread_wakeup_callback_handle_table.Clear(); thread_wakeup_event_type = nullptr; + preemption_event = nullptr; named_ports.clear(); } @@ -133,6 +136,18 @@ struct KernelCore::Impl { system.CoreTiming().RegisterEvent("ThreadWakeupCallback", ThreadWakeupCallback); } + void InitializePreemption() { + preemption_event = system.CoreTiming().RegisterEvent( + "PreemptionCallback", [this](u64 userdata, s64 cycles_late) { + global_scheduler.PreemptThreads(); + s64 time_interval = Core::Timing::msToCycles(std::chrono::milliseconds(10)); + system.CoreTiming().ScheduleEvent(time_interval, preemption_event); + }); + + s64 time_interval = Core::Timing::msToCycles(std::chrono::milliseconds(10)); + system.CoreTiming().ScheduleEvent(time_interval, preemption_event); + } + std::atomic next_object_id{0}; std::atomic next_kernel_process_id{Process::InitialKIPIDMin}; std::atomic next_user_process_id{Process::ProcessIDMin}; @@ -146,6 +161,7 @@ struct KernelCore::Impl { SharedPtr system_resource_limit; Core::Timing::EventType* thread_wakeup_event_type = nullptr; + Core::Timing::EventType* preemption_event = nullptr; // TODO(yuriks): This can be removed if Thread objects are explicitly pooled in the future, // allowing us to simply use a pool index or similar. Kernel::HandleTable thread_wakeup_callback_handle_table; diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp index 451fd8077d..0d45307cd3 100644 --- a/src/core/hle/kernel/scheduler.cpp +++ b/src/core/hle/kernel/scheduler.cpp @@ -238,6 +238,16 @@ bool GlobalScheduler::YieldThreadAndWaitForLoadBalancing(Thread* yielding_thread return AskForReselectionOrMarkRedundant(yielding_thread, winner); } +void GlobalScheduler::PreemptThreads() { + for (std::size_t core_id = 0; core_id < NUM_CPU_CORES; core_id++) { + const u64 priority = preemption_priorities[core_id]; + if (scheduled_queue[core_id].size(priority) > 1) { + scheduled_queue[core_id].yield(priority); + reselection_pending.store(true, std::memory_order_release); + } + } +} + 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); diff --git a/src/core/hle/kernel/scheduler.h b/src/core/hle/kernel/scheduler.h index 8fcc86bae1..c13a368fd4 100644 --- a/src/core/hle/kernel/scheduler.h +++ b/src/core/hle/kernel/scheduler.h @@ -133,6 +133,8 @@ public: */ bool YieldThreadAndWaitForLoadBalancing(Thread* thread); + void PreemptThreads(); + u32 CpuCoresCount() const { return NUM_CPU_CORES; } @@ -153,6 +155,8 @@ private: std::array, NUM_CPU_CORES> suggested_queue; std::atomic reselection_pending; + std::array preemption_priorities = {59, 59, 59, 62}; + /// Lists all thread ids that aren't deleted/etc. std::vector> thread_list; Core::System& system; -- cgit v1.2.3 From abc8856e2c55f5ebc89bc10f4bf7c85581438363 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Wed, 11 Sep 2019 12:47:37 -0400 Subject: Kernel: Remove global system accessor from WaitObject --- src/core/hle/kernel/kernel.cpp | 8 ++++++++ src/core/hle/kernel/kernel.h | 6 ++++++ src/core/hle/kernel/scheduler.cpp | 2 +- src/core/hle/kernel/wait_object.cpp | 3 ++- 4 files changed, 17 insertions(+), 2 deletions(-) (limited to 'src/core/hle/kernel/kernel.cpp') diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 7a913520dc..77edbcd1f1 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -229,6 +229,14 @@ const Kernel::GlobalScheduler& KernelCore::GlobalScheduler() const { return impl->global_scheduler; } +Core::System& KernelCore::System() { + return impl->system; +} + +const Core::System& KernelCore::System() const { + return impl->system; +} + void KernelCore::AddNamedPort(std::string name, SharedPtr port) { impl->named_ports.emplace(std::move(name), std::move(port)); } diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index f9f5bdc88f..0fc4d1f363 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -82,6 +82,12 @@ public: /// Gets the sole instance of the global scheduler const Kernel::GlobalScheduler& GlobalScheduler() const; + /// Gets the sole instance of the system + Core::System& System(); + + /// Gets the sole instance of the system + const Core::System& System() const; + /// Adds a port to the named port table void AddNamedPort(std::string name, SharedPtr port); diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp index 5581c43bf8..60d936c9ac 100644 --- a/src/core/hle/kernel/scheduler.cpp +++ b/src/core/hle/kernel/scheduler.cpp @@ -287,7 +287,7 @@ void GlobalScheduler::PreemptThreads() { if (current_thread != nullptr && current_thread->GetPriority() > priority) { for (auto& thread : suggested_queue[core_id]) { const s32 source_core = thread->GetProcessorID(); - if (thread->GetPriority() > priority) { + if (thread->GetPriority() < priority) { continue; } if (source_core >= 0) { diff --git a/src/core/hle/kernel/wait_object.cpp b/src/core/hle/kernel/wait_object.cpp index a65ec7dbc3..50ed2a2f15 100644 --- a/src/core/hle/kernel/wait_object.cpp +++ b/src/core/hle/kernel/wait_object.cpp @@ -8,6 +8,7 @@ #include "common/logging/log.h" #include "core/core.h" #include "core/core_cpu.h" +#include "core/hle/kernel/kernel.h" #include "core/hle/kernel/object.h" #include "core/hle/kernel/process.h" #include "core/hle/kernel/thread.h" @@ -97,7 +98,7 @@ void WaitObject::WakeupWaitingThread(SharedPtr thread) { } if (resume) { thread->ResumeFromWait(); - Core::System::GetInstance().PrepareReschedule(thread->GetProcessorID()); + kernel.System().PrepareReschedule(thread->GetProcessorID()); } } -- cgit v1.2.3 From 598203b5cfc16a6136826788fb3b76da890f52c4 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Mon, 7 Oct 2019 18:57:13 -0400 Subject: Kernel: Correct Results in Condition Variables and Mutexes --- src/core/hle/kernel/kernel.cpp | 13 +++++++------ src/core/hle/kernel/mutex.cpp | 1 + src/core/hle/kernel/svc.cpp | 27 +++++++++------------------ 3 files changed, 17 insertions(+), 24 deletions(-) (limited to 'src/core/hle/kernel/kernel.cpp') diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 77edbcd1f1..002c5af2bb 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -15,6 +15,7 @@ #include "core/core_timing_util.h" #include "core/hle/kernel/address_arbiter.h" #include "core/hle/kernel/client_port.h" +#include "core/hle/kernel/errors.h" #include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/process.h" @@ -60,12 +61,8 @@ static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] s64 cycles_ if (thread->HasWakeupCallback()) { resume = thread->InvokeWakeupCallback(ThreadWakeupReason::Timeout, thread, nullptr, 0); } - } - - if (thread->GetMutexWaitAddress() != 0 || thread->GetCondVarWaitAddress() != 0 || - thread->GetWaitHandle() != 0) { - ASSERT(thread->GetStatus() == ThreadStatus::WaitMutex || - thread->GetStatus() == ThreadStatus::WaitCondVar); + } else if (thread->GetStatus() == ThreadStatus::WaitMutex || + thread->GetStatus() == ThreadStatus::WaitCondVar) { thread->SetMutexWaitAddress(0); thread->SetCondVarWaitAddress(0); thread->SetWaitHandle(0); @@ -85,6 +82,10 @@ static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] s64 cycles_ } if (resume) { + if (thread->GetStatus() == ThreadStatus::WaitCondVar || + thread->GetStatus() == ThreadStatus::WaitArb) { + thread->SetWaitSynchronizationResult(RESULT_TIMEOUT); + } thread->ResumeFromWait(); } } diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index eb919246cd..663d0f4b6e 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -139,6 +139,7 @@ ResultCode Mutex::Release(VAddr address) { thread->SetCondVarWaitAddress(0); thread->SetMutexWaitAddress(0); thread->SetWaitHandle(0); + thread->SetWaitSynchronizationResult(RESULT_SUCCESS); system.PrepareReschedule(); diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index bd67fc96d7..823d1d4032 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -1677,18 +1677,20 @@ static ResultCode SignalProcessWideKey(Core::System& system, VAddr condition_var // Atomically read the value of the mutex. u32 mutex_val = 0; + u32 update_val = 0; + const VAddr mutex_address = thread->GetMutexWaitAddress(); do { - monitor.SetExclusive(current_core, thread->GetMutexWaitAddress()); + monitor.SetExclusive(current_core, mutex_address); // If the mutex is not yet acquired, acquire it. - mutex_val = Memory::Read32(thread->GetMutexWaitAddress()); + mutex_val = Memory::Read32(mutex_address); if (mutex_val != 0) { - monitor.ClearExclusive(); - break; + update_val = mutex_val | Mutex::MutexHasWaitersFlag; + } else { + update_val = thread->GetWaitHandle(); } - } while (!monitor.ExclusiveWrite32(current_core, thread->GetMutexWaitAddress(), - thread->GetWaitHandle())); + } while (!monitor.ExclusiveWrite32(current_core, mutex_address, update_val)); if (mutex_val == 0) { // We were able to acquire the mutex, resume this thread. ASSERT(thread->GetStatus() == ThreadStatus::WaitCondVar); @@ -1702,20 +1704,9 @@ static ResultCode SignalProcessWideKey(Core::System& system, VAddr condition_var thread->SetLockOwner(nullptr); thread->SetMutexWaitAddress(0); thread->SetWaitHandle(0); + thread->SetWaitSynchronizationResult(RESULT_SUCCESS); system.PrepareReschedule(thread->GetProcessorID()); } else { - // Atomically signal that the mutex now has a waiting thread. - do { - monitor.SetExclusive(current_core, thread->GetMutexWaitAddress()); - - // Ensure that the mutex value is still what we expect. - u32 value = Memory::Read32(thread->GetMutexWaitAddress()); - // TODO(Subv): When this happens, the kernel just clears the exclusive state and - // retries the initial read for this thread. - ASSERT_MSG(mutex_val == value, "Unhandled synchronization primitive case"); - } while (!monitor.ExclusiveWrite32(current_core, thread->GetMutexWaitAddress(), - mutex_val | Mutex::MutexHasWaitersFlag)); - // The mutex is already owned by some other thread, make this thread wait on it. const Handle owner_handle = static_cast(mutex_val & Mutex::MutexOwnerMask); const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); -- cgit v1.2.3 From 17b53b4a5432a97c0ae49f3ff031dbeaaca16c25 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sat, 12 Oct 2019 08:21:51 -0400 Subject: Kernel Scheduler: Make sure the global scheduler shutdowns correctly. --- src/common/multi_level_queue.h | 7 +++++++ src/core/core_cpu.cpp | 4 ++++ src/core/core_cpu.h | 2 ++ src/core/cpu_core_manager.cpp | 1 + src/core/hle/kernel/kernel.cpp | 2 ++ src/core/hle/kernel/scheduler.cpp | 8 ++++++++ src/core/hle/kernel/scheduler.h | 7 +++++++ 7 files changed, 31 insertions(+) (limited to 'src/core/hle/kernel/kernel.cpp') diff --git a/src/common/multi_level_queue.h b/src/common/multi_level_queue.h index 9cb448f567..50acfdbf2f 100644 --- a/src/common/multi_level_queue.h +++ b/src/common/multi_level_queue.h @@ -304,6 +304,13 @@ public: return levels[priority == Depth ? 63 : priority].back(); } + void clear() { + used_priorities = 0; + for (std::size_t i = 0; i < Depth; i++) { + levels[i].clear(); + } + } + private: using const_list_iterator = typename std::list::const_iterator; diff --git a/src/core/core_cpu.cpp b/src/core/core_cpu.cpp index a6f63e437a..233ea572ca 100644 --- a/src/core/core_cpu.cpp +++ b/src/core/core_cpu.cpp @@ -117,4 +117,8 @@ void Cpu::Reschedule() { scheduler->TryDoContextSwitch(); } +void Cpu::Shutdown() { + scheduler->Shutdown(); +} + } // namespace Core diff --git a/src/core/core_cpu.h b/src/core/core_cpu.h index 80261daf75..cafca8df7f 100644 --- a/src/core/core_cpu.h +++ b/src/core/core_cpu.h @@ -84,6 +84,8 @@ public: return core_index; } + void Shutdown(); + static std::unique_ptr MakeExclusiveMonitor(std::size_t num_cores); private: diff --git a/src/core/cpu_core_manager.cpp b/src/core/cpu_core_manager.cpp index 16b384076e..8efd410bba 100644 --- a/src/core/cpu_core_manager.cpp +++ b/src/core/cpu_core_manager.cpp @@ -58,6 +58,7 @@ void CpuCoreManager::Shutdown() { thread_to_cpu.clear(); for (auto& cpu_core : cores) { + cpu_core->Shutdown(); cpu_core.reset(); } diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 002c5af2bb..0d6286f845 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -116,6 +116,8 @@ struct KernelCore::Impl { thread_wakeup_event_type = nullptr; preemption_event = nullptr; + global_scheduler.Shutdown(); + named_ports.clear(); } diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp index 226d15d888..122106267a 100644 --- a/src/core/hle/kernel/scheduler.cpp +++ b/src/core/hle/kernel/scheduler.cpp @@ -342,6 +342,14 @@ bool GlobalScheduler::AskForReselectionOrMarkRedundant(Thread* current_thread, T } } +void GlobalScheduler::Shutdown() { + for (std::size_t core = 0; core < NUM_CPU_CORES; core++) { + scheduled_queue[core].clear(); + suggested_queue[core].clear(); + } + thread_list.clear(); +} + GlobalScheduler::~GlobalScheduler() = default; Scheduler::Scheduler(Core::System& system, Core::ARM_Interface& cpu_core, u32 core_id) diff --git a/src/core/hle/kernel/scheduler.h b/src/core/hle/kernel/scheduler.h index 408e20c883..617553ae36 100644 --- a/src/core/hle/kernel/scheduler.h +++ b/src/core/hle/kernel/scheduler.h @@ -147,6 +147,8 @@ public: return reselection_pending.load(); } + void Shutdown(); + private: bool AskForReselectionOrMarkRedundant(Thread* current_thread, Thread* winner); @@ -189,6 +191,11 @@ public: return context_switch_pending; } + void Shutdown() { + current_thread = nullptr; + selected_thread = nullptr; + } + private: friend class GlobalScheduler; /** -- cgit v1.2.3 From ac9dd91f1ec3a1607f0413308623f903f31d477c Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sat, 12 Oct 2019 10:21:33 -0400 Subject: Kernel: Reverse global accessor removal. --- src/core/hle/kernel/kernel.cpp | 8 -------- src/core/hle/kernel/kernel.h | 6 ------ src/core/hle/kernel/thread.cpp | 16 ++++++++-------- src/core/hle/kernel/wait_object.cpp | 2 +- 4 files changed, 9 insertions(+), 23 deletions(-) (limited to 'src/core/hle/kernel/kernel.cpp') diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 0d6286f845..f94ac150d0 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -232,14 +232,6 @@ const Kernel::GlobalScheduler& KernelCore::GlobalScheduler() const { return impl->global_scheduler; } -Core::System& KernelCore::System() { - return impl->system; -} - -const Core::System& KernelCore::System() const { - return impl->system; -} - void KernelCore::AddNamedPort(std::string name, SharedPtr port) { impl->named_ports.emplace(std::move(name), std::move(port)); } diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 9fb8f52ec9..c4397fc77a 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -82,12 +82,6 @@ public: /// Gets the sole instance of the global scheduler const Kernel::GlobalScheduler& GlobalScheduler() const; - /// Gets the sole instance of the system - Core::System& System(); - - /// Gets the sole instance of the system - const Core::System& System() const; - /// Adds a port to the named port table void AddNamedPort(std::string name, SharedPtr port); diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 8663fe5eed..0c11da1e0e 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -41,7 +41,7 @@ Thread::~Thread() = default; void Thread::Stop() { // Cancel any outstanding wakeup events for this thread - kernel.System().CoreTiming().UnscheduleEvent(kernel.ThreadWakeupCallbackEventType(), + Core::System::GetInstance().CoreTiming().UnscheduleEvent(kernel.ThreadWakeupCallbackEventType(), callback_handle); kernel.ThreadWakeupCallbackHandleTable().Close(callback_handle); callback_handle = 0; @@ -68,12 +68,12 @@ void Thread::WakeAfterDelay(s64 nanoseconds) { // This function might be called from any thread so we have to be cautious and use the // thread-safe version of ScheduleEvent. const s64 cycles = Core::Timing::nsToCycles(std::chrono::nanoseconds{nanoseconds}); - kernel.System().CoreTiming().ScheduleEvent(cycles, kernel.ThreadWakeupCallbackEventType(), + Core::System::GetInstance().CoreTiming().ScheduleEvent(cycles, kernel.ThreadWakeupCallbackEventType(), callback_handle); } void Thread::CancelWakeupTimer() { - kernel.System().CoreTiming().UnscheduleEvent(kernel.ThreadWakeupCallbackEventType(), + Core::System::GetInstance().CoreTiming().UnscheduleEvent(kernel.ThreadWakeupCallbackEventType(), callback_handle); } @@ -176,7 +176,7 @@ ResultVal> Thread::Create(KernelCore& kernel, std::string name return ResultCode(-1); } - auto& system = kernel.System(); + auto& system = Core::System::GetInstance(); SharedPtr thread(new Thread(kernel)); thread->thread_id = kernel.CreateNewThreadID(); @@ -258,7 +258,7 @@ void Thread::SetStatus(ThreadStatus new_status) { } if (status == ThreadStatus::Running) { - last_running_ticks = kernel.System().CoreTiming().GetTicks(); + last_running_ticks = Core::System::GetInstance().CoreTiming().GetTicks(); } status = new_status; @@ -356,7 +356,7 @@ void Thread::SetActivity(ThreadActivity value) { // Set status if not waiting if (status == ThreadStatus::Ready || status == ThreadStatus::Running) { SetStatus(ThreadStatus::Paused); - kernel.System().CpuCore(processor_id).PrepareReschedule(); + Core::System::GetInstance().CpuCore(processor_id).PrepareReschedule(); } } else if (status == ThreadStatus::Paused) { // Ready to reschedule @@ -475,7 +475,7 @@ void Thread::AdjustSchedulingOnPriority(u32 old_priority) { if (GetSchedulingStatus() != ThreadSchedStatus::Runnable) { return; } - auto& scheduler = kernel.System().GlobalScheduler(); + auto& scheduler = Core::System::GetInstance().GlobalScheduler(); if (processor_id >= 0) { scheduler.Unschedule(old_priority, processor_id, this); } @@ -507,7 +507,7 @@ void Thread::AdjustSchedulingOnPriority(u32 old_priority) { } void Thread::AdjustSchedulingOnAffinity(u64 old_affinity_mask, s32 old_core) { - auto& scheduler = kernel.System().GlobalScheduler(); + auto& scheduler = Core::System::GetInstance().GlobalScheduler(); if (GetSchedulingStatus() != ThreadSchedStatus::Runnable || current_priority >= THREADPRIO_COUNT) { return; diff --git a/src/core/hle/kernel/wait_object.cpp b/src/core/hle/kernel/wait_object.cpp index 0f833fb3ac..c00cef0629 100644 --- a/src/core/hle/kernel/wait_object.cpp +++ b/src/core/hle/kernel/wait_object.cpp @@ -95,7 +95,7 @@ void WaitObject::WakeupWaitingThread(SharedPtr thread) { } if (resume) { thread->ResumeFromWait(); - kernel.System().PrepareReschedule(thread->GetProcessorID()); + Core::System::GetInstance().PrepareReschedule(thread->GetProcessorID()); } } -- cgit v1.2.3