| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- // 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/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() = default;
- CpuCoreManager::~CpuCoreManager() = default;
- void CpuCoreManager::Initialize(System& system) {
- barrier = std::make_unique<CpuBarrier>();
- exclusive_monitor = Cpu::MakeExclusiveMonitor(cores.size());
- for (std::size_t index = 0; index < cores.size(); ++index) {
- cores[index] = std::make_unique<Cpu>(system, *exclusive_monitor, *barrier, index);
- }
- // 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.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;
- }
- }
- }
- for (active_core = 0; active_core < NUM_CPU_CORES; ++active_core) {
- cores[active_core]->RunLoop(tight_loop);
- if (Settings::values.use_multi_core) {
- // Cores 1-3 are run on other threads in this mode
- break;
- }
- }
- if (GDBStub::IsServerEnabled()) {
- GDBStub::SetCpuStepFlag(false);
- }
- }
- void CpuCoreManager::InvalidateAllInstructionCaches() {
- for (auto& cpu : cores) {
- cpu->ArmInterface().ClearInstructionCache();
- }
- }
- } // namespace Core
|