yuzu-emu
/
yuzu-mainline
Archived
1
0
Fork 0

Merge pull request #7091 from vonchenplus/fix_memroy_leak

core: Fix memory leak
This commit is contained in:
Ameer J 2021-10-04 00:09:08 -04:00 committed by GitHub
commit 01f79d638f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 114 additions and 9 deletions

View File

@ -216,6 +216,7 @@ add_library(core STATIC
hle/kernel/k_session.h hle/kernel/k_session.h
hle/kernel/k_shared_memory.cpp hle/kernel/k_shared_memory.cpp
hle/kernel/k_shared_memory.h hle/kernel/k_shared_memory.h
hle/kernel/k_shared_memory_info.h
hle/kernel/k_slab_heap.h hle/kernel/k_slab_heap.h
hle/kernel/k_spin_lock.cpp hle/kernel/k_spin_lock.cpp
hle/kernel/k_spin_lock.h hle/kernel/k_spin_lock.h

View File

@ -23,6 +23,7 @@
#include "core/hle/kernel/k_scheduler.h" #include "core/hle/kernel/k_scheduler.h"
#include "core/hle/kernel/k_scoped_resource_reservation.h" #include "core/hle/kernel/k_scoped_resource_reservation.h"
#include "core/hle/kernel/k_shared_memory.h" #include "core/hle/kernel/k_shared_memory.h"
#include "core/hle/kernel/k_shared_memory_info.h"
#include "core/hle/kernel/k_slab_heap.h" #include "core/hle/kernel/k_slab_heap.h"
#include "core/hle/kernel/k_thread.h" #include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/kernel.h" #include "core/hle/kernel/kernel.h"
@ -254,10 +255,26 @@ ResultCode KProcess::AddSharedMemory(KSharedMemory* shmem, [[maybe_unused]] VAdd
// Lock ourselves, to prevent concurrent access. // Lock ourselves, to prevent concurrent access.
KScopedLightLock lk(state_lock); KScopedLightLock lk(state_lock);
// TODO(bunnei): Manage KSharedMemoryInfo list here. // Try to find an existing info for the memory.
KSharedMemoryInfo* shemen_info = nullptr;
const auto iter = std::find_if(
shared_memory_list.begin(), shared_memory_list.end(),
[shmem](const KSharedMemoryInfo* info) { return info->GetSharedMemory() == shmem; });
if (iter != shared_memory_list.end()) {
shemen_info = *iter;
}
// Open a reference to the shared memory. if (shemen_info == nullptr) {
shemen_info = KSharedMemoryInfo::Allocate(kernel);
R_UNLESS(shemen_info != nullptr, ResultOutOfMemory);
shemen_info->Initialize(shmem);
shared_memory_list.push_back(shemen_info);
}
// Open a reference to the shared memory and its info.
shmem->Open(); shmem->Open();
shemen_info->Open();
return ResultSuccess; return ResultSuccess;
} }
@ -267,7 +284,20 @@ void KProcess::RemoveSharedMemory(KSharedMemory* shmem, [[maybe_unused]] VAddr a
// Lock ourselves, to prevent concurrent access. // Lock ourselves, to prevent concurrent access.
KScopedLightLock lk(state_lock); KScopedLightLock lk(state_lock);
// TODO(bunnei): Manage KSharedMemoryInfo list here. KSharedMemoryInfo* shemen_info = nullptr;
const auto iter = std::find_if(
shared_memory_list.begin(), shared_memory_list.end(),
[shmem](const KSharedMemoryInfo* info) { return info->GetSharedMemory() == shmem; });
if (iter != shared_memory_list.end()) {
shemen_info = *iter;
}
ASSERT(shemen_info != nullptr);
if (shemen_info->Close()) {
shared_memory_list.erase(iter);
KSharedMemoryInfo::Free(kernel, shemen_info);
}
// Close a reference to the shared memory. // Close a reference to the shared memory.
shmem->Close(); shmem->Close();
@ -412,6 +442,24 @@ void KProcess::Finalize() {
// Finalize the handle table and close any open handles. // Finalize the handle table and close any open handles.
handle_table.Finalize(); handle_table.Finalize();
// Free all shared memory infos.
{
auto it = shared_memory_list.begin();
while (it != shared_memory_list.end()) {
KSharedMemoryInfo* info = *it;
KSharedMemory* shmem = info->GetSharedMemory();
while (!info->Close()) {
shmem->Close();
}
shmem->Close();
it = shared_memory_list.erase(it);
KSharedMemoryInfo::Free(kernel, info);
}
}
// Perform inherited finalization. // Perform inherited finalization.
KAutoObjectWithSlabHeapAndContainer<KProcess, KSynchronizationObject>::Finalize(); KAutoObjectWithSlabHeapAndContainer<KProcess, KSynchronizationObject>::Finalize();
} }

View File

@ -34,6 +34,7 @@ class KernelCore;
class KPageTable; class KPageTable;
class KResourceLimit; class KResourceLimit;
class KThread; class KThread;
class KSharedMemoryInfo;
class TLSPage; class TLSPage;
struct CodeSet; struct CodeSet;
@ -448,6 +449,9 @@ private:
/// List of threads that are running with this process as their owner. /// List of threads that are running with this process as their owner.
std::list<const KThread*> thread_list; std::list<const KThread*> thread_list;
/// List of shared memory that are running with this process as their owner.
std::list<KSharedMemoryInfo*> shared_memory_list;
/// Address of the top of the main thread's stack /// Address of the top of the main thread's stack
VAddr main_thread_stack_top{}; VAddr main_thread_stack_top{};

View File

@ -0,0 +1,46 @@
// Copyright 2021 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <memory>
#include <string>
#include <boost/intrusive/list.hpp>
#include "common/assert.h"
#include "core/hle/kernel/slab_helpers.h"
namespace Kernel {
class KSharedMemory;
class KSharedMemoryInfo final : public KSlabAllocated<KSharedMemoryInfo>,
public boost::intrusive::list_base_hook<> {
public:
explicit KSharedMemoryInfo() = default;
constexpr void Initialize(KSharedMemory* shmem) {
shared_memory = shmem;
}
constexpr KSharedMemory* GetSharedMemory() const {
return shared_memory;
}
constexpr void Open() {
++reference_count;
}
constexpr bool Close() {
return (--reference_count) == 0;
}
private:
KSharedMemory* shared_memory{};
size_t reference_count{};
};
} // namespace Kernel

View File

@ -49,6 +49,7 @@ class KScheduler;
class KServerSession; class KServerSession;
class KSession; class KSession;
class KSharedMemory; class KSharedMemory;
class KSharedMemoryInfo;
class KThread; class KThread;
class KTransferMemory; class KTransferMemory;
class KWritableEvent; class KWritableEvent;
@ -309,6 +310,8 @@ public:
return slab_heap_container->session; return slab_heap_container->session;
} else if constexpr (std::is_same_v<T, KSharedMemory>) { } else if constexpr (std::is_same_v<T, KSharedMemory>) {
return slab_heap_container->shared_memory; return slab_heap_container->shared_memory;
} else if constexpr (std::is_same_v<T, KSharedMemoryInfo>) {
return slab_heap_container->shared_memory_info;
} else if constexpr (std::is_same_v<T, KThread>) { } else if constexpr (std::is_same_v<T, KThread>) {
return slab_heap_container->thread; return slab_heap_container->thread;
} else if constexpr (std::is_same_v<T, KTransferMemory>) { } else if constexpr (std::is_same_v<T, KTransferMemory>) {
@ -362,6 +365,7 @@ private:
KSlabHeap<KResourceLimit> resource_limit; KSlabHeap<KResourceLimit> resource_limit;
KSlabHeap<KSession> session; KSlabHeap<KSession> session;
KSlabHeap<KSharedMemory> shared_memory; KSlabHeap<KSharedMemory> shared_memory;
KSlabHeap<KSharedMemoryInfo> shared_memory_info;
KSlabHeap<KThread> thread; KSlabHeap<KThread> thread;
KSlabHeap<KTransferMemory> transfer_memory; KSlabHeap<KTransferMemory> transfer_memory;
KSlabHeap<KWritableEvent> writeable_event; KSlabHeap<KWritableEvent> writeable_event;

View File

@ -320,17 +320,19 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) {
auto& kernel = system.Kernel(); auto& kernel = system.Kernel();
KScopedAutoObject session =
kernel.CurrentProcess()->GetHandleTable().GetObject<KClientSession>(handle);
R_UNLESS(session.IsNotNull(), ResultInvalidHandle);
LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName());
auto thread = kernel.CurrentScheduler()->GetCurrentThread(); auto thread = kernel.CurrentScheduler()->GetCurrentThread();
{ {
KScopedSchedulerLock lock(kernel); KScopedSchedulerLock lock(kernel);
thread->SetState(ThreadState::Waiting); thread->SetState(ThreadState::Waiting);
thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC); thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC);
session->SendSyncRequest(thread, system.Memory(), system.CoreTiming());
{
KScopedAutoObject session =
kernel.CurrentProcess()->GetHandleTable().GetObject<KClientSession>(handle);
R_UNLESS(session.IsNotNull(), ResultInvalidHandle);
LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName());
session->SendSyncRequest(thread, system.Memory(), system.CoreTiming());
}
} }
KSynchronizationObject* dummy{}; KSynchronizationObject* dummy{};