diff --git a/README.md b/README.md index 5a36afe95..8f2fb7ac9 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ yuzu emulator early access ============= -This is the source code for early-access 4059. +This is the source code for early-access 4060. ## Legal Notice diff --git a/src/common/page_table.cpp b/src/common/page_table.cpp index 45f937486..b86c78c38 100755 --- a/src/common/page_table.cpp +++ b/src/common/page_table.cpp @@ -2,7 +2,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "common/page_table.h" -#include "common/scope_exit.h" namespace Common { @@ -12,10 +11,29 @@ PageTable::~PageTable() noexcept = default; bool PageTable::BeginTraversal(TraversalEntry* out_entry, TraversalContext* out_context, Common::ProcessAddress address) const { - out_context->next_offset = GetInteger(address); - out_context->next_page = address / page_size; + // Setup invalid defaults. + out_entry->phys_addr = 0; + out_entry->block_size = page_size; + out_context->next_page = 0; - return this->ContinueTraversal(out_entry, out_context); + // Validate that we can read the actual entry. + const auto page = address / page_size; + if (page >= backing_addr.size()) { + return false; + } + + // Validate that the entry is mapped. + const auto phys_addr = backing_addr[page]; + if (phys_addr == 0) { + return false; + } + + // Populate the results. + out_entry->phys_addr = phys_addr + GetInteger(address); + out_context->next_page = page + 1; + out_context->next_offset = GetInteger(address) + page_size; + + return true; } bool PageTable::ContinueTraversal(TraversalEntry* out_entry, TraversalContext* context) const { @@ -23,12 +41,6 @@ bool PageTable::ContinueTraversal(TraversalEntry* out_entry, TraversalContext* c out_entry->phys_addr = 0; out_entry->block_size = page_size; - // Regardless of whether the page was mapped, advance on exit. - SCOPE_EXIT({ - context->next_page += 1; - context->next_offset += page_size; - }); - // Validate that we can read the actual entry. const auto page = context->next_page; if (page >= backing_addr.size()) { @@ -43,6 +55,8 @@ bool PageTable::ContinueTraversal(TraversalEntry* out_entry, TraversalContext* c // Populate the results. out_entry->phys_addr = phys_addr + context->next_offset; + context->next_page = page + 1; + context->next_offset += page_size; return true; } diff --git a/src/core/debugger/debugger.cpp b/src/core/debugger/debugger.cpp index c887046f7..76275f5fd 100755 --- a/src/core/debugger/debugger.cpp +++ b/src/core/debugger/debugger.cpp @@ -114,7 +114,7 @@ public: } Kernel::KThread* GetActiveThread() override { - return state->active_thread.GetPointerUnsafe(); + return state->active_thread; } private: @@ -147,14 +147,11 @@ private: std::scoped_lock lk{connection_lock}; - // Find the process we are going to debug. - SetDebugProcess(); - // Ensure everything is stopped. PauseEmulation(); // Set up the new frontend. - frontend = std::make_unique(*this, system, debug_process.GetPointerUnsafe()); + frontend = std::make_unique(*this, system); // Set the new state. This will tear down any existing state. state = ConnectionState{ @@ -197,20 +194,15 @@ private: UpdateActiveThread(); if (state->info.type == SignalType::Watchpoint) { - frontend->Watchpoint(std::addressof(*state->active_thread), - *state->info.watchpoint); + frontend->Watchpoint(state->active_thread, *state->info.watchpoint); } else { - frontend->Stopped(std::addressof(*state->active_thread)); + frontend->Stopped(state->active_thread); } break; case SignalType::ShuttingDown: frontend->ShuttingDown(); - // Release members. - state->active_thread.Reset(nullptr); - debug_process.Reset(nullptr); - // Wait for emulation to shut down gracefully now. state->signal_pipe.close(); state->client_socket.shutdown(boost::asio::socket_base::shutdown_both); @@ -230,7 +222,7 @@ private: stopped = true; PauseEmulation(); UpdateActiveThread(); - frontend->Stopped(state->active_thread.GetPointerUnsafe()); + frontend->Stopped(state->active_thread); break; } case DebuggerAction::Continue: @@ -240,7 +232,7 @@ private: MarkResumed([&] { state->active_thread->SetStepState(Kernel::StepState::StepPending); state->active_thread->Resume(Kernel::SuspendType::Debug); - ResumeEmulation(state->active_thread.GetPointerUnsafe()); + ResumeEmulation(state->active_thread); }); break; case DebuggerAction::StepThreadLocked: { @@ -263,7 +255,6 @@ private: } void PauseEmulation() { - Kernel::KScopedLightLock ll{debug_process->GetListLock()}; Kernel::KScopedSchedulerLock sl{system.Kernel()}; // Put all threads to sleep on next scheduler round. @@ -273,9 +264,6 @@ private: } void ResumeEmulation(Kernel::KThread* except = nullptr) { - Kernel::KScopedLightLock ll{debug_process->GetListLock()}; - Kernel::KScopedSchedulerLock sl{system.Kernel()}; - // Wake up all threads. for (auto& thread : ThreadList()) { if (std::addressof(thread) == except) { @@ -289,16 +277,15 @@ private: template void MarkResumed(Callback&& cb) { + Kernel::KScopedSchedulerLock sl{system.Kernel()}; stopped = false; cb(); } void UpdateActiveThread() { - Kernel::KScopedLightLock ll{debug_process->GetListLock()}; - auto& threads{ThreadList()}; for (auto& thread : threads) { - if (std::addressof(thread) == state->active_thread.GetPointerUnsafe()) { + if (std::addressof(thread) == state->active_thread) { // Thread is still alive, no need to update. return; } @@ -306,18 +293,12 @@ private: state->active_thread = std::addressof(threads.front()); } -private: - void SetDebugProcess() { - debug_process = std::move(system.Kernel().GetProcessList().back()); - } - Kernel::KProcess::ThreadList& ThreadList() { - return debug_process->GetThreadList(); + return system.ApplicationProcess()->GetThreadList(); } private: System& system; - Kernel::KScopedAutoObject debug_process; std::unique_ptr frontend; boost::asio::io_context io_context; @@ -329,7 +310,7 @@ private: boost::process::async_pipe signal_pipe; SignalInfo info; - Kernel::KScopedAutoObject active_thread; + Kernel::KThread* active_thread; std::array client_data; bool pipe_data; }; diff --git a/src/core/debugger/gdbstub.cpp b/src/core/debugger/gdbstub.cpp index 6756c17c0..65119c30f 100755 --- a/src/core/debugger/gdbstub.cpp +++ b/src/core/debugger/gdbstub.cpp @@ -108,9 +108,9 @@ static std::string EscapeXML(std::string_view data) { return escaped; } -GDBStub::GDBStub(DebuggerBackend& backend_, Core::System& system_, Kernel::KProcess* debug_process_) - : DebuggerFrontend(backend_), system{system_}, debug_process{debug_process_} { - if (GetProcess()->Is64Bit()) { +GDBStub::GDBStub(DebuggerBackend& backend_, Core::System& system_) + : DebuggerFrontend(backend_), system{system_} { + if (system.ApplicationProcess()->Is64Bit()) { arch = std::make_unique(); } else { arch = std::make_unique(); @@ -276,7 +276,7 @@ void GDBStub::ExecuteCommand(std::string_view packet, std::vector(strtoll(command.data() + sep, nullptr, 16))}; std::vector mem(size); - if (GetMemory().ReadBlock(addr, mem.data(), size)) { + if (system.ApplicationMemory().ReadBlock(addr, mem.data(), size)) { // Restore any bytes belonging to replaced instructions. auto it = replaced_instructions.lower_bound(addr); for (; it != replaced_instructions.end() && it->first < addr + size; it++) { @@ -310,8 +310,8 @@ void GDBStub::ExecuteCommand(std::string_view packet, std::vector(strtoll(command.data() + addr_sep, nullptr, 16))}; const size_t size{static_cast(strtoll(command.data() + size_sep, nullptr, 16))}; - if (!GetMemory().IsValidVirtualAddressRange(addr, size)) { + if (!system.ApplicationMemory().IsValidVirtualAddressRange(addr, size)) { SendReply(GDB_STUB_REPLY_ERR); return; } @@ -362,20 +362,22 @@ void GDBStub::HandleBreakpointInsert(std::string_view command) { switch (type) { case BreakpointType::Software: - replaced_instructions[addr] = GetMemory().Read32(addr); - GetMemory().Write32(addr, arch->BreakpointInstruction()); - Core::InvalidateInstructionCacheRange(GetProcess(), addr, sizeof(u32)); + replaced_instructions[addr] = system.ApplicationMemory().Read32(addr); + system.ApplicationMemory().Write32(addr, arch->BreakpointInstruction()); + Core::InvalidateInstructionCacheRange(system.ApplicationProcess(), addr, sizeof(u32)); success = true; break; case BreakpointType::WriteWatch: - success = GetProcess()->InsertWatchpoint(addr, size, Kernel::DebugWatchpointType::Write); + success = system.ApplicationProcess()->InsertWatchpoint(addr, size, + Kernel::DebugWatchpointType::Write); break; case BreakpointType::ReadWatch: - success = GetProcess()->InsertWatchpoint(addr, size, Kernel::DebugWatchpointType::Read); + success = system.ApplicationProcess()->InsertWatchpoint(addr, size, + Kernel::DebugWatchpointType::Read); break; case BreakpointType::AccessWatch: - success = - GetProcess()->InsertWatchpoint(addr, size, Kernel::DebugWatchpointType::ReadOrWrite); + success = system.ApplicationProcess()->InsertWatchpoint( + addr, size, Kernel::DebugWatchpointType::ReadOrWrite); break; case BreakpointType::Hardware: default: @@ -398,7 +400,7 @@ void GDBStub::HandleBreakpointRemove(std::string_view command) { const size_t addr{static_cast(strtoll(command.data() + addr_sep, nullptr, 16))}; const size_t size{static_cast(strtoll(command.data() + size_sep, nullptr, 16))}; - if (!GetMemory().IsValidVirtualAddressRange(addr, size)) { + if (!system.ApplicationMemory().IsValidVirtualAddressRange(addr, size)) { SendReply(GDB_STUB_REPLY_ERR); return; } @@ -409,22 +411,24 @@ void GDBStub::HandleBreakpointRemove(std::string_view command) { case BreakpointType::Software: { const auto orig_insn{replaced_instructions.find(addr)}; if (orig_insn != replaced_instructions.end()) { - GetMemory().Write32(addr, orig_insn->second); - Core::InvalidateInstructionCacheRange(GetProcess(), addr, sizeof(u32)); + system.ApplicationMemory().Write32(addr, orig_insn->second); + Core::InvalidateInstructionCacheRange(system.ApplicationProcess(), addr, sizeof(u32)); replaced_instructions.erase(addr); success = true; } break; } case BreakpointType::WriteWatch: - success = GetProcess()->RemoveWatchpoint(addr, size, Kernel::DebugWatchpointType::Write); + success = system.ApplicationProcess()->RemoveWatchpoint(addr, size, + Kernel::DebugWatchpointType::Write); break; case BreakpointType::ReadWatch: - success = GetProcess()->RemoveWatchpoint(addr, size, Kernel::DebugWatchpointType::Read); + success = system.ApplicationProcess()->RemoveWatchpoint(addr, size, + Kernel::DebugWatchpointType::Read); break; case BreakpointType::AccessWatch: - success = - GetProcess()->RemoveWatchpoint(addr, size, Kernel::DebugWatchpointType::ReadOrWrite); + success = system.ApplicationProcess()->RemoveWatchpoint( + addr, size, Kernel::DebugWatchpointType::ReadOrWrite); break; case BreakpointType::Hardware: default: @@ -462,10 +466,10 @@ void GDBStub::HandleQuery(std::string_view command) { const auto target_xml{arch->GetTargetXML()}; SendReply(PaginateBuffer(target_xml, command.substr(30))); } else if (command.starts_with("Offsets")) { - const auto main_offset = Core::FindMainModuleEntrypoint(GetProcess()); + const auto main_offset = Core::FindMainModuleEntrypoint(system.ApplicationProcess()); SendReply(fmt::format("TextSeg={:x}", GetInteger(main_offset))); } else if (command.starts_with("Xfer:libraries:read::")) { - auto modules = Core::FindModules(GetProcess()); + auto modules = Core::FindModules(system.ApplicationProcess()); std::string buffer; buffer += R"()"; @@ -479,7 +483,7 @@ void GDBStub::HandleQuery(std::string_view command) { SendReply(PaginateBuffer(buffer, command.substr(21))); } else if (command.starts_with("fThreadInfo")) { // beginning of list - const auto& threads = GetProcess()->GetThreadList(); + const auto& threads = system.ApplicationProcess()->GetThreadList(); std::vector thread_ids; for (const auto& thread : threads) { thread_ids.push_back(fmt::format("{:x}", thread.GetThreadId())); @@ -493,7 +497,7 @@ void GDBStub::HandleQuery(std::string_view command) { buffer += R"()"; buffer += ""; - const auto& threads = GetProcess()->GetThreadList(); + const auto& threads = system.ApplicationProcess()->GetThreadList(); for (const auto& thread : threads) { auto thread_name{Core::GetThreadName(&thread)}; if (!thread_name) { @@ -609,7 +613,7 @@ void GDBStub::HandleRcmd(const std::vector& command) { std::string_view command_str{reinterpret_cast(&command[0]), command.size()}; std::string reply; - auto* process = GetProcess(); + auto* process = system.ApplicationProcess(); auto& page_table = process->GetPageTable(); const char* commands = "Commands:\n" @@ -710,7 +714,7 @@ void GDBStub::HandleRcmd(const std::vector& command) { } Kernel::KThread* GDBStub::GetThreadByID(u64 thread_id) { - auto& threads{GetProcess()->GetThreadList()}; + auto& threads{system.ApplicationProcess()->GetThreadList()}; for (auto& thread : threads) { if (thread.GetThreadId() == thread_id) { return std::addressof(thread); @@ -779,12 +783,4 @@ void GDBStub::SendStatus(char status) { backend.WriteToClient(buf); } -Kernel::KProcess* GDBStub::GetProcess() { - return debug_process; -} - -Core::Memory::Memory& GDBStub::GetMemory() { - return GetProcess()->GetMemory(); -} - } // namespace Core diff --git a/src/core/debugger/gdbstub.h b/src/core/debugger/gdbstub.h index a0099f501..19dc6bb7a 100755 --- a/src/core/debugger/gdbstub.h +++ b/src/core/debugger/gdbstub.h @@ -12,22 +12,13 @@ #include "core/debugger/debugger_interface.h" #include "core/debugger/gdbstub_arch.h" -namespace Kernel { -class KProcess; -} - -namespace Core::Memory { -class Memory; -} - namespace Core { class System; class GDBStub : public DebuggerFrontend { public: - explicit GDBStub(DebuggerBackend& backend, Core::System& system, - Kernel::KProcess* debug_process); + explicit GDBStub(DebuggerBackend& backend, Core::System& system); ~GDBStub() override; void Connected() override; @@ -51,12 +42,8 @@ private: void SendReply(std::string_view data); void SendStatus(char status); - Kernel::KProcess* GetProcess(); - Core::Memory::Memory& GetMemory(); - private: Core::System& system; - Kernel::KProcess* debug_process; std::unique_ptr arch; std::vector current_command; std::map replaced_instructions; diff --git a/src/core/hle/kernel/k_page_table_base.cpp b/src/core/hle/kernel/k_page_table_base.cpp index f01eaa164..73fbda331 100755 --- a/src/core/hle/kernel/k_page_table_base.cpp +++ b/src/core/hle/kernel/k_page_table_base.cpp @@ -431,82 +431,9 @@ 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()); - - // HLE processes don't have memory mapped. - R_SUCCEED_IF(m_impl == nullptr); - - // NOTE: Here Nintendo calls an unknown OnFinalize function. - // this->OnFinalize(); - - // NOTE: Here Nintendo calls a second unknown OnFinalize function. - // this->OnFinalize2(); - - // Get implementation objects. - auto& impl = this->GetImpl(); - auto& mm = m_kernel.MemoryManager(); - - // Traverse, freeing all pages. - { - // Get the address space size. - const size_t as_size = this->GetAddressSpaceSize(); - - // Begin the traversal. - TraversalContext context; - TraversalEntry cur_entry = { - .phys_addr = 0, - .block_size = 0, - }; - - bool cur_valid = false; - TraversalEntry next_entry; - bool next_valid; - size_t tot_size = 0; - - next_valid = impl.BeginTraversal(std::addressof(next_entry), std::addressof(context), - this->GetAddressSpaceStart()); - - // Iterate over entries. - while (true) { - if ((!next_valid && !cur_valid) || - (next_valid && cur_valid && - next_entry.phys_addr == cur_entry.phys_addr + cur_entry.block_size)) { - cur_entry.block_size += next_entry.block_size; - } else { - if (cur_valid && IsHeapPhysicalAddressForFinalize(cur_entry.phys_addr)) { - mm.Close(cur_entry.phys_addr, cur_entry.block_size / PageSize); - } - - // Update tracking variables. - tot_size += cur_entry.block_size; - cur_entry = next_entry; - cur_valid = next_valid; - } - - if (cur_entry.block_size + tot_size >= as_size) { - break; - } - - next_valid = - impl.ContinueTraversal(std::addressof(next_entry), std::addressof(context)); - } - - // Handle the last block. - if (cur_valid && IsHeapPhysicalAddressForFinalize(cur_entry.phys_addr)) { - mm.Close(cur_entry.phys_addr, cur_entry.block_size / PageSize); - } - } - - R_SUCCEED(); -} - void KPageTableBase::Finalize() { - this->FinalizeProcess(); - auto HostUnmapCallback = [&](KProcessAddress addr, u64 size) { - if (m_impl->fastmem_arena) { + if (Settings::IsFastmemEnabled()) { m_system.DeviceMemory().buffer.Unmap(GetInteger(addr), size, false); } }; diff --git a/src/core/hle/kernel/k_page_table_base.h b/src/core/hle/kernel/k_page_table_base.h index 748419f86..077cafc96 100755 --- a/src/core/hle/kernel/k_page_table_base.h +++ b/src/core/hle/kernel/k_page_table_base.h @@ -241,7 +241,6 @@ 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 850ecc4c0..1d3245963 100755 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp @@ -172,12 +172,6 @@ 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 20f308b32..2801baa3e 100755 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -770,7 +770,6 @@ struct KernelCore::Impl { std::atomic next_thread_id{1}; // Lists all processes that exist in the current session. - std::mutex process_list_lock; std::vector process_list; std::atomic application_process{}; std::unique_ptr global_scheduler_context; @@ -870,19 +869,9 @@ 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); } @@ -895,15 +884,8 @@ const KProcess* KernelCore::ApplicationProcess() const { return impl->application_process; } -std::list> KernelCore::GetProcessList() { - std::list> processes; - std::scoped_lock lk{impl->process_list_lock}; - - for (auto* const process : impl->process_list) { - processes.emplace_back(process); - } - - return processes; +const std::vector& KernelCore::GetProcessList() const { + return impl->process_list; } Kernel::GlobalSchedulerContext& KernelCore::GlobalSchedulerContext() { diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index b3d76c41b..775783b95 100755 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -5,7 +5,6 @@ #include #include -#include #include #include #include @@ -117,9 +116,8 @@ public: /// Retrieves a shared pointer to the system resource limit instance. KResourceLimit* GetSystemResourceLimit(); - /// Adds/removes the given pointer to an internal list of active processes. + /// Adds the given shared 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); @@ -131,7 +129,7 @@ public: const KProcess* ApplicationProcess() const; /// Retrieves the list of processes. - std::list> GetProcessList(); + const std::vector& GetProcessList() const; /// 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 5c3e8829f..caa8bee9a 100755 --- a/src/core/hle/kernel/svc/svc_process.cpp +++ b/src/core/hle/kernel/svc/svc_process.cpp @@ -74,15 +74,13 @@ Result GetProcessList(Core::System& system, s32* out_num_processes, u64 out_proc } auto& memory = GetCurrentMemory(kernel); - auto process_list = kernel.GetProcessList(); - auto it = process_list.begin(); - + const auto& process_list = kernel.GetProcessList(); const auto num_processes = process_list.size(); const auto copy_amount = std::min(static_cast(out_process_ids_size), num_processes); - for (std::size_t i = 0; i < copy_amount && it != process_list.end(); ++i, ++it) { - memory.Write64(out_process_ids, (*it)->GetProcessId()); + for (std::size_t i = 0; i < copy_amount; ++i) { + memory.Write64(out_process_ids, process_list[i]->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 bd1e4faaf..e79ea9b6e 100755 --- a/src/core/hle/service/glue/arp.cpp +++ b/src/core/hle/service/glue/arp.cpp @@ -15,10 +15,9 @@ namespace Service::Glue { namespace { -std::optional 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) { +std::optional 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) { return process->GetProcessId() == process_id; }); diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index a2def33c3..7138d301f 100755 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -22,10 +22,12 @@ void LoopProcess(Core::System& system) { std::shared_ptr firmware_settings = std::make_shared(); - // TODO: Remove this hack when am is emulated properly. - resource_manager->Initialize(); - resource_manager->RegisterAppletResourceUserId(system.ApplicationProcess()->GetProcessId(), - true); + // 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); + } server_manager->RegisterNamedService( "hid", std::make_shared(system, resource_manager, firmware_settings)); diff --git a/src/core/hle/service/pm/pm.cpp b/src/core/hle/service/pm/pm.cpp index 55f87b3ef..0f9a161e3 100755 --- a/src/core/hle/service/pm/pm.cpp +++ b/src/core/hle/service/pm/pm.cpp @@ -22,26 +22,27 @@ constexpr Result ResultProcessNotFound{ErrorModule::PM, 1}; constexpr u64 NO_PROCESS_FOUND_PID{0}; -using ProcessList = std::list>; - -template -Kernel::KScopedAutoObject SearchProcessList(ProcessList& process_list, - F&& predicate) { +std::optional SearchProcessList( + const std::vector& process_list, + std::function predicate) { const auto iter = std::find_if(process_list.begin(), process_list.end(), predicate); if (iter == process_list.end()) { - return nullptr; + return std::nullopt; } - return iter->GetPointerUnsafe(); + return *iter; } -void GetApplicationPidGeneric(HLERequestContext& ctx, ProcessList& process_list) { - auto process = SearchProcessList(process_list, [](auto& p) { return p->IsApplication(); }); +void GetApplicationPidGeneric(HLERequestContext& ctx, + const std::vector& process_list) { + const auto process = SearchProcessList(process_list, [](const auto& proc) { + return proc->GetProcessId() == Kernel::KProcess::ProcessIdMin; + }); IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); - rb.Push(process.IsNull() ? NO_PROCESS_FOUND_PID : process->GetProcessId()); + rb.Push(process.has_value() ? (*process)->GetProcessId() : NO_PROCESS_FOUND_PID); } } // Anonymous namespace @@ -79,7 +80,8 @@ private: class DebugMonitor final : public ServiceFramework { public: - explicit DebugMonitor(Core::System& system_) : ServiceFramework{system_, "pm:dmnt"} { + explicit DebugMonitor(Core::System& system_) + : ServiceFramework{system_, "pm:dmnt"}, kernel{system_.Kernel()} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetJitDebugProcessIdList"}, @@ -104,11 +106,12 @@ private: LOG_DEBUG(Service_PM, "called, program_id={:016X}", program_id); - auto list = kernel.GetProcessList(); - auto process = SearchProcessList( - list, [program_id](auto& p) { return p->GetProgramId() == program_id; }); + const auto process = + SearchProcessList(kernel.GetProcessList(), [program_id](const auto& proc) { + return proc->GetProgramId() == program_id; + }); - if (process.IsNull()) { + if (!process.has_value()) { IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultProcessNotFound); return; @@ -116,13 +119,12 @@ 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"); - auto list = kernel.GetProcessList(); - GetApplicationPidGeneric(ctx, list); + GetApplicationPidGeneric(ctx, kernel.GetProcessList()); } void AtmosphereGetProcessInfo(HLERequestContext& ctx) { @@ -133,10 +135,11 @@ private: LOG_WARNING(Service_PM, "(Partial Implementation) called, pid={:016X}", pid); - auto list = kernel.GetProcessList(); - auto process = SearchProcessList(list, [pid](auto& p) { return p->GetProcessId() == pid; }); + const auto process = SearchProcessList(kernel.GetProcessList(), [pid](const auto& proc) { + return proc->GetProcessId() == pid; + }); - if (process.IsNull()) { + if (!process.has_value()) { IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultProcessNotFound); return; @@ -156,7 +159,7 @@ private: OverrideStatus override_status{}; ProgramLocation program_location{ - .program_id = process->GetProgramId(), + .program_id = (*process)->GetProgramId(), .storage_id = 0, }; @@ -166,11 +169,14 @@ private: rb.PushRaw(program_location); rb.PushRaw(override_status); } + + const Kernel::KernelCore& kernel; }; class Info final : public ServiceFramework { public: - explicit Info(Core::System& system_) : ServiceFramework{system_, "pm:info"} { + explicit Info(Core::System& system_, const std::vector& process_list_) + : ServiceFramework{system_, "pm:info"}, process_list{process_list_} { static const FunctionInfo functions[] = { {0, &Info::GetProgramId, "GetProgramId"}, {65000, &Info::AtmosphereGetProcessId, "AtmosphereGetProcessId"}, @@ -187,11 +193,11 @@ private: LOG_DEBUG(Service_PM, "called, process_id={:016X}", process_id); - auto list = kernel.GetProcessList(); - auto process = SearchProcessList( - list, [process_id](auto& p) { return p->GetProcessId() == process_id; }); + const auto process = SearchProcessList(process_list, [process_id](const auto& proc) { + return proc->GetProcessId() == process_id; + }); - if (process.IsNull()) { + if (!process.has_value()) { IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultProcessNotFound); return; @@ -199,7 +205,7 @@ private: IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); - rb.Push(process->GetProgramId()); + rb.Push((*process)->GetProgramId()); } void AtmosphereGetProcessId(HLERequestContext& ctx) { @@ -208,11 +214,11 @@ private: LOG_DEBUG(Service_PM, "called, program_id={:016X}", program_id); - auto list = system.Kernel().GetProcessList(); - auto process = SearchProcessList( - list, [program_id](auto& p) { return p->GetProgramId() == program_id; }); + const auto process = SearchProcessList(process_list, [program_id](const auto& proc) { + return proc->GetProgramId() == program_id; + }); - if (process.IsNull()) { + if (!process.has_value()) { IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultProcessNotFound); return; @@ -220,13 +226,16 @@ private: IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); - rb.Push(process->GetProcessId()); + rb.Push((*process)->GetProcessId()); } + + const std::vector& process_list; }; class Shell final : public ServiceFramework { public: - explicit Shell(Core::System& system_) : ServiceFramework{system_, "pm:shell"} { + explicit Shell(Core::System& system_) + : ServiceFramework{system_, "pm:shell"}, kernel{system_.Kernel()} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "LaunchProgram"}, @@ -248,9 +257,10 @@ public: private: void GetApplicationProcessIdForShell(HLERequestContext& ctx) { LOG_DEBUG(Service_PM, "called"); - auto list = kernel.GetProcessList(); - GetApplicationPidGeneric(ctx, list); + GetApplicationPidGeneric(ctx, kernel.GetProcessList()); } + + const Kernel::KernelCore& kernel; }; void LoopProcess(Core::System& system) { @@ -258,7 +268,8 @@ void LoopProcess(Core::System& system) { server_manager->RegisterNamedService("pm:bm", std::make_shared(system)); server_manager->RegisterNamedService("pm:dmnt", std::make_shared(system)); - server_manager->RegisterNamedService("pm:info", std::make_shared(system)); + server_manager->RegisterNamedService( + "pm:info", std::make_shared(system, system.Kernel().GetProcessList())); server_manager->RegisterNamedService("pm:shell", std::make_shared(system)); ServerManager::RunServer(std::move(server_manager)); }