diff options
| author | bunnei <bunneidev@gmail.com> | 2020-01-30 18:13:59 -0500 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-01-30 18:13:59 -0500 | 
| commit | 985d0f35e55f0752c6e147d0140b367708499cb4 (patch) | |
| tree | 119249aee3acc2cc2ee6a5d391288b52c126765b | |
| parent | 8a7cdfc3ff1956f7895bec1c60cfe1a0abc21b12 (diff) | |
| parent | 2d1984c20c75e03ec79eeb3806b12efa1679b977 (diff) | |
Merge pull request #3353 from FernandoS27/aries
System: Refactor CPU Core management and move ARMInterface and Schedulers to Kernel
| -rw-r--r-- | src/core/CMakeLists.txt | 10 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic.cpp | 2 | ||||
| -rw-r--r-- | src/core/arm/exclusive_monitor.cpp | 14 | ||||
| -rw-r--r-- | src/core/arm/exclusive_monitor.h | 9 | ||||
| -rw-r--r-- | src/core/core.cpp | 75 | ||||
| -rw-r--r-- | src/core/core.h | 10 | ||||
| -rw-r--r-- | src/core/core_cpu.cpp | 127 | ||||
| -rw-r--r-- | src/core/core_cpu.h | 120 | ||||
| -rw-r--r-- | src/core/core_manager.cpp | 70 | ||||
| -rw-r--r-- | src/core/core_manager.h | 63 | ||||
| -rw-r--r-- | src/core/cpu_core_manager.cpp | 152 | ||||
| -rw-r--r-- | src/core/cpu_core_manager.h | 62 | ||||
| -rw-r--r-- | src/core/cpu_manager.cpp | 83 | ||||
| -rw-r--r-- | src/core/cpu_manager.h | 50 | ||||
| -rw-r--r-- | src/core/gdbstub/gdbstub.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/address_arbiter.cpp | 1 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.cpp | 52 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.h | 19 | ||||
| -rw-r--r-- | src/core/hle/kernel/physical_core.cpp | 52 | ||||
| -rw-r--r-- | src/core/hle/kernel/physical_core.h | 74 | ||||
| -rw-r--r-- | src/core/hle/kernel/scheduler.cpp | 1 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.cpp | 3 | ||||
| -rw-r--r-- | src/core/hle/kernel/wait_object.cpp | 3 | 
24 files changed, 541 insertions, 515 deletions
| diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 1a3647a67..d342cafe0 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -15,14 +15,14 @@ add_library(core STATIC      constants.h      core.cpp      core.h -    core_cpu.cpp -    core_cpu.h +    core_manager.cpp +    core_manager.h      core_timing.cpp      core_timing.h      core_timing_util.cpp      core_timing_util.h -    cpu_core_manager.cpp -    cpu_core_manager.h +    cpu_manager.cpp +    cpu_manager.h      crypto/aes_util.cpp      crypto/aes_util.h      crypto/encryption_layer.cpp @@ -158,6 +158,8 @@ add_library(core STATIC      hle/kernel/mutex.h      hle/kernel/object.cpp      hle/kernel/object.h +    hle/kernel/physical_core.cpp +    hle/kernel/physical_core.h      hle/kernel/process.cpp      hle/kernel/process.h      hle/kernel/process_capability.cpp diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp index e825c0526..f468e57e4 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic.cpp @@ -10,7 +10,7 @@  #include "common/microprofile.h"  #include "core/arm/dynarmic/arm_dynarmic.h"  #include "core/core.h" -#include "core/core_cpu.h" +#include "core/core_manager.h"  #include "core/core_timing.h"  #include "core/core_timing_util.h"  #include "core/gdbstub/gdbstub.h" diff --git a/src/core/arm/exclusive_monitor.cpp b/src/core/arm/exclusive_monitor.cpp index abd59ff4b..94570e520 100644 --- a/src/core/arm/exclusive_monitor.cpp +++ b/src/core/arm/exclusive_monitor.cpp @@ -2,10 +2,24 @@  // Licensed under GPLv2 or any later version  // Refer to the license.txt file included. +#ifdef ARCHITECTURE_x86_64 +#include "core/arm/dynarmic/arm_dynarmic.h" +#endif  #include "core/arm/exclusive_monitor.h" +#include "core/memory.h"  namespace Core {  ExclusiveMonitor::~ExclusiveMonitor() = default; +std::unique_ptr<Core::ExclusiveMonitor> MakeExclusiveMonitor(Memory::Memory& memory, +                                                             std::size_t num_cores) { +#ifdef ARCHITECTURE_x86_64 +    return std::make_unique<Core::DynarmicExclusiveMonitor>(memory, num_cores); +#else +    // TODO(merry): Passthrough exclusive monitor +    return nullptr; +#endif +} +  } // namespace Core diff --git a/src/core/arm/exclusive_monitor.h b/src/core/arm/exclusive_monitor.h index f59aca667..4ef418b90 100644 --- a/src/core/arm/exclusive_monitor.h +++ b/src/core/arm/exclusive_monitor.h @@ -4,8 +4,14 @@  #pragma once +#include <memory> +  #include "common/common_types.h" +namespace Memory { +class Memory; +} +  namespace Core {  class ExclusiveMonitor { @@ -22,4 +28,7 @@ public:      virtual bool ExclusiveWrite128(std::size_t core_index, VAddr vaddr, u128 value) = 0;  }; +std::unique_ptr<Core::ExclusiveMonitor> MakeExclusiveMonitor(Memory::Memory& memory, +                                                             std::size_t num_cores); +  } // namespace Core diff --git a/src/core/core.cpp b/src/core/core.cpp index d697b80ef..c53d122be 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -11,9 +11,9 @@  #include "common/string_util.h"  #include "core/arm/exclusive_monitor.h"  #include "core/core.h" -#include "core/core_cpu.h" +#include "core/core_manager.h"  #include "core/core_timing.h" -#include "core/cpu_core_manager.h" +#include "core/cpu_manager.h"  #include "core/file_sys/bis_factory.h"  #include "core/file_sys/card_image.h"  #include "core/file_sys/mode.h" @@ -28,6 +28,7 @@  #include "core/hardware_interrupt_manager.h"  #include "core/hle/kernel/client_port.h"  #include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/physical_core.h"  #include "core/hle/kernel/process.h"  #include "core/hle/kernel/scheduler.h"  #include "core/hle/kernel/thread.h" @@ -113,16 +114,25 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,  struct System::Impl {      explicit Impl(System& system)          : kernel{system}, fs_controller{system}, memory{system}, -          cpu_core_manager{system}, reporter{system}, applet_manager{system} {} +          cpu_manager{system}, reporter{system}, applet_manager{system} {} -    Cpu& CurrentCpuCore() { -        return cpu_core_manager.GetCurrentCore(); +    CoreManager& CurrentCoreManager() { +        return cpu_manager.GetCurrentCoreManager(); +    } + +    Kernel::PhysicalCore& CurrentPhysicalCore() { +        const auto index = cpu_manager.GetActiveCoreIndex(); +        return kernel.PhysicalCore(index); +    } + +    Kernel::PhysicalCore& GetPhysicalCore(std::size_t index) { +        return kernel.PhysicalCore(index);      }      ResultStatus RunLoop(bool tight_loop) {          status = ResultStatus::Success; -        cpu_core_manager.RunLoop(tight_loop); +        cpu_manager.RunLoop(tight_loop);          return status;      } @@ -131,8 +141,8 @@ struct System::Impl {          LOG_DEBUG(HW_Memory, "initialized OK");          core_timing.Initialize(); -        cpu_core_manager.Initialize();          kernel.Initialize(); +        cpu_manager.Initialize();          const auto current_time = std::chrono::duration_cast<std::chrono::seconds>(              std::chrono::system_clock::now().time_since_epoch()); @@ -205,7 +215,6 @@ struct System::Impl {          // Main process has been loaded and been made current.          // Begin GPU and CPU execution.          gpu_core->Start(); -        cpu_core_manager.StartThreads();          // Initialize cheat engine          if (cheat_engine) { @@ -272,7 +281,7 @@ struct System::Impl {          gpu_core.reset();          // Close all CPU/threading state -        cpu_core_manager.Shutdown(); +        cpu_manager.Shutdown();          // Shutdown kernel and core timing          kernel.Shutdown(); @@ -342,7 +351,7 @@ struct System::Impl {      std::unique_ptr<Tegra::GPU> gpu_core;      std::unique_ptr<Hardware::InterruptManager> interrupt_manager;      Memory::Memory memory; -    CpuCoreManager cpu_core_manager; +    CpuManager cpu_manager;      bool is_powered_on = false;      bool exit_lock = false; @@ -377,12 +386,12 @@ struct System::Impl {  System::System() : impl{std::make_unique<Impl>(*this)} {}  System::~System() = default; -Cpu& System::CurrentCpuCore() { -    return impl->CurrentCpuCore(); +CoreManager& System::CurrentCoreManager() { +    return impl->CurrentCoreManager();  } -const Cpu& System::CurrentCpuCore() const { -    return impl->CurrentCpuCore(); +const CoreManager& System::CurrentCoreManager() const { +    return impl->CurrentCoreManager();  }  System::ResultStatus System::RunLoop(bool tight_loop) { @@ -394,7 +403,7 @@ System::ResultStatus System::SingleStep() {  }  void System::InvalidateCpuInstructionCaches() { -    impl->cpu_core_manager.InvalidateAllInstructionCaches(); +    impl->kernel.InvalidateAllInstructionCaches();  }  System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath) { @@ -406,13 +415,11 @@ bool System::IsPoweredOn() const {  }  void System::PrepareReschedule() { -    CurrentCpuCore().PrepareReschedule(); +    impl->CurrentPhysicalCore().Stop();  }  void System::PrepareReschedule(const u32 core_index) { -    if (core_index < GlobalScheduler().CpuCoresCount()) { -        CpuCore(core_index).PrepareReschedule(); -    } +    impl->kernel.PrepareReschedule(core_index);  }  PerfStatsResults System::GetAndResetPerfStats() { @@ -428,31 +435,31 @@ const TelemetrySession& System::TelemetrySession() const {  }  ARM_Interface& System::CurrentArmInterface() { -    return CurrentCpuCore().ArmInterface(); +    return impl->CurrentPhysicalCore().ArmInterface();  }  const ARM_Interface& System::CurrentArmInterface() const { -    return CurrentCpuCore().ArmInterface(); +    return impl->CurrentPhysicalCore().ArmInterface();  }  std::size_t System::CurrentCoreIndex() const { -    return CurrentCpuCore().CoreIndex(); +    return impl->cpu_manager.GetActiveCoreIndex();  }  Kernel::Scheduler& System::CurrentScheduler() { -    return CurrentCpuCore().Scheduler(); +    return impl->CurrentPhysicalCore().Scheduler();  }  const Kernel::Scheduler& System::CurrentScheduler() const { -    return CurrentCpuCore().Scheduler(); +    return impl->CurrentPhysicalCore().Scheduler();  }  Kernel::Scheduler& System::Scheduler(std::size_t core_index) { -    return CpuCore(core_index).Scheduler(); +    return impl->GetPhysicalCore(core_index).Scheduler();  }  const Kernel::Scheduler& System::Scheduler(std::size_t core_index) const { -    return CpuCore(core_index).Scheduler(); +    return impl->GetPhysicalCore(core_index).Scheduler();  }  /// Gets the global scheduler @@ -474,28 +481,28 @@ const Kernel::Process* System::CurrentProcess() const {  }  ARM_Interface& System::ArmInterface(std::size_t core_index) { -    return CpuCore(core_index).ArmInterface(); +    return impl->GetPhysicalCore(core_index).ArmInterface();  }  const ARM_Interface& System::ArmInterface(std::size_t core_index) const { -    return CpuCore(core_index).ArmInterface(); +    return impl->GetPhysicalCore(core_index).ArmInterface();  } -Cpu& System::CpuCore(std::size_t core_index) { -    return impl->cpu_core_manager.GetCore(core_index); +CoreManager& System::GetCoreManager(std::size_t core_index) { +    return impl->cpu_manager.GetCoreManager(core_index);  } -const Cpu& System::CpuCore(std::size_t core_index) const { +const CoreManager& System::GetCoreManager(std::size_t core_index) const {      ASSERT(core_index < NUM_CPU_CORES); -    return impl->cpu_core_manager.GetCore(core_index); +    return impl->cpu_manager.GetCoreManager(core_index);  }  ExclusiveMonitor& System::Monitor() { -    return impl->cpu_core_manager.GetExclusiveMonitor(); +    return impl->kernel.GetExclusiveMonitor();  }  const ExclusiveMonitor& System::Monitor() const { -    return impl->cpu_core_manager.GetExclusiveMonitor(); +    return impl->kernel.GetExclusiveMonitor();  }  Memory::Memory& System::Memory() { diff --git a/src/core/core.h b/src/core/core.h index e240c5c58..e69d68fcf 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -93,7 +93,7 @@ class Memory;  namespace Core {  class ARM_Interface; -class Cpu; +class CoreManager;  class ExclusiveMonitor;  class FrameLimiter;  class PerfStats; @@ -218,10 +218,10 @@ public:      const ARM_Interface& ArmInterface(std::size_t core_index) const;      /// Gets a CPU interface to the CPU core with the specified index -    Cpu& CpuCore(std::size_t core_index); +    CoreManager& GetCoreManager(std::size_t core_index);      /// Gets a CPU interface to the CPU core with the specified index -    const Cpu& CpuCore(std::size_t core_index) const; +    const CoreManager& GetCoreManager(std::size_t core_index) const;      /// Gets a reference to the exclusive monitor      ExclusiveMonitor& Monitor(); @@ -364,10 +364,10 @@ private:      System();      /// Returns the currently running CPU core -    Cpu& CurrentCpuCore(); +    CoreManager& CurrentCoreManager();      /// Returns the currently running CPU core -    const Cpu& CurrentCpuCore() const; +    const CoreManager& CurrentCoreManager() const;      /**       * Initialize the emulated system. diff --git a/src/core/core_cpu.cpp b/src/core/core_cpu.cpp deleted file mode 100644 index 630cd4feb..000000000 --- a/src/core/core_cpu.cpp +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright 2018 yuzu emulator team -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <condition_variable> -#include <mutex> - -#include "common/logging/log.h" -#ifdef ARCHITECTURE_x86_64 -#include "core/arm/dynarmic/arm_dynarmic.h" -#endif -#include "core/arm/exclusive_monitor.h" -#include "core/arm/unicorn/arm_unicorn.h" -#include "core/core.h" -#include "core/core_cpu.h" -#include "core/core_timing.h" -#include "core/hle/kernel/scheduler.h" -#include "core/hle/kernel/thread.h" -#include "core/hle/lock.h" -#include "core/settings.h" - -namespace Core { - -void CpuBarrier::NotifyEnd() { -    std::unique_lock lock{mutex}; -    end = true; -    condition.notify_all(); -} - -bool CpuBarrier::Rendezvous() { -    if (!Settings::values.use_multi_core) { -        // Meaningless when running in single-core mode -        return true; -    } - -    if (!end) { -        std::unique_lock lock{mutex}; - -        --cores_waiting; -        if (!cores_waiting) { -            cores_waiting = NUM_CPU_CORES; -            condition.notify_all(); -            return true; -        } - -        condition.wait(lock); -        return true; -    } - -    return false; -} - -Cpu::Cpu(System& system, ExclusiveMonitor& exclusive_monitor, CpuBarrier& cpu_barrier, -         std::size_t core_index) -    : cpu_barrier{cpu_barrier}, global_scheduler{system.GlobalScheduler()}, -      core_timing{system.CoreTiming()}, core_index{core_index} { -#ifdef ARCHITECTURE_x86_64 -    arm_interface = std::make_unique<ARM_Dynarmic>(system, exclusive_monitor, core_index); -#else -    arm_interface = std::make_unique<ARM_Unicorn>(system); -    LOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available"); -#endif - -    scheduler = std::make_unique<Kernel::Scheduler>(system, *arm_interface, core_index); -} - -Cpu::~Cpu() = default; - -std::unique_ptr<ExclusiveMonitor> Cpu::MakeExclusiveMonitor( -    [[maybe_unused]] Memory::Memory& memory, [[maybe_unused]] std::size_t num_cores) { -#ifdef ARCHITECTURE_x86_64 -    return std::make_unique<DynarmicExclusiveMonitor>(memory, num_cores); -#else -    // TODO(merry): Passthrough exclusive monitor -    return nullptr; -#endif -} - -void Cpu::RunLoop(bool tight_loop) { -    // Wait for all other CPU cores to complete the previous slice, such that they run in lock-step -    if (!cpu_barrier.Rendezvous()) { -        // If rendezvous failed, session has been killed -        return; -    } - -    Reschedule(); - -    // If we don't have a currently active thread then don't execute instructions, -    // instead advance to the next event and try to yield to the next thread -    if (Kernel::GetCurrentThread() == nullptr) { -        LOG_TRACE(Core, "Core-{} idling", core_index); -        core_timing.Idle(); -    } else { -        if (tight_loop) { -            arm_interface->Run(); -        } else { -            arm_interface->Step(); -        } -        // We are stopping a run, exclusive state must be cleared -        arm_interface->ClearExclusiveState(); -    } -    core_timing.Advance(); - -    Reschedule(); -} - -void Cpu::SingleStep() { -    return RunLoop(false); -} - -void Cpu::PrepareReschedule() { -    arm_interface->PrepareReschedule(); -} - -void Cpu::Reschedule() { -    // Lock the global kernel mutex when we manipulate the HLE state -    std::lock_guard lock(HLE::g_hle_lock); - -    global_scheduler.SelectThread(core_index); -    scheduler->TryDoContextSwitch(); -} - -void Cpu::Shutdown() { -    scheduler->Shutdown(); -} - -} // namespace Core diff --git a/src/core/core_cpu.h b/src/core/core_cpu.h deleted file mode 100644 index 78f5021a2..000000000 --- a/src/core/core_cpu.h +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright 2018 yuzu emulator team -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include <atomic> -#include <condition_variable> -#include <cstddef> -#include <memory> -#include <mutex> -#include "common/common_types.h" - -namespace Kernel { -class GlobalScheduler; -class Scheduler; -} // namespace Kernel - -namespace Core { -class System; -} - -namespace Core::Timing { -class CoreTiming; -} - -namespace Memory { -class Memory; -} - -namespace Core { - -class ARM_Interface; -class ExclusiveMonitor; - -constexpr unsigned NUM_CPU_CORES{4}; - -class CpuBarrier { -public: -    bool IsAlive() const { -        return !end; -    } - -    void NotifyEnd(); - -    bool Rendezvous(); - -private: -    unsigned cores_waiting{NUM_CPU_CORES}; -    std::mutex mutex; -    std::condition_variable condition; -    std::atomic<bool> end{}; -}; - -class Cpu { -public: -    Cpu(System& system, ExclusiveMonitor& exclusive_monitor, CpuBarrier& cpu_barrier, -        std::size_t core_index); -    ~Cpu(); - -    void RunLoop(bool tight_loop = true); - -    void SingleStep(); - -    void PrepareReschedule(); - -    ARM_Interface& ArmInterface() { -        return *arm_interface; -    } - -    const ARM_Interface& ArmInterface() const { -        return *arm_interface; -    } - -    Kernel::Scheduler& Scheduler() { -        return *scheduler; -    } - -    const Kernel::Scheduler& Scheduler() const { -        return *scheduler; -    } - -    bool IsMainCore() const { -        return core_index == 0; -    } - -    std::size_t CoreIndex() const { -        return core_index; -    } - -    void Shutdown(); - -    /** -     * Creates an exclusive monitor to handle exclusive reads/writes. -     * -     * @param memory The current memory subsystem that the monitor may wish -     *               to keep track of. -     * -     * @param num_cores The number of cores to assume about the CPU. -     * -     * @returns The constructed exclusive monitor instance, or nullptr if the current -     *          CPU backend is unable to use an exclusive monitor. -     */ -    static std::unique_ptr<ExclusiveMonitor> MakeExclusiveMonitor(Memory::Memory& memory, -                                                                  std::size_t num_cores); - -private: -    void Reschedule(); - -    std::unique_ptr<ARM_Interface> arm_interface; -    CpuBarrier& cpu_barrier; -    Kernel::GlobalScheduler& global_scheduler; -    std::unique_ptr<Kernel::Scheduler> scheduler; -    Timing::CoreTiming& core_timing; - -    std::atomic<bool> reschedule_pending = false; -    std::size_t core_index; -}; - -} // namespace Core diff --git a/src/core/core_manager.cpp b/src/core/core_manager.cpp new file mode 100644 index 000000000..8eacf92dd --- /dev/null +++ b/src/core/core_manager.cpp @@ -0,0 +1,70 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include <condition_variable> +#include <mutex> + +#include "common/logging/log.h" +#ifdef ARCHITECTURE_x86_64 +#include "core/arm/dynarmic/arm_dynarmic.h" +#endif +#include "core/arm/exclusive_monitor.h" +#include "core/arm/unicorn/arm_unicorn.h" +#include "core/core.h" +#include "core/core_manager.h" +#include "core/core_timing.h" +#include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/physical_core.h" +#include "core/hle/kernel/scheduler.h" +#include "core/hle/kernel/thread.h" +#include "core/hle/lock.h" +#include "core/settings.h" + +namespace Core { + +CoreManager::CoreManager(System& system, std::size_t core_index) +    : global_scheduler{system.GlobalScheduler()}, physical_core{system.Kernel().PhysicalCore( +                                                      core_index)}, +      core_timing{system.CoreTiming()}, core_index{core_index} {} + +CoreManager::~CoreManager() = default; + +void CoreManager::RunLoop(bool tight_loop) { +    Reschedule(); + +    // If we don't have a currently active thread then don't execute instructions, +    // instead advance to the next event and try to yield to the next thread +    if (Kernel::GetCurrentThread() == nullptr) { +        LOG_TRACE(Core, "Core-{} idling", core_index); +        core_timing.Idle(); +    } else { +        if (tight_loop) { +            physical_core.Run(); +        } else { +            physical_core.Step(); +        } +    } +    core_timing.Advance(); + +    Reschedule(); +} + +void CoreManager::SingleStep() { +    return RunLoop(false); +} + +void CoreManager::PrepareReschedule() { +    physical_core.Stop(); +} + +void CoreManager::Reschedule() { +    // Lock the global kernel mutex when we manipulate the HLE state +    std::lock_guard lock(HLE::g_hle_lock); + +    global_scheduler.SelectThread(core_index); + +    physical_core.Scheduler().TryDoContextSwitch(); +} + +} // namespace Core diff --git a/src/core/core_manager.h b/src/core/core_manager.h new file mode 100644 index 000000000..b14e723d7 --- /dev/null +++ b/src/core/core_manager.h @@ -0,0 +1,63 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <atomic> +#include <cstddef> +#include <memory> +#include "common/common_types.h" + +namespace Kernel { +class GlobalScheduler; +class PhysicalCore; +} // namespace Kernel + +namespace Core { +class System; +} + +namespace Core::Timing { +class CoreTiming; +} + +namespace Memory { +class Memory; +} + +namespace Core { + +constexpr unsigned NUM_CPU_CORES{4}; + +class CoreManager { +public: +    CoreManager(System& system, std::size_t core_index); +    ~CoreManager(); + +    void RunLoop(bool tight_loop = true); + +    void SingleStep(); + +    void PrepareReschedule(); + +    bool IsMainCore() const { +        return core_index == 0; +    } + +    std::size_t CoreIndex() const { +        return core_index; +    } + +private: +    void Reschedule(); + +    Kernel::GlobalScheduler& global_scheduler; +    Kernel::PhysicalCore& physical_core; +    Timing::CoreTiming& core_timing; + +    std::atomic<bool> reschedule_pending = false; +    std::size_t core_index; +}; + +} // namespace Core diff --git a/src/core/cpu_core_manager.cpp b/src/core/cpu_core_manager.cpp deleted file mode 100644 index f04a34133..000000000 --- a/src/core/cpu_core_manager.cpp +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright 2018 yuzu emulator team -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "common/assert.h" -#include "core/arm/exclusive_monitor.h" -#include "core/core.h" -#include "core/core_cpu.h" -#include "core/core_timing.h" -#include "core/cpu_core_manager.h" -#include "core/gdbstub/gdbstub.h" -#include "core/settings.h" - -namespace Core { -namespace { -void RunCpuCore(const System& system, Cpu& cpu_state) { -    while (system.IsPoweredOn()) { -        cpu_state.RunLoop(true); -    } -} -} // Anonymous namespace - -CpuCoreManager::CpuCoreManager(System& system) : system{system} {} -CpuCoreManager::~CpuCoreManager() = default; - -void CpuCoreManager::Initialize() { -    barrier = std::make_unique<CpuBarrier>(); -    exclusive_monitor = Cpu::MakeExclusiveMonitor(system.Memory(), cores.size()); - -    for (std::size_t index = 0; index < cores.size(); ++index) { -        cores[index] = std::make_unique<Cpu>(system, *exclusive_monitor, *barrier, index); -    } -} - -void CpuCoreManager::StartThreads() { -    // Create threads for CPU cores 1-3, and build thread_to_cpu map -    // CPU core 0 is run on the main thread -    thread_to_cpu[std::this_thread::get_id()] = cores[0].get(); -    if (!Settings::values.use_multi_core) { -        return; -    } - -    for (std::size_t index = 0; index < core_threads.size(); ++index) { -        core_threads[index] = std::make_unique<std::thread>(RunCpuCore, std::cref(system), -                                                            std::ref(*cores[index + 1])); -        thread_to_cpu[core_threads[index]->get_id()] = cores[index + 1].get(); -    } -} - -void CpuCoreManager::Shutdown() { -    barrier->NotifyEnd(); -    if (Settings::values.use_multi_core) { -        for (auto& thread : core_threads) { -            thread->join(); -            thread.reset(); -        } -    } - -    thread_to_cpu.clear(); -    for (auto& cpu_core : cores) { -        cpu_core->Shutdown(); -        cpu_core.reset(); -    } - -    exclusive_monitor.reset(); -    barrier.reset(); -} - -Cpu& CpuCoreManager::GetCore(std::size_t index) { -    return *cores.at(index); -} - -const Cpu& CpuCoreManager::GetCore(std::size_t index) const { -    return *cores.at(index); -} - -ExclusiveMonitor& CpuCoreManager::GetExclusiveMonitor() { -    return *exclusive_monitor; -} - -const ExclusiveMonitor& CpuCoreManager::GetExclusiveMonitor() const { -    return *exclusive_monitor; -} - -Cpu& CpuCoreManager::GetCurrentCore() { -    if (Settings::values.use_multi_core) { -        const auto& search = thread_to_cpu.find(std::this_thread::get_id()); -        ASSERT(search != thread_to_cpu.end()); -        ASSERT(search->second); -        return *search->second; -    } - -    // Otherwise, use single-threaded mode active_core variable -    return *cores[active_core]; -} - -const Cpu& CpuCoreManager::GetCurrentCore() const { -    if (Settings::values.use_multi_core) { -        const auto& search = thread_to_cpu.find(std::this_thread::get_id()); -        ASSERT(search != thread_to_cpu.end()); -        ASSERT(search->second); -        return *search->second; -    } - -    // Otherwise, use single-threaded mode active_core variable -    return *cores[active_core]; -} - -void CpuCoreManager::RunLoop(bool tight_loop) { -    // Update thread_to_cpu in case Core 0 is run from a different host thread -    thread_to_cpu[std::this_thread::get_id()] = cores[0].get(); - -    if (GDBStub::IsServerEnabled()) { -        GDBStub::HandlePacket(); - -        // If the loop is halted and we want to step, use a tiny (1) number of instructions to -        // execute. Otherwise, get out of the loop function. -        if (GDBStub::GetCpuHaltFlag()) { -            if (GDBStub::GetCpuStepFlag()) { -                tight_loop = false; -            } else { -                return; -            } -        } -    } - -    auto& core_timing = system.CoreTiming(); -    core_timing.ResetRun(); -    bool keep_running{}; -    do { -        keep_running = false; -        for (active_core = 0; active_core < NUM_CPU_CORES; ++active_core) { -            core_timing.SwitchContext(active_core); -            if (core_timing.CanCurrentContextRun()) { -                cores[active_core]->RunLoop(tight_loop); -            } -            keep_running |= core_timing.CanCurrentContextRun(); -        } -    } while (keep_running); - -    if (GDBStub::IsServerEnabled()) { -        GDBStub::SetCpuStepFlag(false); -    } -} - -void CpuCoreManager::InvalidateAllInstructionCaches() { -    for (auto& cpu : cores) { -        cpu->ArmInterface().ClearInstructionCache(); -    } -} - -} // namespace Core diff --git a/src/core/cpu_core_manager.h b/src/core/cpu_core_manager.h deleted file mode 100644 index 2cbbf8216..000000000 --- a/src/core/cpu_core_manager.h +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2018 yuzu emulator team -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include <array> -#include <map> -#include <memory> -#include <thread> - -namespace Core { - -class Cpu; -class CpuBarrier; -class ExclusiveMonitor; -class System; - -class CpuCoreManager { -public: -    explicit CpuCoreManager(System& system); -    CpuCoreManager(const CpuCoreManager&) = delete; -    CpuCoreManager(CpuCoreManager&&) = delete; - -    ~CpuCoreManager(); - -    CpuCoreManager& operator=(const CpuCoreManager&) = delete; -    CpuCoreManager& operator=(CpuCoreManager&&) = delete; - -    void Initialize(); -    void StartThreads(); -    void Shutdown(); - -    Cpu& GetCore(std::size_t index); -    const Cpu& GetCore(std::size_t index) const; - -    Cpu& GetCurrentCore(); -    const Cpu& GetCurrentCore() const; - -    ExclusiveMonitor& GetExclusiveMonitor(); -    const ExclusiveMonitor& GetExclusiveMonitor() const; - -    void RunLoop(bool tight_loop); - -    void InvalidateAllInstructionCaches(); - -private: -    static constexpr std::size_t NUM_CPU_CORES = 4; - -    std::unique_ptr<ExclusiveMonitor> exclusive_monitor; -    std::unique_ptr<CpuBarrier> barrier; -    std::array<std::unique_ptr<Cpu>, NUM_CPU_CORES> cores; -    std::array<std::unique_ptr<std::thread>, NUM_CPU_CORES - 1> core_threads; -    std::size_t active_core{}; ///< Active core, only used in single thread mode - -    /// Map of guest threads to CPU cores -    std::map<std::thread::id, Cpu*> thread_to_cpu; - -    System& system; -}; - -} // namespace Core diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp new file mode 100644 index 000000000..752534868 --- /dev/null +++ b/src/core/cpu_manager.cpp @@ -0,0 +1,83 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/assert.h" +#include "core/arm/exclusive_monitor.h" +#include "core/core.h" +#include "core/core_manager.h" +#include "core/core_timing.h" +#include "core/cpu_manager.h" +#include "core/gdbstub/gdbstub.h" +#include "core/settings.h" + +namespace Core { + +CpuManager::CpuManager(System& system) : system{system} {} +CpuManager::~CpuManager() = default; + +void CpuManager::Initialize() { +    for (std::size_t index = 0; index < core_managers.size(); ++index) { +        core_managers[index] = std::make_unique<CoreManager>(system, index); +    } +} + +void CpuManager::Shutdown() { +    for (auto& cpu_core : core_managers) { +        cpu_core.reset(); +    } +} + +CoreManager& CpuManager::GetCoreManager(std::size_t index) { +    return *core_managers.at(index); +} + +const CoreManager& CpuManager::GetCoreManager(std::size_t index) const { +    return *core_managers.at(index); +} + +CoreManager& CpuManager::GetCurrentCoreManager() { +    // Otherwise, use single-threaded mode active_core variable +    return *core_managers[active_core]; +} + +const CoreManager& CpuManager::GetCurrentCoreManager() const { +    // Otherwise, use single-threaded mode active_core variable +    return *core_managers[active_core]; +} + +void CpuManager::RunLoop(bool tight_loop) { +    if (GDBStub::IsServerEnabled()) { +        GDBStub::HandlePacket(); + +        // If the loop is halted and we want to step, use a tiny (1) number of instructions to +        // execute. Otherwise, get out of the loop function. +        if (GDBStub::GetCpuHaltFlag()) { +            if (GDBStub::GetCpuStepFlag()) { +                tight_loop = false; +            } else { +                return; +            } +        } +    } + +    auto& core_timing = system.CoreTiming(); +    core_timing.ResetRun(); +    bool keep_running{}; +    do { +        keep_running = false; +        for (active_core = 0; active_core < NUM_CPU_CORES; ++active_core) { +            core_timing.SwitchContext(active_core); +            if (core_timing.CanCurrentContextRun()) { +                core_managers[active_core]->RunLoop(tight_loop); +            } +            keep_running |= core_timing.CanCurrentContextRun(); +        } +    } while (keep_running); + +    if (GDBStub::IsServerEnabled()) { +        GDBStub::SetCpuStepFlag(false); +    } +} + +} // namespace Core diff --git a/src/core/cpu_manager.h b/src/core/cpu_manager.h new file mode 100644 index 000000000..feb619e1b --- /dev/null +++ b/src/core/cpu_manager.h @@ -0,0 +1,50 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <array> +#include <memory> + +namespace Core { + +class CoreManager; +class System; + +class CpuManager { +public: +    explicit CpuManager(System& system); +    CpuManager(const CpuManager&) = delete; +    CpuManager(CpuManager&&) = delete; + +    ~CpuManager(); + +    CpuManager& operator=(const CpuManager&) = delete; +    CpuManager& operator=(CpuManager&&) = delete; + +    void Initialize(); +    void Shutdown(); + +    CoreManager& GetCoreManager(std::size_t index); +    const CoreManager& GetCoreManager(std::size_t index) const; + +    CoreManager& GetCurrentCoreManager(); +    const CoreManager& GetCurrentCoreManager() const; + +    std::size_t GetActiveCoreIndex() const { +        return active_core; +    } + +    void RunLoop(bool tight_loop); + +private: +    static constexpr std::size_t NUM_CPU_CORES = 4; + +    std::array<std::unique_ptr<CoreManager>, NUM_CPU_CORES> core_managers; +    std::size_t active_core{}; ///< Active core, only used in single thread mode + +    System& system; +}; + +} // namespace Core diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp index 37cb28848..67e95999d 100644 --- a/src/core/gdbstub/gdbstub.cpp +++ b/src/core/gdbstub/gdbstub.cpp @@ -35,7 +35,7 @@  #include "common/swap.h"  #include "core/arm/arm_interface.h"  #include "core/core.h" -#include "core/core_cpu.h" +#include "core/core_manager.h"  #include "core/gdbstub/gdbstub.h"  #include "core/hle/kernel/process.h"  #include "core/hle/kernel/scheduler.h" diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp index db189c8e3..2ea3dcb61 100644 --- a/src/core/hle/kernel/address_arbiter.cpp +++ b/src/core/hle/kernel/address_arbiter.cpp @@ -8,7 +8,6 @@  #include "common/assert.h"  #include "common/common_types.h"  #include "core/core.h" -#include "core/core_cpu.h"  #include "core/hle/kernel/address_arbiter.h"  #include "core/hle/kernel/errors.h"  #include "core/hle/kernel/scheduler.h" diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 1d0783bd3..0cf3c8f70 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -3,13 +3,15 @@  // Refer to the license.txt file included.  #include <atomic> +#include <functional>  #include <memory>  #include <mutex>  #include <utility>  #include "common/assert.h"  #include "common/logging/log.h" - +#include "core/arm/arm_interface.h" +#include "core/arm/exclusive_monitor.h"  #include "core/core.h"  #include "core/core_timing.h"  #include "core/core_timing_util.h" @@ -17,6 +19,7 @@  #include "core/hle/kernel/errors.h"  #include "core/hle/kernel/handle_table.h"  #include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/physical_core.h"  #include "core/hle/kernel/process.h"  #include "core/hle/kernel/resource_limit.h"  #include "core/hle/kernel/scheduler.h" @@ -98,6 +101,7 @@ struct KernelCore::Impl {      void Initialize(KernelCore& kernel) {          Shutdown(); +        InitializePhysicalCores(kernel);          InitializeSystemResourceLimit(kernel);          InitializeThreads();          InitializePreemption(); @@ -121,6 +125,21 @@ struct KernelCore::Impl {          global_scheduler.Shutdown();          named_ports.clear(); + +        for (auto& core : cores) { +            core.Shutdown(); +        } +        cores.clear(); + +        exclusive_monitor.reset(nullptr); +    } + +    void InitializePhysicalCores(KernelCore& kernel) { +        exclusive_monitor = +            Core::MakeExclusiveMonitor(system.Memory(), global_scheduler.CpuCoresCount()); +        for (std::size_t i = 0; i < global_scheduler.CpuCoresCount(); i++) { +            cores.emplace_back(system, kernel, i, *exclusive_monitor); +        }      }      // Creates the default system resource limit @@ -186,6 +205,9 @@ struct KernelCore::Impl {      /// the ConnectToPort SVC.      NamedPortTable named_ports; +    std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor; +    std::vector<Kernel::PhysicalCore> cores; +      // System context      Core::System& system;  }; @@ -240,6 +262,34 @@ const Kernel::GlobalScheduler& KernelCore::GlobalScheduler() const {      return impl->global_scheduler;  } +Kernel::PhysicalCore& KernelCore::PhysicalCore(std::size_t id) { +    return impl->cores[id]; +} + +const Kernel::PhysicalCore& KernelCore::PhysicalCore(std::size_t id) const { +    return impl->cores[id]; +} + +Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() { +    return *impl->exclusive_monitor; +} + +const Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() const { +    return *impl->exclusive_monitor; +} + +void KernelCore::InvalidateAllInstructionCaches() { +    for (std::size_t i = 0; i < impl->global_scheduler.CpuCoresCount(); i++) { +        PhysicalCore(i).ArmInterface().ClearInstructionCache(); +    } +} + +void KernelCore::PrepareReschedule(std::size_t id) { +    if (id < impl->global_scheduler.CpuCoresCount()) { +        impl->cores[id].Stop(); +    } +} +  void KernelCore::AddNamedPort(std::string name, std::shared_ptr<ClientPort> 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 3bf0068ed..fccffaf3a 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -11,8 +11,9 @@  #include "core/hle/kernel/object.h"  namespace Core { +class ExclusiveMonitor;  class System; -} +} // namespace Core  namespace Core::Timing {  class CoreTiming; @@ -25,6 +26,7 @@ class AddressArbiter;  class ClientPort;  class GlobalScheduler;  class HandleTable; +class PhysicalCore;  class Process;  class ResourceLimit;  class Thread; @@ -84,6 +86,21 @@ public:      /// Gets the sole instance of the global scheduler      const Kernel::GlobalScheduler& GlobalScheduler() const; +    /// Gets the an instance of the respective physical CPU core. +    Kernel::PhysicalCore& PhysicalCore(std::size_t id); + +    /// Gets the an instance of the respective physical CPU core. +    const Kernel::PhysicalCore& PhysicalCore(std::size_t id) const; + +    /// Stops execution of 'id' core, in order to reschedule a new thread. +    void PrepareReschedule(std::size_t id); + +    Core::ExclusiveMonitor& GetExclusiveMonitor(); + +    const Core::ExclusiveMonitor& GetExclusiveMonitor() const; + +    void InvalidateAllInstructionCaches(); +      /// Adds a port to the named port table      void AddNamedPort(std::string name, std::shared_ptr<ClientPort> port); diff --git a/src/core/hle/kernel/physical_core.cpp b/src/core/hle/kernel/physical_core.cpp new file mode 100644 index 000000000..896a1a87a --- /dev/null +++ b/src/core/hle/kernel/physical_core.cpp @@ -0,0 +1,52 @@ +// Copyright 2020 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/logging/log.h" +#include "core/arm/arm_interface.h" +#ifdef ARCHITECTURE_x86_64 +#include "core/arm/dynarmic/arm_dynarmic.h" +#endif +#include "core/arm/exclusive_monitor.h" +#include "core/arm/unicorn/arm_unicorn.h" +#include "core/core.h" +#include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/physical_core.h" +#include "core/hle/kernel/scheduler.h" +#include "core/hle/kernel/thread.h" + +namespace Kernel { + +PhysicalCore::PhysicalCore(Core::System& system, KernelCore& kernel, std::size_t id, +                           Core::ExclusiveMonitor& exclusive_monitor) +    : core_index{id}, kernel{kernel} { +#ifdef ARCHITECTURE_x86_64 +    arm_interface = std::make_shared<Core::ARM_Dynarmic>(system, exclusive_monitor, core_index); +#else +    arm_interface = std::make_shared<Core::ARM_Unicorn>(system); +    LOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available"); +#endif + +    scheduler = std::make_shared<Kernel::Scheduler>(system, *arm_interface, core_index); +} + +PhysicalCore::~PhysicalCore() = default; + +void PhysicalCore::Run() { +    arm_interface->Run(); +    arm_interface->ClearExclusiveState(); +} + +void PhysicalCore::Step() { +    arm_interface->Step(); +} + +void PhysicalCore::Stop() { +    arm_interface->PrepareReschedule(); +} + +void PhysicalCore::Shutdown() { +    scheduler->Shutdown(); +} + +} // namespace Kernel diff --git a/src/core/hle/kernel/physical_core.h b/src/core/hle/kernel/physical_core.h new file mode 100644 index 000000000..fbef0801f --- /dev/null +++ b/src/core/hle/kernel/physical_core.h @@ -0,0 +1,74 @@ +// Copyright 2020 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <cstddef> +#include <memory> + +namespace Kernel { +class Scheduler; +} // namespace Kernel + +namespace Core { +class ARM_Interface; +class ExclusiveMonitor; +class System; +} // namespace Core + +namespace Kernel { + +class PhysicalCore { +public: +    PhysicalCore(Core::System& system, KernelCore& kernel, std::size_t id, +                 Core::ExclusiveMonitor& exclusive_monitor); + +    ~PhysicalCore(); + +    /// Execute current jit state +    void Run(); +    /// Execute a single instruction in current jit. +    void Step(); +    /// Stop JIT execution/exit +    void Stop(); + +    // Shutdown this physical core. +    void Shutdown(); + +    Core::ARM_Interface& ArmInterface() { +        return *arm_interface; +    } + +    const Core::ARM_Interface& ArmInterface() const { +        return *arm_interface; +    } + +    bool IsMainCore() const { +        return core_index == 0; +    } + +    bool IsSystemCore() const { +        return core_index == 3; +    } + +    std::size_t CoreIndex() const { +        return core_index; +    } + +    Kernel::Scheduler& Scheduler() { +        return *scheduler; +    } + +    const Kernel::Scheduler& Scheduler() const { +        return *scheduler; +    } + +private: +    std::size_t core_index; +    KernelCore& kernel; +    std::shared_ptr<Core::ARM_Interface> arm_interface; +    std::shared_ptr<Kernel::Scheduler> scheduler; +}; + +} // namespace Kernel diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp index d36fcd7d9..eb196a690 100644 --- a/src/core/hle/kernel/scheduler.cpp +++ b/src/core/hle/kernel/scheduler.cpp @@ -14,7 +14,6 @@  #include "common/logging/log.h"  #include "core/arm/arm_interface.h"  #include "core/core.h" -#include "core/core_cpu.h"  #include "core/core_timing.h"  #include "core/hle/kernel/kernel.h"  #include "core/hle/kernel/process.h" diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index dbcdb0b88..1d99bf7a2 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -15,7 +15,7 @@  #include "common/string_util.h"  #include "core/arm/exclusive_monitor.h"  #include "core/core.h" -#include "core/core_cpu.h" +#include "core/core_manager.h"  #include "core/core_timing.h"  #include "core/core_timing_util.h"  #include "core/hle/kernel/address_arbiter.h" diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index e84e5ce0d..e965b5b04 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -13,7 +13,6 @@  #include "common/thread_queue_list.h"  #include "core/arm/arm_interface.h"  #include "core/core.h" -#include "core/core_cpu.h"  #include "core/core_timing.h"  #include "core/core_timing_util.h"  #include "core/hle/kernel/errors.h" @@ -356,7 +355,7 @@ void Thread::SetActivity(ThreadActivity value) {          // Set status if not waiting          if (status == ThreadStatus::Ready || status == ThreadStatus::Running) {              SetStatus(ThreadStatus::Paused); -            Core::System::GetInstance().CpuCore(processor_id).PrepareReschedule(); +            kernel.PrepareReschedule(processor_id);          }      } else if (status == ThreadStatus::Paused) {          // Ready to reschedule diff --git a/src/core/hle/kernel/wait_object.cpp b/src/core/hle/kernel/wait_object.cpp index 745f2c4e8..a0c806e8f 100644 --- a/src/core/hle/kernel/wait_object.cpp +++ b/src/core/hle/kernel/wait_object.cpp @@ -7,7 +7,6 @@  #include "common/common_types.h"  #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" @@ -96,7 +95,7 @@ void WaitObject::WakeupWaitingThread(std::shared_ptr<Thread> thread) {      }      if (resume) {          thread->ResumeFromWait(); -        Core::System::GetInstance().PrepareReschedule(thread->GetProcessorID()); +        kernel.PrepareReschedule(thread->GetProcessorID());      }  } | 
