From e31425df3877636c098ec7426ebd2067920715cb Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Mon, 24 Feb 2020 22:04:12 -0400 Subject: General: Recover Prometheus project from harddrive failure This commit: Implements CPU Interrupts, Replaces Cycle Timing for Host Timing, Reworks the Kernel's Scheduler, Introduce Idle State and Suspended State, Recreates the bootmanager, Initializes Multicore system. --- src/yuzu/debugger/wait_tree.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/yuzu/debugger') diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp index c1ea25fb8..765908c5a 100644 --- a/src/yuzu/debugger/wait_tree.cpp +++ b/src/yuzu/debugger/wait_tree.cpp @@ -59,8 +59,10 @@ std::vector> WaitTreeItem::MakeThreadItemList() std::size_t row = 0; auto add_threads = [&](const std::vector>& threads) { for (std::size_t i = 0; i < threads.size(); ++i) { - item_list.push_back(std::make_unique(*threads[i])); - item_list.back()->row = row; + if (!threads[i]->IsHLEThread()) { + item_list.push_back(std::make_unique(*threads[i])); + item_list.back()->row = row; + } ++row; } }; -- cgit v1.2.3 From 38c6c497f6895cff2f073802e77834aa3347f954 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sat, 7 Mar 2020 13:07:04 -0400 Subject: Yuzu/Debuggers: Correct Wait Tree for Paused threads. --- src/yuzu/debugger/wait_tree.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'src/yuzu/debugger') diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp index 765908c5a..ab7b18abe 100644 --- a/src/yuzu/debugger/wait_tree.cpp +++ b/src/yuzu/debugger/wait_tree.cpp @@ -208,7 +208,11 @@ QString WaitTreeThread::GetText() const { status = tr("running"); break; case Kernel::ThreadStatus::Ready: - status = tr("ready"); + if (!thread.IsPaused()) { + status = tr("ready"); + } else { + status = tr("paused"); + } break; case Kernel::ThreadStatus::Paused: status = tr("paused"); @@ -256,7 +260,11 @@ QColor WaitTreeThread::GetColor() const { case Kernel::ThreadStatus::Running: return QColor(Qt::GlobalColor::darkGreen); case Kernel::ThreadStatus::Ready: - return QColor(Qt::GlobalColor::darkBlue); + if (!thread.IsPaused()) { + return QColor(Qt::GlobalColor::darkBlue); + } else { + return QColor(Qt::GlobalColor::lightGray); + } case Kernel::ThreadStatus::Paused: return QColor(Qt::GlobalColor::lightGray); case Kernel::ThreadStatus::WaitHLEEvent: -- cgit v1.2.3 From 7020d498c5aef7c1180bfc57031cdd7fbfecdf0f Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Thu, 12 Mar 2020 16:48:43 -0400 Subject: General: Fix microprofile on dynarmic/svc, fix wait tree showing which threads were running. --- src/core/arm/dynarmic/arm_dynarmic_32.cpp | 4 ---- src/core/arm/dynarmic/arm_dynarmic_64.cpp | 5 +---- src/core/core.cpp | 15 +++++++++++++++ src/core/core.h | 6 ++++++ src/core/cpu_manager.cpp | 4 ++++ src/core/hle/kernel/kernel.cpp | 15 +++++++++++++++ src/core/hle/kernel/kernel.h | 4 ++++ src/core/hle/kernel/scheduler.cpp | 7 +++++++ src/core/hle/kernel/svc.cpp | 10 +++++++--- src/core/hle/kernel/thread.h | 18 ++++++++++++++++++ src/yuzu/debugger/wait_tree.cpp | 12 ++++++++++-- 11 files changed, 87 insertions(+), 13 deletions(-) (limited to 'src/yuzu/debugger') diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index 30bf62ac1..618f02f30 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp @@ -7,7 +7,6 @@ #include #include #include -#include "common/microprofile.h" #include "core/arm/cpu_interrupt_handler.h" #include "core/arm/dynarmic/arm_dynarmic_32.h" #include "core/arm/dynarmic/arm_dynarmic_64.h" @@ -97,10 +96,7 @@ std::shared_ptr ARM_Dynarmic_32::MakeJit(Common::PageTable& return std::make_unique(config); } -MICROPROFILE_DEFINE(ARM_Jit_Dynarmic_32, "ARM JIT", "Dynarmic", MP_RGB(255, 64, 64)); - void ARM_Dynarmic_32::Run() { - MICROPROFILE_SCOPE(ARM_Jit_Dynarmic_32); jit->Run(); } diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index a22c22bf0..84b872f0b 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp @@ -7,7 +7,6 @@ #include #include #include "common/logging/log.h" -#include "common/microprofile.h" #include "common/page_table.h" #include "core/arm/cpu_interrupt_handler.h" #include "core/arm/dynarmic/arm_dynarmic_64.h" @@ -181,11 +180,9 @@ std::shared_ptr ARM_Dynarmic_64::MakeJit(Common::PageTable& return std::make_shared(config); } -MICROPROFILE_DEFINE(ARM_Jit_Dynarmic_64, "ARM JIT", "Dynarmic", MP_RGB(255, 64, 64)); -void ARM_Dynarmic_64::Run() { - MICROPROFILE_SCOPE(ARM_Jit_Dynarmic_64); +void ARM_Dynarmic_64::Run() { jit->Run(); } diff --git a/src/core/core.cpp b/src/core/core.cpp index fd1bdcaf0..032da7aa5 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -8,6 +8,7 @@ #include "common/file_util.h" #include "common/logging/log.h" +#include "common/microprofile.h" #include "common/string_util.h" #include "core/arm/exclusive_monitor.h" #include "core/core.h" @@ -50,6 +51,8 @@ #include "video_core/renderer_base.h" #include "video_core/video_core.h" +MICROPROFILE_DEFINE(ARM_Jit_Dynarmic, "ARM JIT", "Dynarmic", MP_RGB(255, 64, 64)); + namespace Core { namespace { @@ -391,6 +394,8 @@ struct System::Impl { std::unique_ptr perf_stats; Core::FrameLimiter frame_limiter; + + std::array dynarmic_ticks{}; }; System::System() : impl{std::make_unique(*this)} {} @@ -736,4 +741,14 @@ void System::RegisterHostThread() { impl->kernel.RegisterHostThread(); } +void System::EnterDynarmicProfile() { + std::size_t core = impl->kernel.GetCurrentHostThreadID(); + impl->dynarmic_ticks[core] = MicroProfileEnter(MICROPROFILE_TOKEN(ARM_Jit_Dynarmic)); +} + +void System::ExitDynarmicProfile() { + std::size_t core = impl->kernel.GetCurrentHostThreadID(); + MicroProfileLeave(MICROPROFILE_TOKEN(ARM_Jit_Dynarmic), impl->dynarmic_ticks[core]); +} + } // namespace Core diff --git a/src/core/core.h b/src/core/core.h index 9a0dd1075..87df79d57 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -377,6 +377,12 @@ public: /// Register a host thread as an auxiliary thread. void RegisterHostThread(); + /// Enter Dynarmic Microprofile + void EnterDynarmicProfile(); + + /// Exit Dynarmic Microprofile + void ExitDynarmicProfile(); + private: System(); diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp index 95842aad1..9e2e6d49f 100644 --- a/src/core/cpu_manager.cpp +++ b/src/core/cpu_manager.cpp @@ -118,9 +118,11 @@ void CpuManager::MultiCoreRunGuestLoop() { host_context.reset(); while (true) { auto& physical_core = kernel.CurrentPhysicalCore(); + system.EnterDynarmicProfile(); while (!physical_core.IsInterrupted()) { physical_core.Run(); } + system.ExitDynarmicProfile(); physical_core.ClearExclusive(); auto& scheduler = physical_core.Scheduler(); scheduler.TryDoContextSwitch(); @@ -216,6 +218,7 @@ void CpuManager::SingleCoreRunGuestLoop() { host_context.reset(); while (true) { auto& physical_core = kernel.CurrentPhysicalCore(); + system.EnterDynarmicProfile(); while (!physical_core.IsInterrupted()) { physical_core.Run(); preemption_count++; @@ -224,6 +227,7 @@ void CpuManager::SingleCoreRunGuestLoop() { } } physical_core.ClearExclusive(); + system.ExitDynarmicProfile(); PreemptSingleCore(); auto& scheduler = kernel.Scheduler(current_core); scheduler.TryDoContextSwitch(); diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 24da4367e..d2f5f9bf2 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -13,6 +13,7 @@ #include "common/assert.h" #include "common/logging/log.h" +#include "common/microprofile.h" #include "common/thread.h" #include "core/arm/arm_interface.h" #include "core/arm/exclusive_monitor.h" @@ -41,6 +42,8 @@ #include "core/hle/result.h" #include "core/memory.h" +MICROPROFILE_DEFINE(Kernel_SVC, "Kernel", "SVC", MP_RGB(70, 200, 70)); + namespace Kernel { /** @@ -408,6 +411,8 @@ struct KernelCore::Impl { bool is_multicore{}; std::thread::id single_core_thread_id{}; + std::array svc_ticks{}; + // System context Core::System& system; }; @@ -666,4 +671,14 @@ void KernelCore::ExceptionalExit() { Suspend(true); } +void KernelCore::EnterSVCProfile() { + std::size_t core = impl->GetCurrentHostThreadID(); + impl->svc_ticks[core] = MicroProfileEnter(MICROPROFILE_TOKEN(Kernel_SVC)); +} + +void KernelCore::ExitSVCProfile() { + std::size_t core = impl->GetCurrentHostThreadID(); + MicroProfileLeave(MICROPROFILE_TOKEN(Kernel_SVC), impl->svc_ticks[core]); +} + } // namespace Kernel diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 50eeb50ec..1eb6ede73 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -214,6 +214,10 @@ public: bool IsMulticore() const; + void EnterSVCProfile(); + + void ExitSVCProfile(); + private: friend class Object; friend class Process; diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp index 25fc8a3e8..2ad380b17 100644 --- a/src/core/hle/kernel/scheduler.cpp +++ b/src/core/hle/kernel/scheduler.cpp @@ -354,7 +354,9 @@ void GlobalScheduler::EnableInterruptAndSchedule(u32 cores_pending_reschedule, } if (must_context_switch) { auto& core_scheduler = kernel.CurrentScheduler(); + kernel.ExitSVCProfile(); core_scheduler.TryDoContextSwitch(); + kernel.EnterSVCProfile(); } } @@ -628,6 +630,7 @@ void Scheduler::Reload() { // Cancel any outstanding wakeup events for this thread thread->SetIsRunning(true); + thread->SetWasRunning(false); thread->last_running_ticks = system.CoreTiming().GetCPUTicks(); auto* const thread_owner_process = thread->GetOwnerProcess(); @@ -660,6 +663,7 @@ void Scheduler::SwitchContextStep2() { // Cancel any outstanding wakeup events for this thread new_thread->SetIsRunning(true); new_thread->last_running_ticks = system.CoreTiming().GetCPUTicks(); + new_thread->SetWasRunning(false); auto* const thread_owner_process = current_thread->GetOwnerProcess(); if (previous_process != thread_owner_process && thread_owner_process != nullptr) { @@ -698,6 +702,9 @@ void Scheduler::SwitchContext() { // Save context for previous thread if (previous_thread) { + if (new_thread != nullptr && new_thread->IsSuspendThread()) { + previous_thread->SetWasRunning(true); + } previous_thread->SetContinuousOnSVC(false); previous_thread->last_running_ticks = system.CoreTiming().GetCPUTicks(); if (!previous_thread->IsHLEThread()) { diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index d3d4e7bf9..9b9f9402e 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -2454,10 +2454,10 @@ static const FunctionDef* GetSVCInfo64(u32 func_num) { return &SVC_Table_64[func_num]; } -MICROPROFILE_DEFINE(Kernel_SVC, "Kernel", "SVC", MP_RGB(70, 200, 70)); - void Call(Core::System& system, u32 immediate) { - MICROPROFILE_SCOPE(Kernel_SVC); + system.ExitDynarmicProfile(); + auto& kernel = system.Kernel(); + kernel.EnterSVCProfile(); auto* thread = system.CurrentScheduler().GetCurrentThread(); thread->SetContinuousOnSVC(true); @@ -2474,10 +2474,14 @@ void Call(Core::System& system, u32 immediate) { LOG_CRITICAL(Kernel_SVC, "Unknown SVC function 0x{:X}", immediate); } + kernel.ExitSVCProfile(); + if (!thread->IsContinuousOnSVC()) { auto* host_context = thread->GetHostContext().get(); host_context->Rewind(); } + + system.EnterDynarmicProfile(); } } // namespace Kernel::Svc diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 168828ab0..f42d7bd13 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -350,6 +350,22 @@ public: return (type & THREADTYPE_HLE) != 0; } + bool IsSuspendThread() const { + return (type & THREADTYPE_SUSPEND) != 0; + } + + bool IsIdleThread() const { + return (type & THREADTYPE_IDLE) != 0; + } + + bool WasRunning() const { + return was_running; + } + + void SetWasRunning(bool value) { + was_running = value; + } + std::shared_ptr GetHostContext() const; ThreadStatus GetStatus() const { @@ -684,6 +700,8 @@ private: bool will_be_terminated = false; + bool was_running = false; + std::string name; }; diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp index ab7b18abe..fa091f457 100644 --- a/src/yuzu/debugger/wait_tree.cpp +++ b/src/yuzu/debugger/wait_tree.cpp @@ -209,7 +209,11 @@ QString WaitTreeThread::GetText() const { break; case Kernel::ThreadStatus::Ready: if (!thread.IsPaused()) { - status = tr("ready"); + if (thread.WasRunning()) { + status = tr("running"); + } else { + status = tr("ready"); + } } else { status = tr("paused"); } @@ -261,7 +265,11 @@ QColor WaitTreeThread::GetColor() const { return QColor(Qt::GlobalColor::darkGreen); case Kernel::ThreadStatus::Ready: if (!thread.IsPaused()) { - return QColor(Qt::GlobalColor::darkBlue); + if (thread.WasRunning()) { + return QColor(Qt::GlobalColor::darkGreen); + } else { + return QColor(Qt::GlobalColor::darkBlue); + } } else { return QColor(Qt::GlobalColor::lightGray); } -- cgit v1.2.3 From 7b18174eef70feb434f9319a57a6cfbe362730e3 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Fri, 20 Mar 2020 14:05:47 -0400 Subject: ARM/WaitTree: Better track the CallStack for each thread. --- src/core/arm/arm_interface.cpp | 57 +++++++++++++++++++++++++++++++++++++++++ src/core/arm/arm_interface.h | 3 +++ src/yuzu/debugger/wait_tree.cpp | 25 ++++++++++-------- 3 files changed, 74 insertions(+), 11 deletions(-) (limited to 'src/yuzu/debugger') diff --git a/src/core/arm/arm_interface.cpp b/src/core/arm/arm_interface.cpp index d079a1bc8..d2295ed90 100644 --- a/src/core/arm/arm_interface.cpp +++ b/src/core/arm/arm_interface.cpp @@ -139,6 +139,63 @@ std::optional GetSymbolName(const Symbols& symbols, VAddr func_addr constexpr u64 SEGMENT_BASE = 0x7100000000ull; +std::vector ARM_Interface::GetBacktraceFromContext( + System& system, const ThreadContext64& ctx) { + std::vector out; + auto& memory = system.Memory(); + + auto fp = ctx.cpu_registers[29]; + auto lr = ctx.cpu_registers[30]; + while (true) { + out.push_back({"", 0, lr, 0}); + if (!fp) { + break; + } + lr = memory.Read64(fp + 8) - 4; + fp = memory.Read64(fp); + } + + std::map modules; + auto& loader{system.GetAppLoader()}; + if (loader.ReadNSOModules(modules) != Loader::ResultStatus::Success) { + return {}; + } + + std::map symbols; + for (const auto& module : modules) { + symbols.insert_or_assign(module.second, GetSymbols(module.first, memory)); + } + + for (auto& entry : out) { + VAddr base = 0; + for (auto iter = modules.rbegin(); iter != modules.rend(); ++iter) { + const auto& module{*iter}; + if (entry.original_address >= module.first) { + entry.module = module.second; + base = module.first; + break; + } + } + + entry.offset = entry.original_address - base; + entry.address = SEGMENT_BASE + entry.offset; + + if (entry.module.empty()) + entry.module = "unknown"; + + const auto symbol_set = symbols.find(entry.module); + if (symbol_set != symbols.end()) { + const auto symbol = GetSymbolName(symbol_set->second, entry.offset); + if (symbol.has_value()) { + // TODO(DarkLordZach): Add demangling of symbol names. + entry.name = *symbol; + } + } + } + + return out; +} + std::vector ARM_Interface::GetBacktrace() const { std::vector out; auto& memory = system.Memory(); diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h index 87a1c29cc..e701ddf21 100644 --- a/src/core/arm/arm_interface.h +++ b/src/core/arm/arm_interface.h @@ -164,6 +164,9 @@ public: std::string name; }; + static std::vector GetBacktraceFromContext(System& system, + const ThreadContext64& ctx); + std::vector GetBacktrace() const; /// fp (= r29) points to the last frame record. diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp index fa091f457..d2dbb259c 100644 --- a/src/yuzu/debugger/wait_tree.cpp +++ b/src/yuzu/debugger/wait_tree.cpp @@ -2,10 +2,13 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include + #include "yuzu/debugger/wait_tree.h" #include "yuzu/util/util.h" #include "common/assert.h" +#include "core/arm/arm_interface.h" #include "core/core.h" #include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/mutex.h" @@ -116,20 +119,20 @@ QString WaitTreeCallstack::GetText() const { std::vector> WaitTreeCallstack::GetChildren() const { std::vector> list; - constexpr std::size_t BaseRegister = 29; - auto& memory = Core::System::GetInstance().Memory(); - u64 base_pointer = thread.GetContext64().cpu_registers[BaseRegister]; + if (thread.IsHLEThread()) { + return list; + } - while (base_pointer != 0) { - const u64 lr = memory.Read64(base_pointer + sizeof(u64)); - if (lr == 0) { - break; - } + if (thread.GetOwnerProcess() == nullptr || !thread.GetOwnerProcess()->Is64BitProcess()) { + return list; + } - list.push_back(std::make_unique( - tr("0x%1").arg(lr - sizeof(u32), 16, 16, QLatin1Char{'0'}))); + auto backtrace = Core::ARM_Interface::GetBacktraceFromContext(Core::System::GetInstance(), thread.GetContext64()); - base_pointer = memory.Read64(base_pointer); + for (auto& entry : backtrace) { + std::string s = fmt::format("{:20}{:016X} {:016X} {:016X} {}", entry.module, entry.address, + entry.original_address, entry.offset, entry.name); + list.push_back(std::make_unique(QString::fromStdString(s))); } return list; -- cgit v1.2.3 From 48fa3b7a0f2054a836b0a8061e6b082c246b5ae0 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Wed, 1 Apr 2020 17:28:49 -0400 Subject: General: Cleanup legacy code. --- src/core/CMakeLists.txt | 2 - src/core/arm/dynarmic/arm_dynarmic_32.cpp | 1 - src/core/arm/dynarmic/arm_dynarmic_64.cpp | 1 - src/core/core_manager.cpp | 51 ------ src/core/core_manager.h | 63 -------- src/core/gdbstub/gdbstub.cpp | 1 - src/core/hle/kernel/client_port.cpp | 2 +- src/core/hle/kernel/kernel.cpp | 81 +--------- src/core/hle/kernel/kernel.h | 3 - src/core/hle/kernel/svc.cpp | 3 +- src/core/hle/kernel/synchronization_object.cpp | 64 -------- src/core/hle/kernel/synchronization_object.h | 15 -- src/core/hle/kernel/thread.cpp | 34 ---- src/core/hle/kernel/thread.h | 56 +------ src/core/hle/service/sm/sm.cpp | 2 +- src/core/host_timing.cpp | 206 ------------------------- src/core/host_timing.h | 160 ------------------- src/tests/core/core_timing.cpp | 1 + src/yuzu/debugger/wait_tree.cpp | 2 +- 19 files changed, 8 insertions(+), 740 deletions(-) delete mode 100644 src/core/core_manager.cpp delete mode 100644 src/core/core_manager.h delete mode 100644 src/core/host_timing.cpp delete mode 100644 src/core/host_timing.h (limited to 'src/yuzu/debugger') diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 552094ddb..653b7620b 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -17,8 +17,6 @@ add_library(core STATIC constants.h core.cpp core.h - core_manager.cpp - core_manager.h core_timing.cpp core_timing.h core_timing_util.cpp diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index c4aeedef9..c8adf2866 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp @@ -12,7 +12,6 @@ #include "core/arm/dynarmic/arm_dynarmic_64.h" #include "core/arm/dynarmic/arm_dynarmic_cp15.h" #include "core/core.h" -#include "core/core_manager.h" #include "core/core_timing.h" #include "core/hle/kernel/svc.h" #include "core/memory.h" diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index a518733b6..14b394368 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp @@ -11,7 +11,6 @@ #include "core/arm/cpu_interrupt_handler.h" #include "core/arm/dynarmic/arm_dynarmic_64.h" #include "core/core.h" -#include "core/core_manager.h" #include "core/core_timing.h" #include "core/core_timing_util.h" #include "core/gdbstub/gdbstub.h" diff --git a/src/core/core_manager.cpp b/src/core/core_manager.cpp deleted file mode 100644 index 82d7acb40..000000000 --- a/src/core/core_manager.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2018 yuzu emulator team -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include -#include - -#include "common/logging/log.h" -#include "core/arm/exclusive_monitor.h" -#include "core/arm/unicorn/arm_unicorn.h" -#include "core/core.h" -#include "core/core_manager.h" -#include "core/core_timing.h" -#include "core/hle/kernel/kernel.h" -#include "core/hle/kernel/physical_core.h" -#include "core/hle/kernel/scheduler.h" -#include "core/hle/kernel/thread.h" -#include "core/hle/lock.h" -#include "core/settings.h" - -namespace Core { - -CoreManager::CoreManager(System& system, std::size_t core_index) - : global_scheduler{system.GlobalScheduler()}, physical_core{system.Kernel().PhysicalCore( - core_index)}, - core_timing{system.CoreTiming()}, core_index{core_index} {} - -CoreManager::~CoreManager() = default; - -void CoreManager::RunLoop(bool tight_loop) { - /// Deprecated -} - -void CoreManager::SingleStep() { - return RunLoop(false); -} - -void CoreManager::PrepareReschedule() { - //physical_core.Stop(); -} - -void CoreManager::Reschedule() { - // Lock the global kernel mutex when we manipulate the HLE state - std::lock_guard lock(HLE::g_hle_lock); - - // global_scheduler.SelectThread(core_index); - - physical_core.Scheduler().TryDoContextSwitch(); -} - -} // namespace Core diff --git a/src/core/core_manager.h b/src/core/core_manager.h deleted file mode 100644 index d525de00a..000000000 --- a/src/core/core_manager.h +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2018 yuzu emulator team -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include -#include -#include -#include "common/common_types.h" - -namespace Kernel { -class GlobalScheduler; -class PhysicalCore; -} // namespace Kernel - -namespace Core { -class System; -} - -namespace Core::Timing { -class CoreTiming; -} - -namespace Core::Memory { -class Memory; -} - -namespace Core { - -constexpr unsigned NUM_CPU_CORES{4}; - -class CoreManager { -public: - CoreManager(System& system, std::size_t core_index); - ~CoreManager(); - - void RunLoop(bool tight_loop = true); - - void SingleStep(); - - void PrepareReschedule(); - - bool IsMainCore() const { - return core_index == 0; - } - - std::size_t CoreIndex() const { - return core_index; - } - -private: - void Reschedule(); - - Kernel::GlobalScheduler& global_scheduler; - Kernel::PhysicalCore& physical_core; - Timing::CoreTiming& core_timing; - - std::atomic reschedule_pending = false; - std::size_t core_index; -}; - -} // namespace Core diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp index 70c0f8b80..79f22a403 100644 --- a/src/core/gdbstub/gdbstub.cpp +++ b/src/core/gdbstub/gdbstub.cpp @@ -35,7 +35,6 @@ #include "common/swap.h" #include "core/arm/arm_interface.h" #include "core/core.h" -#include "core/core_manager.h" #include "core/gdbstub/gdbstub.h" #include "core/hle/kernel/memory/page_table.h" #include "core/hle/kernel/process.h" diff --git a/src/core/hle/kernel/client_port.cpp b/src/core/hle/kernel/client_port.cpp index 5498fd313..8aff2227a 100644 --- a/src/core/hle/kernel/client_port.cpp +++ b/src/core/hle/kernel/client_port.cpp @@ -34,7 +34,7 @@ ResultVal> ClientPort::Connect() { } // Wake the threads waiting on the ServerPort - server_port->WakeupAllWaitingThreads(); + server_port->Signal(); return MakeResult(std::move(client)); } diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 1f230fc4a..dbb75416d 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -48,72 +48,6 @@ MICROPROFILE_DEFINE(Kernel_SVC, "Kernel", "SVC", MP_RGB(70, 200, 70)); namespace Kernel { -/** - * Callback that will wake up the thread it was scheduled for - * @param thread_handle The handle of the thread that's been awoken - * @param cycles_late The number of CPU cycles that have passed since the desired wakeup time - */ -static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] s64 cycles_late) { - UNREACHABLE(); - const auto proper_handle = static_cast(thread_handle); - const auto& system = Core::System::GetInstance(); - - // Lock the global kernel mutex when we enter the kernel HLE. - std::lock_guard lock{HLE::g_hle_lock}; - - std::shared_ptr thread = - system.Kernel().RetrieveThreadFromGlobalHandleTable(proper_handle); - if (thread == nullptr) { - LOG_CRITICAL(Kernel, "Callback fired for invalid thread {:08X}", proper_handle); - return; - } - - bool resume = true; - - if (thread->GetStatus() == ThreadStatus::WaitSynch || - thread->GetStatus() == ThreadStatus::WaitHLEEvent) { - // Remove the thread from each of its waiting objects' waitlists - for (const auto& object : thread->GetSynchronizationObjects()) { - object->RemoveWaitingThread(thread); - } - thread->ClearSynchronizationObjects(); - - // Invoke the wakeup callback before clearing the wait objects - if (thread->HasWakeupCallback()) { - resume = thread->InvokeWakeupCallback(ThreadWakeupReason::Timeout, thread, nullptr, 0); - } - } else if (thread->GetStatus() == ThreadStatus::WaitMutex || - thread->GetStatus() == ThreadStatus::WaitCondVar) { - thread->SetMutexWaitAddress(0); - thread->SetWaitHandle(0); - if (thread->GetStatus() == ThreadStatus::WaitCondVar) { - thread->GetOwnerProcess()->RemoveConditionVariableThread(thread); - thread->SetCondVarWaitAddress(0); - } - - auto* const lock_owner = thread->GetLockOwner(); - // Threads waking up by timeout from WaitProcessWideKey do not perform priority inheritance - // and don't have a lock owner unless SignalProcessWideKey was called first and the thread - // wasn't awakened due to the mutex already being acquired. - if (lock_owner != nullptr) { - lock_owner->RemoveMutexWaiter(thread); - } - } - - if (thread->GetStatus() == ThreadStatus::WaitArb) { - auto& address_arbiter = thread->GetOwnerProcess()->GetAddressArbiter(); - address_arbiter.HandleWakeupThread(thread); - } - - if (resume) { - if (thread->GetStatus() == ThreadStatus::WaitCondVar || - thread->GetStatus() == ThreadStatus::WaitArb) { - thread->SetWaitSynchronizationResult(RESULT_TIMEOUT); - } - thread->ResumeFromWait(); - } -} - struct KernelCore::Impl { explicit Impl(Core::System& system, KernelCore& kernel) : global_scheduler{kernel}, synchronization{system}, time_manager{system}, system{system} {} @@ -129,7 +63,6 @@ struct KernelCore::Impl { InitializePhysicalCores(); InitializeSystemResourceLimit(kernel); InitializeMemoryLayout(); - InitializeThreads(); InitializePreemption(kernel); InitializeSchedulers(); InitializeSuspendThreads(); @@ -161,7 +94,6 @@ struct KernelCore::Impl { system_resource_limit = nullptr; global_handle_table.Clear(); - thread_wakeup_event_type = nullptr; preemption_event = nullptr; global_scheduler.Shutdown(); @@ -210,11 +142,6 @@ struct KernelCore::Impl { } } - void InitializeThreads() { - thread_wakeup_event_type = - Core::Timing::CreateEvent("ThreadWakeupCallback", ThreadWakeupCallback); - } - void InitializePreemption(KernelCore& kernel) { preemption_event = Core::Timing::CreateEvent( "PreemptionCallback", [this, &kernel](u64 userdata, s64 cycles_late) { @@ -376,7 +303,6 @@ struct KernelCore::Impl { std::shared_ptr system_resource_limit; - std::shared_ptr thread_wakeup_event_type; std::shared_ptr preemption_event; // This is the kernel's handle table or supervisor handle table which @@ -516,7 +442,8 @@ std::array& KernelCore return impl->interrupts; } -const std::array& KernelCore::Interrupts() const { +const std::array& KernelCore::Interrupts() + const { return impl->interrupts; } @@ -595,10 +522,6 @@ u64 KernelCore::CreateNewUserProcessID() { return impl->next_user_process_id++; } -const std::shared_ptr& KernelCore::ThreadWakeupCallbackEventType() const { - return impl->thread_wakeup_event_type; -} - Kernel::HandleTable& KernelCore::GlobalHandleTable() { return impl->global_handle_table; } diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 846056b85..49bd47e89 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -241,9 +241,6 @@ private: /// Creates a new thread ID, incrementing the internal thread ID counter. u64 CreateNewThreadID(); - /// Retrieves the event type used for thread wakeup callbacks. - const std::shared_ptr& ThreadWakeupCallbackEventType() const; - /// Provides a reference to the global handle table. Kernel::HandleTable& GlobalHandleTable(); diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index dbd35580e..781032cd1 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -16,7 +16,6 @@ #include "common/string_util.h" #include "core/arm/exclusive_monitor.h" #include "core/core.h" -#include "core/core_manager.h" #include "core/core_timing.h" #include "core/core_timing_util.h" #include "core/cpu_manager.h" @@ -1909,7 +1908,7 @@ static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle, return ERR_INVALID_COMBINATION; } - if (core < Core::NUM_CPU_CORES) { + if (core < Core::Hardware::NUM_CPU_CORES) { if ((affinity_mask & (1ULL << core)) == 0) { LOG_ERROR(Kernel_SVC, "Core is not enabled for the current mask, core={}, mask={:016X}", core, diff --git a/src/core/hle/kernel/synchronization_object.cpp b/src/core/hle/kernel/synchronization_object.cpp index be9e09106..ba4d39157 100644 --- a/src/core/hle/kernel/synchronization_object.cpp +++ b/src/core/hle/kernel/synchronization_object.cpp @@ -38,70 +38,6 @@ void SynchronizationObject::RemoveWaitingThread(std::shared_ptr thread) waiting_threads.erase(itr); } -std::shared_ptr SynchronizationObject::GetHighestPriorityReadyThread() const { - Thread* candidate = nullptr; - u32 candidate_priority = THREADPRIO_LOWEST + 1; - - for (const auto& thread : waiting_threads) { - const ThreadStatus thread_status = thread->GetStatus(); - - // The list of waiting threads must not contain threads that are not waiting to be awakened. - ASSERT_MSG(thread_status == ThreadStatus::WaitSynch || - thread_status == ThreadStatus::WaitHLEEvent, - "Inconsistent thread statuses in waiting_threads"); - - if (thread->GetPriority() >= candidate_priority) - continue; - - if (ShouldWait(thread.get())) - continue; - - candidate = thread.get(); - candidate_priority = thread->GetPriority(); - } - - return SharedFrom(candidate); -} - -void SynchronizationObject::WakeupWaitingThread(std::shared_ptr thread) { - ASSERT(!ShouldWait(thread.get())); - - if (!thread) { - return; - } - - if (thread->IsSleepingOnWait()) { - for (const auto& object : thread->GetSynchronizationObjects()) { - ASSERT(!object->ShouldWait(thread.get())); - object->Acquire(thread.get()); - } - } else { - Acquire(thread.get()); - } - - const std::size_t index = thread->GetSynchronizationObjectIndex(SharedFrom(this)); - - thread->ClearSynchronizationObjects(); - - thread->CancelWakeupTimer(); - - bool resume = true; - if (thread->HasWakeupCallback()) { - resume = thread->InvokeWakeupCallback(ThreadWakeupReason::Signal, thread, SharedFrom(this), - index); - } - if (resume) { - thread->ResumeFromWait(); - kernel.PrepareReschedule(thread->GetProcessorID()); - } -} - -void SynchronizationObject::WakeupAllWaitingThreads() { - while (auto thread = GetHighestPriorityReadyThread()) { - WakeupWaitingThread(thread); - } -} - void SynchronizationObject::ClearWaitingThreads() { waiting_threads.clear(); } diff --git a/src/core/hle/kernel/synchronization_object.h b/src/core/hle/kernel/synchronization_object.h index a35544ac1..f89b24204 100644 --- a/src/core/hle/kernel/synchronization_object.h +++ b/src/core/hle/kernel/synchronization_object.h @@ -50,21 +50,6 @@ public: */ void RemoveWaitingThread(std::shared_ptr thread); - /** - * Wake up all threads waiting on this object that can be awoken, in priority order, - * and set the synchronization result and output of the thread. - */ - void /* deprecated */ WakeupAllWaitingThreads(); - - /** - * Wakes up a single thread waiting on this object. - * @param thread Thread that is waiting on this object to wakeup. - */ - void WakeupWaitingThread(std::shared_ptr thread); - - /// Obtains the highest priority thread that is ready to run from this object's waiting list. - std::shared_ptr /* deprecated */ GetHighestPriorityReadyThread() const; - /// Get a const reference to the waiting threads list for debug use const std::vector>& GetWaitingThreads() const; diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index d88039a16..fba2a9c85 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -56,9 +56,6 @@ Thread::~Thread() = default; void Thread::Stop() { { SchedulerLock lock(kernel); - // Cancel any outstanding wakeup events for this thread - Core::System::GetInstance().CoreTiming().UnscheduleEvent( - kernel.ThreadWakeupCallbackEventType(), global_handle); SetStatus(ThreadStatus::Dead); Signal(); kernel.GlobalHandleTable().Close(global_handle); @@ -75,22 +72,6 @@ void Thread::Stop() { global_handle = 0; } -void Thread::WakeAfterDelay(s64 nanoseconds) { - // Don't schedule a wakeup if the thread wants to wait forever - if (nanoseconds == -1) - return; - - // This function might be called from any thread so we have to be cautious and use the - // thread-safe version of ScheduleEvent. - Core::System::GetInstance().CoreTiming().ScheduleEvent( - nanoseconds, kernel.ThreadWakeupCallbackEventType(), global_handle); -} - -void Thread::CancelWakeupTimer() { - Core::System::GetInstance().CoreTiming().UnscheduleEvent(kernel.ThreadWakeupCallbackEventType(), - global_handle); -} - void Thread::ResumeFromWait() { SchedulerLock lock(kernel); switch (status) { @@ -284,14 +265,6 @@ void Thread::SetPriority(u32 priority) { UpdatePriority(); } -void Thread::SetWaitSynchronizationResult(ResultCode result) { - UNREACHABLE(); -} - -void Thread::SetWaitSynchronizationOutput(s32 output) { - UNREACHABLE(); -} - void Thread::SetSynchronizationResults(SynchronizationObject* object, ResultCode result) { signaling_object = object; signaling_result = result; @@ -425,13 +398,6 @@ bool Thread::AllSynchronizationObjectsReady() const { }); } -bool Thread::InvokeWakeupCallback(ThreadWakeupReason reason, std::shared_ptr thread, - std::shared_ptr object, - std::size_t index) { - ASSERT(wakeup_callback); - return wakeup_callback(reason, std::move(thread), std::move(object), index); -} - bool Thread::InvokeHLECallback(std::shared_ptr thread) { ASSERT(hle_callback); return hle_callback(std::move(thread)); diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 61963148d..3ae0df6ef 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -128,9 +128,6 @@ public: using ThreadSynchronizationObjects = std::vector>; - using WakeupCallback = - std::function thread, - std::shared_ptr object, std::size_t index)>; using HLECallback = std::function thread)>; /** @@ -235,7 +232,7 @@ public: } /// Resumes a thread from waiting - void /* deprecated */ ResumeFromWait(); + void ResumeFromWait(); void OnWakeUp(); @@ -249,27 +246,6 @@ public: /// void CancelWait(); - /** - * Schedules an event to wake up the specified thread after the specified delay - * @param nanoseconds The time this thread will be allowed to sleep for - */ - void /* deprecated */ WakeAfterDelay(s64 nanoseconds); - - /// Cancel any outstanding wakeup events for this thread - void /* deprecated */ CancelWakeupTimer(); - - /** - * Sets the result after the thread awakens (from svcWaitSynchronization) - * @param result Value to set to the returned result - */ - void /*deprecated*/ SetWaitSynchronizationResult(ResultCode result); - - /** - * Sets the output parameter value after the thread awakens (from svcWaitSynchronization) - * @param output Value to set to the output parameter - */ - void /*deprecated*/ SetWaitSynchronizationOutput(s32 output); - void SetSynchronizationResults(SynchronizationObject* object, ResultCode result); Core::ARM_Interface& ArmInterface(); @@ -330,11 +306,6 @@ public: */ VAddr GetCommandBufferAddress() const; - /// Returns whether this thread is waiting on objects from a WaitSynchronization call. - bool IsSleepingOnWait() const { - return status == ThreadStatus::WaitSynch; - } - ThreadContext32& GetContext32() { return context_32; } @@ -469,18 +440,10 @@ public: arb_wait_address = address; } - bool HasWakeupCallback() const { - return wakeup_callback != nullptr; - } - bool HasHLECallback() const { return hle_callback != nullptr; } - void SetWakeupCallback(WakeupCallback callback) { - wakeup_callback = std::move(callback); - } - void SetHLECallback(HLECallback callback) { hle_callback = std::move(callback); } @@ -501,22 +464,10 @@ public: return hle_object; } - void InvalidateWakeupCallback() { - SetWakeupCallback(nullptr); - } - void InvalidateHLECallback() { SetHLECallback(nullptr); } - /** - * Invokes the thread's wakeup callback. - * - * @pre A valid wakeup callback has been set. Violating this precondition - * will cause an assertion to trigger. - */ - bool InvokeWakeupCallback(ThreadWakeupReason reason, std::shared_ptr thread, - std::shared_ptr object, std::size_t index); bool InvokeHLECallback(std::shared_ptr thread); u32 GetIdealCore() const { @@ -698,11 +649,6 @@ private: /// Handle used as userdata to reference this object when inserting into the CoreTiming queue. Handle global_handle = 0; - /// Callback that will be invoked when the thread is resumed from a waiting state. If the thread - /// was waiting via WaitSynchronization then the object will be the last object that became - /// available. In case of a timeout, the object will be nullptr. DEPRECATED - WakeupCallback wakeup_callback; - /// Callback for HLE Events HLECallback hle_callback; Handle hle_time_event; diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp index 6ada13be4..d872de16c 100644 --- a/src/core/hle/service/sm/sm.cpp +++ b/src/core/hle/service/sm/sm.cpp @@ -142,7 +142,7 @@ void SM::GetService(Kernel::HLERequestContext& ctx) { } // Wake the threads waiting on the ServerPort - server_port->WakeupAllWaitingThreads(); + server_port->Signal(); LOG_DEBUG(Service_SM, "called service={} -> session={}", name, client->GetObjectId()); IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; diff --git a/src/core/host_timing.cpp b/src/core/host_timing.cpp deleted file mode 100644 index 2f40de1a1..000000000 --- a/src/core/host_timing.cpp +++ /dev/null @@ -1,206 +0,0 @@ -// Copyright 2020 yuzu Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/host_timing.h" - -#include -#include -#include -#include - -#include "common/assert.h" -#include "core/core_timing_util.h" - -namespace Core::HostTiming { - -std::shared_ptr CreateEvent(std::string name, TimedCallback&& callback) { - return std::make_shared(std::move(callback), std::move(name)); -} - -struct CoreTiming::Event { - u64 time; - u64 fifo_order; - u64 userdata; - std::weak_ptr type; - - // Sort by time, unless the times are the same, in which case sort by - // the order added to the queue - friend bool operator>(const Event& left, const Event& right) { - return std::tie(left.time, left.fifo_order) > std::tie(right.time, right.fifo_order); - } - - friend bool operator<(const Event& left, const Event& right) { - return std::tie(left.time, left.fifo_order) < std::tie(right.time, right.fifo_order); - } -}; - -CoreTiming::CoreTiming() { - clock = - Common::CreateBestMatchingClock(Core::Hardware::BASE_CLOCK_RATE, Core::Hardware::CNTFREQ); -} - -CoreTiming::~CoreTiming() = default; - -void CoreTiming::ThreadEntry(CoreTiming& instance) { - instance.ThreadLoop(); -} - -void CoreTiming::Initialize() { - event_fifo_id = 0; - const auto empty_timed_callback = [](u64, s64) {}; - ev_lost = CreateEvent("_lost_event", empty_timed_callback); - timer_thread = std::make_unique(ThreadEntry, std::ref(*this)); -} - -void CoreTiming::Shutdown() { - paused = true; - shutting_down = true; - event.Set(); - timer_thread->join(); - ClearPendingEvents(); - timer_thread.reset(); - has_started = false; -} - -void CoreTiming::Pause(bool is_paused) { - paused = is_paused; -} - -void CoreTiming::SyncPause(bool is_paused) { - if (is_paused == paused && paused_set == paused) { - return; - } - Pause(is_paused); - event.Set(); - while (paused_set != is_paused) - ; -} - -bool CoreTiming::IsRunning() const { - return !paused_set; -} - -bool CoreTiming::HasPendingEvents() const { - return !(wait_set && event_queue.empty()); -} - -void CoreTiming::ScheduleEvent(s64 ns_into_future, const std::shared_ptr& event_type, - u64 userdata) { - basic_lock.lock(); - const u64 timeout = static_cast(GetGlobalTimeNs().count() + ns_into_future); - - event_queue.emplace_back(Event{timeout, event_fifo_id++, userdata, event_type}); - - std::push_heap(event_queue.begin(), event_queue.end(), std::greater<>()); - basic_lock.unlock(); - event.Set(); -} - -void CoreTiming::UnscheduleEvent(const std::shared_ptr& event_type, u64 userdata) { - basic_lock.lock(); - const auto itr = std::remove_if(event_queue.begin(), event_queue.end(), [&](const Event& e) { - return e.type.lock().get() == event_type.get() && e.userdata == userdata; - }); - - // Removing random items breaks the invariant so we have to re-establish it. - if (itr != event_queue.end()) { - event_queue.erase(itr, event_queue.end()); - std::make_heap(event_queue.begin(), event_queue.end(), std::greater<>()); - } - basic_lock.unlock(); -} - -void CoreTiming::AddTicks(std::size_t core_index, u64 ticks) { - ticks_count[core_index] += ticks; -} - -void CoreTiming::ResetTicks(std::size_t core_index) { - ticks_count[core_index] = 0; -} - -u64 CoreTiming::GetCPUTicks() const { - return clock->GetCPUCycles(); -} - -u64 CoreTiming::GetClockTicks() const { - return clock->GetClockCycles(); -} - -void CoreTiming::ClearPendingEvents() { - event_queue.clear(); -} - -void CoreTiming::RemoveEvent(const std::shared_ptr& event_type) { - basic_lock.lock(); - - const auto itr = std::remove_if(event_queue.begin(), event_queue.end(), [&](const Event& e) { - return e.type.lock().get() == event_type.get(); - }); - - // Removing random items breaks the invariant so we have to re-establish it. - if (itr != event_queue.end()) { - event_queue.erase(itr, event_queue.end()); - std::make_heap(event_queue.begin(), event_queue.end(), std::greater<>()); - } - basic_lock.unlock(); -} - -std::optional CoreTiming::Advance() { - advance_lock.lock(); - basic_lock.lock(); - global_timer = GetGlobalTimeNs().count(); - - while (!event_queue.empty() && event_queue.front().time <= global_timer) { - Event evt = std::move(event_queue.front()); - std::pop_heap(event_queue.begin(), event_queue.end(), std::greater<>()); - event_queue.pop_back(); - basic_lock.unlock(); - - if (auto event_type{evt.type.lock()}) { - event_type->callback(evt.userdata, global_timer - evt.time); - } - - basic_lock.lock(); - } - - if (!event_queue.empty()) { - const u64 next_time = event_queue.front().time - global_timer; - basic_lock.unlock(); - advance_lock.unlock(); - return next_time; - } else { - basic_lock.unlock(); - advance_lock.unlock(); - return std::nullopt; - } -} - -void CoreTiming::ThreadLoop() { - has_started = true; - while (!shutting_down) { - while (!paused) { - paused_set = false; - const auto next_time = Advance(); - if (next_time) { - std::chrono::nanoseconds next_time_ns = std::chrono::nanoseconds(*next_time); - event.WaitFor(next_time_ns); - } else { - wait_set = true; - event.Wait(); - } - wait_set = false; - } - paused_set = true; - } -} - -std::chrono::nanoseconds CoreTiming::GetGlobalTimeNs() const { - return clock->GetTimeNS(); -} - -std::chrono::microseconds CoreTiming::GetGlobalTimeUs() const { - return clock->GetTimeUS(); -} - -} // namespace Core::HostTiming diff --git a/src/core/host_timing.h b/src/core/host_timing.h deleted file mode 100644 index be6b68d7c..000000000 --- a/src/core/host_timing.h +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright 2020 yuzu Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "common/common_types.h" -#include "common/spin_lock.h" -#include "common/thread.h" -#include "common/threadsafe_queue.h" -#include "common/wall_clock.h" -#include "core/hardware_properties.h" - -namespace Core::HostTiming { - -/// A callback that may be scheduled for a particular core timing event. -using TimedCallback = std::function; - -/// Contains the characteristics of a particular event. -struct EventType { - EventType(TimedCallback&& callback, std::string&& name) - : callback{std::move(callback)}, name{std::move(name)} {} - - /// The event's callback function. - TimedCallback callback; - /// A pointer to the name of the event. - const std::string name; -}; - -/** - * This is a system to schedule events into the emulated machine's future. Time is measured - * in main CPU clock cycles. - * - * To schedule an event, you first have to register its type. This is where you pass in the - * callback. You then schedule events using the type id you get back. - * - * The int cyclesLate that the callbacks get is how many cycles late it was. - * So to schedule a new event on a regular basis: - * inside callback: - * ScheduleEvent(periodInCycles - cyclesLate, callback, "whatever") - */ -class CoreTiming { -public: - CoreTiming(); - ~CoreTiming(); - - CoreTiming(const CoreTiming&) = delete; - CoreTiming(CoreTiming&&) = delete; - - CoreTiming& operator=(const CoreTiming&) = delete; - CoreTiming& operator=(CoreTiming&&) = delete; - - /// CoreTiming begins at the boundary of timing slice -1. An initial call to Advance() is - /// required to end slice - 1 and start slice 0 before the first cycle of code is executed. - void Initialize(); - - /// Tears down all timing related functionality. - void Shutdown(); - - /// Pauses/Unpauses the execution of the timer thread. - void Pause(bool is_paused); - - /// Pauses/Unpauses the execution of the timer thread and waits until paused. - void SyncPause(bool is_paused); - - /// Checks if core timing is running. - bool IsRunning() const; - - /// Checks if the timer thread has started. - bool HasStarted() const { - return has_started; - } - - /// Checks if there are any pending time events. - bool HasPendingEvents() const; - - /// Schedules an event in core timing - void ScheduleEvent(s64 ns_into_future, const std::shared_ptr& event_type, - u64 userdata = 0); - - void UnscheduleEvent(const std::shared_ptr& event_type, u64 userdata); - - /// We only permit one event of each type in the queue at a time. - void RemoveEvent(const std::shared_ptr& event_type); - - void AddTicks(std::size_t core_index, u64 ticks); - - void ResetTicks(std::size_t core_index); - - /// Returns current time in emulated CPU cycles - u64 GetCPUTicks() const; - - /// Returns current time in emulated in Clock cycles - u64 GetClockTicks() const; - - /// Returns current time in microseconds. - std::chrono::microseconds GetGlobalTimeUs() const; - - /// Returns current time in nanoseconds. - std::chrono::nanoseconds GetGlobalTimeNs() const; - - /// Checks for events manually and returns time in nanoseconds for next event, threadsafe. - std::optional Advance(); - -private: - struct Event; - - /// Clear all pending events. This should ONLY be done on exit. - void ClearPendingEvents(); - - static void ThreadEntry(CoreTiming& instance); - void ThreadLoop(); - - std::unique_ptr clock; - - u64 global_timer = 0; - - std::chrono::nanoseconds start_point; - - // The queue is a min-heap using std::make_heap/push_heap/pop_heap. - // We don't use std::priority_queue because we need to be able to serialize, unserialize and - // erase arbitrary events (RemoveEvent()) regardless of the queue order. These aren't - // accomodated by the standard adaptor class. - std::vector event_queue; - u64 event_fifo_id = 0; - - std::shared_ptr ev_lost; - Common::Event event{}; - Common::SpinLock basic_lock{}; - Common::SpinLock advance_lock{}; - std::unique_ptr timer_thread; - std::atomic paused{}; - std::atomic paused_set{}; - std::atomic wait_set{}; - std::atomic shutting_down{}; - std::atomic has_started{}; - - std::array, Core::Hardware::NUM_CPU_CORES> ticks_count{}; -}; - -/// Creates a core timing event with the given name and callback. -/// -/// @param name The name of the core timing event to create. -/// @param callback The callback to execute for the event. -/// -/// @returns An EventType instance representing the created event. -/// -std::shared_ptr CreateEvent(std::string name, TimedCallback&& callback); - -} // namespace Core::HostTiming diff --git a/src/tests/core/core_timing.cpp b/src/tests/core/core_timing.cpp index 795f3da09..21a5840fb 100644 --- a/src/tests/core/core_timing.cpp +++ b/src/tests/core/core_timing.cpp @@ -39,6 +39,7 @@ u64 callbacks_done = 0; struct ScopeInit final { ScopeInit() { + core_timing.SetMulticore(true); core_timing.Initialize([]() {}); } ~ScopeInit() { diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp index d2dbb259c..0226ae2e2 100644 --- a/src/yuzu/debugger/wait_tree.cpp +++ b/src/yuzu/debugger/wait_tree.cpp @@ -340,7 +340,7 @@ std::vector> WaitTreeThread::GetChildren() const { if (thread.GetStatus() == Kernel::ThreadStatus::WaitSynch) { list.push_back(std::make_unique(thread.GetSynchronizationObjects(), - thread.IsSleepingOnWait())); + thread.IsWaitingSync())); } list.push_back(std::make_unique(thread)); -- cgit v1.2.3 From 467d43570e10b98fa33067352d35fe62ceb3cb9e Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Fri, 8 May 2020 18:53:13 -0400 Subject: Clang Format. --- src/common/atomic_ops.cpp | 14 +++++++------- src/common/atomic_ops.h | 2 +- src/common/thread.cpp | 30 +++++++++++++++--------------- src/core/arm/unicorn/arm_unicorn.cpp | 4 ++-- src/core/arm/unicorn/arm_unicorn.h | 4 ++-- src/core/core.h | 2 -- src/core/hle/kernel/mutex.cpp | 11 +++++------ src/core/hle/kernel/mutex.h | 3 ++- src/core/hle/kernel/physical_core.h | 7 +++---- src/core/hle/kernel/server_session.cpp | 2 +- src/yuzu/bootmanager.cpp | 1 - src/yuzu/bootmanager.h | 3 ++- src/yuzu/debugger/wait_tree.cpp | 5 +++-- src/yuzu/main.cpp | 9 ++++++--- 14 files changed, 49 insertions(+), 48 deletions(-) (limited to 'src/yuzu/debugger') diff --git a/src/common/atomic_ops.cpp b/src/common/atomic_ops.cpp index 65cdfb4fd..6b2236114 100644 --- a/src/common/atomic_ops.cpp +++ b/src/common/atomic_ops.cpp @@ -35,26 +35,26 @@ bool AtomicCompareAndSwap(u64 volatile* pointer, u64 value, u64 expected) { } bool AtomicCompareAndSwap(u64 volatile* pointer, u128 value, u128 expected) { - return _InterlockedCompareExchange128((__int64*)pointer, value[1], value[0], (__int64*)expected.data()) != 0; + return _InterlockedCompareExchange128((__int64*)pointer, value[1], value[0], + (__int64*)expected.data()) != 0; } - #else bool AtomicCompareAndSwap(u8 volatile* pointer, u8 value, u8 expected) { - return __sync_bool_compare_and_swap (pointer, value, expected); + return __sync_bool_compare_and_swap(pointer, value, expected); } bool AtomicCompareAndSwap(u16 volatile* pointer, u16 value, u16 expected) { - return __sync_bool_compare_and_swap (pointer, value, expected); + return __sync_bool_compare_and_swap(pointer, value, expected); } bool AtomicCompareAndSwap(u32 volatile* pointer, u32 value, u32 expected) { - return __sync_bool_compare_and_swap (pointer, value, expected); + return __sync_bool_compare_and_swap(pointer, value, expected); } bool AtomicCompareAndSwap(u64 volatile* pointer, u64 value, u64 expected) { - return __sync_bool_compare_and_swap (pointer, value, expected); + return __sync_bool_compare_and_swap(pointer, value, expected); } bool AtomicCompareAndSwap(u64 volatile* pointer, u128 value, u128 expected) { @@ -62,7 +62,7 @@ bool AtomicCompareAndSwap(u64 volatile* pointer, u128 value, u128 expected) { unsigned __int128 expected_a; std::memcpy(&value_a, value.data(), sizeof(u128)); std::memcpy(&expected_a, expected.data(), sizeof(u128)); - return __sync_bool_compare_and_swap ((unsigned __int128*)pointer, value_a, expected_a); + return __sync_bool_compare_and_swap((unsigned __int128*)pointer, value_a, expected_a); } #endif diff --git a/src/common/atomic_ops.h b/src/common/atomic_ops.h index 22cb3a402..e6181d521 100644 --- a/src/common/atomic_ops.h +++ b/src/common/atomic_ops.h @@ -8,7 +8,7 @@ namespace Common { -bool AtomicCompareAndSwap(u8 volatile * pointer, u8 value, u8 expected); +bool AtomicCompareAndSwap(u8 volatile* pointer, u8 value, u8 expected); bool AtomicCompareAndSwap(u16 volatile* pointer, u16 value, u16 expected); bool AtomicCompareAndSwap(u32 volatile* pointer, u32 value, u32 expected); bool AtomicCompareAndSwap(u64 volatile* pointer, u64 value, u64 expected); diff --git a/src/common/thread.cpp b/src/common/thread.cpp index 33c8437f5..8e5935e6a 100644 --- a/src/common/thread.cpp +++ b/src/common/thread.cpp @@ -31,21 +31,21 @@ void SetCurrentThreadPriority(ThreadPriority new_priority) { auto handle = GetCurrentThread(); int windows_priority = 0; switch (new_priority) { - case ThreadPriority::Low: - windows_priority = THREAD_PRIORITY_BELOW_NORMAL; - break; - case ThreadPriority::Normal: - windows_priority = THREAD_PRIORITY_NORMAL; - break; - case ThreadPriority::High: - windows_priority = THREAD_PRIORITY_ABOVE_NORMAL; - break; - case ThreadPriority::VeryHigh: - windows_priority = THREAD_PRIORITY_HIGHEST; - break; - default: - windows_priority = THREAD_PRIORITY_NORMAL; - break; + case ThreadPriority::Low: + windows_priority = THREAD_PRIORITY_BELOW_NORMAL; + break; + case ThreadPriority::Normal: + windows_priority = THREAD_PRIORITY_NORMAL; + break; + case ThreadPriority::High: + windows_priority = THREAD_PRIORITY_ABOVE_NORMAL; + break; + case ThreadPriority::VeryHigh: + windows_priority = THREAD_PRIORITY_HIGHEST; + break; + default: + windows_priority = THREAD_PRIORITY_NORMAL; + break; } SetThreadPriority(handle, windows_priority); } diff --git a/src/core/arm/unicorn/arm_unicorn.cpp b/src/core/arm/unicorn/arm_unicorn.cpp index 9f9690454..35e8f42e8 100644 --- a/src/core/arm/unicorn/arm_unicorn.cpp +++ b/src/core/arm/unicorn/arm_unicorn.cpp @@ -63,8 +63,8 @@ static bool UnmappedMemoryHook(uc_engine* uc, uc_mem_type type, u64 addr, int si return false; } -ARM_Unicorn::ARM_Unicorn(System& system, CPUInterrupts& interrupt_handlers, - bool uses_wall_clock, Arch architecture, std::size_t core_index) +ARM_Unicorn::ARM_Unicorn(System& system, CPUInterrupts& interrupt_handlers, bool uses_wall_clock, + Arch architecture, std::size_t core_index) : ARM_Interface{system, interrupt_handlers, uses_wall_clock}, core_index{core_index} { const auto arch = architecture == Arch::AArch32 ? UC_ARCH_ARM : UC_ARCH_ARM64; CHECKED(uc_open(arch, UC_MODE_ARM, &uc)); diff --git a/src/core/arm/unicorn/arm_unicorn.h b/src/core/arm/unicorn/arm_unicorn.h index 9b7d7f6c2..8ace8b86f 100644 --- a/src/core/arm/unicorn/arm_unicorn.h +++ b/src/core/arm/unicorn/arm_unicorn.h @@ -20,8 +20,8 @@ public: AArch64, // 64-bit ARM }; - explicit ARM_Unicorn(System& system, CPUInterrupts& interrupt_handlers, - bool uses_wall_clock, Arch architecture, std::size_t core_index); + explicit ARM_Unicorn(System& system, CPUInterrupts& interrupt_handlers, bool uses_wall_clock, + Arch architecture, std::size_t core_index); ~ARM_Unicorn() override; void SetPC(u64 pc) override; diff --git a/src/core/core.h b/src/core/core.h index 87df79d57..d2d1fcc5b 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -148,8 +148,6 @@ public: */ ResultStatus Pause(); - - /** * Step the CPU one instruction * @return Result status, indicating whether or not the operation succeeded. diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 32dc1ffae..8f6c944d1 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -9,7 +9,6 @@ #include "common/assert.h" #include "common/logging/log.h" #include "core/core.h" -#include "core/core.h" #include "core/hle/kernel/errors.h" #include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/kernel.h" @@ -126,11 +125,11 @@ ResultCode Mutex::TryAcquire(VAddr address, Handle holding_thread_handle, std::pair> Mutex::Unlock(std::shared_ptr owner, VAddr address) { - // The mutex address must be 4-byte aligned - if ((address % sizeof(u32)) != 0) { - LOG_ERROR(Kernel, "Address is not 4-byte aligned! address={:016X}", address); - return {ERR_INVALID_ADDRESS, nullptr}; - } + // The mutex address must be 4-byte aligned + if ((address % sizeof(u32)) != 0) { + LOG_ERROR(Kernel, "Address is not 4-byte aligned! address={:016X}", address); + return {ERR_INVALID_ADDRESS, nullptr}; + } auto [new_owner, num_waiters] = GetHighestPriorityMutexWaitingThread(owner, address); if (new_owner == nullptr) { diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h index bce06ecea..3b81dc3df 100644 --- a/src/core/hle/kernel/mutex.h +++ b/src/core/hle/kernel/mutex.h @@ -29,7 +29,8 @@ public: Handle requesting_thread_handle); /// Unlocks a mutex for owner at address - std::pair> Unlock(std::shared_ptr owner, VAddr address); + std::pair> Unlock(std::shared_ptr owner, + VAddr address); /// Releases the mutex at the specified address. ResultCode Release(VAddr address); diff --git a/src/core/hle/kernel/physical_core.h b/src/core/hle/kernel/physical_core.h index 751b994a7..85f6dec05 100644 --- a/src/core/hle/kernel/physical_core.h +++ b/src/core/hle/kernel/physical_core.h @@ -10,7 +10,7 @@ #include "core/arm/cpu_interrupt_handler.h" namespace Common { - class SpinLock; +class SpinLock; } namespace Kernel { @@ -27,9 +27,8 @@ namespace Kernel { class PhysicalCore { public: - PhysicalCore(Core::System& system, std::size_t id, - Kernel::Scheduler& scheduler, - Core::CPUInterruptHandler& interrupt_handler); + PhysicalCore(Core::System& system, std::size_t id, Kernel::Scheduler& scheduler, + Core::CPUInterruptHandler& interrupt_handler); ~PhysicalCore(); PhysicalCore(const PhysicalCore&) = delete; diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp index e988a3f22..7b23a6889 100644 --- a/src/core/hle/kernel/server_session.cpp +++ b/src/core/hle/kernel/server_session.cpp @@ -17,9 +17,9 @@ #include "core/hle/kernel/hle_ipc.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/process.h" +#include "core/hle/kernel/scheduler.h" #include "core/hle/kernel/server_session.h" #include "core/hle/kernel/session.h" -#include "core/hle/kernel/scheduler.h" #include "core/hle/kernel/thread.h" #include "core/memory.h" diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index 5f93bd432..4bfce48a4 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp @@ -71,7 +71,6 @@ void EmuThread::run() { gpu.ReleaseContext(); - // Holds whether the cpu was running during the last iteration, // so that the DebugModeLeft signal can be emitted before the // next execution step diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h index 768568b3e..6c59b4d5c 100644 --- a/src/yuzu/bootmanager.h +++ b/src/yuzu/bootmanager.h @@ -62,7 +62,8 @@ public: if (!running) { running_wait.Set(); /// Wait until effectively paused - while (running_guard); + while (running_guard) + ; } } diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp index 0226ae2e2..9bb0a0109 100644 --- a/src/yuzu/debugger/wait_tree.cpp +++ b/src/yuzu/debugger/wait_tree.cpp @@ -127,11 +127,12 @@ std::vector> WaitTreeCallstack::GetChildren() cons return list; } - auto backtrace = Core::ARM_Interface::GetBacktraceFromContext(Core::System::GetInstance(), thread.GetContext64()); + auto backtrace = Core::ARM_Interface::GetBacktraceFromContext(Core::System::GetInstance(), + thread.GetContext64()); for (auto& entry : backtrace) { std::string s = fmt::format("{:20}{:016X} {:016X} {:016X} {}", entry.module, entry.address, - entry.original_address, entry.offset, entry.name); + entry.original_address, entry.offset, entry.name); list.push_back(std::make_unique(QString::fromStdString(s))); } diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index f1d9ec326..53790c89c 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -534,7 +534,8 @@ void GMainWindow::InitializeWidgets() { if (emulation_running) { return; } - bool is_async = !Settings::values.use_asynchronous_gpu_emulation || Settings::values.use_multi_core; + bool is_async = + !Settings::values.use_asynchronous_gpu_emulation || Settings::values.use_multi_core; Settings::values.use_asynchronous_gpu_emulation = is_async; async_status_button->setChecked(Settings::values.use_asynchronous_gpu_emulation); Settings::Apply(); @@ -552,7 +553,8 @@ void GMainWindow::InitializeWidgets() { return; } Settings::values.use_multi_core = !Settings::values.use_multi_core; - bool is_async = Settings::values.use_asynchronous_gpu_emulation || Settings::values.use_multi_core; + bool is_async = + Settings::values.use_asynchronous_gpu_emulation || Settings::values.use_multi_core; Settings::values.use_asynchronous_gpu_emulation = is_async; async_status_button->setChecked(Settings::values.use_asynchronous_gpu_emulation); multicore_status_button->setChecked(Settings::values.use_multi_core); @@ -1958,7 +1960,8 @@ void GMainWindow::OnConfigure() { dock_status_button->setChecked(Settings::values.use_docked_mode); multicore_status_button->setChecked(Settings::values.use_multi_core); - Settings::values.use_asynchronous_gpu_emulation = Settings::values.use_asynchronous_gpu_emulation || Settings::values.use_multi_core; + Settings::values.use_asynchronous_gpu_emulation = + Settings::values.use_asynchronous_gpu_emulation || Settings::values.use_multi_core; async_status_button->setChecked(Settings::values.use_asynchronous_gpu_emulation); #ifdef HAS_VULKAN -- cgit v1.2.3