diff --git a/stratosphere/pm/source/pm_boot2.cpp b/stratosphere/pm/source/pm_boot2.cpp index a7cdd8e3a..d37a0c025 100644 --- a/stratosphere/pm/source/pm_boot2.cpp +++ b/stratosphere/pm/source/pm_boot2.cpp @@ -283,13 +283,10 @@ void EmbeddedBoot2::Main() { } closedir(titles_dir); } - - /* Free the memory used to track what boot2 launches. */ - ClearLaunchedTitles(); /* We no longer need the SD card. */ fsdevUnmountAll(); - /* Clear titles. */ + /* Free the memory used to track what boot2 launches. */ ClearLaunchedTitles(); } diff --git a/stratosphere/pm/source/pm_debug_monitor.cpp b/stratosphere/pm/source/pm_debug_monitor.cpp index 69f9eaab9..776f79576 100644 --- a/stratosphere/pm/source/pm_debug_monitor.cpp +++ b/stratosphere/pm/source/pm_debug_monitor.cpp @@ -42,7 +42,7 @@ Result DebugMonitorService::LaunchDebugProcess(u64 pid) { } Result DebugMonitorService::GetTitleProcessId(Out pid, u64 tid) { - auto auto_lock = Registration::GetProcessListUniqueLock(); + std::scoped_lock lk(Registration::GetProcessList()); std::shared_ptr proc = Registration::GetProcessByTitleId(tid); if (proc != nullptr) { @@ -57,7 +57,7 @@ Result DebugMonitorService::EnableDebugForTitleId(Out event, u64 t } Result DebugMonitorService::GetApplicationProcessId(Out pid) { - auto auto_lock = Registration::GetProcessListUniqueLock(); + std::scoped_lock lk(Registration::GetProcessList()); std::shared_ptr app_proc; if (Registration::HasApplicationProcess(&app_proc)) { diff --git a/stratosphere/pm/source/pm_info.cpp b/stratosphere/pm/source/pm_info.cpp index 4498a9f1a..847bb7df4 100644 --- a/stratosphere/pm/source/pm_info.cpp +++ b/stratosphere/pm/source/pm_info.cpp @@ -19,7 +19,7 @@ #include "pm_info.hpp" Result InformationService::GetTitleId(Out tid, u64 pid) { - auto auto_lock = Registration::GetProcessListUniqueLock(); + std::scoped_lock lk(Registration::GetProcessList()); std::shared_ptr proc = Registration::GetProcess(pid); if (proc != NULL) { diff --git a/stratosphere/pm/source/pm_process_wait.hpp b/stratosphere/pm/source/pm_process_wait.hpp index 14df0468a..bc46a3361 100644 --- a/stratosphere/pm/source/pm_process_wait.hpp +++ b/stratosphere/pm/source/pm_process_wait.hpp @@ -44,12 +44,24 @@ class ProcessWaiter final : public IWaitable { class ProcessList final { private: - HosRecursiveMutex mutex; + HosRecursiveMutex m; + + HosRecursiveMutex *GetMutex() { + return &this->m; + } public: std::vector> processes; - auto GetUniqueLock() { - return std::unique_lock{this->mutex}; + void lock() { + GetMutex()->lock(); + } + + void unlock() { + GetMutex()->unlock(); + } + + void try_lock() { + GetMutex()->try_lock(); } }; diff --git a/stratosphere/pm/source/pm_registration.cpp b/stratosphere/pm/source/pm_registration.cpp index bf7958dec..508790dd7 100644 --- a/stratosphere/pm/source/pm_registration.cpp +++ b/stratosphere/pm/source/pm_registration.cpp @@ -13,14 +13,12 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - #include #include #include #include "pm_registration.hpp" #include "pm_resource_limits.hpp" -#include "pm_process_wait.hpp" static ProcessList g_process_list; static ProcessList g_dead_process_list; @@ -38,8 +36,10 @@ static IEvent *g_process_event = nullptr; static IEvent *g_debug_title_event = nullptr; static IEvent *g_debug_application_event = nullptr; -std::unique_lock Registration::GetProcessListUniqueLock() { - return g_process_list.GetUniqueLock(); +static u8 g_ac_buf[4 * sizeof(LoaderProgramInfo)]; + +ProcessList &Registration::GetProcessList() { + return g_process_list; } void Registration::InitializeSystemResources() { @@ -70,9 +70,8 @@ void Registration::HandleProcessLaunch() { u64 *out_pid = g_process_launch_state.out_pid; Process new_process = {0}; new_process.tid_sid = g_process_launch_state.tid_sid; - auto ac_buf = std::vector(4 * sizeof(LoaderProgramInfo)); - std::fill(ac_buf.begin(), ac_buf.end(), 0xCC); - u8 *acid_sac = ac_buf.data(), *aci0_sac = acid_sac + sizeof(LoaderProgramInfo), *fac = aci0_sac + sizeof(LoaderProgramInfo), *fah = fac + sizeof(LoaderProgramInfo); + std::memset(g_ac_buf, 0xCC, sizeof(g_ac_buf)); + u8 *acid_sac = g_ac_buf, *aci0_sac = acid_sac + sizeof(LoaderProgramInfo), *fac = aci0_sac + sizeof(LoaderProgramInfo), *fah = fac + sizeof(LoaderProgramInfo); /* Check that this is a real program. */ if (R_FAILED((rc = ldrPmGetProgramInfo(new_process.tid_sid.title_id, new_process.tid_sid.storage_id, &program_info)))) { @@ -185,7 +184,7 @@ HANDLE_PROCESS_LAUNCH_END: Result Registration::LaunchDebugProcess(u64 pid) { - auto auto_lock = GetProcessListUniqueLock(); + std::scoped_lock lk(GetProcessList()); LoaderProgramInfo program_info = {0}; Result rc; @@ -288,48 +287,56 @@ Result Registration::HandleSignaledProcess(std::shared_ptr process) { - auto auto_lock = GetProcessListUniqueLock(); - bool signal_debug_process_5x = kernelAbove500() && process->flags & PROCESSFLAGS_NOTIFYWHENEXITED; - /* Unregister with FS. */ - if (R_FAILED(fsprUnregisterProgram(process->pid))) { - std::abort(); - } - /* Unregister with SM. */ - if (R_FAILED(smManagerUnregisterProcess(process->pid))) { - std::abort(); - } - /* Unregister with LDR. */ - if (R_FAILED(ldrPmUnregisterTitle(process->ldr_queue_index))) { - std::abort(); - } - - /* Close the process's handle. */ - svcCloseHandle(process->handle); - process->handle = 0; - - /* Insert into dead process list, if relevant. */ - if (signal_debug_process_5x) { - auto lk = g_dead_process_list.GetUniqueLock(); - g_dead_process_list.processes.push_back(process); - } - - /* Remove NOTE: This probably frees process. */ - RemoveProcessFromList(process->pid); + bool signal_debug_process_5x; + + /* Scope to manage process list lock. */ + { + std::scoped_lock lk(GetProcessList()); + + signal_debug_process_5x = kernelAbove500() && process->flags & PROCESSFLAGS_NOTIFYWHENEXITED; + + /* Unregister with FS. */ + if (R_FAILED(fsprUnregisterProgram(process->pid))) { + std::abort(); + } + /* Unregister with SM. */ + if (R_FAILED(smManagerUnregisterProcess(process->pid))) { + std::abort(); + } + /* Unregister with LDR. */ + if (R_FAILED(ldrPmUnregisterTitle(process->ldr_queue_index))) { + std::abort(); + } + + /* Close the process's handle. */ + svcCloseHandle(process->handle); + process->handle = 0; + + /* Insert into dead process list, if relevant. */ + if (signal_debug_process_5x) { + std::scoped_lock dead_lk(g_dead_process_list); + + g_dead_process_list.processes.push_back(process); + } + + /* Remove NOTE: This probably frees process. */ + RemoveProcessFromList(process->pid); + } - auto_lock.unlock(); if (signal_debug_process_5x) { g_process_event->Signal(); } } void Registration::AddProcessToList(std::shared_ptr process) { - auto auto_lock = GetProcessListUniqueLock(); + std::scoped_lock lk(GetProcessList()); + g_process_list.processes.push_back(process); g_process_launch_start_event->GetManager()->AddWaitable(new ProcessWaiter(process)); } void Registration::RemoveProcessFromList(u64 pid) { - auto auto_lock = GetProcessListUniqueLock(); + std::scoped_lock lk(GetProcessList()); /* Remove process from list. */ for (unsigned int i = 0; i < g_process_list.processes.size(); i++) { @@ -344,7 +351,7 @@ void Registration::RemoveProcessFromList(u64 pid) { } void Registration::SetProcessState(u64 pid, ProcessState new_state) { - auto auto_lock = GetProcessListUniqueLock(); + std::scoped_lock lk(GetProcessList()); /* Set process state. */ for (auto &process : g_process_list.processes) { @@ -356,7 +363,7 @@ void Registration::SetProcessState(u64 pid, ProcessState new_state) { } bool Registration::HasApplicationProcess(std::shared_ptr *out) { - auto auto_lock = GetProcessListUniqueLock(); + std::scoped_lock lk(GetProcessList()); for (auto &process : g_process_list.processes) { if (process->flags & PROCESSFLAGS_APPLICATION) { @@ -371,7 +378,7 @@ bool Registration::HasApplicationProcess(std::shared_ptr } std::shared_ptr Registration::GetProcess(u64 pid) { - auto auto_lock = GetProcessListUniqueLock(); + std::scoped_lock lk(GetProcessList()); for (auto &process : g_process_list.processes) { if (process->pid == pid) { @@ -383,7 +390,7 @@ std::shared_ptr Registration::GetProcess(u64 pid) { } std::shared_ptr Registration::GetProcessByTitleId(u64 tid) { - auto auto_lock = GetProcessListUniqueLock(); + std::scoped_lock lk(GetProcessList()); for (auto &process : g_process_list.processes) { if (process->tid_sid.title_id == tid) { @@ -396,7 +403,7 @@ std::shared_ptr Registration::GetProcessByTitleId(u64 tid Result Registration::GetDebugProcessIds(u64 *out_pids, u32 max_out, u32 *num_out) { - auto auto_lock = GetProcessListUniqueLock(); + std::scoped_lock lk(GetProcessList()); u32 num = 0; @@ -415,42 +422,49 @@ Handle Registration::GetProcessEventHandle() { } void Registration::GetProcessEventType(u64 *out_pid, u64 *out_type) { - auto auto_lock = GetProcessListUniqueLock(); - - for (auto &p : g_process_list.processes) { - if (kernelAbove200() && p->state >= ProcessState_Running && p->flags & PROCESSFLAGS_DEBUGDETACHED) { - p->flags &= ~PROCESSFLAGS_DEBUGDETACHED; - *out_pid = p->pid; - *out_type = kernelAbove500() ? PROCESSEVENTTYPE_500_DEBUGDETACHED : PROCESSEVENTTYPE_DEBUGDETACHED; - return; - } - if (p->flags & PROCESSFLAGS_DEBUGEVENTPENDING) { - u64 old_flags = p->flags; - p->flags &= ~PROCESSFLAGS_DEBUGEVENTPENDING; - *out_pid = p->pid; - *out_type = kernelAbove500() ? - ((old_flags & PROCESSFLAGS_DEBUGSUSPENDED) ? - PROCESSEVENTTYPE_500_SUSPENDED : - PROCESSEVENTTYPE_500_RUNNING) : - ((old_flags & PROCESSFLAGS_DEBUGSUSPENDED) ? - PROCESSEVENTTYPE_SUSPENDED : - PROCESSEVENTTYPE_RUNNING); - return; - } - if (p->flags & PROCESSFLAGS_CRASHED) { - *out_pid = p->pid; - *out_type = kernelAbove500() ? PROCESSEVENTTYPE_500_CRASH : PROCESSEVENTTYPE_CRASH; - return; - } - if (!kernelAbove500() && p->flags & PROCESSFLAGS_NOTIFYWHENEXITED && p->state == ProcessState_Exited) { - *out_pid = p->pid; - *out_type = PROCESSEVENTTYPE_EXIT; - return; + /* Scope to manage process list lock. */ + { + std::scoped_lock lk(GetProcessList()); + + for (auto &p : g_process_list.processes) { + if (kernelAbove200() && p->state >= ProcessState_Running && p->flags & PROCESSFLAGS_DEBUGDETACHED) { + p->flags &= ~PROCESSFLAGS_DEBUGDETACHED; + *out_pid = p->pid; + *out_type = kernelAbove500() ? PROCESSEVENTTYPE_500_DEBUGDETACHED : PROCESSEVENTTYPE_DEBUGDETACHED; + return; + } + if (p->flags & PROCESSFLAGS_DEBUGEVENTPENDING) { + u64 old_flags = p->flags; + p->flags &= ~PROCESSFLAGS_DEBUGEVENTPENDING; + *out_pid = p->pid; + *out_type = kernelAbove500() ? + ((old_flags & PROCESSFLAGS_DEBUGSUSPENDED) ? + PROCESSEVENTTYPE_500_SUSPENDED : + PROCESSEVENTTYPE_500_RUNNING) : + ((old_flags & PROCESSFLAGS_DEBUGSUSPENDED) ? + PROCESSEVENTTYPE_SUSPENDED : + PROCESSEVENTTYPE_RUNNING); + return; + } + if (p->flags & PROCESSFLAGS_CRASHED) { + *out_pid = p->pid; + *out_type = kernelAbove500() ? PROCESSEVENTTYPE_500_CRASH : PROCESSEVENTTYPE_CRASH; + return; + } + if (!kernelAbove500() && p->flags & PROCESSFLAGS_NOTIFYWHENEXITED && p->state == ProcessState_Exited) { + *out_pid = p->pid; + *out_type = PROCESSEVENTTYPE_EXIT; + return; + } } + + *out_pid = 0; + *out_type = 0; } + if (kernelAbove500()) { - auto_lock.unlock(); - auto dead_process_list_lock = g_dead_process_list.GetUniqueLock(); + std::scoped_lock dead_lk(g_dead_process_list); + if (g_dead_process_list.processes.size()) { std::shared_ptr process = g_dead_process_list.processes[0]; g_dead_process_list.processes.erase(g_dead_process_list.processes.begin()); @@ -459,8 +473,6 @@ void Registration::GetProcessEventType(u64 *out_pid, u64 *out_type) { return; } } - *out_pid = 0; - *out_type = 0; } diff --git a/stratosphere/pm/source/pm_registration.hpp b/stratosphere/pm/source/pm_registration.hpp index 8b440ade4..80bf6bbe2 100644 --- a/stratosphere/pm/source/pm_registration.hpp +++ b/stratosphere/pm/source/pm_registration.hpp @@ -20,6 +20,8 @@ #include #include +class ProcessList; + #define LAUNCHFLAGS_NOTIFYWHENEXITED(flags) (flags & 1) #define LAUNCHFLAGS_STARTSUSPENDED(flags) (flags & (kernelAbove500() ? 0x10 : 0x2)) #define LAUNCHFLAGS_ARGLOW(flags) (kernelAbove500() ? ((flags & 0x14) != 0x10) : (kernelAbove200() ? ((flags & 0x6) != 0x2) : ((flags >> 2) & 1))) @@ -171,7 +173,7 @@ class Registration { static void InitializeSystemResources(); static IWaitable *GetProcessLaunchStartEvent(); - static std::unique_lock GetProcessListUniqueLock(); + static ProcessList &GetProcessList(); static Result ProcessLaunchStartCallback(u64 timeout); static Result HandleSignaledProcess(std::shared_ptr process); @@ -201,3 +203,4 @@ class Registration { static bool HasApplicationProcess(std::shared_ptr *out); }; +#include "pm_process_wait.hpp" diff --git a/stratosphere/pm/source/pm_shell.cpp b/stratosphere/pm/source/pm_shell.cpp index 0dc429a95..258431912 100644 --- a/stratosphere/pm/source/pm_shell.cpp +++ b/stratosphere/pm/source/pm_shell.cpp @@ -28,7 +28,7 @@ Result ShellService::LaunchProcess(Out pid, Registration::TidSid tid_sid, u } Result ShellService::TerminateProcessId(u64 pid) { - auto auto_lock = Registration::GetProcessListUniqueLock(); + std::scoped_lock lk(Registration::GetProcessList()); auto proc = Registration::GetProcess(pid); if (proc != nullptr) { @@ -39,7 +39,7 @@ Result ShellService::TerminateProcessId(u64 pid) { } Result ShellService::TerminateTitleId(u64 tid) { - auto auto_lock = Registration::GetProcessListUniqueLock(); + std::scoped_lock lk(Registration::GetProcessList()); auto proc = Registration::GetProcessByTitleId(tid); if (proc != NULL) { @@ -58,7 +58,7 @@ void ShellService::GetProcessEventType(Out type, Out pid) { } Result ShellService::FinalizeExitedProcess(u64 pid) { - auto auto_lock = Registration::GetProcessListUniqueLock(); + std::scoped_lock lk(Registration::GetProcessList()); auto proc = Registration::GetProcess(pid); if (proc == NULL) { @@ -72,7 +72,7 @@ Result ShellService::FinalizeExitedProcess(u64 pid) { } Result ShellService::ClearProcessNotificationFlag(u64 pid) { - auto auto_lock = Registration::GetProcessListUniqueLock(); + std::scoped_lock lk(Registration::GetProcessList()); auto proc = Registration::GetProcess(pid); if (proc != NULL) { @@ -91,7 +91,7 @@ void ShellService::NotifyBootFinished() { } Result ShellService::GetApplicationProcessId(Out pid) { - auto auto_lock = Registration::GetProcessListUniqueLock(); + std::scoped_lock lk(Registration::GetProcessList()); std::shared_ptr app_proc; if (Registration::HasApplicationProcess(&app_proc)) {