diff options
| author | 2021-10-25 18:55:20 +0800 | |
|---|---|---|
| committer | 2021-10-27 09:06:22 +0800 | |
| commit | a8b01049235bffa13d18a010311c16c8b9c316b4 (patch) | |
| tree | 3e8f433c3da629b09a4b3e000047ceb6f8ac3ec0 | |
| parent | Merge pull request #7218 from bylaws/aswdqdsam (diff) | |
| download | yuzu-a8b01049235bffa13d18a010311c16c8b9c316b4.tar.gz yuzu-a8b01049235bffa13d18a010311c16c8b9c316b4.tar.xz yuzu-a8b01049235bffa13d18a010311c16c8b9c316b4.zip | |
Fix memory leak
| -rw-r--r-- | src/core/hle/kernel/k_handle_table.cpp | 1 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.cpp | 23 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.h | 8 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 6 |
4 files changed, 38 insertions, 0 deletions
diff --git a/src/core/hle/kernel/k_handle_table.cpp b/src/core/hle/kernel/k_handle_table.cpp index 44d13169f..e90fc0628 100644 --- a/src/core/hle/kernel/k_handle_table.cpp +++ b/src/core/hle/kernel/k_handle_table.cpp | |||
| @@ -56,6 +56,7 @@ bool KHandleTable::Remove(Handle handle) { | |||
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | // Close the object. | 58 | // Close the object. |
| 59 | kernel.UnregisterInUseObject(obj); | ||
| 59 | obj->Close(); | 60 | obj->Close(); |
| 60 | return true; | 61 | return true; |
| 61 | } | 62 | } |
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index bea945301..d054a7925 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -170,6 +170,17 @@ struct KernelCore::Impl { | |||
| 170 | // Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others | 170 | // Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others |
| 171 | next_host_thread_id = Core::Hardware::NUM_CPU_CORES; | 171 | next_host_thread_id = Core::Hardware::NUM_CPU_CORES; |
| 172 | 172 | ||
| 173 | // Close kernel objects that were not freed on shutdown | ||
| 174 | { | ||
| 175 | std::lock_guard lk(registered_in_use_objects_lock); | ||
| 176 | if (registered_in_use_objects.size()) { | ||
| 177 | for (auto thread : registered_in_use_objects) { | ||
| 178 | thread->Close(); | ||
| 179 | } | ||
| 180 | registered_in_use_objects.clear(); | ||
| 181 | } | ||
| 182 | } | ||
| 183 | |||
| 173 | // Track kernel objects that were not freed on shutdown | 184 | // Track kernel objects that were not freed on shutdown |
| 174 | { | 185 | { |
| 175 | std::lock_guard lk(registered_objects_lock); | 186 | std::lock_guard lk(registered_objects_lock); |
| @@ -714,9 +725,11 @@ struct KernelCore::Impl { | |||
| 714 | std::unordered_set<KServerPort*> server_ports; | 725 | std::unordered_set<KServerPort*> server_ports; |
| 715 | std::unordered_set<KServerSession*> server_sessions; | 726 | std::unordered_set<KServerSession*> server_sessions; |
| 716 | std::unordered_set<KAutoObject*> registered_objects; | 727 | std::unordered_set<KAutoObject*> registered_objects; |
| 728 | std::unordered_set<KAutoObject*> registered_in_use_objects; | ||
| 717 | std::mutex server_ports_lock; | 729 | std::mutex server_ports_lock; |
| 718 | std::mutex server_sessions_lock; | 730 | std::mutex server_sessions_lock; |
| 719 | std::mutex registered_objects_lock; | 731 | std::mutex registered_objects_lock; |
| 732 | std::mutex registered_in_use_objects_lock; | ||
| 720 | 733 | ||
| 721 | std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor; | 734 | std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor; |
| 722 | std::vector<Kernel::PhysicalCore> cores; | 735 | std::vector<Kernel::PhysicalCore> cores; |
| @@ -928,6 +941,16 @@ void KernelCore::UnregisterKernelObject(KAutoObject* object) { | |||
| 928 | impl->registered_objects.erase(object); | 941 | impl->registered_objects.erase(object); |
| 929 | } | 942 | } |
| 930 | 943 | ||
| 944 | void KernelCore::RegisterInUseObject(KAutoObject* object) { | ||
| 945 | std::lock_guard lk(impl->registered_in_use_objects_lock); | ||
| 946 | impl->registered_in_use_objects.insert(object); | ||
| 947 | } | ||
| 948 | |||
| 949 | void KernelCore::UnregisterInUseObject(KAutoObject* object) { | ||
| 950 | std::lock_guard lk(impl->registered_in_use_objects_lock); | ||
| 951 | impl->registered_in_use_objects.erase(object); | ||
| 952 | } | ||
| 953 | |||
| 931 | bool KernelCore::IsValidNamedPort(NamedPortTable::const_iterator port) const { | 954 | bool KernelCore::IsValidNamedPort(NamedPortTable::const_iterator port) const { |
| 932 | return port != impl->named_ports.cend(); | 955 | return port != impl->named_ports.cend(); |
| 933 | } | 956 | } |
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index b6658b437..d2ceae950 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h | |||
| @@ -204,6 +204,14 @@ public: | |||
| 204 | /// destroyed during the current emulation session. | 204 | /// destroyed during the current emulation session. |
| 205 | void UnregisterKernelObject(KAutoObject* object); | 205 | void UnregisterKernelObject(KAutoObject* object); |
| 206 | 206 | ||
| 207 | /// Registers kernel objects with guest in use state, this is purely for close | ||
| 208 | /// after emulation has been shutdown. | ||
| 209 | void RegisterInUseObject(KAutoObject* object); | ||
| 210 | |||
| 211 | /// Unregisters a kernel object previously registered with RegisterInUseObject when it was | ||
| 212 | /// destroyed during the current emulation session. | ||
| 213 | void UnregisterInUseObject(KAutoObject* object); | ||
| 214 | |||
| 207 | /// Determines whether or not the given port is a valid named port. | 215 | /// Determines whether or not the given port is a valid named port. |
| 208 | bool IsValidNamedPort(NamedPortTable::const_iterator port) const; | 216 | bool IsValidNamedPort(NamedPortTable::const_iterator port) const; |
| 209 | 217 | ||
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index f98f24a60..d30755b7e 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -427,11 +427,15 @@ static ResultCode WaitSynchronization(Core::System& system, s32* index, VAddr ha | |||
| 427 | R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(objs.data(), handles, | 427 | R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(objs.data(), handles, |
| 428 | num_handles), | 428 | num_handles), |
| 429 | ResultInvalidHandle); | 429 | ResultInvalidHandle); |
| 430 | for (const auto& obj : objs) { | ||
| 431 | kernel.RegisterInUseObject(obj); | ||
| 432 | } | ||
| 430 | } | 433 | } |
| 431 | 434 | ||
| 432 | // Ensure handles are closed when we're done. | 435 | // Ensure handles are closed when we're done. |
| 433 | SCOPE_EXIT({ | 436 | SCOPE_EXIT({ |
| 434 | for (u64 i = 0; i < num_handles; ++i) { | 437 | for (u64 i = 0; i < num_handles; ++i) { |
| 438 | kernel.UnregisterInUseObject(objs[i]); | ||
| 435 | objs[i]->Close(); | 439 | objs[i]->Close(); |
| 436 | } | 440 | } |
| 437 | }); | 441 | }); |
| @@ -1544,6 +1548,7 @@ static ResultCode StartThread(Core::System& system, Handle thread_handle) { | |||
| 1544 | 1548 | ||
| 1545 | // If we succeeded, persist a reference to the thread. | 1549 | // If we succeeded, persist a reference to the thread. |
| 1546 | thread->Open(); | 1550 | thread->Open(); |
| 1551 | system.Kernel().RegisterInUseObject(thread.GetPointerUnsafe()); | ||
| 1547 | 1552 | ||
| 1548 | return ResultSuccess; | 1553 | return ResultSuccess; |
| 1549 | } | 1554 | } |
| @@ -1559,6 +1564,7 @@ static void ExitThread(Core::System& system) { | |||
| 1559 | auto* const current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread(); | 1564 | auto* const current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread(); |
| 1560 | system.GlobalSchedulerContext().RemoveThread(current_thread); | 1565 | system.GlobalSchedulerContext().RemoveThread(current_thread); |
| 1561 | current_thread->Exit(); | 1566 | current_thread->Exit(); |
| 1567 | system.Kernel().UnregisterInUseObject(current_thread); | ||
| 1562 | } | 1568 | } |
| 1563 | 1569 | ||
| 1564 | static void ExitThread32(Core::System& system) { | 1570 | static void ExitThread32(Core::System& system) { |