From 7020d498c5aef7c1180bfc57031cdd7fbfecdf0f Mon Sep 17 00:00:00 2001
From: Fernando Sahmkow <fsahmkow27@gmail.com>
Date: Thu, 12 Mar 2020 16:48:43 -0400
Subject: [PATCH] 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(-)

diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
index 30bf62ac1c..618f02f30a 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
@@ -7,7 +7,6 @@
 #include <dynarmic/A32/a32.h>
 #include <dynarmic/A32/config.h>
 #include <dynarmic/A32/context.h>
-#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<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable&
     return std::make_unique<Dynarmic::A32::Jit>(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 a22c22bf00..84b872f0b8 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
@@ -7,7 +7,6 @@
 #include <dynarmic/A64/a64.h>
 #include <dynarmic/A64/config.h>
 #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<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable&
     return std::make_shared<Dynarmic::A64::Jit>(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);
-
     jit->Run();
 }
 
diff --git a/src/core/core.cpp b/src/core/core.cpp
index fd1bdcaf0a..032da7aa58 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<Core::PerfStats> perf_stats;
     Core::FrameLimiter frame_limiter;
+
+    std::array<u64, Core::Hardware::NUM_CPU_CORES> dynarmic_ticks{};
 };
 
 System::System() : impl{std::make_unique<Impl>(*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 9a0dd10753..87df79d573 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 95842aad10..9e2e6d49fb 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 24da4367e4..d2f5f9bf23 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<u64, Core::Hardware::NUM_CPU_CORES> 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 50eeb50ec1..1eb6ede73e 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 25fc8a3e8b..2ad380b175 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 d3d4e7bf9f..9b9f9402ea 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 168828ab0f..f42d7bd136 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<Common::Fiber> 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 ab7b18abec..fa091f4573 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);
         }