Difference between revisions of "Process Manager services"

From Nintendo Switch Brew
Jump to navigation Jump to search
Line 1: Line 1:
 +
= Process Tracker thread =
 
PM has a separate thread that is waiting for synchronization on process handles.
 
PM has a separate thread that is waiting for synchronization on process handles.
  
 +
== State changes ==
 
When the kernel signals a process handle, it uses svcResetSignal on the process handle and then it uses svcGetProcessInfo to read out the ProcessState.
 
When the kernel signals a process handle, it uses svcResetSignal on the process handle and then it uses svcGetProcessInfo to read out the ProcessState.
  
Line 14: Line 16:
  
 
If mask 1 is not set, it immediately does what is otherwise done by the [[#FinalizeDeadProcess]] command.
 
If mask 1 is not set, it immediately does what is otherwise done by the [[#FinalizeDeadProcess]] command.
 +
 +
== Process launch ==
 +
This thread can also be triggered by the pm:shell [[#LaunchProcess]] cmd.
 +
 +
It uses [[Loader_services|ldr:pm]] GetProgramInfo with the supplied title-id.
 +
 +
If ((*(u8*) (info_output+2)) & 3) is == 1, it goes through the process list and errors if any has bit 0x40 set. Thus only one process can have bit 0x40 set at a time.
 +
 +
It calls [[Loader_services|ldr:pm]] RegisterTitle, then [[Loader_services|ldr:pm]] CreateProcess, then [[Filesystem_services|fsp-pr]] RegisterTitle, then [[Services_API|sm:m]] RegisterTitle.
 +
 +
The second input argument for [[Loader_services|ldr:pm]] CreateProcess is (launch_flags >> 2) & 3.
 +
 +
If launch_flags has mask 1 set, it sets mask 1 in process flags.
 +
 +
If launch_flags flags has mask 0x10 set, it sets mask 8 in process flags.
 +
 +
If ((*(u8*) (info_output+2)) & 3) is == 1, it sets 0x40 in the process flags, and signals the event returned by [[#EnableDebug]].
 +
 +
Finally it does svcStartProcess on the process handle that was returned by [[Loader_services|ldr:pm]] CreateProcess.
 +
 +
Thus at the point of launch, the pid is already registered in ldr, fs, sm, and pm.
  
 
= pm:bm =
 
= pm:bm =
Line 38: Line 61:
 
| 3 || GetProcessTitleIdByPid
 
| 3 || GetProcessTitleIdByPid
 
|-
 
|-
| 4 || .. Returns a handle.
+
| 4 || [[#EnableDebugForTitleId]]
 
|-
 
|-
 
| 5 || GetCrashingProcessPid
 
| 5 || GetCrashingProcessPid
 
|-
 
|-
| 6 || .. Returns a handle.
+
| 6 || [[#EnableDebug]]
 
|}
 
|}
  
Line 55: Line 78:
  
 
After that, it sets process state to 2.
 
After that, it sets process state to 2.
 +
 +
== EnableDebugForTitleId ==
 +
Takes a title-id of the program to debug. Sets this to a global field. Next time it gets launched it will be handled differently.
 +
 +
Returns an event handle that is signaled when the requested title is launched.
 +
 +
== EnableDebug ==
 +
Does *not* take a specific title-id as input.
 +
 +
Returns an event handle that is triggered for debug titles.
  
 
= pm:info =
 
= pm:info =
Line 69: Line 102:
 
! Cmd || Name
 
! Cmd || Name
 
|-
 
|-
| 0 || LaunchProcess
+
| 0 || [[#LaunchProcess]]
 
|-
 
|-
 
| 1 || TerminateProcessByPid
 
| 1 || TerminateProcessByPid
Line 87: Line 120:
 
| 8 || [[#GetCrashingProcessPid]]
 
| 8 || [[#GetCrashingProcessPid]]
 
|}
 
|}
 +
 +
== LaunchProcess ==
 +
Takes a title-id and launch_flags. See [[#Process launch]].
  
 
== FinalizeDeadProcess ==
 
== FinalizeDeadProcess ==

Revision as of 00:53, 19 July 2017

Process Tracker thread

PM has a separate thread that is waiting for synchronization on process handles.

State changes

When the kernel signals a process handle, it uses svcResetSignal on the process handle and then it uses svcGetProcessInfo to read out the ProcessState.

If the process moved state non-3 -> 3 it clears bit4 in process flags.

If process flags has mask 8 set:

  • If new state is 2, it clears 0x20 and sets 0x10 in process flags, and signals the ProcessEventWaiter handle.
  • If new state is 4, it clears 0x20 and sets 0x10 in process flags, and signals the ProcessEventWaiter handle.
  • If new state is 7, it sets 0x30 in process flags, and signals the ProcessEventWaiter handle.

If process flags has mask 1 set:

  • If new state is 6, it signals the ProcessEventWaiter handle.

If mask 1 is not set, it immediately does what is otherwise done by the #FinalizeDeadProcess command.

Process launch

This thread can also be triggered by the pm:shell #LaunchProcess cmd.

It uses ldr:pm GetProgramInfo with the supplied title-id.

If ((*(u8*) (info_output+2)) & 3) is == 1, it goes through the process list and errors if any has bit 0x40 set. Thus only one process can have bit 0x40 set at a time.

It calls ldr:pm RegisterTitle, then ldr:pm CreateProcess, then fsp-pr RegisterTitle, then sm:m RegisterTitle.

The second input argument for ldr:pm CreateProcess is (launch_flags >> 2) & 3.

If launch_flags has mask 1 set, it sets mask 1 in process flags.

If launch_flags flags has mask 0x10 set, it sets mask 8 in process flags.

If ((*(u8*) (info_output+2)) & 3) is == 1, it sets 0x40 in the process flags, and signals the event returned by #EnableDebug.

Finally it does svcStartProcess on the process handle that was returned by ldr:pm CreateProcess.

Thus at the point of launch, the pid is already registered in ldr, fs, sm, and pm.

pm:bm

Cmd Name
0 GetMaintenanceMode
1 EnableMaintenanceMode

pm:dmnt

Cmd Name
0 #GetZero
1 #GetProcessesWithFlag4
2 #StartProcess
3 GetProcessTitleIdByPid
4 #EnableDebugForTitleId
5 GetCrashingProcessPid
6 #EnableDebug

GetZero

Always returns u32 0.

GetProcessesWithFlag4

Returns an array of pids of all processes that have mask 4 set in process flags.

StartProcess

Takes a pid. Process state must be 0 or 1. Then it uses svcStartProcess(process_handle, u8, u8, u32) with args coming from ldr:pm GetProgramInfo.

After that, it sets process state to 2.

EnableDebugForTitleId

Takes a title-id of the program to debug. Sets this to a global field. Next time it gets launched it will be handled differently.

Returns an event handle that is signaled when the requested title is launched.

EnableDebug

Does *not* take a specific title-id as input.

Returns an event handle that is triggered for debug titles.

pm:info

Cmd Name
0 GetProcessTitleIdByPid

pm:shell

Cmd Name
0 #LaunchProcess
1 TerminateProcessByPid
2 TerminateProcessByTitleID
3 GetProcessEventWaiter
4 GetProcessEventType (0=CONTINUE, 1=CRASHING, 2,3,5)
5 #FinalizeDeadProcess
6 #ClearProcessCrashedFlag
7 #NotifyBootFinished
8 #GetCrashingProcessPid

LaunchProcess

Takes a title-id and launch_flags. See #Process launch.

FinalizeDeadProcess

Takes a pid as input. If the process with pid has the state "dead", it unregisters the pid in fsp:pr, sm:m, and ldr:pm.

Then it removes the process from PMs internal linked-list of active processes.

ClearProcessCrashedFlag

Takes a pid as input. Clears 0x10 from process flags.

NotifyBootFinished

Launches a process with hardcoded boot2 title-id.

GetCrashingProcessPid

Loops through the internal linked-list of processes, looks for mask 0x40 set in process flags. Returns pid of first such entry.