summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Liam2024-01-02 17:12:16 -0500
committerGravatar Liam2024-01-12 18:31:33 -0500
commitf90a022d3a20c86399f49a8154847b73bc1b8fd3 (patch)
tree672214411189aaf408febc5aa9cc01e45aed5f5f /src
parentkernel: fix page leak on process termination (diff)
downloadyuzu-f90a022d3a20c86399f49a8154847b73bc1b8fd3.tar.gz
yuzu-f90a022d3a20c86399f49a8154847b73bc1b8fd3.tar.xz
yuzu-f90a022d3a20c86399f49a8154847b73bc1b8fd3.zip
kernel: fix debugger and process list lifetime
Diffstat (limited to 'src')
-rw-r--r--src/core/debugger/debugger.cpp39
-rw-r--r--src/core/debugger/gdbstub.cpp66
-rw-r--r--src/core/debugger/gdbstub.h15
-rw-r--r--src/core/hle/kernel/kernel.cpp31
-rw-r--r--src/core/hle/kernel/kernel.h6
-rw-r--r--src/core/hle/kernel/svc/svc_process.cpp8
-rw-r--r--src/core/hle/service/glue/arp.cpp7
-rw-r--r--src/core/hle/service/hid/hid.cpp10
-rw-r--r--src/core/hle/service/pm/pm.cpp85
9 files changed, 160 insertions, 107 deletions
diff --git a/src/core/debugger/debugger.cpp b/src/core/debugger/debugger.cpp
index 0e270eb50..e86aae846 100644
--- a/src/core/debugger/debugger.cpp
+++ b/src/core/debugger/debugger.cpp
@@ -114,7 +114,7 @@ public:
114 } 114 }
115 115
116 Kernel::KThread* GetActiveThread() override { 116 Kernel::KThread* GetActiveThread() override {
117 return state->active_thread; 117 return state->active_thread.GetPointerUnsafe();
118 } 118 }
119 119
120private: 120private:
@@ -147,11 +147,14 @@ private:
147 147
148 std::scoped_lock lk{connection_lock}; 148 std::scoped_lock lk{connection_lock};
149 149
150 // Find the process we are going to debug.
151 SetDebugProcess();
152
150 // Ensure everything is stopped. 153 // Ensure everything is stopped.
151 PauseEmulation(); 154 PauseEmulation();
152 155
153 // Set up the new frontend. 156 // Set up the new frontend.
154 frontend = std::make_unique<GDBStub>(*this, system); 157 frontend = std::make_unique<GDBStub>(*this, system, debug_process.GetPointerUnsafe());
155 158
156 // Set the new state. This will tear down any existing state. 159 // Set the new state. This will tear down any existing state.
157 state = ConnectionState{ 160 state = ConnectionState{
@@ -194,15 +197,20 @@ private:
194 UpdateActiveThread(); 197 UpdateActiveThread();
195 198
196 if (state->info.type == SignalType::Watchpoint) { 199 if (state->info.type == SignalType::Watchpoint) {
197 frontend->Watchpoint(state->active_thread, *state->info.watchpoint); 200 frontend->Watchpoint(std::addressof(*state->active_thread),
201 *state->info.watchpoint);
198 } else { 202 } else {
199 frontend->Stopped(state->active_thread); 203 frontend->Stopped(std::addressof(*state->active_thread));
200 } 204 }
201 205
202 break; 206 break;
203 case SignalType::ShuttingDown: 207 case SignalType::ShuttingDown:
204 frontend->ShuttingDown(); 208 frontend->ShuttingDown();
205 209
210 // Release members.
211 state->active_thread.Reset(nullptr);
212 debug_process.Reset(nullptr);
213
206 // Wait for emulation to shut down gracefully now. 214 // Wait for emulation to shut down gracefully now.
207 state->signal_pipe.close(); 215 state->signal_pipe.close();
208 state->client_socket.shutdown(boost::asio::socket_base::shutdown_both); 216 state->client_socket.shutdown(boost::asio::socket_base::shutdown_both);
@@ -222,7 +230,7 @@ private:
222 stopped = true; 230 stopped = true;
223 PauseEmulation(); 231 PauseEmulation();
224 UpdateActiveThread(); 232 UpdateActiveThread();
225 frontend->Stopped(state->active_thread); 233 frontend->Stopped(state->active_thread.GetPointerUnsafe());
226 break; 234 break;
227 } 235 }
228 case DebuggerAction::Continue: 236 case DebuggerAction::Continue:
@@ -232,7 +240,7 @@ private:
232 MarkResumed([&] { 240 MarkResumed([&] {
233 state->active_thread->SetStepState(Kernel::StepState::StepPending); 241 state->active_thread->SetStepState(Kernel::StepState::StepPending);
234 state->active_thread->Resume(Kernel::SuspendType::Debug); 242 state->active_thread->Resume(Kernel::SuspendType::Debug);
235 ResumeEmulation(state->active_thread); 243 ResumeEmulation(state->active_thread.GetPointerUnsafe());
236 }); 244 });
237 break; 245 break;
238 case DebuggerAction::StepThreadLocked: { 246 case DebuggerAction::StepThreadLocked: {
@@ -255,6 +263,7 @@ private:
255 } 263 }
256 264
257 void PauseEmulation() { 265 void PauseEmulation() {
266 Kernel::KScopedLightLock ll{debug_process->GetListLock()};
258 Kernel::KScopedSchedulerLock sl{system.Kernel()}; 267 Kernel::KScopedSchedulerLock sl{system.Kernel()};
259 268
260 // Put all threads to sleep on next scheduler round. 269 // Put all threads to sleep on next scheduler round.
@@ -264,6 +273,9 @@ private:
264 } 273 }
265 274
266 void ResumeEmulation(Kernel::KThread* except = nullptr) { 275 void ResumeEmulation(Kernel::KThread* except = nullptr) {
276 Kernel::KScopedLightLock ll{debug_process->GetListLock()};
277 Kernel::KScopedSchedulerLock sl{system.Kernel()};
278
267 // Wake up all threads. 279 // Wake up all threads.
268 for (auto& thread : ThreadList()) { 280 for (auto& thread : ThreadList()) {
269 if (std::addressof(thread) == except) { 281 if (std::addressof(thread) == except) {
@@ -277,15 +289,16 @@ private:
277 289
278 template <typename Callback> 290 template <typename Callback>
279 void MarkResumed(Callback&& cb) { 291 void MarkResumed(Callback&& cb) {
280 Kernel::KScopedSchedulerLock sl{system.Kernel()};
281 stopped = false; 292 stopped = false;
282 cb(); 293 cb();
283 } 294 }
284 295
285 void UpdateActiveThread() { 296 void UpdateActiveThread() {
297 Kernel::KScopedLightLock ll{debug_process->GetListLock()};
298
286 auto& threads{ThreadList()}; 299 auto& threads{ThreadList()};
287 for (auto& thread : threads) { 300 for (auto& thread : threads) {
288 if (std::addressof(thread) == state->active_thread) { 301 if (std::addressof(thread) == state->active_thread.GetPointerUnsafe()) {
289 // Thread is still alive, no need to update. 302 // Thread is still alive, no need to update.
290 return; 303 return;
291 } 304 }
@@ -293,12 +306,18 @@ private:
293 state->active_thread = std::addressof(threads.front()); 306 state->active_thread = std::addressof(threads.front());
294 } 307 }
295 308
309private:
310 void SetDebugProcess() {
311 debug_process = std::move(system.Kernel().GetProcessList().back());
312 }
313
296 Kernel::KProcess::ThreadList& ThreadList() { 314 Kernel::KProcess::ThreadList& ThreadList() {
297 return system.ApplicationProcess()->GetThreadList(); 315 return debug_process->GetThreadList();
298 } 316 }
299 317
300private: 318private:
301 System& system; 319 System& system;
320 Kernel::KScopedAutoObject<Kernel::KProcess> debug_process;
302 std::unique_ptr<DebuggerFrontend> frontend; 321 std::unique_ptr<DebuggerFrontend> frontend;
303 322
304 boost::asio::io_context io_context; 323 boost::asio::io_context io_context;
@@ -310,7 +329,7 @@ private:
310 boost::process::async_pipe signal_pipe; 329 boost::process::async_pipe signal_pipe;
311 330
312 SignalInfo info; 331 SignalInfo info;
313 Kernel::KThread* active_thread; 332 Kernel::KScopedAutoObject<Kernel::KThread> active_thread;
314 std::array<u8, 4096> client_data; 333 std::array<u8, 4096> client_data;
315 bool pipe_data; 334 bool pipe_data;
316 }; 335 };
diff --git a/src/core/debugger/gdbstub.cpp b/src/core/debugger/gdbstub.cpp
index 4051ed4af..80091cc7e 100644
--- a/src/core/debugger/gdbstub.cpp
+++ b/src/core/debugger/gdbstub.cpp
@@ -108,9 +108,9 @@ static std::string EscapeXML(std::string_view data) {
108 return escaped; 108 return escaped;
109} 109}
110 110
111GDBStub::GDBStub(DebuggerBackend& backend_, Core::System& system_) 111GDBStub::GDBStub(DebuggerBackend& backend_, Core::System& system_, Kernel::KProcess* debug_process_)
112 : DebuggerFrontend(backend_), system{system_} { 112 : DebuggerFrontend(backend_), system{system_}, debug_process{debug_process_} {
113 if (system.ApplicationProcess()->Is64Bit()) { 113 if (GetProcess()->Is64Bit()) {
114 arch = std::make_unique<GDBStubA64>(); 114 arch = std::make_unique<GDBStubA64>();
115 } else { 115 } else {
116 arch = std::make_unique<GDBStubA32>(); 116 arch = std::make_unique<GDBStubA32>();
@@ -276,7 +276,7 @@ void GDBStub::ExecuteCommand(std::string_view packet, std::vector<DebuggerAction
276 const size_t size{static_cast<size_t>(strtoll(command.data() + sep, nullptr, 16))}; 276 const size_t size{static_cast<size_t>(strtoll(command.data() + sep, nullptr, 16))};
277 277
278 std::vector<u8> mem(size); 278 std::vector<u8> mem(size);
279 if (system.ApplicationMemory().ReadBlock(addr, mem.data(), size)) { 279 if (GetMemory().ReadBlock(addr, mem.data(), size)) {
280 // Restore any bytes belonging to replaced instructions. 280 // Restore any bytes belonging to replaced instructions.
281 auto it = replaced_instructions.lower_bound(addr); 281 auto it = replaced_instructions.lower_bound(addr);
282 for (; it != replaced_instructions.end() && it->first < addr + size; it++) { 282 for (; it != replaced_instructions.end() && it->first < addr + size; it++) {
@@ -310,8 +310,8 @@ void GDBStub::ExecuteCommand(std::string_view packet, std::vector<DebuggerAction
310 const auto mem_substr{std::string_view(command).substr(mem_sep)}; 310 const auto mem_substr{std::string_view(command).substr(mem_sep)};
311 const auto mem{Common::HexStringToVector(mem_substr, false)}; 311 const auto mem{Common::HexStringToVector(mem_substr, false)};
312 312
313 if (system.ApplicationMemory().WriteBlock(addr, mem.data(), size)) { 313 if (GetMemory().WriteBlock(addr, mem.data(), size)) {
314 Core::InvalidateInstructionCacheRange(system.ApplicationProcess(), addr, size); 314 Core::InvalidateInstructionCacheRange(GetProcess(), addr, size);
315 SendReply(GDB_STUB_REPLY_OK); 315 SendReply(GDB_STUB_REPLY_OK);
316 } else { 316 } else {
317 SendReply(GDB_STUB_REPLY_ERR); 317 SendReply(GDB_STUB_REPLY_ERR);
@@ -353,7 +353,7 @@ void GDBStub::HandleBreakpointInsert(std::string_view command) {
353 const size_t addr{static_cast<size_t>(strtoll(command.data() + addr_sep, nullptr, 16))}; 353 const size_t addr{static_cast<size_t>(strtoll(command.data() + addr_sep, nullptr, 16))};
354 const size_t size{static_cast<size_t>(strtoll(command.data() + size_sep, nullptr, 16))}; 354 const size_t size{static_cast<size_t>(strtoll(command.data() + size_sep, nullptr, 16))};
355 355
356 if (!system.ApplicationMemory().IsValidVirtualAddressRange(addr, size)) { 356 if (!GetMemory().IsValidVirtualAddressRange(addr, size)) {
357 SendReply(GDB_STUB_REPLY_ERR); 357 SendReply(GDB_STUB_REPLY_ERR);
358 return; 358 return;
359 } 359 }
@@ -362,22 +362,20 @@ void GDBStub::HandleBreakpointInsert(std::string_view command) {
362 362
363 switch (type) { 363 switch (type) {
364 case BreakpointType::Software: 364 case BreakpointType::Software:
365 replaced_instructions[addr] = system.ApplicationMemory().Read32(addr); 365 replaced_instructions[addr] = GetMemory().Read32(addr);
366 system.ApplicationMemory().Write32(addr, arch->BreakpointInstruction()); 366 GetMemory().Write32(addr, arch->BreakpointInstruction());
367 Core::InvalidateInstructionCacheRange(system.ApplicationProcess(), addr, sizeof(u32)); 367 Core::InvalidateInstructionCacheRange(GetProcess(), addr, sizeof(u32));
368 success = true; 368 success = true;
369 break; 369 break;
370 case BreakpointType::WriteWatch: 370 case BreakpointType::WriteWatch:
371 success = system.ApplicationProcess()->InsertWatchpoint(addr, size, 371 success = GetProcess()->InsertWatchpoint(addr, size, Kernel::DebugWatchpointType::Write);
372 Kernel::DebugWatchpointType::Write);
373 break; 372 break;
374 case BreakpointType::ReadWatch: 373 case BreakpointType::ReadWatch:
375 success = system.ApplicationProcess()->InsertWatchpoint(addr, size, 374 success = GetProcess()->InsertWatchpoint(addr, size, Kernel::DebugWatchpointType::Read);
376 Kernel::DebugWatchpointType::Read);
377 break; 375 break;
378 case BreakpointType::AccessWatch: 376 case BreakpointType::AccessWatch:
379 success = system.ApplicationProcess()->InsertWatchpoint( 377 success =
380 addr, size, Kernel::DebugWatchpointType::ReadOrWrite); 378 GetProcess()->InsertWatchpoint(addr, size, Kernel::DebugWatchpointType::ReadOrWrite);
381 break; 379 break;
382 case BreakpointType::Hardware: 380 case BreakpointType::Hardware:
383 default: 381 default:
@@ -400,7 +398,7 @@ void GDBStub::HandleBreakpointRemove(std::string_view command) {
400 const size_t addr{static_cast<size_t>(strtoll(command.data() + addr_sep, nullptr, 16))}; 398 const size_t addr{static_cast<size_t>(strtoll(command.data() + addr_sep, nullptr, 16))};
401 const size_t size{static_cast<size_t>(strtoll(command.data() + size_sep, nullptr, 16))}; 399 const size_t size{static_cast<size_t>(strtoll(command.data() + size_sep, nullptr, 16))};
402 400
403 if (!system.ApplicationMemory().IsValidVirtualAddressRange(addr, size)) { 401 if (!GetMemory().IsValidVirtualAddressRange(addr, size)) {
404 SendReply(GDB_STUB_REPLY_ERR); 402 SendReply(GDB_STUB_REPLY_ERR);
405 return; 403 return;
406 } 404 }
@@ -411,24 +409,22 @@ void GDBStub::HandleBreakpointRemove(std::string_view command) {
411 case BreakpointType::Software: { 409 case BreakpointType::Software: {
412 const auto orig_insn{replaced_instructions.find(addr)}; 410 const auto orig_insn{replaced_instructions.find(addr)};
413 if (orig_insn != replaced_instructions.end()) { 411 if (orig_insn != replaced_instructions.end()) {
414 system.ApplicationMemory().Write32(addr, orig_insn->second); 412 GetMemory().Write32(addr, orig_insn->second);
415 Core::InvalidateInstructionCacheRange(system.ApplicationProcess(), addr, sizeof(u32)); 413 Core::InvalidateInstructionCacheRange(GetProcess(), addr, sizeof(u32));
416 replaced_instructions.erase(addr); 414 replaced_instructions.erase(addr);
417 success = true; 415 success = true;
418 } 416 }
419 break; 417 break;
420 } 418 }
421 case BreakpointType::WriteWatch: 419 case BreakpointType::WriteWatch:
422 success = system.ApplicationProcess()->RemoveWatchpoint(addr, size, 420 success = GetProcess()->RemoveWatchpoint(addr, size, Kernel::DebugWatchpointType::Write);
423 Kernel::DebugWatchpointType::Write);
424 break; 421 break;
425 case BreakpointType::ReadWatch: 422 case BreakpointType::ReadWatch:
426 success = system.ApplicationProcess()->RemoveWatchpoint(addr, size, 423 success = GetProcess()->RemoveWatchpoint(addr, size, Kernel::DebugWatchpointType::Read);
427 Kernel::DebugWatchpointType::Read);
428 break; 424 break;
429 case BreakpointType::AccessWatch: 425 case BreakpointType::AccessWatch:
430 success = system.ApplicationProcess()->RemoveWatchpoint( 426 success =
431 addr, size, Kernel::DebugWatchpointType::ReadOrWrite); 427 GetProcess()->RemoveWatchpoint(addr, size, Kernel::DebugWatchpointType::ReadOrWrite);
432 break; 428 break;
433 case BreakpointType::Hardware: 429 case BreakpointType::Hardware:
434 default: 430 default:
@@ -466,10 +462,10 @@ void GDBStub::HandleQuery(std::string_view command) {
466 const auto target_xml{arch->GetTargetXML()}; 462 const auto target_xml{arch->GetTargetXML()};
467 SendReply(PaginateBuffer(target_xml, command.substr(30))); 463 SendReply(PaginateBuffer(target_xml, command.substr(30)));
468 } else if (command.starts_with("Offsets")) { 464 } else if (command.starts_with("Offsets")) {
469 const auto main_offset = Core::FindMainModuleEntrypoint(system.ApplicationProcess()); 465 const auto main_offset = Core::FindMainModuleEntrypoint(GetProcess());
470 SendReply(fmt::format("TextSeg={:x}", GetInteger(main_offset))); 466 SendReply(fmt::format("TextSeg={:x}", GetInteger(main_offset)));
471 } else if (command.starts_with("Xfer:libraries:read::")) { 467 } else if (command.starts_with("Xfer:libraries:read::")) {
472 auto modules = Core::FindModules(system.ApplicationProcess()); 468 auto modules = Core::FindModules(GetProcess());
473 469
474 std::string buffer; 470 std::string buffer;
475 buffer += R"(<?xml version="1.0"?>)"; 471 buffer += R"(<?xml version="1.0"?>)";
@@ -483,7 +479,7 @@ void GDBStub::HandleQuery(std::string_view command) {
483 SendReply(PaginateBuffer(buffer, command.substr(21))); 479 SendReply(PaginateBuffer(buffer, command.substr(21)));
484 } else if (command.starts_with("fThreadInfo")) { 480 } else if (command.starts_with("fThreadInfo")) {
485 // beginning of list 481 // beginning of list
486 const auto& threads = system.ApplicationProcess()->GetThreadList(); 482 const auto& threads = GetProcess()->GetThreadList();
487 std::vector<std::string> thread_ids; 483 std::vector<std::string> thread_ids;
488 for (const auto& thread : threads) { 484 for (const auto& thread : threads) {
489 thread_ids.push_back(fmt::format("{:x}", thread.GetThreadId())); 485 thread_ids.push_back(fmt::format("{:x}", thread.GetThreadId()));
@@ -497,7 +493,7 @@ void GDBStub::HandleQuery(std::string_view command) {
497 buffer += R"(<?xml version="1.0"?>)"; 493 buffer += R"(<?xml version="1.0"?>)";
498 buffer += "<threads>"; 494 buffer += "<threads>";
499 495
500 const auto& threads = system.ApplicationProcess()->GetThreadList(); 496 const auto& threads = GetProcess()->GetThreadList();
501 for (const auto& thread : threads) { 497 for (const auto& thread : threads) {
502 auto thread_name{Core::GetThreadName(&thread)}; 498 auto thread_name{Core::GetThreadName(&thread)};
503 if (!thread_name) { 499 if (!thread_name) {
@@ -613,7 +609,7 @@ void GDBStub::HandleRcmd(const std::vector<u8>& command) {
613 std::string_view command_str{reinterpret_cast<const char*>(&command[0]), command.size()}; 609 std::string_view command_str{reinterpret_cast<const char*>(&command[0]), command.size()};
614 std::string reply; 610 std::string reply;
615 611
616 auto* process = system.ApplicationProcess(); 612 auto* process = GetProcess();
617 auto& page_table = process->GetPageTable(); 613 auto& page_table = process->GetPageTable();
618 614
619 const char* commands = "Commands:\n" 615 const char* commands = "Commands:\n"
@@ -714,7 +710,7 @@ void GDBStub::HandleRcmd(const std::vector<u8>& command) {
714} 710}
715 711
716Kernel::KThread* GDBStub::GetThreadByID(u64 thread_id) { 712Kernel::KThread* GDBStub::GetThreadByID(u64 thread_id) {
717 auto& threads{system.ApplicationProcess()->GetThreadList()}; 713 auto& threads{GetProcess()->GetThreadList()};
718 for (auto& thread : threads) { 714 for (auto& thread : threads) {
719 if (thread.GetThreadId() == thread_id) { 715 if (thread.GetThreadId() == thread_id) {
720 return std::addressof(thread); 716 return std::addressof(thread);
@@ -783,4 +779,12 @@ void GDBStub::SendStatus(char status) {
783 backend.WriteToClient(buf); 779 backend.WriteToClient(buf);
784} 780}
785 781
782Kernel::KProcess* GDBStub::GetProcess() {
783 return debug_process;
784}
785
786Core::Memory::Memory& GDBStub::GetMemory() {
787 return GetProcess()->GetMemory();
788}
789
786} // namespace Core 790} // namespace Core
diff --git a/src/core/debugger/gdbstub.h b/src/core/debugger/gdbstub.h
index 368197920..232dcf49f 100644
--- a/src/core/debugger/gdbstub.h
+++ b/src/core/debugger/gdbstub.h
@@ -12,13 +12,22 @@
12#include "core/debugger/debugger_interface.h" 12#include "core/debugger/debugger_interface.h"
13#include "core/debugger/gdbstub_arch.h" 13#include "core/debugger/gdbstub_arch.h"
14 14
15namespace Kernel {
16class KProcess;
17}
18
19namespace Core::Memory {
20class Memory;
21}
22
15namespace Core { 23namespace Core {
16 24
17class System; 25class System;
18 26
19class GDBStub : public DebuggerFrontend { 27class GDBStub : public DebuggerFrontend {
20public: 28public:
21 explicit GDBStub(DebuggerBackend& backend, Core::System& system); 29 explicit GDBStub(DebuggerBackend& backend, Core::System& system,
30 Kernel::KProcess* debug_process);
22 ~GDBStub() override; 31 ~GDBStub() override;
23 32
24 void Connected() override; 33 void Connected() override;
@@ -42,8 +51,12 @@ private:
42 void SendReply(std::string_view data); 51 void SendReply(std::string_view data);
43 void SendStatus(char status); 52 void SendStatus(char status);
44 53
54 Kernel::KProcess* GetProcess();
55 Core::Memory::Memory& GetMemory();
56
45private: 57private:
46 Core::System& system; 58 Core::System& system;
59 Kernel::KProcess* debug_process;
47 std::unique_ptr<GDBStubArch> arch; 60 std::unique_ptr<GDBStubArch> arch;
48 std::vector<char> current_command; 61 std::vector<char> current_command;
49 std::map<VAddr, u32> replaced_instructions; 62 std::map<VAddr, u32> replaced_instructions;
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 {
112 old_process->Close(); 112 old_process->Close();
113 } 113 }
114 114
115 process_list.clear(); 115 {
116 std::scoped_lock lk{process_list_lock};
117 for (auto* const process : process_list) {
118 process->Terminate();
119 process->Close();
120 }
121 process_list.clear();
122 }
116 123
117 next_object_id = 0; 124 next_object_id = 0;
118 next_kernel_process_id = KProcess::InitialProcessIdMin; 125 next_kernel_process_id = KProcess::InitialProcessIdMin;
@@ -770,6 +777,7 @@ struct KernelCore::Impl {
770 std::atomic<u64> next_thread_id{1}; 777 std::atomic<u64> next_thread_id{1};
771 778
772 // Lists all processes that exist in the current session. 779 // Lists all processes that exist in the current session.
780 std::mutex process_list_lock;
773 std::vector<KProcess*> process_list; 781 std::vector<KProcess*> process_list;
774 std::atomic<KProcess*> application_process{}; 782 std::atomic<KProcess*> application_process{};
775 std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context; 783 std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context;
@@ -869,9 +877,19 @@ KResourceLimit* KernelCore::GetSystemResourceLimit() {
869} 877}
870 878
871void KernelCore::AppendNewProcess(KProcess* process) { 879void KernelCore::AppendNewProcess(KProcess* process) {
880 process->Open();
881
882 std::scoped_lock lk{impl->process_list_lock};
872 impl->process_list.push_back(process); 883 impl->process_list.push_back(process);
873} 884}
874 885
886void KernelCore::RemoveProcess(KProcess* process) {
887 std::scoped_lock lk{impl->process_list_lock};
888 if (std::erase(impl->process_list, process)) {
889 process->Close();
890 }
891}
892
875void KernelCore::MakeApplicationProcess(KProcess* process) { 893void KernelCore::MakeApplicationProcess(KProcess* process) {
876 impl->MakeApplicationProcess(process); 894 impl->MakeApplicationProcess(process);
877} 895}
@@ -884,8 +902,15 @@ const KProcess* KernelCore::ApplicationProcess() const {
884 return impl->application_process; 902 return impl->application_process;
885} 903}
886 904
887const std::vector<KProcess*>& KernelCore::GetProcessList() const { 905std::list<KScopedAutoObject<KProcess>> KernelCore::GetProcessList() {
888 return impl->process_list; 906 std::list<KScopedAutoObject<KProcess>> processes;
907 std::scoped_lock lk{impl->process_list_lock};
908
909 for (auto* const process : impl->process_list) {
910 processes.emplace_back(process);
911 }
912
913 return processes;
889} 914}
890 915
891Kernel::GlobalSchedulerContext& KernelCore::GlobalSchedulerContext() { 916Kernel::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 @@
5 5
6#include <array> 6#include <array>
7#include <functional> 7#include <functional>
8#include <list>
8#include <memory> 9#include <memory>
9#include <string> 10#include <string>
10#include <unordered_map> 11#include <unordered_map>
@@ -116,8 +117,9 @@ public:
116 /// Retrieves a shared pointer to the system resource limit instance. 117 /// Retrieves a shared pointer to the system resource limit instance.
117 KResourceLimit* GetSystemResourceLimit(); 118 KResourceLimit* GetSystemResourceLimit();
118 119
119 /// Adds the given shared pointer to an internal list of active processes. 120 /// Adds/removes the given pointer to an internal list of active processes.
120 void AppendNewProcess(KProcess* process); 121 void AppendNewProcess(KProcess* process);
122 void RemoveProcess(KProcess* process);
121 123
122 /// Makes the given process the new application process. 124 /// Makes the given process the new application process.
123 void MakeApplicationProcess(KProcess* process); 125 void MakeApplicationProcess(KProcess* process);
@@ -129,7 +131,7 @@ public:
129 const KProcess* ApplicationProcess() const; 131 const KProcess* ApplicationProcess() const;
130 132
131 /// Retrieves the list of processes. 133 /// Retrieves the list of processes.
132 const std::vector<KProcess*>& GetProcessList() const; 134 std::list<KScopedAutoObject<KProcess>> GetProcessList();
133 135
134 /// Gets the sole instance of the global scheduler 136 /// Gets the sole instance of the global scheduler
135 Kernel::GlobalSchedulerContext& GlobalSchedulerContext(); 137 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
74 } 74 }
75 75
76 auto& memory = GetCurrentMemory(kernel); 76 auto& memory = GetCurrentMemory(kernel);
77 const auto& process_list = kernel.GetProcessList(); 77 auto process_list = kernel.GetProcessList();
78 auto it = process_list.begin();
79
78 const auto num_processes = process_list.size(); 80 const auto num_processes = process_list.size();
79 const auto copy_amount = 81 const auto copy_amount =
80 std::min(static_cast<std::size_t>(out_process_ids_size), num_processes); 82 std::min(static_cast<std::size_t>(out_process_ids_size), num_processes);
81 83
82 for (std::size_t i = 0; i < copy_amount; ++i) { 84 for (std::size_t i = 0; i < copy_amount && it != process_list.end(); ++i, ++it) {
83 memory.Write64(out_process_ids, process_list[i]->GetProcessId()); 85 memory.Write64(out_process_ids, (*it)->GetProcessId());
84 out_process_ids += sizeof(u64); 86 out_process_ids += sizeof(u64);
85 } 87 }
86 88
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 @@
15namespace Service::Glue { 15namespace Service::Glue {
16 16
17namespace { 17namespace {
18std::optional<u64> GetTitleIDForProcessID(const Core::System& system, u64 process_id) { 18std::optional<u64> GetTitleIDForProcessID(Core::System& system, u64 process_id) {
19 const auto& list = system.Kernel().GetProcessList(); 19 auto list = system.Kernel().GetProcessList();
20 const auto iter = std::find_if(list.begin(), list.end(), [&process_id](const auto& process) { 20
21 const auto iter = std::find_if(list.begin(), list.end(), [&process_id](auto& process) {
21 return process->GetProcessId() == process_id; 22 return process->GetProcessId() == process_id;
22 }); 23 });
23 24
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) {
22 std::shared_ptr<HidFirmwareSettings> firmware_settings = 22 std::shared_ptr<HidFirmwareSettings> firmware_settings =
23 std::make_shared<HidFirmwareSettings>(); 23 std::make_shared<HidFirmwareSettings>();
24 24
25 // TODO: Remove this hack until this service is emulated properly. 25 // TODO: Remove this hack when am is emulated properly.
26 const auto process_list = system.Kernel().GetProcessList(); 26 resource_manager->Initialize();
27 if (!process_list.empty()) { 27 resource_manager->RegisterAppletResourceUserId(system.ApplicationProcess()->GetProcessId(),
28 resource_manager->Initialize(); 28 true);
29 resource_manager->RegisterAppletResourceUserId(process_list[0]->GetId(), true);
30 }
31 29
32 server_manager->RegisterNamedService( 30 server_manager->RegisterNamedService(
33 "hid", std::make_shared<IHidServer>(system, resource_manager, firmware_settings)); 31 "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};
22 22
23constexpr u64 NO_PROCESS_FOUND_PID{0}; 23constexpr u64 NO_PROCESS_FOUND_PID{0};
24 24
25std::optional<Kernel::KProcess*> SearchProcessList( 25using ProcessList = std::list<Kernel::KScopedAutoObject<Kernel::KProcess>>;
26 const std::vector<Kernel::KProcess*>& process_list, 26
27 std::function<bool(Kernel::KProcess*)> predicate) { 27template <typename F>
28Kernel::KScopedAutoObject<Kernel::KProcess> SearchProcessList(ProcessList& process_list,
29 F&& predicate) {
28 const auto iter = std::find_if(process_list.begin(), process_list.end(), predicate); 30 const auto iter = std::find_if(process_list.begin(), process_list.end(), predicate);
29 31
30 if (iter == process_list.end()) { 32 if (iter == process_list.end()) {
31 return std::nullopt; 33 return nullptr;
32 } 34 }
33 35
34 return *iter; 36 return iter->GetPointerUnsafe();
35} 37}
36 38
37void GetApplicationPidGeneric(HLERequestContext& ctx, 39void GetApplicationPidGeneric(HLERequestContext& ctx, ProcessList& process_list) {
38 const std::vector<Kernel::KProcess*>& process_list) { 40 auto process = SearchProcessList(process_list, [](auto& p) { return p->IsApplication(); });
39 const auto process = SearchProcessList(process_list, [](const auto& proc) {
40 return proc->GetProcessId() == Kernel::KProcess::ProcessIdMin;
41 });
42 41
43 IPC::ResponseBuilder rb{ctx, 4}; 42 IPC::ResponseBuilder rb{ctx, 4};
44 rb.Push(ResultSuccess); 43 rb.Push(ResultSuccess);
45 rb.Push(process.has_value() ? (*process)->GetProcessId() : NO_PROCESS_FOUND_PID); 44 rb.Push(process.IsNull() ? NO_PROCESS_FOUND_PID : process->GetProcessId());
46} 45}
47 46
48} // Anonymous namespace 47} // Anonymous namespace
@@ -80,8 +79,7 @@ private:
80 79
81class DebugMonitor final : public ServiceFramework<DebugMonitor> { 80class DebugMonitor final : public ServiceFramework<DebugMonitor> {
82public: 81public:
83 explicit DebugMonitor(Core::System& system_) 82 explicit DebugMonitor(Core::System& system_) : ServiceFramework{system_, "pm:dmnt"} {
84 : ServiceFramework{system_, "pm:dmnt"}, kernel{system_.Kernel()} {
85 // clang-format off 83 // clang-format off
86 static const FunctionInfo functions[] = { 84 static const FunctionInfo functions[] = {
87 {0, nullptr, "GetJitDebugProcessIdList"}, 85 {0, nullptr, "GetJitDebugProcessIdList"},
@@ -106,12 +104,11 @@ private:
106 104
107 LOG_DEBUG(Service_PM, "called, program_id={:016X}", program_id); 105 LOG_DEBUG(Service_PM, "called, program_id={:016X}", program_id);
108 106
109 const auto process = 107 auto list = kernel.GetProcessList();
110 SearchProcessList(kernel.GetProcessList(), [program_id](const auto& proc) { 108 auto process = SearchProcessList(
111 return proc->GetProgramId() == program_id; 109 list, [program_id](auto& p) { return p->GetProgramId() == program_id; });
112 });
113 110
114 if (!process.has_value()) { 111 if (process.IsNull()) {
115 IPC::ResponseBuilder rb{ctx, 2}; 112 IPC::ResponseBuilder rb{ctx, 2};
116 rb.Push(ResultProcessNotFound); 113 rb.Push(ResultProcessNotFound);
117 return; 114 return;
@@ -119,12 +116,13 @@ private:
119 116
120 IPC::ResponseBuilder rb{ctx, 4}; 117 IPC::ResponseBuilder rb{ctx, 4};
121 rb.Push(ResultSuccess); 118 rb.Push(ResultSuccess);
122 rb.Push((*process)->GetProcessId()); 119 rb.Push(process->GetProcessId());
123 } 120 }
124 121
125 void GetApplicationProcessId(HLERequestContext& ctx) { 122 void GetApplicationProcessId(HLERequestContext& ctx) {
126 LOG_DEBUG(Service_PM, "called"); 123 LOG_DEBUG(Service_PM, "called");
127 GetApplicationPidGeneric(ctx, kernel.GetProcessList()); 124 auto list = kernel.GetProcessList();
125 GetApplicationPidGeneric(ctx, list);
128 } 126 }
129 127
130 void AtmosphereGetProcessInfo(HLERequestContext& ctx) { 128 void AtmosphereGetProcessInfo(HLERequestContext& ctx) {
@@ -135,11 +133,10 @@ private:
135 133
136 LOG_WARNING(Service_PM, "(Partial Implementation) called, pid={:016X}", pid); 134 LOG_WARNING(Service_PM, "(Partial Implementation) called, pid={:016X}", pid);
137 135
138 const auto process = SearchProcessList(kernel.GetProcessList(), [pid](const auto& proc) { 136 auto list = kernel.GetProcessList();
139 return proc->GetProcessId() == pid; 137 auto process = SearchProcessList(list, [pid](auto& p) { return p->GetProcessId() == pid; });
140 });
141 138
142 if (!process.has_value()) { 139 if (process.IsNull()) {
143 IPC::ResponseBuilder rb{ctx, 2}; 140 IPC::ResponseBuilder rb{ctx, 2};
144 rb.Push(ResultProcessNotFound); 141 rb.Push(ResultProcessNotFound);
145 return; 142 return;
@@ -159,7 +156,7 @@ private:
159 156
160 OverrideStatus override_status{}; 157 OverrideStatus override_status{};
161 ProgramLocation program_location{ 158 ProgramLocation program_location{
162 .program_id = (*process)->GetProgramId(), 159 .program_id = process->GetProgramId(),
163 .storage_id = 0, 160 .storage_id = 0,
164 }; 161 };
165 162
@@ -169,14 +166,11 @@ private:
169 rb.PushRaw(program_location); 166 rb.PushRaw(program_location);
170 rb.PushRaw(override_status); 167 rb.PushRaw(override_status);
171 } 168 }
172
173 const Kernel::KernelCore& kernel;
174}; 169};
175 170
176class Info final : public ServiceFramework<Info> { 171class Info final : public ServiceFramework<Info> {
177public: 172public:
178 explicit Info(Core::System& system_, const std::vector<Kernel::KProcess*>& process_list_) 173 explicit Info(Core::System& system_) : ServiceFramework{system_, "pm:info"} {
179 : ServiceFramework{system_, "pm:info"}, process_list{process_list_} {
180 static const FunctionInfo functions[] = { 174 static const FunctionInfo functions[] = {
181 {0, &Info::GetProgramId, "GetProgramId"}, 175 {0, &Info::GetProgramId, "GetProgramId"},
182 {65000, &Info::AtmosphereGetProcessId, "AtmosphereGetProcessId"}, 176 {65000, &Info::AtmosphereGetProcessId, "AtmosphereGetProcessId"},
@@ -193,11 +187,11 @@ private:
193 187
194 LOG_DEBUG(Service_PM, "called, process_id={:016X}", process_id); 188 LOG_DEBUG(Service_PM, "called, process_id={:016X}", process_id);
195 189
196 const auto process = SearchProcessList(process_list, [process_id](const auto& proc) { 190 auto list = kernel.GetProcessList();
197 return proc->GetProcessId() == process_id; 191 auto process = SearchProcessList(
198 }); 192 list, [process_id](auto& p) { return p->GetProcessId() == process_id; });
199 193
200 if (!process.has_value()) { 194 if (process.IsNull()) {
201 IPC::ResponseBuilder rb{ctx, 2}; 195 IPC::ResponseBuilder rb{ctx, 2};
202 rb.Push(ResultProcessNotFound); 196 rb.Push(ResultProcessNotFound);
203 return; 197 return;
@@ -205,7 +199,7 @@ private:
205 199
206 IPC::ResponseBuilder rb{ctx, 4}; 200 IPC::ResponseBuilder rb{ctx, 4};
207 rb.Push(ResultSuccess); 201 rb.Push(ResultSuccess);
208 rb.Push((*process)->GetProgramId()); 202 rb.Push(process->GetProgramId());
209 } 203 }
210 204
211 void AtmosphereGetProcessId(HLERequestContext& ctx) { 205 void AtmosphereGetProcessId(HLERequestContext& ctx) {
@@ -214,11 +208,11 @@ private:
214 208
215 LOG_DEBUG(Service_PM, "called, program_id={:016X}", program_id); 209 LOG_DEBUG(Service_PM, "called, program_id={:016X}", program_id);
216 210
217 const auto process = SearchProcessList(process_list, [program_id](const auto& proc) { 211 auto list = system.Kernel().GetProcessList();
218 return proc->GetProgramId() == program_id; 212 auto process = SearchProcessList(
219 }); 213 list, [program_id](auto& p) { return p->GetProgramId() == program_id; });
220 214
221 if (!process.has_value()) { 215 if (process.IsNull()) {
222 IPC::ResponseBuilder rb{ctx, 2}; 216 IPC::ResponseBuilder rb{ctx, 2};
223 rb.Push(ResultProcessNotFound); 217 rb.Push(ResultProcessNotFound);
224 return; 218 return;
@@ -226,16 +220,13 @@ private:
226 220
227 IPC::ResponseBuilder rb{ctx, 4}; 221 IPC::ResponseBuilder rb{ctx, 4};
228 rb.Push(ResultSuccess); 222 rb.Push(ResultSuccess);
229 rb.Push((*process)->GetProcessId()); 223 rb.Push(process->GetProcessId());
230 } 224 }
231
232 const std::vector<Kernel::KProcess*>& process_list;
233}; 225};
234 226
235class Shell final : public ServiceFramework<Shell> { 227class Shell final : public ServiceFramework<Shell> {
236public: 228public:
237 explicit Shell(Core::System& system_) 229 explicit Shell(Core::System& system_) : ServiceFramework{system_, "pm:shell"} {
238 : ServiceFramework{system_, "pm:shell"}, kernel{system_.Kernel()} {
239 // clang-format off 230 // clang-format off
240 static const FunctionInfo functions[] = { 231 static const FunctionInfo functions[] = {
241 {0, nullptr, "LaunchProgram"}, 232 {0, nullptr, "LaunchProgram"},
@@ -257,10 +248,9 @@ public:
257private: 248private:
258 void GetApplicationProcessIdForShell(HLERequestContext& ctx) { 249 void GetApplicationProcessIdForShell(HLERequestContext& ctx) {
259 LOG_DEBUG(Service_PM, "called"); 250 LOG_DEBUG(Service_PM, "called");
260 GetApplicationPidGeneric(ctx, kernel.GetProcessList()); 251 auto list = kernel.GetProcessList();
252 GetApplicationPidGeneric(ctx, list);
261 } 253 }
262
263 const Kernel::KernelCore& kernel;
264}; 254};
265 255
266void LoopProcess(Core::System& system) { 256void LoopProcess(Core::System& system) {
@@ -268,8 +258,7 @@ void LoopProcess(Core::System& system) {
268 258
269 server_manager->RegisterNamedService("pm:bm", std::make_shared<BootMode>(system)); 259 server_manager->RegisterNamedService("pm:bm", std::make_shared<BootMode>(system));
270 server_manager->RegisterNamedService("pm:dmnt", std::make_shared<DebugMonitor>(system)); 260 server_manager->RegisterNamedService("pm:dmnt", std::make_shared<DebugMonitor>(system));
271 server_manager->RegisterNamedService( 261 server_manager->RegisterNamedService("pm:info", std::make_shared<Info>(system));
272 "pm:info", std::make_shared<Info>(system, system.Kernel().GetProcessList()));
273 server_manager->RegisterNamedService("pm:shell", std::make_shared<Shell>(system)); 262 server_manager->RegisterNamedService("pm:shell", std::make_shared<Shell>(system));
274 ServerManager::RunServer(std::move(server_manager)); 263 ServerManager::RunServer(std::move(server_manager));
275} 264}