소스 검색

hle: kernel: Provide methods for tracking dangling kernel objects.

bunnei 5 년 전
부모
커밋
929994132a
4개의 변경된 파일43개의 추가작업 그리고 2개의 파일을 삭제
  1. 9 0
      src/core/hle/kernel/k_auto_object.cpp
  2. 10 2
      src/core/hle/kernel/k_auto_object.h
  3. 16 0
      src/core/hle/kernel/kernel.cpp
  4. 8 0
      src/core/hle/kernel/kernel.h

+ 9 - 0
src/core/hle/kernel/k_auto_object.cpp

@@ -3,6 +3,7 @@
 // Refer to the license.txt file included.
 // Refer to the license.txt file included.
 
 
 #include "core/hle/kernel/k_auto_object.h"
 #include "core/hle/kernel/k_auto_object.h"
+#include "core/hle/kernel/kernel.h"
 
 
 namespace Kernel {
 namespace Kernel {
 
 
@@ -11,4 +12,12 @@ KAutoObject* KAutoObject::Create(KAutoObject* obj) {
     return obj;
     return obj;
 }
 }
 
 
+void KAutoObject::RegisterWithKernel() {
+    kernel.RegisterKernelObject(this);
+}
+
+void KAutoObject::UnregisterWithKernel() {
+    kernel.UnregisterKernelObject(this);
+}
+
 } // namespace Kernel
 } // namespace Kernel

+ 10 - 2
src/core/hle/kernel/k_auto_object.h

@@ -85,8 +85,12 @@ private:
     KERNEL_AUTOOBJECT_TRAITS(KAutoObject, KAutoObject);
     KERNEL_AUTOOBJECT_TRAITS(KAutoObject, KAutoObject);
 
 
 public:
 public:
-    explicit KAutoObject(KernelCore& kernel_) : kernel(kernel_) {}
-    virtual ~KAutoObject() = default;
+    explicit KAutoObject(KernelCore& kernel_) : kernel(kernel_) {
+        RegisterWithKernel();
+    }
+    virtual ~KAutoObject() {
+        UnregisterWithKernel();
+    }
 
 
     static KAutoObject* Create(KAutoObject* ptr);
     static KAutoObject* Create(KAutoObject* ptr);
 
 
@@ -166,6 +170,10 @@ public:
         }
         }
     }
     }
 
 
+private:
+    void RegisterWithKernel();
+    void UnregisterWithKernel();
+
 protected:
 protected:
     KernelCore& kernel;
     KernelCore& kernel;
     std::string name;
     std::string name;

+ 16 - 0
src/core/hle/kernel/kernel.cpp

@@ -142,6 +142,13 @@ struct KernelCore::Impl {
 
 
         // Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others
         // Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others
         next_host_thread_id = Core::Hardware::NUM_CPU_CORES;
         next_host_thread_id = Core::Hardware::NUM_CPU_CORES;
+
+        // Track kernel objects that were not freed on shutdown
+        if (registered_objects.size()) {
+            LOG_WARNING(Kernel, "{} kernel objects were dangling on shutdown!",
+                        registered_objects.size());
+            registered_objects.clear();
+        }
     }
     }
 
 
     void InitializePhysicalCores() {
     void InitializePhysicalCores() {
@@ -656,6 +663,7 @@ struct KernelCore::Impl {
     /// the ConnectToPort SVC.
     /// the ConnectToPort SVC.
     std::unordered_map<std::string, ServiceInterfaceFactory> service_interface_factory;
     std::unordered_map<std::string, ServiceInterfaceFactory> service_interface_factory;
     NamedPortTable named_ports;
     NamedPortTable named_ports;
+    std::unordered_set<KAutoObject*> registered_objects;
 
 
     std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor;
     std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor;
     std::vector<Kernel::PhysicalCore> cores;
     std::vector<Kernel::PhysicalCore> cores;
@@ -852,6 +860,14 @@ KClientPort* KernelCore::CreateNamedServicePort(std::string name) {
     return &search->second(impl->system.ServiceManager(), impl->system);
     return &search->second(impl->system.ServiceManager(), impl->system);
 }
 }
 
 
+void KernelCore::RegisterKernelObject(KAutoObject* object) {
+    impl->registered_objects.insert(object);
+}
+
+void KernelCore::UnregisterKernelObject(KAutoObject* object) {
+    impl->registered_objects.erase(object);
+}
+
 bool KernelCore::IsValidNamedPort(NamedPortTable::const_iterator port) const {
 bool KernelCore::IsValidNamedPort(NamedPortTable::const_iterator port) const {
     return port != impl->named_ports.cend();
     return port != impl->named_ports.cend();
 }
 }

+ 8 - 0
src/core/hle/kernel/kernel.h

@@ -185,6 +185,14 @@ public:
     /// Opens a port to a service previously registered with RegisterNamedService.
     /// Opens a port to a service previously registered with RegisterNamedService.
     KClientPort* CreateNamedServicePort(std::string name);
     KClientPort* CreateNamedServicePort(std::string name);
 
 
+    /// Registers all kernel objects with the global emulation state, this is purely for tracking
+    /// leaks after emulation has been shutdown.
+    void RegisterKernelObject(KAutoObject* object);
+
+    /// Unregisters a kernel object previously registered with RegisterKernelObject when it was
+    /// destroyed during the current emulation session.
+    void UnregisterKernelObject(KAutoObject* object);
+
     /// Determines whether or not the given port is a valid named port.
     /// Determines whether or not the given port is a valid named port.
     bool IsValidNamedPort(NamedPortTable::const_iterator port) const;
     bool IsValidNamedPort(NamedPortTable::const_iterator port) const;