early-access version 2817
This commit is contained in:
parent
f3d9b67d42
commit
cc9e0b702e
8 changed files with 89 additions and 69 deletions
|
@ -1,7 +1,7 @@
|
||||||
yuzu emulator early access
|
yuzu emulator early access
|
||||||
=============
|
=============
|
||||||
|
|
||||||
This is the source code for early-access 2816.
|
This is the source code for early-access 2817.
|
||||||
|
|
||||||
## Legal Notice
|
## Legal Notice
|
||||||
|
|
||||||
|
|
|
@ -138,6 +138,7 @@ struct System::Impl {
|
||||||
|
|
||||||
kernel.Suspend(false);
|
kernel.Suspend(false);
|
||||||
core_timing.SyncPause(false);
|
core_timing.SyncPause(false);
|
||||||
|
cpu_manager.Pause(false);
|
||||||
is_paused = false;
|
is_paused = false;
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
|
@ -149,6 +150,7 @@ struct System::Impl {
|
||||||
|
|
||||||
core_timing.SyncPause(true);
|
core_timing.SyncPause(true);
|
||||||
kernel.Suspend(true);
|
kernel.Suspend(true);
|
||||||
|
cpu_manager.Pause(true);
|
||||||
is_paused = true;
|
is_paused = true;
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
|
@ -158,6 +160,7 @@ struct System::Impl {
|
||||||
std::unique_lock<std::mutex> lk(suspend_guard);
|
std::unique_lock<std::mutex> lk(suspend_guard);
|
||||||
kernel.Suspend(true);
|
kernel.Suspend(true);
|
||||||
core_timing.SyncPause(true);
|
core_timing.SyncPause(true);
|
||||||
|
cpu_manager.Pause(true);
|
||||||
return lk;
|
return lk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,6 +168,7 @@ struct System::Impl {
|
||||||
if (!is_paused) {
|
if (!is_paused) {
|
||||||
core_timing.SyncPause(false);
|
core_timing.SyncPause(false);
|
||||||
kernel.Suspend(false);
|
kernel.Suspend(false);
|
||||||
|
cpu_manager.Pause(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,8 +334,6 @@ struct System::Impl {
|
||||||
gpu_core->NotifyShutdown();
|
gpu_core->NotifyShutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
kernel.ShutdownCores();
|
|
||||||
cpu_manager.Shutdown();
|
|
||||||
debugger.reset();
|
debugger.reset();
|
||||||
services.reset();
|
services.reset();
|
||||||
service_manager.reset();
|
service_manager.reset();
|
||||||
|
|
|
@ -25,8 +25,10 @@ void CpuManager::ThreadStart(std::stop_token stop_token, CpuManager& cpu_manager
|
||||||
}
|
}
|
||||||
|
|
||||||
void CpuManager::Initialize() {
|
void CpuManager::Initialize() {
|
||||||
|
running_mode = true;
|
||||||
num_cores = is_multicore ? Core::Hardware::NUM_CPU_CORES : 1;
|
num_cores = is_multicore ? Core::Hardware::NUM_CPU_CORES : 1;
|
||||||
gpu_barrier = std::make_unique<Common::Barrier>(num_cores + 1);
|
gpu_barrier = std::make_unique<Common::Barrier>(num_cores + 1);
|
||||||
|
pause_barrier = std::make_unique<Common::Barrier>(num_cores + 1);
|
||||||
|
|
||||||
for (std::size_t core = 0; core < num_cores; core++) {
|
for (std::size_t core = 0; core < num_cores; core++) {
|
||||||
core_data[core].host_thread = std::jthread(ThreadStart, std::ref(*this), core);
|
core_data[core].host_thread = std::jthread(ThreadStart, std::ref(*this), core);
|
||||||
|
@ -34,11 +36,8 @@ void CpuManager::Initialize() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CpuManager::Shutdown() {
|
void CpuManager::Shutdown() {
|
||||||
for (std::size_t core = 0; core < num_cores; core++) {
|
running_mode = false;
|
||||||
if (core_data[core].host_thread.joinable()) {
|
Pause(false);
|
||||||
core_data[core].host_thread.join();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CpuManager::GuestThreadFunction() {
|
void CpuManager::GuestThreadFunction() {
|
||||||
|
@ -65,10 +64,6 @@ void CpuManager::IdleThreadFunction() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CpuManager::ShutdownThreadFunction() {
|
|
||||||
ShutdownThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
/// MultiCore ///
|
/// MultiCore ///
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -181,13 +176,41 @@ void CpuManager::PreemptSingleCore(bool from_running_enviroment) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CpuManager::ShutdownThread() {
|
void CpuManager::SuspendThread() {
|
||||||
auto& kernel = system.Kernel();
|
auto& kernel = system.Kernel();
|
||||||
auto core = is_multicore ? kernel.CurrentPhysicalCoreIndex() : 0;
|
kernel.CurrentScheduler()->OnThreadStart();
|
||||||
auto* current_thread = kernel.GetCurrentEmuThread();
|
|
||||||
|
|
||||||
Common::Fiber::YieldTo(current_thread->GetHostContext(), *core_data[core].host_context);
|
while (true) {
|
||||||
UNREACHABLE();
|
auto core = is_multicore ? kernel.CurrentPhysicalCoreIndex() : 0;
|
||||||
|
auto& scheduler = *kernel.CurrentScheduler();
|
||||||
|
Kernel::KThread* current_thread = scheduler.GetSchedulerCurrentThread();
|
||||||
|
Common::Fiber::YieldTo(current_thread->GetHostContext(), *core_data[core].host_context);
|
||||||
|
|
||||||
|
// This shouldn't be here. This is here because the scheduler needs the current
|
||||||
|
// thread to have dispatch disabled before explicitly rescheduling. Ideally in the
|
||||||
|
// future this will be called by RequestScheduleOnInterrupt and explicitly disabling
|
||||||
|
// dispatch outside the scheduler will not be necessary.
|
||||||
|
current_thread->DisableDispatch();
|
||||||
|
|
||||||
|
scheduler.RescheduleCurrentCore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CpuManager::Pause(bool paused) {
|
||||||
|
std::scoped_lock lk{pause_lock};
|
||||||
|
|
||||||
|
if (pause_state == paused) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the new state
|
||||||
|
pause_state.store(paused);
|
||||||
|
|
||||||
|
// Wake up any waiting threads
|
||||||
|
pause_state.notify_all();
|
||||||
|
|
||||||
|
// Wait for all threads to successfully change state before returning
|
||||||
|
pause_barrier->Sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CpuManager::RunThread(std::size_t core) {
|
void CpuManager::RunThread(std::size_t core) {
|
||||||
|
@ -218,9 +241,27 @@ void CpuManager::RunThread(std::size_t core) {
|
||||||
system.GPU().ObtainContext();
|
system.GPU().ObtainContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* current_thread = system.Kernel().CurrentScheduler()->GetIdleThread();
|
{
|
||||||
Kernel::SetCurrentThread(system.Kernel(), current_thread);
|
// Set the current thread on entry
|
||||||
Common::Fiber::YieldTo(data.host_context, *current_thread->GetHostContext());
|
auto* current_thread = system.Kernel().CurrentScheduler()->GetIdleThread();
|
||||||
|
Kernel::SetCurrentThread(system.Kernel(), current_thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (running_mode) {
|
||||||
|
if (pause_state.load(std::memory_order_relaxed)) {
|
||||||
|
// Wait for caller to acknowledge pausing
|
||||||
|
pause_barrier->Sync();
|
||||||
|
|
||||||
|
// Wait until unpaused
|
||||||
|
pause_state.wait(true, std::memory_order_relaxed);
|
||||||
|
|
||||||
|
// Wait for caller to acknowledge unpausing
|
||||||
|
pause_barrier->Sync();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto current_thread = system.Kernel().CurrentScheduler()->GetSchedulerCurrentThread();
|
||||||
|
Common::Fiber::YieldTo(data.host_context, *current_thread->GetHostContext());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Core
|
} // namespace Core
|
||||||
|
|
|
@ -50,14 +50,16 @@ public:
|
||||||
void Initialize();
|
void Initialize();
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
|
void Pause(bool paused);
|
||||||
|
|
||||||
std::function<void()> GetGuestThreadStartFunc() {
|
std::function<void()> GetGuestThreadStartFunc() {
|
||||||
return [this] { GuestThreadFunction(); };
|
return [this] { GuestThreadFunction(); };
|
||||||
}
|
}
|
||||||
std::function<void()> GetIdleThreadStartFunc() {
|
std::function<void()> GetIdleThreadStartFunc() {
|
||||||
return [this] { IdleThreadFunction(); };
|
return [this] { IdleThreadFunction(); };
|
||||||
}
|
}
|
||||||
std::function<void()> GetShutdownThreadStartFunc() {
|
std::function<void()> GetSuspendThreadStartFunc() {
|
||||||
return [this] { ShutdownThreadFunction(); };
|
return [this] { SuspendThread(); };
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreemptSingleCore(bool from_running_enviroment = true);
|
void PreemptSingleCore(bool from_running_enviroment = true);
|
||||||
|
@ -70,7 +72,6 @@ private:
|
||||||
void GuestThreadFunction();
|
void GuestThreadFunction();
|
||||||
void GuestRewindFunction();
|
void GuestRewindFunction();
|
||||||
void IdleThreadFunction();
|
void IdleThreadFunction();
|
||||||
void ShutdownThreadFunction();
|
|
||||||
|
|
||||||
void MultiCoreRunGuestThread();
|
void MultiCoreRunGuestThread();
|
||||||
void MultiCoreRunGuestLoop();
|
void MultiCoreRunGuestLoop();
|
||||||
|
@ -82,7 +83,7 @@ private:
|
||||||
|
|
||||||
static void ThreadStart(std::stop_token stop_token, CpuManager& cpu_manager, std::size_t core);
|
static void ThreadStart(std::stop_token stop_token, CpuManager& cpu_manager, std::size_t core);
|
||||||
|
|
||||||
void ShutdownThread();
|
void SuspendThread();
|
||||||
void RunThread(std::size_t core);
|
void RunThread(std::size_t core);
|
||||||
|
|
||||||
struct CoreData {
|
struct CoreData {
|
||||||
|
@ -90,7 +91,12 @@ private:
|
||||||
std::jthread host_thread;
|
std::jthread host_thread;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::atomic<bool> running_mode{};
|
||||||
|
std::atomic<bool> pause_state{};
|
||||||
|
std::unique_ptr<Common::Barrier> pause_barrier{};
|
||||||
std::unique_ptr<Common::Barrier> gpu_barrier{};
|
std::unique_ptr<Common::Barrier> gpu_barrier{};
|
||||||
|
std::mutex pause_lock{};
|
||||||
|
|
||||||
std::array<CoreData, Core::Hardware::NUM_CPU_CORES> core_data{};
|
std::array<CoreData, Core::Hardware::NUM_CPU_CORES> core_data{};
|
||||||
|
|
||||||
bool is_async_gpu{};
|
bool is_async_gpu{};
|
||||||
|
|
|
@ -269,7 +269,7 @@ Result KThread::InitializeIdleThread(Core::System& system, KThread* thread, s32
|
||||||
Result KThread::InitializeHighPriorityThread(Core::System& system, KThread* thread,
|
Result KThread::InitializeHighPriorityThread(Core::System& system, KThread* thread,
|
||||||
KThreadFunction func, uintptr_t arg, s32 virt_core) {
|
KThreadFunction func, uintptr_t arg, s32 virt_core) {
|
||||||
return InitializeThread(thread, func, arg, {}, {}, virt_core, nullptr, ThreadType::HighPriority,
|
return InitializeThread(thread, func, arg, {}, {}, virt_core, nullptr, ThreadType::HighPriority,
|
||||||
system.GetCpuManager().GetShutdownThreadStartFunc());
|
system.GetCpuManager().GetSuspendThreadStartFunc());
|
||||||
}
|
}
|
||||||
|
|
||||||
Result KThread::InitializeUserThread(Core::System& system, KThread* thread, KThreadFunction func,
|
Result KThread::InitializeUserThread(Core::System& system, KThread* thread, KThreadFunction func,
|
||||||
|
@ -739,19 +739,6 @@ void KThread::Continue() {
|
||||||
KScheduler::OnThreadStateChanged(kernel, this, old_state);
|
KScheduler::OnThreadStateChanged(kernel, this, old_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void KThread::WaitUntilSuspended() {
|
|
||||||
// Make sure we have a suspend requested.
|
|
||||||
ASSERT(IsSuspendRequested());
|
|
||||||
|
|
||||||
// Loop until the thread is not executing on any core.
|
|
||||||
for (std::size_t i = 0; i < static_cast<std::size_t>(Core::Hardware::NUM_CPU_CORES); ++i) {
|
|
||||||
KThread* core_thread{};
|
|
||||||
do {
|
|
||||||
core_thread = kernel.Scheduler(i).GetSchedulerCurrentThread();
|
|
||||||
} while (core_thread == this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Result KThread::SetActivity(Svc::ThreadActivity activity) {
|
Result KThread::SetActivity(Svc::ThreadActivity activity) {
|
||||||
// Lock ourselves.
|
// Lock ourselves.
|
||||||
KScopedLightLock lk(activity_pause_lock);
|
KScopedLightLock lk(activity_pause_lock);
|
||||||
|
|
|
@ -208,8 +208,6 @@ public:
|
||||||
|
|
||||||
void Continue();
|
void Continue();
|
||||||
|
|
||||||
void WaitUntilSuspended();
|
|
||||||
|
|
||||||
constexpr void SetSyncedIndex(s32 index) {
|
constexpr void SetSyncedIndex(s32 index) {
|
||||||
synced_index = index;
|
synced_index = index;
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,7 +76,7 @@ struct KernelCore::Impl {
|
||||||
InitializeMemoryLayout();
|
InitializeMemoryLayout();
|
||||||
Init::InitializeKPageBufferSlabHeap(system);
|
Init::InitializeKPageBufferSlabHeap(system);
|
||||||
InitializeSchedulers();
|
InitializeSchedulers();
|
||||||
InitializeShutdownThreads();
|
InitializeSuspendThreads();
|
||||||
InitializePreemption(kernel);
|
InitializePreemption(kernel);
|
||||||
|
|
||||||
RegisterHostThread();
|
RegisterHostThread();
|
||||||
|
@ -143,9 +143,9 @@ struct KernelCore::Impl {
|
||||||
CleanupObject(system_resource_limit);
|
CleanupObject(system_resource_limit);
|
||||||
|
|
||||||
for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) {
|
for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) {
|
||||||
if (shutdown_threads[core_id]) {
|
if (suspend_threads[core_id]) {
|
||||||
shutdown_threads[core_id]->Close();
|
suspend_threads[core_id]->Close();
|
||||||
shutdown_threads[core_id] = nullptr;
|
suspend_threads[core_id] = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
schedulers[core_id]->Finalize();
|
schedulers[core_id]->Finalize();
|
||||||
|
@ -247,13 +247,13 @@ struct KernelCore::Impl {
|
||||||
system.CoreTiming().ScheduleEvent(time_interval, preemption_event);
|
system.CoreTiming().ScheduleEvent(time_interval, preemption_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitializeShutdownThreads() {
|
void InitializeSuspendThreads() {
|
||||||
for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) {
|
for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) {
|
||||||
shutdown_threads[core_id] = KThread::Create(system.Kernel());
|
suspend_threads[core_id] = KThread::Create(system.Kernel());
|
||||||
ASSERT(KThread::InitializeHighPriorityThread(system, shutdown_threads[core_id], {}, {},
|
ASSERT(KThread::InitializeHighPriorityThread(system, suspend_threads[core_id], {}, {},
|
||||||
core_id)
|
core_id)
|
||||||
.IsSuccess());
|
.IsSuccess());
|
||||||
shutdown_threads[core_id]->SetName(fmt::format("SuspendThread:{}", core_id));
|
suspend_threads[core_id]->SetName(fmt::format("SuspendThread:{}", core_id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -775,7 +775,7 @@ struct KernelCore::Impl {
|
||||||
std::weak_ptr<ServiceThread> default_service_thread;
|
std::weak_ptr<ServiceThread> default_service_thread;
|
||||||
Common::ThreadWorker service_threads_manager;
|
Common::ThreadWorker service_threads_manager;
|
||||||
|
|
||||||
std::array<KThread*, Core::Hardware::NUM_CPU_CORES> shutdown_threads;
|
std::array<KThread*, Core::Hardware::NUM_CPU_CORES> suspend_threads;
|
||||||
std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES> interrupts{};
|
std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES> interrupts{};
|
||||||
std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{};
|
std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{};
|
||||||
|
|
||||||
|
@ -1085,27 +1085,16 @@ const Kernel::KSharedMemory& KernelCore::GetHidBusSharedMem() const {
|
||||||
|
|
||||||
void KernelCore::Suspend(bool suspended) {
|
void KernelCore::Suspend(bool suspended) {
|
||||||
const bool should_suspend{exception_exited || suspended};
|
const bool should_suspend{exception_exited || suspended};
|
||||||
const auto activity = should_suspend ? ProcessActivity::Paused : ProcessActivity::Runnable;
|
const auto state{should_suspend ? ThreadState::Runnable : ThreadState::Waiting};
|
||||||
|
{
|
||||||
for (auto* process : GetProcessList()) {
|
KScopedSchedulerLock lk{*this};
|
||||||
process->SetActivity(activity);
|
for (auto* thread : impl->suspend_threads) {
|
||||||
|
thread->SetState(state);
|
||||||
if (should_suspend) {
|
thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Suspended);
|
||||||
// Wait for execution to stop
|
|
||||||
for (auto* thread : process->GetThreadList()) {
|
|
||||||
thread->WaitUntilSuspended();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void KernelCore::ShutdownCores() {
|
|
||||||
for (auto* thread : impl->shutdown_threads) {
|
|
||||||
void(thread->Run());
|
|
||||||
}
|
|
||||||
InterruptAllPhysicalCores();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool KernelCore::IsMulticore() const {
|
bool KernelCore::IsMulticore() const {
|
||||||
return impl->is_multicore;
|
return impl->is_multicore;
|
||||||
}
|
}
|
||||||
|
|
|
@ -280,9 +280,6 @@ public:
|
||||||
/// Exceptional exit all processes.
|
/// Exceptional exit all processes.
|
||||||
void ExceptionalExit();
|
void ExceptionalExit();
|
||||||
|
|
||||||
/// Notify emulated CPU cores to shut down.
|
|
||||||
void ShutdownCores();
|
|
||||||
|
|
||||||
bool IsMulticore() const;
|
bool IsMulticore() const;
|
||||||
|
|
||||||
bool IsShuttingDown() const;
|
bool IsShuttingDown() const;
|
||||||
|
|
Loading…
Reference in a new issue