Difference between revisions of "Process Manager services"
Line 3: | Line 3: | ||
== State changes == | == 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 | + | When the kernel signals a process handle, it uses svcResetSignal on the process handle and then it uses svcGetProcessInfo to read out the ProcessEvent. |
− | If the process moved | + | If the process moved from non-3 -> 3 it clears 4 in process flags. |
If process flags has mask 8 set: | If process flags has mask 8 set: | ||
− | * If | + | * If event is ProcessEvent_Running or ProcessEvent_DebugDetached, it clears 0x20 and sets 0x10 in process flags, and signals the ProcessEventWaiter handle. |
− | * If | + | * If event is ProcessEvent_DebugSuspended, it sets 0x30 in process flags, and signals the ProcessEventWaiter handle. |
− | |||
− | [2.0.0+] If new state is | + | [2.0.0+] If new state is ProcessEvent_DebugDetached, and process flags has 0x80 set, it sets mask 0x100 and signals the ProcessEventWaiter handle. |
If process flags has mask 1 set: | If process flags has mask 1 set: | ||
− | * If new state is | + | * If new state is ProcessEvent_Exited, it signals the ProcessEventWaiter handle. |
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. | ||
Line 24: | Line 23: | ||
It uses [[Loader_services|ldr:pm]] GetProgramInfo with the supplied title-id. | 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 | + | If ((*(u8*) (info_output+2)) & 3) is == 1, it goes through the process list and errors if any has bit 0x40 set. Thus you can only run one application at a time. |
Resource limits for the process is selected by ApplicationType which is ((*(u8*) (info_output+2)) & 3) being 0, 1, or 2. Value 3 is not used. 0 = sysmodule(sysmodules don't have the ApplicationType kernel [[NPDM|descriptor]]), 1 = application, 2 = applet. | Resource limits for the process is selected by ApplicationType which is ((*(u8*) (info_output+2)) & 3) being 0, 1, or 2. Value 3 is not used. 0 = sysmodule(sysmodules don't have the ApplicationType kernel [[NPDM|descriptor]]), 1 = application, 2 = applet. | ||
Line 69: | Line 68: | ||
! Cmd || Name | ! Cmd || Name | ||
|- | |- | ||
− | | 0 || [[# | + | | 0 || [[#IsDebugMode]] |
|- | |- | ||
| 1 || [[#GetDebugProcesses]] | | 1 || [[#GetDebugProcesses]] | ||
Line 75: | Line 74: | ||
| 2 || [[#StartDebugProcess]] | | 2 || [[#StartDebugProcess]] | ||
|- | |- | ||
− | | 3 || [[# | + | | 3 || [[#GetDebuggedTitleId]] |
|- | |- | ||
| 4 || [[#EnableDebugForTitleId]] | | 4 || [[#EnableDebugForTitleId]] | ||
|- | |- | ||
− | | 5 || [[# | + | | 5 || [[#GetDebuggedPid]] |
|- | |- | ||
| 6 || [[#EnableDebug]] | | 6 || [[#EnableDebug]] | ||
|} | |} | ||
− | == | + | == IsDebugMode == |
Always returns u32 0 on retail. | Always returns u32 0 on retail. | ||
Line 95: | Line 94: | ||
== StartDebugProcess == | == StartDebugProcess == | ||
− | Takes a pid. | + | Takes a pid. Last process event must be ProcessEvent_Created or ProcessEvent_DebugAttached. |
− | + | Then it uses svcStartProcess(process_handle, u8, u8, u32) with args coming from ldr:pm GetProgramInfo. | |
− | == | + | After that, it sets last process state to ProcessEvent_DebugDetached. |
− | + | ||
+ | == GetDebuggedTitleId == | ||
+ | Takes a pid and returns the title-id. | ||
== EnableDebugForTitleId == | == 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. | + | 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. | + | Returns an event handle that is signaled when the requested title is about to be launched. |
− | == | + | == GetDebuggedPid == |
− | + | Returns the pid of the debugged process. | |
== EnableDebug == | == EnableDebug == | ||
Line 120: | Line 123: | ||
! Cmd || Name | ! Cmd || Name | ||
|- | |- | ||
− | | 0 || [[# | + | | 0 || [[#GetTitleId]] |
|} | |} | ||
− | == | + | == GetTitleId == |
Takes a pid and returns the title-id associated with the process. | Takes a pid and returns the title-id associated with the process. | ||
Line 147: | Line 150: | ||
| 7 || [[#NotifyBootFinished]] | | 7 || [[#NotifyBootFinished]] | ||
|- | |- | ||
− | | 8 || [[# | + | | 8 || [[#GetApplicationPid]] |
|} | |} | ||
Line 179: | Line 182: | ||
Launches a process with hardcoded [[boot2]] title-id. | Launches a process with hardcoded [[boot2]] title-id. | ||
− | == | + | == GetApplicationPid == |
Loops through the internal linked-list of processes, looks for mask 0x40 set in process flags. Returns pid of first such entry. | Loops through the internal linked-list of processes, looks for mask 0x40 set in process flags. Returns pid of first such entry. | ||
[[Category:Services]] | [[Category:Services]] |
Revision as of 01:24, 18 November 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 ProcessEvent.
If the process moved from non-3 -> 3 it clears 4 in process flags.
If process flags has mask 8 set:
- If event is ProcessEvent_Running or ProcessEvent_DebugDetached, it clears 0x20 and sets 0x10 in process flags, and signals the ProcessEventWaiter handle.
- If event is ProcessEvent_DebugSuspended, it sets 0x30 in process flags, and signals the ProcessEventWaiter handle.
[2.0.0+] If new state is ProcessEvent_DebugDetached, and process flags has 0x80 set, it sets mask 0x100 and signals the ProcessEventWaiter handle.
If process flags has mask 1 set:
- If new state is ProcessEvent_Exited, 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 you can only run one application at a time.
Resource limits for the process is selected by ApplicationType which is ((*(u8*) (info_output+2)) & 3) being 0, 1, or 2. Value 3 is not used. 0 = sysmodule(sysmodules don't have the ApplicationType kernel descriptor), 1 = application, 2 = applet.
It calls ldr:pm RegisterTitle, then ldr:pm CreateProcess, then fsp-pr RegisterTitle, then sm:m RegisterTitle.
[1.0.0] The second input argument for ldr:pm CreateProcess is (launch_flags >> 2) & 3.
[2.0.0+] The second input argument for ldr:pm CreateProcess is ((launch_flags >> 2) & 2) | ((launch_flags >> 1) != 1).
If launch_flags has mask 1 set, it sets mask 1 in process flags.
If launch_flags has mask 0x10 set, it sets mask 8 in process flags.
[2.0.0+] If launch_flags has mask 0x20 set, it sets mask 0x80 in process flags.
[2.0.0+] The launch_flags mask 0x10 and 0x20 will be ignored unless ((*(u8*) (info_output+2)) & 4) is set.
If ((*(u8*) (info_output+2)) & 3) is == 1, it sets 0x40 in the process flags, and signals the event returned by #EnableDebug. svcStartProcess is not called in this case, it has to be done manually by the #StartProcess command.
If the title-id matches the title-id given in #EnableDebugForTitleId, then svcStartProcess is not called. Instead process remains in suspended state, and has to be done manually by the #StartProcess command.
If launch_flags has mask 2 set, svcStartProcess is skipped.
Finally it does svcStartProcess on the process handle that was returned by ldr:pm CreateProcess, and sets process state to 2.
The arguments for svcStartProcess are process_handle, *(u8*)info_output, *(u8*)(info_output+1), *(u32*)(info_output+4).
Thus at the point of launch, the pid is already registered in ldr, fs, sm, and pm.
pm:bm
Cmd | Name |
---|---|
0 | GetBootMode |
1 | SetMaintenanceBoot |
pm:dmnt
Cmd | Name |
---|---|
0 | #IsDebugMode |
1 | #GetDebugProcesses |
2 | #StartDebugProcess |
3 | #GetDebuggedTitleId |
4 | #EnableDebugForTitleId |
5 | #GetDebuggedPid |
6 | #EnableDebug |
IsDebugMode
Always returns u32 0 on retail.
[2.0.0+] Additional check on input that can return 0xC0F. The meaning is probably useless because function is somewhat nopped on non-dev builds anyway.
GetDebugProcesses
Returns an array of pids of all processes that have mask 4 set in process flags.
[2.0.0+] Additional check on input that can return 0xC0F. The meaning is probably useless because function is somewhat nopped on non-dev builds anyway.
StartDebugProcess
Takes a pid. Last process event must be ProcessEvent_Created or ProcessEvent_DebugAttached.
Then it uses svcStartProcess(process_handle, u8, u8, u32) with args coming from ldr:pm GetProgramInfo.
After that, it sets last process state to ProcessEvent_DebugDetached.
GetDebuggedTitleId
Takes a pid and returns the title-id.
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 about to be launched.
GetDebuggedPid
Returns the pid of the debugged process.
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 | #GetTitleId |
GetTitleId
Takes a pid and returns the title-id associated with the process.
pm:shell
Cmd | Name |
---|---|
0 | #LaunchProcess |
1 | TerminateProcessByPid |
2 | TerminateProcessByTitleId |
3 | GetProcessEventWaiter |
4 | #GetProcessEventType |
5 | #FinalizeDeadProcess |
6 | #ClearProcessNotificationFlag |
7 | #NotifyBootFinished |
8 | #GetApplicationPid |
LaunchProcess
Takes launch_flags, title-id, and storageID. See #Process launch.
Returns the u64 title PID.
GetProcessEventType
Returns 1 if flags has mask 2 set.
Returns 2 if flags has mask 1 set and state is 6.
Returns 3 if flags has mask 0x10 set and not bit5.
Returns 4 if flags has mask 0x30 set.
[2.0.0+] returns 5 if state >= 2 and flags has mask 0x100 set.
Returns 0 if process is not found.
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.
ClearProcessNotificationFlag
Takes a pid as input. Clears 0x10 from process flags.
NotifyBootFinished
Launches a process with hardcoded boot2 title-id.
GetApplicationPid
Loops through the internal linked-list of processes, looks for mask 0x40 set in process flags. Returns pid of first such entry.