2020-01-26 19:07:22 +01:00
|
|
|
// Copyright 2018 yuzu emulator team
|
|
|
|
// Licensed under GPLv2 or any later version
|
|
|
|
// Refer to the license.txt file included.
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <array>
|
2020-03-10 16:50:33 +01:00
|
|
|
#include <atomic>
|
2020-02-25 03:04:12 +01:00
|
|
|
#include <functional>
|
2020-01-26 19:07:22 +01:00
|
|
|
#include <memory>
|
2020-02-25 03:04:12 +01:00
|
|
|
#include <thread>
|
2020-02-12 00:56:24 +01:00
|
|
|
#include "core/hardware_properties.h"
|
2020-01-26 19:07:22 +01:00
|
|
|
|
2020-02-25 03:04:12 +01:00
|
|
|
namespace Common {
|
|
|
|
class Event;
|
|
|
|
class Fiber;
|
|
|
|
} // namespace Common
|
|
|
|
|
2020-03-16 02:34:22 +01:00
|
|
|
namespace Core::Frontend {
|
|
|
|
class EmuWindow;
|
|
|
|
} // namespace Core::Frontend
|
|
|
|
|
2020-01-26 19:07:22 +01:00
|
|
|
namespace Core {
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
2020-03-09 03:39:41 +01:00
|
|
|
/// Sets if emulation is multicore or single core, must be set before Initialize
|
|
|
|
void SetMulticore(bool is_multicore) {
|
|
|
|
this->is_multicore = is_multicore;
|
|
|
|
}
|
2020-03-16 02:34:22 +01:00
|
|
|
|
|
|
|
/// Sets if emulation is using an asynchronous GPU.
|
|
|
|
void SetAsyncGpu(bool is_async_gpu) {
|
|
|
|
this->is_async_gpu = is_async_gpu;
|
|
|
|
}
|
|
|
|
|
2020-01-26 19:07:22 +01:00
|
|
|
void Initialize();
|
|
|
|
void Shutdown();
|
|
|
|
|
2020-02-25 03:04:12 +01:00
|
|
|
void Pause(bool paused);
|
|
|
|
|
|
|
|
std::function<void(void*)> GetGuestThreadStartFunc();
|
|
|
|
std::function<void(void*)> GetIdleThreadStartFunc();
|
|
|
|
std::function<void(void*)> GetSuspendThreadStartFunc();
|
|
|
|
void* GetStartFuncParamater();
|
2020-01-26 19:07:22 +01:00
|
|
|
|
2020-03-28 20:23:28 +01:00
|
|
|
void PreemptSingleCore(bool from_running_enviroment = true);
|
2020-03-10 18:13:39 +01:00
|
|
|
|
2020-03-09 03:39:41 +01:00
|
|
|
std::size_t CurrentCore() const {
|
2020-03-10 16:50:33 +01:00
|
|
|
return current_core.load();
|
2020-03-09 03:39:41 +01:00
|
|
|
}
|
|
|
|
|
2020-03-16 02:34:22 +01:00
|
|
|
void SetRenderWindow(Core::Frontend::EmuWindow& render_window);
|
|
|
|
|
2020-02-25 03:04:12 +01:00
|
|
|
private:
|
|
|
|
static void GuestThreadFunction(void* cpu_manager);
|
2020-02-28 00:12:41 +01:00
|
|
|
static void GuestRewindFunction(void* cpu_manager);
|
2020-02-25 03:04:12 +01:00
|
|
|
static void IdleThreadFunction(void* cpu_manager);
|
|
|
|
static void SuspendThreadFunction(void* cpu_manager);
|
2020-01-26 19:07:22 +01:00
|
|
|
|
2020-03-09 03:39:41 +01:00
|
|
|
void MultiCoreRunGuestThread();
|
|
|
|
void MultiCoreRunGuestLoop();
|
|
|
|
void MultiCoreRunIdleThread();
|
|
|
|
void MultiCoreRunSuspendThread();
|
|
|
|
void MultiCorePause(bool paused);
|
|
|
|
|
|
|
|
void SingleCoreRunGuestThread();
|
|
|
|
void SingleCoreRunGuestLoop();
|
|
|
|
void SingleCoreRunIdleThread();
|
|
|
|
void SingleCoreRunSuspendThread();
|
|
|
|
void SingleCorePause(bool paused);
|
2020-01-26 19:07:22 +01:00
|
|
|
|
2020-02-25 03:04:12 +01:00
|
|
|
static void ThreadStart(CpuManager& cpu_manager, std::size_t core);
|
2020-01-26 19:07:22 +01:00
|
|
|
|
2020-02-25 03:04:12 +01:00
|
|
|
void RunThread(std::size_t core);
|
|
|
|
|
|
|
|
struct CoreData {
|
|
|
|
std::shared_ptr<Common::Fiber> host_context;
|
|
|
|
std::unique_ptr<Common::Event> enter_barrier;
|
|
|
|
std::unique_ptr<Common::Event> exit_barrier;
|
|
|
|
std::atomic<bool> is_running;
|
|
|
|
std::atomic<bool> is_paused;
|
|
|
|
std::atomic<bool> initialized;
|
|
|
|
std::unique_ptr<std::thread> host_thread;
|
|
|
|
};
|
|
|
|
|
|
|
|
std::atomic<bool> running_mode{};
|
|
|
|
std::atomic<bool> paused_state{};
|
|
|
|
|
|
|
|
std::array<CoreData, Core::Hardware::NUM_CPU_CORES> core_data{};
|
2020-01-26 19:07:22 +01:00
|
|
|
|
2020-03-16 02:34:22 +01:00
|
|
|
bool is_async_gpu{};
|
2020-03-09 03:39:41 +01:00
|
|
|
bool is_multicore{};
|
2020-03-10 16:50:33 +01:00
|
|
|
std::atomic<std::size_t> current_core{};
|
2020-03-09 03:39:41 +01:00
|
|
|
std::size_t preemption_count{};
|
2020-03-19 18:09:32 +01:00
|
|
|
std::size_t idle_count{};
|
2020-03-09 03:39:41 +01:00
|
|
|
static constexpr std::size_t max_cycle_runs = 5;
|
2020-03-16 02:34:22 +01:00
|
|
|
Core::Frontend::EmuWindow* render_window;
|
2020-03-09 03:39:41 +01:00
|
|
|
|
2020-01-26 19:07:22 +01:00
|
|
|
System& system;
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace Core
|