kernel/scheduler: Pass in system instance in constructor
Avoids directly relying on the global system instance and instead makes an arbitrary system instance an explicit dependency on construction. This also allows removing dependencies on some global accessor functions as well.
This commit is contained in:
parent
07e13d6728
commit
fad20213e6
|
@ -11,6 +11,7 @@
|
||||||
#endif
|
#endif
|
||||||
#include "core/arm/exclusive_monitor.h"
|
#include "core/arm/exclusive_monitor.h"
|
||||||
#include "core/arm/unicorn/arm_unicorn.h"
|
#include "core/arm/unicorn/arm_unicorn.h"
|
||||||
|
#include "core/core.h"
|
||||||
#include "core/core_cpu.h"
|
#include "core/core_cpu.h"
|
||||||
#include "core/core_timing.h"
|
#include "core/core_timing.h"
|
||||||
#include "core/hle/kernel/scheduler.h"
|
#include "core/hle/kernel/scheduler.h"
|
||||||
|
@ -49,9 +50,9 @@ bool CpuBarrier::Rendezvous() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Cpu::Cpu(Timing::CoreTiming& core_timing, ExclusiveMonitor& exclusive_monitor,
|
Cpu::Cpu(System& system, ExclusiveMonitor& exclusive_monitor, CpuBarrier& cpu_barrier,
|
||||||
CpuBarrier& cpu_barrier, std::size_t core_index)
|
std::size_t core_index)
|
||||||
: cpu_barrier{cpu_barrier}, core_timing{core_timing}, core_index{core_index} {
|
: cpu_barrier{cpu_barrier}, core_timing{system.CoreTiming()}, core_index{core_index} {
|
||||||
if (Settings::values.use_cpu_jit) {
|
if (Settings::values.use_cpu_jit) {
|
||||||
#ifdef ARCHITECTURE_x86_64
|
#ifdef ARCHITECTURE_x86_64
|
||||||
arm_interface = std::make_unique<ARM_Dynarmic>(core_timing, exclusive_monitor, core_index);
|
arm_interface = std::make_unique<ARM_Dynarmic>(core_timing, exclusive_monitor, core_index);
|
||||||
|
@ -63,7 +64,7 @@ Cpu::Cpu(Timing::CoreTiming& core_timing, ExclusiveMonitor& exclusive_monitor,
|
||||||
arm_interface = std::make_unique<ARM_Unicorn>(core_timing);
|
arm_interface = std::make_unique<ARM_Unicorn>(core_timing);
|
||||||
}
|
}
|
||||||
|
|
||||||
scheduler = std::make_unique<Kernel::Scheduler>(*arm_interface);
|
scheduler = std::make_unique<Kernel::Scheduler>(system, *arm_interface);
|
||||||
}
|
}
|
||||||
|
|
||||||
Cpu::~Cpu() = default;
|
Cpu::~Cpu() = default;
|
||||||
|
|
|
@ -15,6 +15,10 @@ namespace Kernel {
|
||||||
class Scheduler;
|
class Scheduler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
class System;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Core::Timing {
|
namespace Core::Timing {
|
||||||
class CoreTiming;
|
class CoreTiming;
|
||||||
}
|
}
|
||||||
|
@ -45,8 +49,8 @@ private:
|
||||||
|
|
||||||
class Cpu {
|
class Cpu {
|
||||||
public:
|
public:
|
||||||
Cpu(Timing::CoreTiming& core_timing, ExclusiveMonitor& exclusive_monitor,
|
Cpu(System& system, ExclusiveMonitor& exclusive_monitor, CpuBarrier& cpu_barrier,
|
||||||
CpuBarrier& cpu_barrier, std::size_t core_index);
|
std::size_t core_index);
|
||||||
~Cpu();
|
~Cpu();
|
||||||
|
|
||||||
void RunLoop(bool tight_loop = true);
|
void RunLoop(bool tight_loop = true);
|
||||||
|
|
|
@ -27,8 +27,7 @@ void CpuCoreManager::Initialize(System& system) {
|
||||||
exclusive_monitor = Cpu::MakeExclusiveMonitor(cores.size());
|
exclusive_monitor = Cpu::MakeExclusiveMonitor(cores.size());
|
||||||
|
|
||||||
for (std::size_t index = 0; index < cores.size(); ++index) {
|
for (std::size_t index = 0; index < cores.size(); ++index) {
|
||||||
cores[index] =
|
cores[index] = std::make_unique<Cpu>(system, *exclusive_monitor, *barrier, index);
|
||||||
std::make_unique<Cpu>(system.CoreTiming(), *exclusive_monitor, *barrier, index);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create threads for CPU cores 1-3, and build thread_to_cpu map
|
// Create threads for CPU cores 1-3, and build thread_to_cpu map
|
||||||
|
|
|
@ -19,7 +19,8 @@ namespace Kernel {
|
||||||
|
|
||||||
std::mutex Scheduler::scheduler_mutex;
|
std::mutex Scheduler::scheduler_mutex;
|
||||||
|
|
||||||
Scheduler::Scheduler(Core::ARM_Interface& cpu_core) : cpu_core(cpu_core) {}
|
Scheduler::Scheduler(Core::System& system, Core::ARM_Interface& cpu_core)
|
||||||
|
: cpu_core{cpu_core}, system{system} {}
|
||||||
|
|
||||||
Scheduler::~Scheduler() {
|
Scheduler::~Scheduler() {
|
||||||
for (auto& thread : thread_list) {
|
for (auto& thread : thread_list) {
|
||||||
|
@ -61,7 +62,7 @@ Thread* Scheduler::PopNextReadyThread() {
|
||||||
|
|
||||||
void Scheduler::SwitchContext(Thread* new_thread) {
|
void Scheduler::SwitchContext(Thread* new_thread) {
|
||||||
Thread* const previous_thread = GetCurrentThread();
|
Thread* const previous_thread = GetCurrentThread();
|
||||||
Process* const previous_process = Core::CurrentProcess();
|
Process* const previous_process = system.Kernel().CurrentProcess();
|
||||||
|
|
||||||
UpdateLastContextSwitchTime(previous_thread, previous_process);
|
UpdateLastContextSwitchTime(previous_thread, previous_process);
|
||||||
|
|
||||||
|
@ -94,8 +95,8 @@ void Scheduler::SwitchContext(Thread* new_thread) {
|
||||||
|
|
||||||
auto* const thread_owner_process = current_thread->GetOwnerProcess();
|
auto* const thread_owner_process = current_thread->GetOwnerProcess();
|
||||||
if (previous_process != thread_owner_process) {
|
if (previous_process != thread_owner_process) {
|
||||||
Core::System::GetInstance().Kernel().MakeCurrentProcess(thread_owner_process);
|
system.Kernel().MakeCurrentProcess(thread_owner_process);
|
||||||
SetCurrentPageTable(&Core::CurrentProcess()->VMManager().page_table);
|
SetCurrentPageTable(&thread_owner_process->VMManager().page_table);
|
||||||
}
|
}
|
||||||
|
|
||||||
cpu_core.LoadContext(new_thread->GetContext());
|
cpu_core.LoadContext(new_thread->GetContext());
|
||||||
|
@ -111,7 +112,7 @@ void Scheduler::SwitchContext(Thread* new_thread) {
|
||||||
|
|
||||||
void Scheduler::UpdateLastContextSwitchTime(Thread* thread, Process* process) {
|
void Scheduler::UpdateLastContextSwitchTime(Thread* thread, Process* process) {
|
||||||
const u64 prev_switch_ticks = last_context_switch_time;
|
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;
|
const u64 update_ticks = most_recent_switch_ticks - prev_switch_ticks;
|
||||||
|
|
||||||
if (thread != nullptr) {
|
if (thread != nullptr) {
|
||||||
|
@ -223,8 +224,7 @@ void Scheduler::YieldWithLoadBalancing(Thread* thread) {
|
||||||
// Take the first non-nullptr one
|
// Take the first non-nullptr one
|
||||||
for (unsigned cur_core = 0; cur_core < Core::NUM_CPU_CORES; ++cur_core) {
|
for (unsigned cur_core = 0; cur_core < Core::NUM_CPU_CORES; ++cur_core) {
|
||||||
const auto res =
|
const auto res =
|
||||||
Core::System::GetInstance().CpuCore(cur_core).Scheduler().GetNextSuggestedThread(
|
system.CpuCore(cur_core).Scheduler().GetNextSuggestedThread(core, priority);
|
||||||
core, priority);
|
|
||||||
|
|
||||||
// If scheduler provides a suggested thread
|
// If scheduler provides a suggested thread
|
||||||
if (res != nullptr) {
|
if (res != nullptr) {
|
||||||
|
|
|
@ -13,7 +13,8 @@
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
class ARM_Interface;
|
class ARM_Interface;
|
||||||
}
|
class System;
|
||||||
|
} // namespace Core
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
|
@ -21,7 +22,7 @@ class Process;
|
||||||
|
|
||||||
class Scheduler final {
|
class Scheduler final {
|
||||||
public:
|
public:
|
||||||
explicit Scheduler(Core::ARM_Interface& cpu_core);
|
explicit Scheduler(Core::System& system, Core::ARM_Interface& cpu_core);
|
||||||
~Scheduler();
|
~Scheduler();
|
||||||
|
|
||||||
/// Returns whether there are any threads that are ready to run.
|
/// Returns whether there are any threads that are ready to run.
|
||||||
|
@ -162,6 +163,7 @@ private:
|
||||||
Core::ARM_Interface& cpu_core;
|
Core::ARM_Interface& cpu_core;
|
||||||
u64 last_context_switch_time = 0;
|
u64 last_context_switch_time = 0;
|
||||||
|
|
||||||
|
Core::System& system;
|
||||||
static std::mutex scheduler_mutex;
|
static std::mutex scheduler_mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Reference in New Issue