forked from suyu/suyu
Merge pull request #7091 from vonchenplus/fix_memroy_leak
core: Fix memory leak
This commit is contained in:
commit
01f79d638f
6 changed files with 114 additions and 9 deletions
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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{};
|
||||||
|
|
||||||
|
|
46
src/core/hle/kernel/k_shared_memory_info.h
Normal file
46
src/core/hle/kernel/k_shared_memory_info.h
Normal 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
|
|
@ -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;
|
||||||
|
|
|
@ -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{};
|
||||||
|
|
Loading…
Reference in a new issue