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_shared_memory.cpp
|
||||
hle/kernel/k_shared_memory.h
|
||||
hle/kernel/k_shared_memory_info.h
|
||||
hle/kernel/k_slab_heap.h
|
||||
hle/kernel/k_spin_lock.cpp
|
||||
hle/kernel/k_spin_lock.h
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "core/hle/kernel/k_scheduler.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_info.h"
|
||||
#include "core/hle/kernel/k_slab_heap.h"
|
||||
#include "core/hle/kernel/k_thread.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.
|
||||
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();
|
||||
shemen_info->Open();
|
||||
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
@ -267,7 +284,20 @@ void KProcess::RemoveSharedMemory(KSharedMemory* shmem, [[maybe_unused]] VAddr a
|
|||
// Lock ourselves, to prevent concurrent access.
|
||||
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.
|
||||
shmem->Close();
|
||||
|
@ -412,6 +442,24 @@ void KProcess::Finalize() {
|
|||
// Finalize the handle table and close any open handles.
|
||||
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.
|
||||
KAutoObjectWithSlabHeapAndContainer<KProcess, KSynchronizationObject>::Finalize();
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ class KernelCore;
|
|||
class KPageTable;
|
||||
class KResourceLimit;
|
||||
class KThread;
|
||||
class KSharedMemoryInfo;
|
||||
class TLSPage;
|
||||
|
||||
struct CodeSet;
|
||||
|
@ -448,6 +449,9 @@ private:
|
|||
/// List of threads that are running with this process as their owner.
|
||||
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
|
||||
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 KSession;
|
||||
class KSharedMemory;
|
||||
class KSharedMemoryInfo;
|
||||
class KThread;
|
||||
class KTransferMemory;
|
||||
class KWritableEvent;
|
||||
|
@ -309,6 +310,8 @@ public:
|
|||
return slab_heap_container->session;
|
||||
} else if constexpr (std::is_same_v<T, KSharedMemory>) {
|
||||
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>) {
|
||||
return slab_heap_container->thread;
|
||||
} else if constexpr (std::is_same_v<T, KTransferMemory>) {
|
||||
|
@ -362,6 +365,7 @@ private:
|
|||
KSlabHeap<KResourceLimit> resource_limit;
|
||||
KSlabHeap<KSession> session;
|
||||
KSlabHeap<KSharedMemory> shared_memory;
|
||||
KSlabHeap<KSharedMemoryInfo> shared_memory_info;
|
||||
KSlabHeap<KThread> thread;
|
||||
KSlabHeap<KTransferMemory> transfer_memory;
|
||||
KSlabHeap<KWritableEvent> writeable_event;
|
||||
|
|
|
@ -320,18 +320,20 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) {
|
|||
|
||||
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();
|
||||
{
|
||||
KScopedSchedulerLock lock(kernel);
|
||||
thread->SetState(ThreadState::Waiting);
|
||||
thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC);
|
||||
|
||||
{
|
||||
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{};
|
||||
return thread->GetWaitResult(std::addressof(dummy));
|
||||
|
|
Loading…
Reference in a new issue