From 2cb8aadafc4888a3ffd802f8eda33fde39e2aa7f Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Mon, 14 Oct 2019 23:12:07 -0700 Subject: [PATCH] pm: statically allocate more resources to save memory --- .../pm/source/impl/pm_process_manager.cpp | 55 ++++++++++++++++++- stratosphere/pm/source/pm_main.cpp | 4 +- 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/stratosphere/pm/source/impl/pm_process_manager.cpp b/stratosphere/pm/source/impl/pm_process_manager.cpp index b608c3550..881b3b689 100644 --- a/stratosphere/pm/source/impl/pm_process_manager.cpp +++ b/stratosphere/pm/source/impl/pm_process_manager.cpp @@ -138,6 +138,49 @@ namespace sts::pm::impl { } } + template + class ProcessInfoAllocator { + NON_COPYABLE(ProcessInfoAllocator); + NON_MOVEABLE(ProcessInfoAllocator); + static_assert(MaxProcessInfos >= 0x40, "MaxProcessInfos is too small."); + private: + TYPED_STORAGE(ProcessInfo) process_info_storages[MaxProcessInfos]; + bool process_info_allocated[MaxProcessInfos]; + os::Mutex lock; + private: + constexpr inline size_t GetProcessInfoIndex(ProcessInfo *process_info) const { + return process_info - GetPointer(this->process_info_storages[0]); + } + public: + constexpr ProcessInfoAllocator() { + std::memset(this->process_info_storages, 0, sizeof(this->process_info_storages)); + std::memset(this->process_info_allocated, 0, sizeof(this->process_info_allocated)); + } + + void *AllocateProcessInfoStorage() { + std::scoped_lock lk(this->lock); + for (size_t i = 0; i < MaxProcessInfos; i++) { + if (!this->process_info_allocated[i]) { + this->process_info_allocated[i] = true; + return GetPointer(this->process_info_storages[i]); + } + } + return nullptr; + } + + void FreeProcessInfo(ProcessInfo *process_info) { + std::scoped_lock lk(this->lock); + + const size_t index = this->GetProcessInfoIndex(process_info); + STS_ASSERT(index < MaxProcessInfos); + STS_ASSERT(this->process_info_allocated[index]); + + process_info->~ProcessInfo(); + std::memset(process_info, 0, sizeof(*process_info)); + this->process_info_allocated[index] = false; + } + }; + /* Process Tracking globals. */ os::Thread g_process_track_thread; @@ -145,6 +188,11 @@ namespace sts::pm::impl { ProcessList g_process_list; ProcessList g_dead_process_list; + /* Process Info Allocation. */ + /* Note: The kernel slabheap is size 0x50 -- we allow slightly larger to account for the dead process list. */ + constexpr size_t MaxProcessCount = 0x60; + ProcessInfoAllocator g_process_info_allocator; + /* Global events. */ os::SystemEvent g_process_event; os::SystemEvent g_hook_to_create_process_event; @@ -227,7 +275,7 @@ namespace sts::pm::impl { list->Remove(process_info); /* Delete the process. */ - delete process_info; + g_process_info_allocator.FreeProcessInfo(process_info); } Result LaunchProcess(os::WaitableManager &waitable_manager, const LaunchProcessArgs &args) { @@ -263,7 +311,9 @@ namespace sts::pm::impl { R_ASSERT(svcGetProcessId(&process_id.value, process_handle)); /* Make new process info. */ - ProcessInfo *process_info = new ProcessInfo(process_handle, process_id, pin_id, location); + void *process_info_storage = g_process_info_allocator.AllocateProcessInfoStorage(); + STS_ASSERT(process_info_storage != nullptr); + ProcessInfo *process_info = new (process_info_storage) ProcessInfo(process_handle, process_id, pin_id, location); /* Link new process info. */ { @@ -418,6 +468,7 @@ namespace sts::pm::impl { R_TRY(resource::InitializeResourceManager()); /* Start thread. */ + /* TODO: Allocate thread stack resources statically, will require PR to libnx. */ R_ASSERT(g_process_track_thread.Initialize(&ProcessTrackingMain, nullptr, 0x4000, 0x15)); R_ASSERT(g_process_track_thread.Start()); diff --git a/stratosphere/pm/source/pm_main.cpp b/stratosphere/pm/source/pm_main.cpp index 608445755..854933f90 100644 --- a/stratosphere/pm/source/pm_main.cpp +++ b/stratosphere/pm/source/pm_main.cpp @@ -37,7 +37,9 @@ extern "C" { u32 __nx_applet_type = AppletType_None; u32 __nx_fs_num_sessions = 1; - #define INNER_HEAP_SIZE 0x40000 + /* TODO: Statically allocate PM resource thread stack, reduce this. */ + /* TODO: Determine what the minimum consistent value for this is (dump heap at runtime). */ + #define INNER_HEAP_SIZE 0xC000 size_t nx_inner_heap_size = INNER_HEAP_SIZE; char nx_inner_heap[INNER_HEAP_SIZE];