mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-05 19:51:45 +00:00
ProcessManager: Implement almost all of pm:shell
This commit is contained in:
parent
bceb00ad8d
commit
e596fd0de5
4 changed files with 197 additions and 42 deletions
|
@ -39,6 +39,24 @@ static u64 g_resource_limits[3][5] = {
|
||||||
|
|
||||||
static Handle g_resource_limit_handles[3] = {0};
|
static Handle g_resource_limit_handles[3] = {0};
|
||||||
|
|
||||||
|
Registration::AutoProcessListLock::AutoProcessListLock() {
|
||||||
|
g_process_list.Lock();
|
||||||
|
this->has_lock = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Registration::AutoProcessListLock::~AutoProcessListLock() {
|
||||||
|
if (this->has_lock) {
|
||||||
|
this->Unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Registration::AutoProcessListLock::Unlock() {
|
||||||
|
if (this->has_lock) {
|
||||||
|
g_process_list.Unlock();
|
||||||
|
}
|
||||||
|
this->has_lock = false;
|
||||||
|
}
|
||||||
|
|
||||||
void Registration::InitializeSystemResources() {
|
void Registration::InitializeSystemResources() {
|
||||||
g_process_event = new SystemEvent(&IEvent::PanicCallback);
|
g_process_event = new SystemEvent(&IEvent::PanicCallback);
|
||||||
g_debug_title_event = new SystemEvent(&IEvent::PanicCallback);
|
g_debug_title_event = new SystemEvent(&IEvent::PanicCallback);
|
||||||
|
@ -124,7 +142,7 @@ void Registration::HandleProcessLaunch() {
|
||||||
|
|
||||||
/* Get the resource limit handle, ensure that we can launch the program. */
|
/* Get the resource limit handle, ensure that we can launch the program. */
|
||||||
if ((program_info.application_type & 3) == 1) {
|
if ((program_info.application_type & 3) == 1) {
|
||||||
if (HasApplicationProcess()) {
|
if (HasApplicationProcess(NULL)) {
|
||||||
rc = 0xA0F;
|
rc = 0xA0F;
|
||||||
goto HANDLE_PROCESS_LAUNCH_END;
|
goto HANDLE_PROCESS_LAUNCH_END;
|
||||||
}
|
}
|
||||||
|
@ -310,8 +328,8 @@ void Registration::HandleSignaledProcess(Process *process) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Registration::FinalizeExitedProcess(Process *process) {
|
void Registration::FinalizeExitedProcess(Process *process) {
|
||||||
|
AutoProcessListLock auto_lock;
|
||||||
bool signal_debug_process_5x = kernelAbove500() && process->flags & 1;
|
bool signal_debug_process_5x = kernelAbove500() && process->flags & 1;
|
||||||
g_process_list.Lock();
|
|
||||||
/* Unregister with FS. */
|
/* Unregister with FS. */
|
||||||
if (R_FAILED(fsprUnregisterProgram(process->pid))) {
|
if (R_FAILED(fsprUnregisterProgram(process->pid))) {
|
||||||
/* TODO: Panic. */
|
/* TODO: Panic. */
|
||||||
|
@ -338,20 +356,20 @@ void Registration::FinalizeExitedProcess(Process *process) {
|
||||||
/* Remove NOTE: This probably frees process. */
|
/* Remove NOTE: This probably frees process. */
|
||||||
RemoveProcessFromList(process->pid);
|
RemoveProcessFromList(process->pid);
|
||||||
|
|
||||||
g_process_list.Unlock();
|
auto_lock.Unlock();
|
||||||
if (signal_debug_process_5x) {
|
if (signal_debug_process_5x) {
|
||||||
g_process_event->signal_event();
|
g_process_event->signal_event();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Registration::AddProcessToList(Process *process) {
|
void Registration::AddProcessToList(Process *process) {
|
||||||
g_process_list.Lock();
|
AutoProcessListLock auto_lock;
|
||||||
g_process_list.process_waiters.push_back(new ProcessWaiter(process));
|
g_process_list.process_waiters.push_back(new ProcessWaiter(process));
|
||||||
g_process_list.Unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Registration::RemoveProcessFromList(u64 pid) {
|
void Registration::RemoveProcessFromList(u64 pid) {
|
||||||
g_process_list.Lock();
|
AutoProcessListLock auto_lock;
|
||||||
|
|
||||||
/* Remove process from list. */
|
/* Remove process from list. */
|
||||||
for (unsigned int i = 0; i < g_process_list.process_waiters.size(); i++) {
|
for (unsigned int i = 0; i < g_process_list.process_waiters.size(); i++) {
|
||||||
ProcessWaiter *pw = g_process_list.process_waiters[i];
|
ProcessWaiter *pw = g_process_list.process_waiters[i];
|
||||||
|
@ -363,36 +381,120 @@ void Registration::RemoveProcessFromList(u64 pid) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g_process_list.Unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Registration::SetProcessState(u64 pid, ProcessState new_state) {
|
void Registration::SetProcessState(u64 pid, ProcessState new_state) {
|
||||||
g_process_list.Lock();
|
AutoProcessListLock auto_lock;
|
||||||
|
|
||||||
/* Set process state. */
|
/* Set process state. */
|
||||||
for (unsigned int i = 0; i < g_process_list.process_waiters.size(); i++) {
|
for (auto &pw : g_process_list.process_waiters) {
|
||||||
ProcessWaiter *pw = g_process_list.process_waiters[i];
|
|
||||||
Registration::Process *process = pw->get_process();
|
Registration::Process *process = pw->get_process();
|
||||||
if (process->pid == pid) {
|
if (process->pid == pid) {
|
||||||
process->state = new_state;
|
process->state = new_state;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g_process_list.Unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Registration::HasApplicationProcess() {
|
bool Registration::HasApplicationProcess(Process **out) {
|
||||||
bool has_app = false;
|
AutoProcessListLock auto_lock;
|
||||||
g_process_list.Lock();
|
|
||||||
|
|
||||||
for (auto &pw : g_process_list.process_waiters) {
|
for (auto &pw : g_process_list.process_waiters) {
|
||||||
if (pw->get_process()->flags & 0x40) {
|
Registration::Process *process = pw->get_process();
|
||||||
has_app = true;
|
if (process->flags & 0x40) {
|
||||||
break;
|
if (out != NULL) {
|
||||||
|
*out = process;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g_process_list.Unlock();
|
return false;
|
||||||
return has_app;
|
}
|
||||||
|
|
||||||
|
Registration::Process *Registration::GetProcess(u64 pid) {
|
||||||
|
AutoProcessListLock auto_lock;
|
||||||
|
|
||||||
|
for (auto &pw : g_process_list.process_waiters) {
|
||||||
|
Process *p = pw->get_process();
|
||||||
|
if (p->pid == pid) {
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Registration::Process *Registration::GetProcessByTitleId(u64 tid) {
|
||||||
|
AutoProcessListLock auto_lock;
|
||||||
|
|
||||||
|
for (auto &pw : g_process_list.process_waiters) {
|
||||||
|
Process *p = pw->get_process();
|
||||||
|
if (p->tid_sid.title_id == tid) {
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Handle Registration::GetProcessEventHandle() {
|
||||||
|
return g_process_event->get_handle();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Registration::GetProcessEventType(u64 *out_pid, u64 *out_type) {
|
||||||
|
AutoProcessListLock auto_lock;
|
||||||
|
|
||||||
|
for (auto &pw : g_process_list.process_waiters) {
|
||||||
|
Process *p = pw->get_process();
|
||||||
|
if (kernelAbove200() && p->state >= ProcessState_DebugDetached && p->flags & 0x100) {
|
||||||
|
p->flags &= ~0x100;
|
||||||
|
*out_pid = p->pid;
|
||||||
|
*out_type = kernelAbove500() ? 2 : 5;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (p->flags & 0x10) {
|
||||||
|
p->flags &= ~0x10;
|
||||||
|
*out_pid = p->pid;
|
||||||
|
*out_type = kernelAbove500() ? (((p->flags >> 5) & 1) | 4) : (((p->flags >> 5) & 1) + 3);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (p->flags & 2) {
|
||||||
|
*out_pid = p->pid;
|
||||||
|
*out_type = kernelAbove500() ? 3 : 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!kernelAbove500() && p->flags & 1 && p->state == ProcessState_Exited) {
|
||||||
|
*out_pid = p->pid;
|
||||||
|
*out_type = 2;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (kernelAbove500()) {
|
||||||
|
auto_lock.Unlock();
|
||||||
|
g_dead_process_list.Lock();
|
||||||
|
if (g_dead_process_list.process_waiters.size()) {
|
||||||
|
ProcessWaiter *pw = g_dead_process_list.process_waiters[0];
|
||||||
|
Registration::Process *process = pw->get_process();
|
||||||
|
g_dead_process_list.process_waiters.erase(g_dead_process_list.process_waiters.begin());
|
||||||
|
*out_pid = process->pid;
|
||||||
|
*out_type = 1;
|
||||||
|
delete pw;
|
||||||
|
g_dead_process_list.Unlock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g_dead_process_list.Unlock();
|
||||||
|
}
|
||||||
|
*out_pid = 0;
|
||||||
|
*out_type = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Handle Registration::GetDebugTitleEventHandle() {
|
||||||
|
return g_debug_title_event->get_handle();
|
||||||
|
}
|
||||||
|
|
||||||
|
Handle Registration::GetDebugApplicationEventHandle() {
|
||||||
|
return g_debug_application_event->get_handle();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Registration::EnsureApplicationResourcesAvailable() {
|
void Registration::EnsureApplicationResourcesAvailable() {
|
||||||
|
|
|
@ -31,7 +31,15 @@ class Registration {
|
||||||
u64* out_pid;
|
u64* out_pid;
|
||||||
Result result;
|
Result result;
|
||||||
};
|
};
|
||||||
|
class AutoProcessListLock {
|
||||||
|
private:
|
||||||
|
bool has_lock;
|
||||||
|
public:
|
||||||
|
AutoProcessListLock();
|
||||||
|
~AutoProcessListLock();
|
||||||
|
void Unlock();
|
||||||
|
};
|
||||||
|
|
||||||
static void InitializeSystemResources();
|
static void InitializeSystemResources();
|
||||||
static IWaitable *GetProcessLaunchStartEvent();
|
static IWaitable *GetProcessLaunchStartEvent();
|
||||||
static Result ProcessLaunchStartCallback(Handle *handles, size_t num_handles, u64 timeout);
|
static Result ProcessLaunchStartCallback(Handle *handles, size_t num_handles, u64 timeout);
|
||||||
|
@ -44,12 +52,19 @@ class Registration {
|
||||||
static void RemoveProcessFromList(u64 pid);
|
static void RemoveProcessFromList(u64 pid);
|
||||||
static void SetProcessState(u64 pid, ProcessState new_state);
|
static void SetProcessState(u64 pid, ProcessState new_state);
|
||||||
|
|
||||||
|
static Process *GetProcess(u64 pid);
|
||||||
|
static Process *GetProcessByTitleId(u64 tid);
|
||||||
|
static Handle GetProcessEventHandle();
|
||||||
|
static void GetProcessEventType(u64 *out_pid, u64 *out_type);
|
||||||
|
static Handle GetDebugTitleEventHandle();
|
||||||
|
static Handle GetDebugApplicationEventHandle();
|
||||||
|
|
||||||
static void HandleProcessLaunch();
|
static void HandleProcessLaunch();
|
||||||
static void SignalFinishLaunchProcess();
|
static void SignalFinishLaunchProcess();
|
||||||
static Result LaunchProcess(u64 title_id, FsStorageId storage_id, u64 launch_flags, u64 *out_pid);
|
static Result LaunchProcess(u64 title_id, FsStorageId storage_id, u64 launch_flags, u64 *out_pid);
|
||||||
static Result LaunchProcessByTidSid(TidSid tid_sid, u64 launch_flags, u64 *out_pid);
|
static Result LaunchProcessByTidSid(TidSid tid_sid, u64 launch_flags, u64 *out_pid);
|
||||||
|
|
||||||
static bool HasApplicationProcess();
|
static bool HasApplicationProcess(Process **out);
|
||||||
static void EnsureApplicationResourcesAvailable();
|
static void EnsureApplicationResourcesAvailable();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ Result ShellService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id
|
||||||
case Shell_Cmd_GetProcessEventType:
|
case Shell_Cmd_GetProcessEventType:
|
||||||
rc = WrapIpcCommandImpl<&ShellService::get_process_event_type>(this, r, out_c, pointer_buffer, pointer_buffer_size);
|
rc = WrapIpcCommandImpl<&ShellService::get_process_event_type>(this, r, out_c, pointer_buffer, pointer_buffer_size);
|
||||||
break;
|
break;
|
||||||
case Shell_Cmd_FinalizeDeadProcess:
|
case Shell_Cmd_FinalizeExitedProcess:
|
||||||
rc = WrapIpcCommandImpl<&ShellService::finalize_dead_process>(this, r, out_c, pointer_buffer, pointer_buffer_size);
|
rc = WrapIpcCommandImpl<&ShellService::finalize_dead_process>(this, r, out_c, pointer_buffer, pointer_buffer_size);
|
||||||
break;
|
break;
|
||||||
case Shell_Cmd_ClearProcessNotificationFlag:
|
case Shell_Cmd_ClearProcessNotificationFlag:
|
||||||
|
@ -78,55 +78,93 @@ Result ShellService::handle_deferred() {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tuple<Result, u64> launch_process(u64 launch_flags, Registration::TidSid tid_sid) {
|
std::tuple<Result, u64> launch_process(u64 launch_flags, Registration::TidSid tid_sid) {
|
||||||
/* TODO */
|
u64 pid = 0;
|
||||||
return {0xF601, 0};
|
Result rc = Registration::LaunchProcessByTidSid(tid_sid, launch_flags, &pid);
|
||||||
|
return {rc, pid};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tuple<Result> terminate_process_id(u64 pid) {
|
std::tuple<Result> terminate_process_id(u64 pid) {
|
||||||
/* TODO */
|
Registration::AutoProcessListLock auto_lock;
|
||||||
return {0xF601};
|
|
||||||
|
Registration::Process *proc = Registration::GetProcess(pid);
|
||||||
|
if (proc != NULL) {
|
||||||
|
return {svcCloseHandle(proc->handle)};
|
||||||
|
} else {
|
||||||
|
return {0x20F};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tuple<Result> terminate_title_id(u64 tid) {
|
std::tuple<Result> terminate_title_id(u64 tid) {
|
||||||
/* TODO */
|
Registration::AutoProcessListLock auto_lock;
|
||||||
return {0xF601};
|
|
||||||
|
Registration::Process *proc = Registration::GetProcessByTitleId(tid);
|
||||||
|
if (proc != NULL) {
|
||||||
|
return {svcCloseHandle(proc->handle)};
|
||||||
|
} else {
|
||||||
|
return {0x20F};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tuple<Result, CopiedHandle> get_process_wait_event() {
|
std::tuple<Result, CopiedHandle> get_process_wait_event() {
|
||||||
/* TODO */
|
return {0x0, Registration::GetProcessEventHandle()};
|
||||||
return {0xF601, 0};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tuple<Result, u64, u64> get_process_event_type() {
|
std::tuple<Result, u64, u64> get_process_event_type() {
|
||||||
/* TODO */
|
u64 type, pid;
|
||||||
return {0xF601, 0, 0};
|
Registration::GetProcessEventType(&pid, &type);
|
||||||
|
return {0x0, type, pid};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tuple<Result> finalize_dead_process(u64 pid) {
|
std::tuple<Result> finalize_exited_process(u64 pid) {
|
||||||
/* TODO */
|
Registration::AutoProcessListLock auto_lock;
|
||||||
return {0xF601};
|
|
||||||
|
Registration::Process *proc = Registration::GetProcess(pid);
|
||||||
|
if (proc == NULL) {
|
||||||
|
return {0x20F};
|
||||||
|
} else if (proc->state != ProcessState_Exited) {
|
||||||
|
return {0x60F};
|
||||||
|
} else {
|
||||||
|
Registration::FinalizeExitedProcess(proc);
|
||||||
|
return {0x0};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tuple<Result> clear_process_notification_flag(u64 pid) {
|
std::tuple<Result> clear_process_notification_flag(u64 pid) {
|
||||||
/* TODO */
|
Registration::AutoProcessListLock auto_lock;
|
||||||
return {0xF601};
|
|
||||||
|
Registration::Process *proc = Registration::GetProcess(pid);
|
||||||
|
if (proc != NULL) {
|
||||||
|
proc->flags &= ~2;
|
||||||
|
return {0x0};
|
||||||
|
} else {
|
||||||
|
return {0x20F};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tuple<Result> notify_boot_finished() {
|
std::tuple<Result> notify_boot_finished() {
|
||||||
u64 boot_pid;
|
u64 boot2_pid;
|
||||||
if (!g_has_boot_finished) {
|
if (!g_has_boot_finished) {
|
||||||
Registration::LaunchProcess(BOOT2_TITLE_ID, FsStorageId_NandSystem, 0, &boot_pid);
|
|
||||||
g_has_boot_finished = true;
|
g_has_boot_finished = true;
|
||||||
|
return {Registration::LaunchProcess(BOOT2_TITLE_ID, FsStorageId_NandSystem, 0, &boot2_pid)};
|
||||||
}
|
}
|
||||||
return {0};
|
return {0};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tuple<Result, u64> get_application_process_id() {
|
std::tuple<Result, u64> get_application_process_id() {
|
||||||
/* TODO */
|
Registration::AutoProcessListLock auto_lock;
|
||||||
return {0xF601, 0};
|
|
||||||
|
Registration::Process *app_proc;
|
||||||
|
if (Registration::HasApplicationProcess(&app_proc)) {
|
||||||
|
return {0, app_proc->pid};
|
||||||
|
}
|
||||||
|
return {0x20F, 0};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tuple<Result> boost_system_memory_resource_limit() {
|
std::tuple<Result> boost_system_memory_resource_limit() {
|
||||||
|
if (!kernelAbove400()) {
|
||||||
|
return {0xF601};
|
||||||
|
}
|
||||||
|
|
||||||
/* TODO */
|
/* TODO */
|
||||||
return {0xF601};
|
return {0xF601};
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ enum ShellCmd {
|
||||||
Shell_Cmd_TerminateTitleId = 2,
|
Shell_Cmd_TerminateTitleId = 2,
|
||||||
Shell_Cmd_GetProcessWaitEvent = 3,
|
Shell_Cmd_GetProcessWaitEvent = 3,
|
||||||
Shell_Cmd_GetProcessEventType = 4,
|
Shell_Cmd_GetProcessEventType = 4,
|
||||||
Shell_Cmd_FinalizeDeadProcess = 5,
|
Shell_Cmd_FinalizeExitedProcess = 5,
|
||||||
Shell_Cmd_ClearProcessNotificationFlag = 6,
|
Shell_Cmd_ClearProcessNotificationFlag = 6,
|
||||||
Shell_Cmd_NotifyBootFinished = 7,
|
Shell_Cmd_NotifyBootFinished = 7,
|
||||||
Shell_Cmd_GetApplicationProcessId = 8,
|
Shell_Cmd_GetApplicationProcessId = 8,
|
||||||
|
|
Loading…
Reference in a new issue