committed by
GitHub
24 changed files with 613 additions and 189 deletions
-
2src/core/CMakeLists.txt
-
2src/core/arm/unicorn/arm_unicorn.cpp
-
117src/core/core.cpp
-
56src/core/core.h
-
119src/core/core_cpu.cpp
-
78src/core/core_cpu.h
-
24src/core/gdbstub/gdbstub.cpp
-
15src/core/hle/kernel/scheduler.cpp
-
3src/core/hle/kernel/scheduler.h
-
171src/core/hle/kernel/svc.cpp
-
24src/core/hle/kernel/svc_wrap.h
-
102src/core/hle/kernel/thread.cpp
-
10src/core/hle/kernel/thread.h
-
23src/core/hle/kernel/vm_manager.cpp
-
9src/core/memory.cpp
-
1src/core/settings.h
-
2src/core/telemetry_session.cpp
-
2src/yuzu/configuration/config.cpp
-
3src/yuzu/configuration/configure_general.cpp
-
7src/yuzu/configuration/configure_general.ui
-
4src/yuzu/debugger/registers.cpp
-
23src/yuzu/debugger/wait_tree.cpp
-
1src/yuzu_cmd/config.cpp
-
4src/yuzu_cmd/default_ini.h
@ -0,0 +1,119 @@ |
|||
// 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/unicorn/arm_unicorn.h"
|
|||
#include "core/core_cpu.h"
|
|||
#include "core/core_timing.h"
|
|||
#include "core/hle/kernel/kernel.h"
|
|||
#include "core/hle/kernel/scheduler.h"
|
|||
#include "core/hle/kernel/thread.h"
|
|||
#include "core/settings.h"
|
|||
|
|||
namespace Core { |
|||
|
|||
void CpuBarrier::NotifyEnd() { |
|||
std::unique_lock<std::mutex> 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<std::mutex> 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(std::shared_ptr<CpuBarrier> cpu_barrier, size_t core_index) |
|||
: cpu_barrier{std::move(cpu_barrier)}, core_index{core_index} { |
|||
|
|||
if (Settings::values.use_cpu_jit) { |
|||
#ifdef ARCHITECTURE_x86_64
|
|||
arm_interface = std::make_shared<ARM_Dynarmic>(); |
|||
#else
|
|||
cpu_core = std::make_shared<ARM_Unicorn>(); |
|||
NGLOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available"); |
|||
#endif
|
|||
} else { |
|||
arm_interface = std::make_shared<ARM_Unicorn>(); |
|||
} |
|||
|
|||
scheduler = std::make_shared<Kernel::Scheduler>(arm_interface.get()); |
|||
} |
|||
|
|||
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; |
|||
} |
|||
|
|||
// 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) { |
|||
NGLOG_TRACE(Core, "Core-{} idling", core_index); |
|||
|
|||
if (IsMainCore()) { |
|||
CoreTiming::Idle(); |
|||
CoreTiming::Advance(); |
|||
} |
|||
|
|||
PrepareReschedule(); |
|||
} else { |
|||
if (IsMainCore()) { |
|||
CoreTiming::Advance(); |
|||
} |
|||
|
|||
if (tight_loop) { |
|||
arm_interface->Run(); |
|||
} else { |
|||
arm_interface->Step(); |
|||
} |
|||
} |
|||
|
|||
Reschedule(); |
|||
} |
|||
|
|||
void Cpu::SingleStep() { |
|||
return RunLoop(false); |
|||
} |
|||
|
|||
void Cpu::PrepareReschedule() { |
|||
arm_interface->PrepareReschedule(); |
|||
reschedule_pending = true; |
|||
} |
|||
|
|||
void Cpu::Reschedule() { |
|||
if (!reschedule_pending) { |
|||
return; |
|||
} |
|||
|
|||
reschedule_pending = false; |
|||
scheduler->Reschedule(); |
|||
} |
|||
|
|||
} // namespace Core
|
|||
@ -0,0 +1,78 @@ |
|||
// 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 <memory> |
|||
#include <mutex> |
|||
#include <string> |
|||
#include "common/common_types.h" |
|||
|
|||
class ARM_Interface; |
|||
|
|||
namespace Kernel { |
|||
class Scheduler; |
|||
} |
|||
|
|||
namespace Core { |
|||
|
|||
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(std::shared_ptr<CpuBarrier> cpu_barrier, size_t core_index); |
|||
|
|||
void RunLoop(bool tight_loop = true); |
|||
|
|||
void SingleStep(); |
|||
|
|||
void PrepareReschedule(); |
|||
|
|||
ARM_Interface& ArmInterface() { |
|||
return *arm_interface; |
|||
} |
|||
|
|||
const ARM_Interface& ArmInterface() const { |
|||
return *arm_interface; |
|||
} |
|||
|
|||
const std::shared_ptr<Kernel::Scheduler>& Scheduler() const { |
|||
return scheduler; |
|||
} |
|||
|
|||
bool IsMainCore() const { |
|||
return core_index == 0; |
|||
} |
|||
|
|||
private: |
|||
void Reschedule(); |
|||
|
|||
std::shared_ptr<ARM_Interface> arm_interface; |
|||
std::shared_ptr<CpuBarrier> cpu_barrier; |
|||
std::shared_ptr<Kernel::Scheduler> scheduler; |
|||
|
|||
bool reschedule_pending{}; |
|||
size_t core_index; |
|||
}; |
|||
|
|||
} // namespace Core |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue