mirror of
				https://git.suyu.dev/suyu/suyu.git
				synced 2025-10-31 06:46:40 +08:00 
			
		
		
		
	Merge pull request #12611 from liamwhite/resource-management-is-hard
kernel: fix resource management issues
This commit is contained in:
		
						commit
						0127cec371
					
				| @ -2,6 +2,7 @@ | |||||||
| // SPDX-License-Identifier: GPL-2.0-or-later
 | // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||||
| 
 | 
 | ||||||
| #include "common/page_table.h" | #include "common/page_table.h" | ||||||
|  | #include "common/scope_exit.h" | ||||||
| 
 | 
 | ||||||
| namespace Common { | namespace Common { | ||||||
| 
 | 
 | ||||||
| @ -11,29 +12,10 @@ PageTable::~PageTable() noexcept = default; | |||||||
| 
 | 
 | ||||||
| bool PageTable::BeginTraversal(TraversalEntry* out_entry, TraversalContext* out_context, | bool PageTable::BeginTraversal(TraversalEntry* out_entry, TraversalContext* out_context, | ||||||
|                                Common::ProcessAddress address) const { |                                Common::ProcessAddress address) const { | ||||||
|     // Setup invalid defaults.
 |     out_context->next_offset = GetInteger(address); | ||||||
|     out_entry->phys_addr = 0; |     out_context->next_page = address / page_size; | ||||||
|     out_entry->block_size = page_size; |  | ||||||
|     out_context->next_page = 0; |  | ||||||
| 
 | 
 | ||||||
|     // Validate that we can read the actual entry.
 |     return this->ContinueTraversal(out_entry, out_context); | ||||||
|     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 { | bool PageTable::ContinueTraversal(TraversalEntry* out_entry, TraversalContext* context) const { | ||||||
| @ -41,6 +23,12 @@ bool PageTable::ContinueTraversal(TraversalEntry* out_entry, TraversalContext* c | |||||||
|     out_entry->phys_addr = 0; |     out_entry->phys_addr = 0; | ||||||
|     out_entry->block_size = page_size; |     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.
 |     // Validate that we can read the actual entry.
 | ||||||
|     const auto page = context->next_page; |     const auto page = context->next_page; | ||||||
|     if (page >= backing_addr.size()) { |     if (page >= backing_addr.size()) { | ||||||
| @ -55,8 +43,6 @@ bool PageTable::ContinueTraversal(TraversalEntry* out_entry, TraversalContext* c | |||||||
| 
 | 
 | ||||||
|     // Populate the results.
 |     // Populate the results.
 | ||||||
|     out_entry->phys_addr = phys_addr + context->next_offset; |     out_entry->phys_addr = phys_addr + context->next_offset; | ||||||
|     context->next_page = page + 1; |  | ||||||
|     context->next_offset += page_size; |  | ||||||
| 
 | 
 | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
|  | |||||||
| @ -114,7 +114,7 @@ public: | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     Kernel::KThread* GetActiveThread() override { |     Kernel::KThread* GetActiveThread() override { | ||||||
|         return state->active_thread; |         return state->active_thread.GetPointerUnsafe(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
| @ -147,11 +147,14 @@ private: | |||||||
| 
 | 
 | ||||||
|         std::scoped_lock lk{connection_lock}; |         std::scoped_lock lk{connection_lock}; | ||||||
| 
 | 
 | ||||||
|  |         // Find the process we are going to debug.
 | ||||||
|  |         SetDebugProcess(); | ||||||
|  | 
 | ||||||
|         // Ensure everything is stopped.
 |         // Ensure everything is stopped.
 | ||||||
|         PauseEmulation(); |         PauseEmulation(); | ||||||
| 
 | 
 | ||||||
|         // Set up the new frontend.
 |         // Set up the new frontend.
 | ||||||
|         frontend = std::make_unique<GDBStub>(*this, system); |         frontend = std::make_unique<GDBStub>(*this, system, debug_process.GetPointerUnsafe()); | ||||||
| 
 | 
 | ||||||
|         // Set the new state. This will tear down any existing state.
 |         // Set the new state. This will tear down any existing state.
 | ||||||
|         state = ConnectionState{ |         state = ConnectionState{ | ||||||
| @ -194,15 +197,20 @@ private: | |||||||
|             UpdateActiveThread(); |             UpdateActiveThread(); | ||||||
| 
 | 
 | ||||||
|             if (state->info.type == SignalType::Watchpoint) { |             if (state->info.type == SignalType::Watchpoint) { | ||||||
|                 frontend->Watchpoint(state->active_thread, *state->info.watchpoint); |                 frontend->Watchpoint(std::addressof(*state->active_thread), | ||||||
|  |                                      *state->info.watchpoint); | ||||||
|             } else { |             } else { | ||||||
|                 frontend->Stopped(state->active_thread); |                 frontend->Stopped(std::addressof(*state->active_thread)); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             break; |             break; | ||||||
|         case SignalType::ShuttingDown: |         case SignalType::ShuttingDown: | ||||||
|             frontend->ShuttingDown(); |             frontend->ShuttingDown(); | ||||||
| 
 | 
 | ||||||
|  |             // Release members.
 | ||||||
|  |             state->active_thread.Reset(nullptr); | ||||||
|  |             debug_process.Reset(nullptr); | ||||||
|  | 
 | ||||||
|             // Wait for emulation to shut down gracefully now.
 |             // Wait for emulation to shut down gracefully now.
 | ||||||
|             state->signal_pipe.close(); |             state->signal_pipe.close(); | ||||||
|             state->client_socket.shutdown(boost::asio::socket_base::shutdown_both); |             state->client_socket.shutdown(boost::asio::socket_base::shutdown_both); | ||||||
| @ -222,7 +230,7 @@ private: | |||||||
|                 stopped = true; |                 stopped = true; | ||||||
|                 PauseEmulation(); |                 PauseEmulation(); | ||||||
|                 UpdateActiveThread(); |                 UpdateActiveThread(); | ||||||
|                 frontend->Stopped(state->active_thread); |                 frontend->Stopped(state->active_thread.GetPointerUnsafe()); | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|             case DebuggerAction::Continue: |             case DebuggerAction::Continue: | ||||||
| @ -232,7 +240,7 @@ private: | |||||||
|                 MarkResumed([&] { |                 MarkResumed([&] { | ||||||
|                     state->active_thread->SetStepState(Kernel::StepState::StepPending); |                     state->active_thread->SetStepState(Kernel::StepState::StepPending); | ||||||
|                     state->active_thread->Resume(Kernel::SuspendType::Debug); |                     state->active_thread->Resume(Kernel::SuspendType::Debug); | ||||||
|                     ResumeEmulation(state->active_thread); |                     ResumeEmulation(state->active_thread.GetPointerUnsafe()); | ||||||
|                 }); |                 }); | ||||||
|                 break; |                 break; | ||||||
|             case DebuggerAction::StepThreadLocked: { |             case DebuggerAction::StepThreadLocked: { | ||||||
| @ -255,6 +263,7 @@ private: | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void PauseEmulation() { |     void PauseEmulation() { | ||||||
|  |         Kernel::KScopedLightLock ll{debug_process->GetListLock()}; | ||||||
|         Kernel::KScopedSchedulerLock sl{system.Kernel()}; |         Kernel::KScopedSchedulerLock sl{system.Kernel()}; | ||||||
| 
 | 
 | ||||||
|         // Put all threads to sleep on next scheduler round.
 |         // Put all threads to sleep on next scheduler round.
 | ||||||
| @ -264,6 +273,9 @@ private: | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void ResumeEmulation(Kernel::KThread* except = nullptr) { |     void ResumeEmulation(Kernel::KThread* except = nullptr) { | ||||||
|  |         Kernel::KScopedLightLock ll{debug_process->GetListLock()}; | ||||||
|  |         Kernel::KScopedSchedulerLock sl{system.Kernel()}; | ||||||
|  | 
 | ||||||
|         // Wake up all threads.
 |         // Wake up all threads.
 | ||||||
|         for (auto& thread : ThreadList()) { |         for (auto& thread : ThreadList()) { | ||||||
|             if (std::addressof(thread) == except) { |             if (std::addressof(thread) == except) { | ||||||
| @ -277,15 +289,16 @@ private: | |||||||
| 
 | 
 | ||||||
|     template <typename Callback> |     template <typename Callback> | ||||||
|     void MarkResumed(Callback&& cb) { |     void MarkResumed(Callback&& cb) { | ||||||
|         Kernel::KScopedSchedulerLock sl{system.Kernel()}; |  | ||||||
|         stopped = false; |         stopped = false; | ||||||
|         cb(); |         cb(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void UpdateActiveThread() { |     void UpdateActiveThread() { | ||||||
|  |         Kernel::KScopedLightLock ll{debug_process->GetListLock()}; | ||||||
|  | 
 | ||||||
|         auto& threads{ThreadList()}; |         auto& threads{ThreadList()}; | ||||||
|         for (auto& thread : threads) { |         for (auto& thread : threads) { | ||||||
|             if (std::addressof(thread) == state->active_thread) { |             if (std::addressof(thread) == state->active_thread.GetPointerUnsafe()) { | ||||||
|                 // Thread is still alive, no need to update.
 |                 // Thread is still alive, no need to update.
 | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
| @ -293,12 +306,18 @@ private: | |||||||
|         state->active_thread = std::addressof(threads.front()); |         state->active_thread = std::addressof(threads.front()); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | private: | ||||||
|  |     void SetDebugProcess() { | ||||||
|  |         debug_process = std::move(system.Kernel().GetProcessList().back()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     Kernel::KProcess::ThreadList& ThreadList() { |     Kernel::KProcess::ThreadList& ThreadList() { | ||||||
|         return system.ApplicationProcess()->GetThreadList(); |         return debug_process->GetThreadList(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     System& system; |     System& system; | ||||||
|  |     Kernel::KScopedAutoObject<Kernel::KProcess> debug_process; | ||||||
|     std::unique_ptr<DebuggerFrontend> frontend; |     std::unique_ptr<DebuggerFrontend> frontend; | ||||||
| 
 | 
 | ||||||
|     boost::asio::io_context io_context; |     boost::asio::io_context io_context; | ||||||
| @ -310,7 +329,7 @@ private: | |||||||
|         boost::process::async_pipe signal_pipe; |         boost::process::async_pipe signal_pipe; | ||||||
| 
 | 
 | ||||||
|         SignalInfo info; |         SignalInfo info; | ||||||
|         Kernel::KThread* active_thread; |         Kernel::KScopedAutoObject<Kernel::KThread> active_thread; | ||||||
|         std::array<u8, 4096> client_data; |         std::array<u8, 4096> client_data; | ||||||
|         bool pipe_data; |         bool pipe_data; | ||||||
|     }; |     }; | ||||||
|  | |||||||
| @ -108,9 +108,9 @@ static std::string EscapeXML(std::string_view data) { | |||||||
|     return escaped; |     return escaped; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| GDBStub::GDBStub(DebuggerBackend& backend_, Core::System& system_) | GDBStub::GDBStub(DebuggerBackend& backend_, Core::System& system_, Kernel::KProcess* debug_process_) | ||||||
|     : DebuggerFrontend(backend_), system{system_} { |     : DebuggerFrontend(backend_), system{system_}, debug_process{debug_process_} { | ||||||
|     if (system.ApplicationProcess()->Is64Bit()) { |     if (GetProcess()->Is64Bit()) { | ||||||
|         arch = std::make_unique<GDBStubA64>(); |         arch = std::make_unique<GDBStubA64>(); | ||||||
|     } else { |     } else { | ||||||
|         arch = std::make_unique<GDBStubA32>(); |         arch = std::make_unique<GDBStubA32>(); | ||||||
| @ -276,7 +276,7 @@ void GDBStub::ExecuteCommand(std::string_view packet, std::vector<DebuggerAction | |||||||
|         const size_t size{static_cast<size_t>(strtoll(command.data() + sep, nullptr, 16))}; |         const size_t size{static_cast<size_t>(strtoll(command.data() + sep, nullptr, 16))}; | ||||||
| 
 | 
 | ||||||
|         std::vector<u8> mem(size); |         std::vector<u8> mem(size); | ||||||
|         if (system.ApplicationMemory().ReadBlock(addr, mem.data(), size)) { |         if (GetMemory().ReadBlock(addr, mem.data(), size)) { | ||||||
|             // Restore any bytes belonging to replaced instructions.
 |             // Restore any bytes belonging to replaced instructions.
 | ||||||
|             auto it = replaced_instructions.lower_bound(addr); |             auto it = replaced_instructions.lower_bound(addr); | ||||||
|             for (; it != replaced_instructions.end() && it->first < addr + size; it++) { |             for (; it != replaced_instructions.end() && it->first < addr + size; it++) { | ||||||
| @ -310,8 +310,8 @@ void GDBStub::ExecuteCommand(std::string_view packet, std::vector<DebuggerAction | |||||||
|         const auto mem_substr{std::string_view(command).substr(mem_sep)}; |         const auto mem_substr{std::string_view(command).substr(mem_sep)}; | ||||||
|         const auto mem{Common::HexStringToVector(mem_substr, false)}; |         const auto mem{Common::HexStringToVector(mem_substr, false)}; | ||||||
| 
 | 
 | ||||||
|         if (system.ApplicationMemory().WriteBlock(addr, mem.data(), size)) { |         if (GetMemory().WriteBlock(addr, mem.data(), size)) { | ||||||
|             Core::InvalidateInstructionCacheRange(system.ApplicationProcess(), addr, size); |             Core::InvalidateInstructionCacheRange(GetProcess(), addr, size); | ||||||
|             SendReply(GDB_STUB_REPLY_OK); |             SendReply(GDB_STUB_REPLY_OK); | ||||||
|         } else { |         } else { | ||||||
|             SendReply(GDB_STUB_REPLY_ERR); |             SendReply(GDB_STUB_REPLY_ERR); | ||||||
| @ -353,7 +353,7 @@ void GDBStub::HandleBreakpointInsert(std::string_view command) { | |||||||
|     const size_t addr{static_cast<size_t>(strtoll(command.data() + addr_sep, nullptr, 16))}; |     const size_t addr{static_cast<size_t>(strtoll(command.data() + addr_sep, nullptr, 16))}; | ||||||
|     const size_t size{static_cast<size_t>(strtoll(command.data() + size_sep, nullptr, 16))}; |     const size_t size{static_cast<size_t>(strtoll(command.data() + size_sep, nullptr, 16))}; | ||||||
| 
 | 
 | ||||||
|     if (!system.ApplicationMemory().IsValidVirtualAddressRange(addr, size)) { |     if (!GetMemory().IsValidVirtualAddressRange(addr, size)) { | ||||||
|         SendReply(GDB_STUB_REPLY_ERR); |         SendReply(GDB_STUB_REPLY_ERR); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| @ -362,22 +362,20 @@ void GDBStub::HandleBreakpointInsert(std::string_view command) { | |||||||
| 
 | 
 | ||||||
|     switch (type) { |     switch (type) { | ||||||
|     case BreakpointType::Software: |     case BreakpointType::Software: | ||||||
|         replaced_instructions[addr] = system.ApplicationMemory().Read32(addr); |         replaced_instructions[addr] = GetMemory().Read32(addr); | ||||||
|         system.ApplicationMemory().Write32(addr, arch->BreakpointInstruction()); |         GetMemory().Write32(addr, arch->BreakpointInstruction()); | ||||||
|         Core::InvalidateInstructionCacheRange(system.ApplicationProcess(), addr, sizeof(u32)); |         Core::InvalidateInstructionCacheRange(GetProcess(), addr, sizeof(u32)); | ||||||
|         success = true; |         success = true; | ||||||
|         break; |         break; | ||||||
|     case BreakpointType::WriteWatch: |     case BreakpointType::WriteWatch: | ||||||
|         success = system.ApplicationProcess()->InsertWatchpoint(addr, size, |         success = GetProcess()->InsertWatchpoint(addr, size, Kernel::DebugWatchpointType::Write); | ||||||
|                                                                 Kernel::DebugWatchpointType::Write); |  | ||||||
|         break; |         break; | ||||||
|     case BreakpointType::ReadWatch: |     case BreakpointType::ReadWatch: | ||||||
|         success = system.ApplicationProcess()->InsertWatchpoint(addr, size, |         success = GetProcess()->InsertWatchpoint(addr, size, Kernel::DebugWatchpointType::Read); | ||||||
|                                                                 Kernel::DebugWatchpointType::Read); |  | ||||||
|         break; |         break; | ||||||
|     case BreakpointType::AccessWatch: |     case BreakpointType::AccessWatch: | ||||||
|         success = system.ApplicationProcess()->InsertWatchpoint( |         success = | ||||||
|             addr, size, Kernel::DebugWatchpointType::ReadOrWrite); |             GetProcess()->InsertWatchpoint(addr, size, Kernel::DebugWatchpointType::ReadOrWrite); | ||||||
|         break; |         break; | ||||||
|     case BreakpointType::Hardware: |     case BreakpointType::Hardware: | ||||||
|     default: |     default: | ||||||
| @ -400,7 +398,7 @@ void GDBStub::HandleBreakpointRemove(std::string_view command) { | |||||||
|     const size_t addr{static_cast<size_t>(strtoll(command.data() + addr_sep, nullptr, 16))}; |     const size_t addr{static_cast<size_t>(strtoll(command.data() + addr_sep, nullptr, 16))}; | ||||||
|     const size_t size{static_cast<size_t>(strtoll(command.data() + size_sep, nullptr, 16))}; |     const size_t size{static_cast<size_t>(strtoll(command.data() + size_sep, nullptr, 16))}; | ||||||
| 
 | 
 | ||||||
|     if (!system.ApplicationMemory().IsValidVirtualAddressRange(addr, size)) { |     if (!GetMemory().IsValidVirtualAddressRange(addr, size)) { | ||||||
|         SendReply(GDB_STUB_REPLY_ERR); |         SendReply(GDB_STUB_REPLY_ERR); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| @ -411,24 +409,22 @@ void GDBStub::HandleBreakpointRemove(std::string_view command) { | |||||||
|     case BreakpointType::Software: { |     case BreakpointType::Software: { | ||||||
|         const auto orig_insn{replaced_instructions.find(addr)}; |         const auto orig_insn{replaced_instructions.find(addr)}; | ||||||
|         if (orig_insn != replaced_instructions.end()) { |         if (orig_insn != replaced_instructions.end()) { | ||||||
|             system.ApplicationMemory().Write32(addr, orig_insn->second); |             GetMemory().Write32(addr, orig_insn->second); | ||||||
|             Core::InvalidateInstructionCacheRange(system.ApplicationProcess(), addr, sizeof(u32)); |             Core::InvalidateInstructionCacheRange(GetProcess(), addr, sizeof(u32)); | ||||||
|             replaced_instructions.erase(addr); |             replaced_instructions.erase(addr); | ||||||
|             success = true; |             success = true; | ||||||
|         } |         } | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|     case BreakpointType::WriteWatch: |     case BreakpointType::WriteWatch: | ||||||
|         success = system.ApplicationProcess()->RemoveWatchpoint(addr, size, |         success = GetProcess()->RemoveWatchpoint(addr, size, Kernel::DebugWatchpointType::Write); | ||||||
|                                                                 Kernel::DebugWatchpointType::Write); |  | ||||||
|         break; |         break; | ||||||
|     case BreakpointType::ReadWatch: |     case BreakpointType::ReadWatch: | ||||||
|         success = system.ApplicationProcess()->RemoveWatchpoint(addr, size, |         success = GetProcess()->RemoveWatchpoint(addr, size, Kernel::DebugWatchpointType::Read); | ||||||
|                                                                 Kernel::DebugWatchpointType::Read); |  | ||||||
|         break; |         break; | ||||||
|     case BreakpointType::AccessWatch: |     case BreakpointType::AccessWatch: | ||||||
|         success = system.ApplicationProcess()->RemoveWatchpoint( |         success = | ||||||
|             addr, size, Kernel::DebugWatchpointType::ReadOrWrite); |             GetProcess()->RemoveWatchpoint(addr, size, Kernel::DebugWatchpointType::ReadOrWrite); | ||||||
|         break; |         break; | ||||||
|     case BreakpointType::Hardware: |     case BreakpointType::Hardware: | ||||||
|     default: |     default: | ||||||
| @ -466,10 +462,10 @@ void GDBStub::HandleQuery(std::string_view command) { | |||||||
|         const auto target_xml{arch->GetTargetXML()}; |         const auto target_xml{arch->GetTargetXML()}; | ||||||
|         SendReply(PaginateBuffer(target_xml, command.substr(30))); |         SendReply(PaginateBuffer(target_xml, command.substr(30))); | ||||||
|     } else if (command.starts_with("Offsets")) { |     } else if (command.starts_with("Offsets")) { | ||||||
|         const auto main_offset = Core::FindMainModuleEntrypoint(system.ApplicationProcess()); |         const auto main_offset = Core::FindMainModuleEntrypoint(GetProcess()); | ||||||
|         SendReply(fmt::format("TextSeg={:x}", GetInteger(main_offset))); |         SendReply(fmt::format("TextSeg={:x}", GetInteger(main_offset))); | ||||||
|     } else if (command.starts_with("Xfer:libraries:read::")) { |     } else if (command.starts_with("Xfer:libraries:read::")) { | ||||||
|         auto modules = Core::FindModules(system.ApplicationProcess()); |         auto modules = Core::FindModules(GetProcess()); | ||||||
| 
 | 
 | ||||||
|         std::string buffer; |         std::string buffer; | ||||||
|         buffer += R"(<?xml version="1.0"?>)"; |         buffer += R"(<?xml version="1.0"?>)"; | ||||||
| @ -483,7 +479,7 @@ void GDBStub::HandleQuery(std::string_view command) { | |||||||
|         SendReply(PaginateBuffer(buffer, command.substr(21))); |         SendReply(PaginateBuffer(buffer, command.substr(21))); | ||||||
|     } else if (command.starts_with("fThreadInfo")) { |     } else if (command.starts_with("fThreadInfo")) { | ||||||
|         // beginning of list
 |         // beginning of list
 | ||||||
|         const auto& threads = system.ApplicationProcess()->GetThreadList(); |         const auto& threads = GetProcess()->GetThreadList(); | ||||||
|         std::vector<std::string> thread_ids; |         std::vector<std::string> thread_ids; | ||||||
|         for (const auto& thread : threads) { |         for (const auto& thread : threads) { | ||||||
|             thread_ids.push_back(fmt::format("{:x}", thread.GetThreadId())); |             thread_ids.push_back(fmt::format("{:x}", thread.GetThreadId())); | ||||||
| @ -497,7 +493,7 @@ void GDBStub::HandleQuery(std::string_view command) { | |||||||
|         buffer += R"(<?xml version="1.0"?>)"; |         buffer += R"(<?xml version="1.0"?>)"; | ||||||
|         buffer += "<threads>"; |         buffer += "<threads>"; | ||||||
| 
 | 
 | ||||||
|         const auto& threads = system.ApplicationProcess()->GetThreadList(); |         const auto& threads = GetProcess()->GetThreadList(); | ||||||
|         for (const auto& thread : threads) { |         for (const auto& thread : threads) { | ||||||
|             auto thread_name{Core::GetThreadName(&thread)}; |             auto thread_name{Core::GetThreadName(&thread)}; | ||||||
|             if (!thread_name) { |             if (!thread_name) { | ||||||
| @ -613,7 +609,7 @@ void GDBStub::HandleRcmd(const std::vector<u8>& command) { | |||||||
|     std::string_view command_str{reinterpret_cast<const char*>(&command[0]), command.size()}; |     std::string_view command_str{reinterpret_cast<const char*>(&command[0]), command.size()}; | ||||||
|     std::string reply; |     std::string reply; | ||||||
| 
 | 
 | ||||||
|     auto* process = system.ApplicationProcess(); |     auto* process = GetProcess(); | ||||||
|     auto& page_table = process->GetPageTable(); |     auto& page_table = process->GetPageTable(); | ||||||
| 
 | 
 | ||||||
|     const char* commands = "Commands:\n" |     const char* commands = "Commands:\n" | ||||||
| @ -714,7 +710,7 @@ void GDBStub::HandleRcmd(const std::vector<u8>& command) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Kernel::KThread* GDBStub::GetThreadByID(u64 thread_id) { | Kernel::KThread* GDBStub::GetThreadByID(u64 thread_id) { | ||||||
|     auto& threads{system.ApplicationProcess()->GetThreadList()}; |     auto& threads{GetProcess()->GetThreadList()}; | ||||||
|     for (auto& thread : threads) { |     for (auto& thread : threads) { | ||||||
|         if (thread.GetThreadId() == thread_id) { |         if (thread.GetThreadId() == thread_id) { | ||||||
|             return std::addressof(thread); |             return std::addressof(thread); | ||||||
| @ -783,4 +779,12 @@ void GDBStub::SendStatus(char status) { | |||||||
|     backend.WriteToClient(buf); |     backend.WriteToClient(buf); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | Kernel::KProcess* GDBStub::GetProcess() { | ||||||
|  |     return debug_process; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Core::Memory::Memory& GDBStub::GetMemory() { | ||||||
|  |     return GetProcess()->GetMemory(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| } // namespace Core
 | } // namespace Core
 | ||||||
|  | |||||||
| @ -12,13 +12,22 @@ | |||||||
| #include "core/debugger/debugger_interface.h" | #include "core/debugger/debugger_interface.h" | ||||||
| #include "core/debugger/gdbstub_arch.h" | #include "core/debugger/gdbstub_arch.h" | ||||||
| 
 | 
 | ||||||
|  | namespace Kernel { | ||||||
|  | class KProcess; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | namespace Core::Memory { | ||||||
|  | class Memory; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| namespace Core { | namespace Core { | ||||||
| 
 | 
 | ||||||
| class System; | class System; | ||||||
| 
 | 
 | ||||||
| class GDBStub : public DebuggerFrontend { | class GDBStub : public DebuggerFrontend { | ||||||
| public: | public: | ||||||
|     explicit GDBStub(DebuggerBackend& backend, Core::System& system); |     explicit GDBStub(DebuggerBackend& backend, Core::System& system, | ||||||
|  |                      Kernel::KProcess* debug_process); | ||||||
|     ~GDBStub() override; |     ~GDBStub() override; | ||||||
| 
 | 
 | ||||||
|     void Connected() override; |     void Connected() override; | ||||||
| @ -42,8 +51,12 @@ private: | |||||||
|     void SendReply(std::string_view data); |     void SendReply(std::string_view data); | ||||||
|     void SendStatus(char status); |     void SendStatus(char status); | ||||||
| 
 | 
 | ||||||
|  |     Kernel::KProcess* GetProcess(); | ||||||
|  |     Core::Memory::Memory& GetMemory(); | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
|     Core::System& system; |     Core::System& system; | ||||||
|  |     Kernel::KProcess* debug_process; | ||||||
|     std::unique_ptr<GDBStubArch> arch; |     std::unique_ptr<GDBStubArch> arch; | ||||||
|     std::vector<char> current_command; |     std::vector<char> current_command; | ||||||
|     std::map<VAddr, u32> replaced_instructions; |     std::map<VAddr, u32> replaced_instructions; | ||||||
|  | |||||||
| @ -28,14 +28,14 @@ Result KMemoryBlockManager::Initialize(KProcessAddress st, KProcessAddress nd, | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void KMemoryBlockManager::Finalize(KMemoryBlockSlabManager* slab_manager, | void KMemoryBlockManager::Finalize(KMemoryBlockSlabManager* slab_manager, | ||||||
|                                    HostUnmapCallback&& host_unmap_callback) { |                                    BlockCallback&& block_callback) { | ||||||
|     // Erase every block until we have none left.
 |     // Erase every block until we have none left.
 | ||||||
|     auto it = m_memory_block_tree.begin(); |     auto it = m_memory_block_tree.begin(); | ||||||
|     while (it != m_memory_block_tree.end()) { |     while (it != m_memory_block_tree.end()) { | ||||||
|         KMemoryBlock* block = std::addressof(*it); |         KMemoryBlock* block = std::addressof(*it); | ||||||
|         it = m_memory_block_tree.erase(it); |         it = m_memory_block_tree.erase(it); | ||||||
|  |         block_callback(block->GetAddress(), block->GetSize()); | ||||||
|         slab_manager->Free(block); |         slab_manager->Free(block); | ||||||
|         host_unmap_callback(block->GetAddress(), block->GetSize()); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     ASSERT(m_memory_block_tree.empty()); |     ASSERT(m_memory_block_tree.empty()); | ||||||
|  | |||||||
| @ -85,11 +85,11 @@ public: | |||||||
| public: | public: | ||||||
|     KMemoryBlockManager(); |     KMemoryBlockManager(); | ||||||
| 
 | 
 | ||||||
|     using HostUnmapCallback = std::function<void(Common::ProcessAddress, u64)>; |     using BlockCallback = std::function<void(Common::ProcessAddress, u64)>; | ||||||
| 
 | 
 | ||||||
|     Result Initialize(KProcessAddress st, KProcessAddress nd, |     Result Initialize(KProcessAddress st, KProcessAddress nd, | ||||||
|                       KMemoryBlockSlabManager* slab_manager); |                       KMemoryBlockSlabManager* slab_manager); | ||||||
|     void Finalize(KMemoryBlockSlabManager* slab_manager, HostUnmapCallback&& host_unmap_callback); |     void Finalize(KMemoryBlockSlabManager* slab_manager, BlockCallback&& block_callback); | ||||||
| 
 | 
 | ||||||
|     iterator end() { |     iterator end() { | ||||||
|         return m_memory_block_tree.end(); |         return m_memory_block_tree.end(); | ||||||
|  | |||||||
| @ -431,15 +431,43 @@ Result KPageTableBase::InitializeForProcess(Svc::CreateProcessFlag as_type, bool | |||||||
|                                                m_memory_block_slab_manager)); |                                                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() { | void KPageTableBase::Finalize() { | ||||||
|     auto HostUnmapCallback = [&](KProcessAddress addr, u64 size) { |     this->FinalizeProcess(); | ||||||
|         if (Settings::IsFastmemEnabled()) { | 
 | ||||||
|  |     auto BlockCallback = [&](KProcessAddress addr, u64 size) { | ||||||
|  |         if (m_impl->fastmem_arena) { | ||||||
|             m_system.DeviceMemory().buffer.Unmap(GetInteger(addr), size, false); |             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.
 |     // 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.
 |     // Free any unsafe mapped memory.
 | ||||||
|     if (m_mapped_unsafe_physical_memory) { |     if (m_mapped_unsafe_physical_memory) { | ||||||
|  | |||||||
| @ -241,6 +241,7 @@ public: | |||||||
|                                 KResourceLimit* resource_limit, Core::Memory::Memory& memory, |                                 KResourceLimit* resource_limit, Core::Memory::Memory& memory, | ||||||
|                                 KProcessAddress aslr_space_start); |                                 KProcessAddress aslr_space_start); | ||||||
| 
 | 
 | ||||||
|  |     Result FinalizeProcess(); | ||||||
|     void Finalize(); |     void Finalize(); | ||||||
| 
 | 
 | ||||||
|     bool IsKernel() const { |     bool IsKernel() const { | ||||||
|  | |||||||
| @ -171,6 +171,12 @@ void KProcess::Finalize() { | |||||||
|         m_resource_limit->Close(); |         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.
 |     // Perform inherited finalization.
 | ||||||
|     KSynchronizationObject::Finalize(); |     KSynchronizationObject::Finalize(); | ||||||
| } | } | ||||||
|  | |||||||
| @ -112,7 +112,14 @@ struct KernelCore::Impl { | |||||||
|             old_process->Close(); |             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_object_id = 0; | ||||||
|         next_kernel_process_id = KProcess::InitialProcessIdMin; |         next_kernel_process_id = KProcess::InitialProcessIdMin; | ||||||
| @ -770,6 +777,7 @@ struct KernelCore::Impl { | |||||||
|     std::atomic<u64> next_thread_id{1}; |     std::atomic<u64> next_thread_id{1}; | ||||||
| 
 | 
 | ||||||
|     // Lists all processes that exist in the current session.
 |     // Lists all processes that exist in the current session.
 | ||||||
|  |     std::mutex process_list_lock; | ||||||
|     std::vector<KProcess*> process_list; |     std::vector<KProcess*> process_list; | ||||||
|     std::atomic<KProcess*> application_process{}; |     std::atomic<KProcess*> application_process{}; | ||||||
|     std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context; |     std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context; | ||||||
| @ -869,9 +877,19 @@ KResourceLimit* KernelCore::GetSystemResourceLimit() { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void KernelCore::AppendNewProcess(KProcess* process) { | void KernelCore::AppendNewProcess(KProcess* process) { | ||||||
|  |     process->Open(); | ||||||
|  | 
 | ||||||
|  |     std::scoped_lock lk{impl->process_list_lock}; | ||||||
|     impl->process_list.push_back(process); |     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) { | void KernelCore::MakeApplicationProcess(KProcess* process) { | ||||||
|     impl->MakeApplicationProcess(process); |     impl->MakeApplicationProcess(process); | ||||||
| } | } | ||||||
| @ -884,8 +902,15 @@ const KProcess* KernelCore::ApplicationProcess() const { | |||||||
|     return impl->application_process; |     return impl->application_process; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const std::vector<KProcess*>& KernelCore::GetProcessList() const { | std::list<KScopedAutoObject<KProcess>> KernelCore::GetProcessList() { | ||||||
|     return impl->process_list; |     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() { | Kernel::GlobalSchedulerContext& KernelCore::GlobalSchedulerContext() { | ||||||
|  | |||||||
| @ -5,6 +5,7 @@ | |||||||
| 
 | 
 | ||||||
| #include <array> | #include <array> | ||||||
| #include <functional> | #include <functional> | ||||||
|  | #include <list> | ||||||
| #include <memory> | #include <memory> | ||||||
| #include <string> | #include <string> | ||||||
| #include <unordered_map> | #include <unordered_map> | ||||||
| @ -116,8 +117,9 @@ public: | |||||||
|     /// Retrieves a shared pointer to the system resource limit instance.
 |     /// Retrieves a shared pointer to the system resource limit instance.
 | ||||||
|     KResourceLimit* GetSystemResourceLimit(); |     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 AppendNewProcess(KProcess* process); | ||||||
|  |     void RemoveProcess(KProcess* process); | ||||||
| 
 | 
 | ||||||
|     /// Makes the given process the new application process.
 |     /// Makes the given process the new application process.
 | ||||||
|     void MakeApplicationProcess(KProcess* process); |     void MakeApplicationProcess(KProcess* process); | ||||||
| @ -129,7 +131,7 @@ public: | |||||||
|     const KProcess* ApplicationProcess() const; |     const KProcess* ApplicationProcess() const; | ||||||
| 
 | 
 | ||||||
|     /// Retrieves the list of processes.
 |     /// Retrieves the list of processes.
 | ||||||
|     const std::vector<KProcess*>& GetProcessList() const; |     std::list<KScopedAutoObject<KProcess>> GetProcessList(); | ||||||
| 
 | 
 | ||||||
|     /// Gets the sole instance of the global scheduler
 |     /// Gets the sole instance of the global scheduler
 | ||||||
|     Kernel::GlobalSchedulerContext& GlobalSchedulerContext(); |     Kernel::GlobalSchedulerContext& GlobalSchedulerContext(); | ||||||
|  | |||||||
| @ -74,13 +74,15 @@ Result GetProcessList(Core::System& system, s32* out_num_processes, u64 out_proc | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     auto& memory = GetCurrentMemory(kernel); |     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 num_processes = process_list.size(); | ||||||
|     const auto copy_amount = |     const auto copy_amount = | ||||||
|         std::min(static_cast<std::size_t>(out_process_ids_size), num_processes); |         std::min(static_cast<std::size_t>(out_process_ids_size), num_processes); | ||||||
| 
 | 
 | ||||||
|     for (std::size_t i = 0; i < copy_amount; ++i) { |     for (std::size_t i = 0; i < copy_amount && it != process_list.end(); ++i, ++it) { | ||||||
|         memory.Write64(out_process_ids, process_list[i]->GetProcessId()); |         memory.Write64(out_process_ids, (*it)->GetProcessId()); | ||||||
|         out_process_ids += sizeof(u64); |         out_process_ids += sizeof(u64); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -15,9 +15,10 @@ | |||||||
| namespace Service::Glue { | namespace Service::Glue { | ||||||
| 
 | 
 | ||||||
| namespace { | namespace { | ||||||
| std::optional<u64> GetTitleIDForProcessID(const Core::System& system, u64 process_id) { | std::optional<u64> GetTitleIDForProcessID(Core::System& system, u64 process_id) { | ||||||
|     const auto& list = system.Kernel().GetProcessList(); |     auto list = system.Kernel().GetProcessList(); | ||||||
|     const auto iter = std::find_if(list.begin(), list.end(), [&process_id](const auto& process) { | 
 | ||||||
|  |     const auto iter = std::find_if(list.begin(), list.end(), [&process_id](auto& process) { | ||||||
|         return process->GetProcessId() == process_id; |         return process->GetProcessId() == process_id; | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -22,12 +22,10 @@ void LoopProcess(Core::System& system) { | |||||||
|     std::shared_ptr<HidFirmwareSettings> firmware_settings = |     std::shared_ptr<HidFirmwareSettings> firmware_settings = | ||||||
|         std::make_shared<HidFirmwareSettings>(); |         std::make_shared<HidFirmwareSettings>(); | ||||||
| 
 | 
 | ||||||
|     // TODO: Remove this hack until this service is emulated properly.
 |     // TODO: Remove this hack when am is emulated properly.
 | ||||||
|     const auto process_list = system.Kernel().GetProcessList(); |     resource_manager->Initialize(); | ||||||
|     if (!process_list.empty()) { |     resource_manager->RegisterAppletResourceUserId(system.ApplicationProcess()->GetProcessId(), | ||||||
|         resource_manager->Initialize(); |                                                    true); | ||||||
|         resource_manager->RegisterAppletResourceUserId(process_list[0]->GetId(), true); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     server_manager->RegisterNamedService( |     server_manager->RegisterNamedService( | ||||||
|         "hid", std::make_shared<IHidServer>(system, resource_manager, firmware_settings)); |         "hid", std::make_shared<IHidServer>(system, resource_manager, firmware_settings)); | ||||||
|  | |||||||
| @ -22,27 +22,26 @@ constexpr Result ResultProcessNotFound{ErrorModule::PM, 1}; | |||||||
| 
 | 
 | ||||||
| constexpr u64 NO_PROCESS_FOUND_PID{0}; | constexpr u64 NO_PROCESS_FOUND_PID{0}; | ||||||
| 
 | 
 | ||||||
| std::optional<Kernel::KProcess*> SearchProcessList( | using ProcessList = std::list<Kernel::KScopedAutoObject<Kernel::KProcess>>; | ||||||
|     const std::vector<Kernel::KProcess*>& process_list, | 
 | ||||||
|     std::function<bool(Kernel::KProcess*)> predicate) { | 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); |     const auto iter = std::find_if(process_list.begin(), process_list.end(), predicate); | ||||||
| 
 | 
 | ||||||
|     if (iter == process_list.end()) { |     if (iter == process_list.end()) { | ||||||
|         return std::nullopt; |         return nullptr; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return *iter; |     return iter->GetPointerUnsafe(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GetApplicationPidGeneric(HLERequestContext& ctx, | void GetApplicationPidGeneric(HLERequestContext& ctx, ProcessList& process_list) { | ||||||
|                               const std::vector<Kernel::KProcess*>& process_list) { |     auto process = SearchProcessList(process_list, [](auto& p) { return p->IsApplication(); }); | ||||||
|     const auto process = SearchProcessList(process_list, [](const auto& proc) { |  | ||||||
|         return proc->GetProcessId() == Kernel::KProcess::ProcessIdMin; |  | ||||||
|     }); |  | ||||||
| 
 | 
 | ||||||
|     IPC::ResponseBuilder rb{ctx, 4}; |     IPC::ResponseBuilder rb{ctx, 4}; | ||||||
|     rb.Push(ResultSuccess); |     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
 | } // Anonymous namespace
 | ||||||
| @ -80,8 +79,7 @@ private: | |||||||
| 
 | 
 | ||||||
| class DebugMonitor final : public ServiceFramework<DebugMonitor> { | class DebugMonitor final : public ServiceFramework<DebugMonitor> { | ||||||
| public: | public: | ||||||
|     explicit DebugMonitor(Core::System& system_) |     explicit DebugMonitor(Core::System& system_) : ServiceFramework{system_, "pm:dmnt"} { | ||||||
|         : ServiceFramework{system_, "pm:dmnt"}, kernel{system_.Kernel()} { |  | ||||||
|         // clang-format off
 |         // clang-format off
 | ||||||
|         static const FunctionInfo functions[] = { |         static const FunctionInfo functions[] = { | ||||||
|             {0, nullptr, "GetJitDebugProcessIdList"}, |             {0, nullptr, "GetJitDebugProcessIdList"}, | ||||||
| @ -106,12 +104,11 @@ private: | |||||||
| 
 | 
 | ||||||
|         LOG_DEBUG(Service_PM, "called, program_id={:016X}", program_id); |         LOG_DEBUG(Service_PM, "called, program_id={:016X}", program_id); | ||||||
| 
 | 
 | ||||||
|         const auto process = |         auto list = kernel.GetProcessList(); | ||||||
|             SearchProcessList(kernel.GetProcessList(), [program_id](const auto& proc) { |         auto process = SearchProcessList( | ||||||
|                 return proc->GetProgramId() == program_id; |             list, [program_id](auto& p) { return p->GetProgramId() == program_id; }); | ||||||
|             }); |  | ||||||
| 
 | 
 | ||||||
|         if (!process.has_value()) { |         if (process.IsNull()) { | ||||||
|             IPC::ResponseBuilder rb{ctx, 2}; |             IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|             rb.Push(ResultProcessNotFound); |             rb.Push(ResultProcessNotFound); | ||||||
|             return; |             return; | ||||||
| @ -119,12 +116,13 @@ private: | |||||||
| 
 | 
 | ||||||
|         IPC::ResponseBuilder rb{ctx, 4}; |         IPC::ResponseBuilder rb{ctx, 4}; | ||||||
|         rb.Push(ResultSuccess); |         rb.Push(ResultSuccess); | ||||||
|         rb.Push((*process)->GetProcessId()); |         rb.Push(process->GetProcessId()); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void GetApplicationProcessId(HLERequestContext& ctx) { |     void GetApplicationProcessId(HLERequestContext& ctx) { | ||||||
|         LOG_DEBUG(Service_PM, "called"); |         LOG_DEBUG(Service_PM, "called"); | ||||||
|         GetApplicationPidGeneric(ctx, kernel.GetProcessList()); |         auto list = kernel.GetProcessList(); | ||||||
|  |         GetApplicationPidGeneric(ctx, list); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void AtmosphereGetProcessInfo(HLERequestContext& ctx) { |     void AtmosphereGetProcessInfo(HLERequestContext& ctx) { | ||||||
| @ -135,11 +133,10 @@ private: | |||||||
| 
 | 
 | ||||||
|         LOG_WARNING(Service_PM, "(Partial Implementation) called, pid={:016X}", pid); |         LOG_WARNING(Service_PM, "(Partial Implementation) called, pid={:016X}", pid); | ||||||
| 
 | 
 | ||||||
|         const auto process = SearchProcessList(kernel.GetProcessList(), [pid](const auto& proc) { |         auto list = kernel.GetProcessList(); | ||||||
|             return proc->GetProcessId() == pid; |         auto process = SearchProcessList(list, [pid](auto& p) { return p->GetProcessId() == pid; }); | ||||||
|         }); |  | ||||||
| 
 | 
 | ||||||
|         if (!process.has_value()) { |         if (process.IsNull()) { | ||||||
|             IPC::ResponseBuilder rb{ctx, 2}; |             IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|             rb.Push(ResultProcessNotFound); |             rb.Push(ResultProcessNotFound); | ||||||
|             return; |             return; | ||||||
| @ -159,7 +156,7 @@ private: | |||||||
| 
 | 
 | ||||||
|         OverrideStatus override_status{}; |         OverrideStatus override_status{}; | ||||||
|         ProgramLocation program_location{ |         ProgramLocation program_location{ | ||||||
|             .program_id = (*process)->GetProgramId(), |             .program_id = process->GetProgramId(), | ||||||
|             .storage_id = 0, |             .storage_id = 0, | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
| @ -169,14 +166,11 @@ private: | |||||||
|         rb.PushRaw(program_location); |         rb.PushRaw(program_location); | ||||||
|         rb.PushRaw(override_status); |         rb.PushRaw(override_status); | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
|     const Kernel::KernelCore& kernel; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class Info final : public ServiceFramework<Info> { | class Info final : public ServiceFramework<Info> { | ||||||
| public: | public: | ||||||
|     explicit Info(Core::System& system_, const std::vector<Kernel::KProcess*>& process_list_) |     explicit Info(Core::System& system_) : ServiceFramework{system_, "pm:info"} { | ||||||
|         : ServiceFramework{system_, "pm:info"}, process_list{process_list_} { |  | ||||||
|         static const FunctionInfo functions[] = { |         static const FunctionInfo functions[] = { | ||||||
|             {0, &Info::GetProgramId, "GetProgramId"}, |             {0, &Info::GetProgramId, "GetProgramId"}, | ||||||
|             {65000, &Info::AtmosphereGetProcessId, "AtmosphereGetProcessId"}, |             {65000, &Info::AtmosphereGetProcessId, "AtmosphereGetProcessId"}, | ||||||
| @ -193,11 +187,11 @@ private: | |||||||
| 
 | 
 | ||||||
|         LOG_DEBUG(Service_PM, "called, process_id={:016X}", process_id); |         LOG_DEBUG(Service_PM, "called, process_id={:016X}", process_id); | ||||||
| 
 | 
 | ||||||
|         const auto process = SearchProcessList(process_list, [process_id](const auto& proc) { |         auto list = kernel.GetProcessList(); | ||||||
|             return proc->GetProcessId() == process_id; |         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}; |             IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|             rb.Push(ResultProcessNotFound); |             rb.Push(ResultProcessNotFound); | ||||||
|             return; |             return; | ||||||
| @ -205,7 +199,7 @@ private: | |||||||
| 
 | 
 | ||||||
|         IPC::ResponseBuilder rb{ctx, 4}; |         IPC::ResponseBuilder rb{ctx, 4}; | ||||||
|         rb.Push(ResultSuccess); |         rb.Push(ResultSuccess); | ||||||
|         rb.Push((*process)->GetProgramId()); |         rb.Push(process->GetProgramId()); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void AtmosphereGetProcessId(HLERequestContext& ctx) { |     void AtmosphereGetProcessId(HLERequestContext& ctx) { | ||||||
| @ -214,11 +208,11 @@ private: | |||||||
| 
 | 
 | ||||||
|         LOG_DEBUG(Service_PM, "called, program_id={:016X}", program_id); |         LOG_DEBUG(Service_PM, "called, program_id={:016X}", program_id); | ||||||
| 
 | 
 | ||||||
|         const auto process = SearchProcessList(process_list, [program_id](const auto& proc) { |         auto list = system.Kernel().GetProcessList(); | ||||||
|             return proc->GetProgramId() == program_id; |         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}; |             IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|             rb.Push(ResultProcessNotFound); |             rb.Push(ResultProcessNotFound); | ||||||
|             return; |             return; | ||||||
| @ -226,16 +220,13 @@ private: | |||||||
| 
 | 
 | ||||||
|         IPC::ResponseBuilder rb{ctx, 4}; |         IPC::ResponseBuilder rb{ctx, 4}; | ||||||
|         rb.Push(ResultSuccess); |         rb.Push(ResultSuccess); | ||||||
|         rb.Push((*process)->GetProcessId()); |         rb.Push(process->GetProcessId()); | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
|     const std::vector<Kernel::KProcess*>& process_list; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class Shell final : public ServiceFramework<Shell> { | class Shell final : public ServiceFramework<Shell> { | ||||||
| public: | public: | ||||||
|     explicit Shell(Core::System& system_) |     explicit Shell(Core::System& system_) : ServiceFramework{system_, "pm:shell"} { | ||||||
|         : ServiceFramework{system_, "pm:shell"}, kernel{system_.Kernel()} { |  | ||||||
|         // clang-format off
 |         // clang-format off
 | ||||||
|         static const FunctionInfo functions[] = { |         static const FunctionInfo functions[] = { | ||||||
|             {0, nullptr, "LaunchProgram"}, |             {0, nullptr, "LaunchProgram"}, | ||||||
| @ -257,10 +248,9 @@ public: | |||||||
| private: | private: | ||||||
|     void GetApplicationProcessIdForShell(HLERequestContext& ctx) { |     void GetApplicationProcessIdForShell(HLERequestContext& ctx) { | ||||||
|         LOG_DEBUG(Service_PM, "called"); |         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) { | 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:bm", std::make_shared<BootMode>(system)); | ||||||
|     server_manager->RegisterNamedService("pm:dmnt", std::make_shared<DebugMonitor>(system)); |     server_manager->RegisterNamedService("pm:dmnt", std::make_shared<DebugMonitor>(system)); | ||||||
|     server_manager->RegisterNamedService( |     server_manager->RegisterNamedService("pm:info", std::make_shared<Info>(system)); | ||||||
|         "pm:info", std::make_shared<Info>(system, system.Kernel().GetProcessList())); |  | ||||||
|     server_manager->RegisterNamedService("pm:shell", std::make_shared<Shell>(system)); |     server_manager->RegisterNamedService("pm:shell", std::make_shared<Shell>(system)); | ||||||
|     ServerManager::RunServer(std::move(server_manager)); |     ServerManager::RunServer(std::move(server_manager)); | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user