early-access version 2817

This commit is contained in:
pineappleEA 2022-07-06 03:26:28 +02:00
parent f3d9b67d42
commit cc9e0b702e
8 changed files with 89 additions and 69 deletions

View file

@ -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

View file

@ -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();

View file

@ -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();
while (true) {
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); Common::Fiber::YieldTo(current_thread->GetHostContext(), *core_data[core].host_context);
UNREACHABLE();
// 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();
} }
{
// Set the current thread on entry
auto* current_thread = system.Kernel().CurrentScheduler()->GetIdleThread(); auto* current_thread = system.Kernel().CurrentScheduler()->GetIdleThread();
Kernel::SetCurrentThread(system.Kernel(), current_thread); 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()); Common::Fiber::YieldTo(data.host_context, *current_thread->GetHostContext());
}
} }
} // namespace Core } // namespace Core

View file

@ -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{};

View file

@ -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);

View file

@ -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;
} }

View file

@ -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,25 +1085,14 @@ 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 {

View file

@ -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;