core: Add a configuration setting for use_multi_core.

This commit is contained in:
bunnei 2018-05-03 00:34:54 -04:00
parent cba69fdcd4
commit 9bf2a428f9
10 changed files with 56 additions and 17 deletions

View file

@ -126,6 +126,21 @@ PerfStats::Results System::GetAndResetPerfStats() {
return perf_stats.GetAndResetStats(CoreTiming::GetGlobalTimeUs()); return perf_stats.GetAndResetStats(CoreTiming::GetGlobalTimeUs());
} }
const std::shared_ptr<Kernel::Scheduler>& System::Scheduler(size_t core_index) {
if (!Settings::values.use_multi_core) {
// Always use Core 0 scheduler when multicore is disabled
return cpu_cores[0]->Scheduler();
}
ASSERT(core_index < NUM_CPU_CORES);
return cpu_cores[core_index]->Scheduler();
}
ARM_Interface& System::ArmInterface(size_t core_index) {
ASSERT(core_index < NUM_CPU_CORES);
return cpu_cores[core_index]->ArmInterface();
}
System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) { System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) {
NGLOG_DEBUG(HW_Memory, "initialized OK"); NGLOG_DEBUG(HW_Memory, "initialized OK");
@ -154,10 +169,13 @@ System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) {
// 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
// CPU core 0 is run on the main thread // CPU core 0 is run on the main thread
thread_to_cpu[std::this_thread::get_id()] = cpu_cores[0]; thread_to_cpu[std::this_thread::get_id()] = cpu_cores[0];
if (Settings::values.use_multi_core) {
for (size_t index = 0; index < cpu_core_threads.size(); ++index) { for (size_t index = 0; index < cpu_core_threads.size(); ++index) {
cpu_core_threads[index] = std::make_unique<std::thread>(RunCpuCore, cpu_cores[index + 1]); cpu_core_threads[index] =
std::make_unique<std::thread>(RunCpuCore, cpu_cores[index + 1]);
thread_to_cpu[cpu_core_threads[index]->get_id()] = cpu_cores[index + 1]; thread_to_cpu[cpu_core_threads[index]->get_id()] = cpu_cores[index + 1];
} }
}
NGLOG_DEBUG(Core, "Initialized OK"); NGLOG_DEBUG(Core, "Initialized OK");
@ -190,10 +208,12 @@ void System::Shutdown() {
// Close all CPU/threading state // Close all CPU/threading state
cpu_barrier->NotifyEnd(); cpu_barrier->NotifyEnd();
if (Settings::values.use_multi_core) {
for (auto& thread : cpu_core_threads) { for (auto& thread : cpu_core_threads) {
thread->join(); thread->join();
thread.reset(); thread.reset();
} }
}
thread_to_cpu.clear(); thread_to_cpu.clear();
for (auto& cpu_core : cpu_cores) { for (auto& cpu_core : cpu_cores) {
cpu_core.reset(); cpu_core.reset();

View file

@ -112,10 +112,7 @@ public:
return CurrentCpuCore().ArmInterface(); return CurrentCpuCore().ArmInterface();
} }
ARM_Interface& ArmInterface(size_t core_index) { ARM_Interface& ArmInterface(size_t core_index);
ASSERT(core_index < NUM_CPU_CORES);
return cpu_cores[core_index]->ArmInterface();
}
Tegra::GPU& GPU() { Tegra::GPU& GPU() {
return *gpu_core; return *gpu_core;
@ -125,10 +122,7 @@ public:
return *CurrentCpuCore().Scheduler(); return *CurrentCpuCore().Scheduler();
} }
const std::shared_ptr<Kernel::Scheduler>& Scheduler(size_t core_index) { const std::shared_ptr<Kernel::Scheduler>& Scheduler(size_t core_index);
ASSERT(core_index < NUM_CPU_CORES);
return cpu_cores[core_index]->Scheduler();
}
Kernel::SharedPtr<Kernel::Process>& CurrentProcess() { Kernel::SharedPtr<Kernel::Process>& CurrentProcess() {
return current_process; return current_process;

View file

@ -26,9 +26,12 @@ void CpuBarrier::NotifyEnd() {
} }
bool CpuBarrier::Rendezvous() { bool CpuBarrier::Rendezvous() {
if (end) { if (!Settings::values.use_multi_core) {
return false; // Meaningless when running in single-core mode
} else { return true;
}
if (!end) {
std::unique_lock<std::mutex> lock(mutex); std::unique_lock<std::mutex> lock(mutex);
--cores_waiting; --cores_waiting;
@ -41,6 +44,8 @@ bool CpuBarrier::Rendezvous() {
condition.wait(lock); condition.wait(lock);
return true; return true;
} }
return false;
} }
Cpu::Cpu(std::shared_ptr<CpuBarrier> cpu_barrier, size_t core_index) Cpu::Cpu(std::shared_ptr<CpuBarrier> cpu_barrier, size_t core_index)

View file

@ -121,6 +121,7 @@ struct Values {
// Core // Core
bool use_cpu_jit; bool use_cpu_jit;
bool use_multi_core;
// Data Storage // Data Storage
bool use_virtual_sd; bool use_virtual_sd;

View file

@ -155,6 +155,8 @@ TelemetrySession::TelemetrySession() {
// Log user configuration information // Log user configuration information
AddField(Telemetry::FieldType::UserConfig, "Core_UseCpuJit", Settings::values.use_cpu_jit); AddField(Telemetry::FieldType::UserConfig, "Core_UseCpuJit", Settings::values.use_cpu_jit);
AddField(Telemetry::FieldType::UserConfig, "Core_UseMultiCore",
Settings::values.use_multi_core);
AddField(Telemetry::FieldType::UserConfig, "Renderer_ResolutionFactor", AddField(Telemetry::FieldType::UserConfig, "Renderer_ResolutionFactor",
Settings::values.resolution_factor); Settings::values.resolution_factor);
AddField(Telemetry::FieldType::UserConfig, "Renderer_ToggleFramelimit", AddField(Telemetry::FieldType::UserConfig, "Renderer_ToggleFramelimit",

View file

@ -78,6 +78,7 @@ void Config::ReadValues() {
qt_config->beginGroup("Core"); qt_config->beginGroup("Core");
Settings::values.use_cpu_jit = qt_config->value("use_cpu_jit", true).toBool(); Settings::values.use_cpu_jit = qt_config->value("use_cpu_jit", true).toBool();
Settings::values.use_multi_core = qt_config->value("use_multi_core", false).toBool();
qt_config->endGroup(); qt_config->endGroup();
qt_config->beginGroup("Renderer"); qt_config->beginGroup("Renderer");
@ -177,6 +178,7 @@ void Config::SaveValues() {
qt_config->beginGroup("Core"); qt_config->beginGroup("Core");
qt_config->setValue("use_cpu_jit", Settings::values.use_cpu_jit); qt_config->setValue("use_cpu_jit", Settings::values.use_cpu_jit);
qt_config->setValue("use_multi_core", Settings::values.use_multi_core);
qt_config->endGroup(); qt_config->endGroup();
qt_config->beginGroup("Renderer"); qt_config->beginGroup("Renderer");

View file

@ -20,6 +20,7 @@ ConfigureGeneral::ConfigureGeneral(QWidget* parent)
this->setConfiguration(); this->setConfiguration();
ui->use_cpu_jit->setEnabled(!Core::System::GetInstance().IsPoweredOn()); ui->use_cpu_jit->setEnabled(!Core::System::GetInstance().IsPoweredOn());
ui->use_multi_core->setEnabled(!Core::System::GetInstance().IsPoweredOn());
ui->use_docked_mode->setEnabled(!Core::System::GetInstance().IsPoweredOn()); ui->use_docked_mode->setEnabled(!Core::System::GetInstance().IsPoweredOn());
} }
@ -30,6 +31,7 @@ void ConfigureGeneral::setConfiguration() {
ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing); ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing);
ui->theme_combobox->setCurrentIndex(ui->theme_combobox->findData(UISettings::values.theme)); ui->theme_combobox->setCurrentIndex(ui->theme_combobox->findData(UISettings::values.theme));
ui->use_cpu_jit->setChecked(Settings::values.use_cpu_jit); ui->use_cpu_jit->setChecked(Settings::values.use_cpu_jit);
ui->use_multi_core->setChecked(Settings::values.use_multi_core);
ui->use_docked_mode->setChecked(Settings::values.use_docked_mode); ui->use_docked_mode->setChecked(Settings::values.use_docked_mode);
} }
@ -40,6 +42,7 @@ void ConfigureGeneral::applyConfiguration() {
ui->theme_combobox->itemData(ui->theme_combobox->currentIndex()).toString(); ui->theme_combobox->itemData(ui->theme_combobox->currentIndex()).toString();
Settings::values.use_cpu_jit = ui->use_cpu_jit->isChecked(); Settings::values.use_cpu_jit = ui->use_cpu_jit->isChecked();
Settings::values.use_multi_core = ui->use_multi_core->isChecked();
Settings::values.use_docked_mode = ui->use_docked_mode->isChecked(); Settings::values.use_docked_mode = ui->use_docked_mode->isChecked();
Settings::Apply(); Settings::Apply();
} }

View file

@ -58,6 +58,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QCheckBox" name="use_multi_core">
<property name="text">
<string>Enable multi-core</string>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
</layout> </layout>

View file

@ -91,6 +91,7 @@ void Config::ReadValues() {
// Core // Core
Settings::values.use_cpu_jit = sdl2_config->GetBoolean("Core", "use_cpu_jit", true); Settings::values.use_cpu_jit = sdl2_config->GetBoolean("Core", "use_cpu_jit", true);
Settings::values.use_multi_core = sdl2_config->GetBoolean("Core", "use_multi_core", false);
// Renderer // Renderer
Settings::values.resolution_factor = Settings::values.resolution_factor =

View file

@ -80,6 +80,10 @@ touch_device=
# 0: Interpreter (slow), 1 (default): JIT (fast) # 0: Interpreter (slow), 1 (default): JIT (fast)
use_cpu_jit = use_cpu_jit =
# Whether to use multi-core for CPU emulation
# 0 (default): Disabled, 1: Enabled
use_multi_core=
[Renderer] [Renderer]
# Whether to use software or hardware rendering. # Whether to use software or hardware rendering.
# 0: Software, 1 (default): Hardware # 0: Software, 1 (default): Hardware