diff options
Diffstat (limited to 'src/core/hle')
-rw-r--r-- | src/core/hle/kernel/k_memory_block_manager.cpp | 4 | ||||
-rw-r--r-- | src/core/hle/kernel/k_memory_block_manager.h | 4 | ||||
-rw-r--r-- | src/core/hle/kernel/k_page_table_base.cpp | 34 | ||||
-rw-r--r-- | src/core/hle/kernel/k_page_table_base.h | 1 | ||||
-rw-r--r-- | src/core/hle/kernel/k_process.cpp | 6 | ||||
-rw-r--r-- | src/core/hle/kernel/kernel.cpp | 31 | ||||
-rw-r--r-- | src/core/hle/kernel/kernel.h | 6 | ||||
-rw-r--r-- | src/core/hle/kernel/svc/svc_process.cpp | 8 | ||||
-rw-r--r-- | src/core/hle/service/glue/arp.cpp | 7 | ||||
-rw-r--r-- | src/core/hle/service/hid/hid.cpp | 10 | ||||
-rw-r--r-- | src/core/hle/service/pm/pm.cpp | 85 |
11 files changed, 124 insertions, 72 deletions
diff --git a/src/core/hle/kernel/k_memory_block_manager.cpp b/src/core/hle/kernel/k_memory_block_manager.cpp index 58a1e7216..f08a6e448 100644 --- a/src/core/hle/kernel/k_memory_block_manager.cpp +++ b/src/core/hle/kernel/k_memory_block_manager.cpp @@ -28,14 +28,14 @@ Result KMemoryBlockManager::Initialize(KProcessAddress st, KProcessAddress nd, } void KMemoryBlockManager::Finalize(KMemoryBlockSlabManager* slab_manager, - HostUnmapCallback&& host_unmap_callback) { + BlockCallback&& block_callback) { // Erase every block until we have none left. auto it = m_memory_block_tree.begin(); while (it != m_memory_block_tree.end()) { KMemoryBlock* block = std::addressof(*it); it = m_memory_block_tree.erase(it); + block_callback(block->GetAddress(), block->GetSize()); slab_manager->Free(block); - host_unmap_callback(block->GetAddress(), block->GetSize()); } ASSERT(m_memory_block_tree.empty()); diff --git a/src/core/hle/kernel/k_memory_block_manager.h b/src/core/hle/kernel/k_memory_block_manager.h index cb7b6f430..377628504 100644 --- a/src/core/hle/kernel/k_memory_block_manager.h +++ b/src/core/hle/kernel/k_memory_block_manager.h @@ -85,11 +85,11 @@ public: public: KMemoryBlockManager(); - using HostUnmapCallback = std::function<void(Common::ProcessAddress, u64)>; + using BlockCallback = std::function<void(Common::ProcessAddress, u64)>; Result Initialize(KProcessAddress st, KProcessAddress nd, KMemoryBlockSlabManager* slab_manager); - void Finalize(KMemoryBlockSlabManager* slab_manager, HostUnmapCallback&& host_unmap_callback); + void Finalize(KMemoryBlockSlabManager* slab_manager, BlockCallback&& block_callback); iterator end() { return m_memory_block_tree.end(); diff --git a/src/core/hle/kernel/k_page_table_base.cpp b/src/core/hle/kernel/k_page_table_base.cpp index 73fbda331..3f0a39d33 100644 --- a/src/core/hle/kernel/k_page_table_base.cpp +++ b/src/core/hle/kernel/k_page_table_base.cpp @@ -431,15 +431,43 @@ Result KPageTableBase::InitializeForProcess(Svc::CreateProcessFlag as_type, bool m_memory_block_slab_manager)); } +Result KPageTableBase::FinalizeProcess() { + // Only process tables should be finalized. + ASSERT(!this->IsKernel()); + + // NOTE: Here Nintendo calls an unknown OnFinalize function. + // this->OnFinalize(); + + // NOTE: Here Nintendo calls a second unknown OnFinalize function. + // this->OnFinalize2(); + + // NOTE: Here Nintendo does a page table walk to discover heap pages to free. + // We will use the block manager finalization below to free them. + + R_SUCCEED(); +} + void KPageTableBase::Finalize() { - auto HostUnmapCallback = [&](KProcessAddress addr, u64 size) { - if (Settings::IsFastmemEnabled()) { + this->FinalizeProcess(); + + auto BlockCallback = [&](KProcessAddress addr, u64 size) { + if (m_impl->fastmem_arena) { m_system.DeviceMemory().buffer.Unmap(GetInteger(addr), size, false); } + + // Get physical pages. + KPageGroup pg(m_kernel, m_block_info_manager); + this->MakePageGroup(pg, addr, size / PageSize); + + // Free the pages. + pg.CloseAndReset(); }; // Finalize memory blocks. - m_memory_block_manager.Finalize(m_memory_block_slab_manager, std::move(HostUnmapCallback)); + { + KScopedLightLock lk(m_general_lock); + m_memory_block_manager.Finalize(m_memory_block_slab_manager, std::move(BlockCallback)); + } // Free any unsafe mapped memory. if (m_mapped_unsafe_physical_memory) { diff --git a/src/core/hle/kernel/k_page_table_base.h b/src/core/hle/kernel/k_page_table_base.h index 077cafc96..748419f86 100644 --- a/src/core/hle/kernel/k_page_table_base.h +++ b/src/core/hle/kernel/k_page_table_base.h @@ -241,6 +241,7 @@ public: KResourceLimit* resource_limit, Core::Memory::Memory& memory, KProcessAddress aslr_space_start); + Result FinalizeProcess(); void Finalize(); bool IsKernel() const { diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index 068e71dff..ae332a550 100644 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp @@ -171,6 +171,12 @@ void KProcess::Finalize() { m_resource_limit->Close(); } + // Clear expensive resources, as the destructor is not called for guest objects. + for (auto& interface : m_arm_interfaces) { + interface.reset(); + } + m_exclusive_monitor.reset(); + // Perform inherited finalization. KSynchronizationObject::Finalize(); } diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 1030f0c12..f3683cdcc 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -112,7 +112,14 @@ struct KernelCore::Impl { old_process->Close(); } - process_list.clear(); + { + std::scoped_lock lk{process_list_lock}; + for (auto* const process : process_list) { + process->Terminate(); + process->Close(); + } + process_list.clear(); + } next_object_id = 0; next_kernel_process_id = KProcess::InitialProcessIdMin; @@ -770,6 +777,7 @@ struct KernelCore::Impl { std::atomic<u64> next_thread_id{1}; // Lists all processes that exist in the current session. + std::mutex process_list_lock; std::vector<KProcess*> process_list; std::atomic<KProcess*> application_process{}; std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context; @@ -869,9 +877,19 @@ KResourceLimit* KernelCore::GetSystemResourceLimit() { } void KernelCore::AppendNewProcess(KProcess* process) { + process->Open(); + + std::scoped_lock lk{impl->process_list_lock}; impl->process_list.push_back(process); } +void KernelCore::RemoveProcess(KProcess* process) { + std::scoped_lock lk{impl->process_list_lock}; + if (std::erase(impl->process_list, process)) { + process->Close(); + } +} + void KernelCore::MakeApplicationProcess(KProcess* process) { impl->MakeApplicationProcess(process); } @@ -884,8 +902,15 @@ const KProcess* KernelCore::ApplicationProcess() const { return impl->application_process; } -const std::vector<KProcess*>& KernelCore::GetProcessList() const { - return impl->process_list; +std::list<KScopedAutoObject<KProcess>> KernelCore::GetProcessList() { + std::list<KScopedAutoObject<KProcess>> processes; + std::scoped_lock lk{impl->process_list_lock}; + + for (auto* const process : impl->process_list) { + processes.emplace_back(process); + } + + return processes; } Kernel::GlobalSchedulerContext& KernelCore::GlobalSchedulerContext() { diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 5d4102145..8ea5bed1c 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -5,6 +5,7 @@ #include <array> #include <functional> +#include <list> #include <memory> #include <string> #include <unordered_map> @@ -116,8 +117,9 @@ public: /// Retrieves a shared pointer to the system resource limit instance. KResourceLimit* GetSystemResourceLimit(); - /// Adds the given shared pointer to an internal list of active processes. + /// Adds/removes the given pointer to an internal list of active processes. void AppendNewProcess(KProcess* process); + void RemoveProcess(KProcess* process); /// Makes the given process the new application process. void MakeApplicationProcess(KProcess* process); @@ -129,7 +131,7 @@ public: const KProcess* ApplicationProcess() const; /// Retrieves the list of processes. - const std::vector<KProcess*>& GetProcessList() const; + std::list<KScopedAutoObject<KProcess>> GetProcessList(); /// Gets the sole instance of the global scheduler Kernel::GlobalSchedulerContext& GlobalSchedulerContext(); diff --git a/src/core/hle/kernel/svc/svc_process.cpp b/src/core/hle/kernel/svc/svc_process.cpp index caa8bee9a..5c3e8829f 100644 --- a/src/core/hle/kernel/svc/svc_process.cpp +++ b/src/core/hle/kernel/svc/svc_process.cpp @@ -74,13 +74,15 @@ Result GetProcessList(Core::System& system, s32* out_num_processes, u64 out_proc } auto& memory = GetCurrentMemory(kernel); - const auto& process_list = kernel.GetProcessList(); + auto process_list = kernel.GetProcessList(); + auto it = process_list.begin(); + const auto num_processes = process_list.size(); const auto copy_amount = std::min(static_cast<std::size_t>(out_process_ids_size), num_processes); - for (std::size_t i = 0; i < copy_amount; ++i) { - memory.Write64(out_process_ids, process_list[i]->GetProcessId()); + for (std::size_t i = 0; i < copy_amount && it != process_list.end(); ++i, ++it) { + memory.Write64(out_process_ids, (*it)->GetProcessId()); out_process_ids += sizeof(u64); } diff --git a/src/core/hle/service/glue/arp.cpp b/src/core/hle/service/glue/arp.cpp index 6f1151b03..1254b6d49 100644 --- a/src/core/hle/service/glue/arp.cpp +++ b/src/core/hle/service/glue/arp.cpp @@ -15,9 +15,10 @@ namespace Service::Glue { namespace { -std::optional<u64> GetTitleIDForProcessID(const Core::System& system, u64 process_id) { - const auto& list = system.Kernel().GetProcessList(); - const auto iter = std::find_if(list.begin(), list.end(), [&process_id](const auto& process) { +std::optional<u64> GetTitleIDForProcessID(Core::System& system, u64 process_id) { + auto list = system.Kernel().GetProcessList(); + + const auto iter = std::find_if(list.begin(), list.end(), [&process_id](auto& process) { return process->GetProcessId() == process_id; }); diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index fc03a0a5f..4ce0a9834 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -22,12 +22,10 @@ void LoopProcess(Core::System& system) { std::shared_ptr<HidFirmwareSettings> firmware_settings = std::make_shared<HidFirmwareSettings>(); - // TODO: Remove this hack until this service is emulated properly. - const auto process_list = system.Kernel().GetProcessList(); - if (!process_list.empty()) { - resource_manager->Initialize(); - resource_manager->RegisterAppletResourceUserId(process_list[0]->GetId(), true); - } + // TODO: Remove this hack when am is emulated properly. + resource_manager->Initialize(); + resource_manager->RegisterAppletResourceUserId(system.ApplicationProcess()->GetProcessId(), + true); server_manager->RegisterNamedService( "hid", std::make_shared<IHidServer>(system, resource_manager, firmware_settings)); diff --git a/src/core/hle/service/pm/pm.cpp b/src/core/hle/service/pm/pm.cpp index d92499f05..b52468e41 100644 --- a/src/core/hle/service/pm/pm.cpp +++ b/src/core/hle/service/pm/pm.cpp @@ -22,27 +22,26 @@ constexpr Result ResultProcessNotFound{ErrorModule::PM, 1}; constexpr u64 NO_PROCESS_FOUND_PID{0}; -std::optional<Kernel::KProcess*> SearchProcessList( - const std::vector<Kernel::KProcess*>& process_list, - std::function<bool(Kernel::KProcess*)> predicate) { +using ProcessList = std::list<Kernel::KScopedAutoObject<Kernel::KProcess>>; + +template <typename F> +Kernel::KScopedAutoObject<Kernel::KProcess> SearchProcessList(ProcessList& process_list, + F&& predicate) { const auto iter = std::find_if(process_list.begin(), process_list.end(), predicate); if (iter == process_list.end()) { - return std::nullopt; + return nullptr; } - return *iter; + return iter->GetPointerUnsafe(); } -void GetApplicationPidGeneric(HLERequestContext& ctx, - const std::vector<Kernel::KProcess*>& process_list) { - const auto process = SearchProcessList(process_list, [](const auto& proc) { - return proc->GetProcessId() == Kernel::KProcess::ProcessIdMin; - }); +void GetApplicationPidGeneric(HLERequestContext& ctx, ProcessList& process_list) { + auto process = SearchProcessList(process_list, [](auto& p) { return p->IsApplication(); }); IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); - rb.Push(process.has_value() ? (*process)->GetProcessId() : NO_PROCESS_FOUND_PID); + rb.Push(process.IsNull() ? NO_PROCESS_FOUND_PID : process->GetProcessId()); } } // Anonymous namespace @@ -80,8 +79,7 @@ private: class DebugMonitor final : public ServiceFramework<DebugMonitor> { public: - explicit DebugMonitor(Core::System& system_) - : ServiceFramework{system_, "pm:dmnt"}, kernel{system_.Kernel()} { + explicit DebugMonitor(Core::System& system_) : ServiceFramework{system_, "pm:dmnt"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetJitDebugProcessIdList"}, @@ -106,12 +104,11 @@ private: LOG_DEBUG(Service_PM, "called, program_id={:016X}", program_id); - const auto process = - SearchProcessList(kernel.GetProcessList(), [program_id](const auto& proc) { - return proc->GetProgramId() == program_id; - }); + auto list = kernel.GetProcessList(); + auto process = SearchProcessList( + list, [program_id](auto& p) { return p->GetProgramId() == program_id; }); - if (!process.has_value()) { + if (process.IsNull()) { IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultProcessNotFound); return; @@ -119,12 +116,13 @@ private: IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); - rb.Push((*process)->GetProcessId()); + rb.Push(process->GetProcessId()); } void GetApplicationProcessId(HLERequestContext& ctx) { LOG_DEBUG(Service_PM, "called"); - GetApplicationPidGeneric(ctx, kernel.GetProcessList()); + auto list = kernel.GetProcessList(); + GetApplicationPidGeneric(ctx, list); } void AtmosphereGetProcessInfo(HLERequestContext& ctx) { @@ -135,11 +133,10 @@ private: LOG_WARNING(Service_PM, "(Partial Implementation) called, pid={:016X}", pid); - const auto process = SearchProcessList(kernel.GetProcessList(), [pid](const auto& proc) { - return proc->GetProcessId() == pid; - }); + auto list = kernel.GetProcessList(); + auto process = SearchProcessList(list, [pid](auto& p) { return p->GetProcessId() == pid; }); - if (!process.has_value()) { + if (process.IsNull()) { IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultProcessNotFound); return; @@ -159,7 +156,7 @@ private: OverrideStatus override_status{}; ProgramLocation program_location{ - .program_id = (*process)->GetProgramId(), + .program_id = process->GetProgramId(), .storage_id = 0, }; @@ -169,14 +166,11 @@ private: rb.PushRaw(program_location); rb.PushRaw(override_status); } - - const Kernel::KernelCore& kernel; }; class Info final : public ServiceFramework<Info> { public: - explicit Info(Core::System& system_, const std::vector<Kernel::KProcess*>& process_list_) - : ServiceFramework{system_, "pm:info"}, process_list{process_list_} { + explicit Info(Core::System& system_) : ServiceFramework{system_, "pm:info"} { static const FunctionInfo functions[] = { {0, &Info::GetProgramId, "GetProgramId"}, {65000, &Info::AtmosphereGetProcessId, "AtmosphereGetProcessId"}, @@ -193,11 +187,11 @@ private: LOG_DEBUG(Service_PM, "called, process_id={:016X}", process_id); - const auto process = SearchProcessList(process_list, [process_id](const auto& proc) { - return proc->GetProcessId() == process_id; - }); + auto list = kernel.GetProcessList(); + auto process = SearchProcessList( + list, [process_id](auto& p) { return p->GetProcessId() == process_id; }); - if (!process.has_value()) { + if (process.IsNull()) { IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultProcessNotFound); return; @@ -205,7 +199,7 @@ private: IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); - rb.Push((*process)->GetProgramId()); + rb.Push(process->GetProgramId()); } void AtmosphereGetProcessId(HLERequestContext& ctx) { @@ -214,11 +208,11 @@ private: LOG_DEBUG(Service_PM, "called, program_id={:016X}", program_id); - const auto process = SearchProcessList(process_list, [program_id](const auto& proc) { - return proc->GetProgramId() == program_id; - }); + auto list = system.Kernel().GetProcessList(); + auto process = SearchProcessList( + list, [program_id](auto& p) { return p->GetProgramId() == program_id; }); - if (!process.has_value()) { + if (process.IsNull()) { IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultProcessNotFound); return; @@ -226,16 +220,13 @@ private: IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); - rb.Push((*process)->GetProcessId()); + rb.Push(process->GetProcessId()); } - - const std::vector<Kernel::KProcess*>& process_list; }; class Shell final : public ServiceFramework<Shell> { public: - explicit Shell(Core::System& system_) - : ServiceFramework{system_, "pm:shell"}, kernel{system_.Kernel()} { + explicit Shell(Core::System& system_) : ServiceFramework{system_, "pm:shell"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "LaunchProgram"}, @@ -257,10 +248,9 @@ public: private: void GetApplicationProcessIdForShell(HLERequestContext& ctx) { LOG_DEBUG(Service_PM, "called"); - GetApplicationPidGeneric(ctx, kernel.GetProcessList()); + auto list = kernel.GetProcessList(); + GetApplicationPidGeneric(ctx, list); } - - const Kernel::KernelCore& kernel; }; void LoopProcess(Core::System& system) { @@ -268,8 +258,7 @@ void LoopProcess(Core::System& system) { server_manager->RegisterNamedService("pm:bm", std::make_shared<BootMode>(system)); server_manager->RegisterNamedService("pm:dmnt", std::make_shared<DebugMonitor>(system)); - server_manager->RegisterNamedService( - "pm:info", std::make_shared<Info>(system, system.Kernel().GetProcessList())); + server_manager->RegisterNamedService("pm:info", std::make_shared<Info>(system)); server_manager->RegisterNamedService("pm:shell", std::make_shared<Shell>(system)); ServerManager::RunServer(std::move(server_manager)); } |