Add client code for new custom pm commands, use them, fix pm race conditions
This commit is contained in:
@@ -128,11 +128,16 @@ Result GetTitleExHeaderFlags(ExHeader_Arm11CoreInfo *outCoreInfo, ExHeader_Syste
|
||||
|
||||
Result GetCurrentAppTitleId(u64 *outTitleId)
|
||||
{
|
||||
ProcessList_Lock(&g_manager.processList);
|
||||
Result res;
|
||||
if (g_manager.runningApplicationData != NULL) {
|
||||
*outTitleId = g_manager.runningApplicationData->titleId;
|
||||
return 0;
|
||||
res = 0;
|
||||
} else {
|
||||
*outTitleId = 0;
|
||||
return MAKERESULT(RL_TEMPORARY, RS_NOTFOUND, RM_PM, 0x100);
|
||||
res = MAKERESULT(RL_TEMPORARY, RS_NOTFOUND, RM_PM, 0x100);
|
||||
}
|
||||
ProcessList_Unlock(&g_manager.processList);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -243,6 +243,7 @@ static Result launchTitleImpl(Handle *debug, ProcessData **outProcessData, const
|
||||
// note: official pm doesn't terminate the proc. if it fails here either, but will because of the svcCloseHandle and the svcRun codepath
|
||||
}
|
||||
|
||||
ProcessList_Lock(&g_manager.processList);
|
||||
ProcessData *process = *outProcessData;
|
||||
if (launchFlags & PMLAUNCHFLAG_QUEUE_DEBUG_APPLICATION) {
|
||||
// saved field is different in official pm
|
||||
@@ -271,6 +272,7 @@ static Result launchTitleImpl(Handle *debug, ProcessData **outProcessData, const
|
||||
process->flags |= (launchFlags & PMLAUNCHFLAG_NOTIFY_TERMINATION) ? PROCESSFLAG_NOTIFY_TERMINATION : 0;
|
||||
}
|
||||
|
||||
ProcessList_Unlock(&g_manager.processList);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -323,11 +325,12 @@ Result LaunchTitle(u32 *outPid, const FS_ProgramInfo *programInfo, u32 launchFla
|
||||
panic(4);
|
||||
}
|
||||
|
||||
ProcessList_Lock(&g_manager.processList);
|
||||
if (g_manager.runningApplicationData != NULL && (launchFlags & PMLAUNCHFLAG_NORMAL_APPLICATION) != 0) {
|
||||
ProcessList_Unlock(&g_manager.processList);
|
||||
return 0xC8A05BF0;
|
||||
}
|
||||
|
||||
ProcessList_Lock(&g_manager.processList);
|
||||
FOREACH_PROCESS(&g_manager.processList, process) {
|
||||
if ((process->titleId & ~0xFFULL) == (programInfo->programId & ~0xFFULL)) {
|
||||
foundProcess = process;
|
||||
@@ -370,15 +373,18 @@ Result LaunchTitle(u32 *outPid, const FS_ProgramInfo *programInfo, u32 launchFla
|
||||
|
||||
Result LaunchTitleUpdate(const FS_ProgramInfo *programInfo, const FS_ProgramInfo *programInfoUpdate, u32 launchFlags)
|
||||
{
|
||||
ProcessList_Lock(&g_manager.processList);
|
||||
if (g_manager.preparingForReboot) {
|
||||
return 0xC8A05801;
|
||||
}
|
||||
if (g_manager.runningApplicationData != NULL) {
|
||||
ProcessList_Unlock(&g_manager.processList);
|
||||
return 0xC8A05BF0;
|
||||
}
|
||||
if (!(launchFlags & ~PMLAUNCHFLAG_NORMAL_APPLICATION)) {
|
||||
return 0xD8E05802;
|
||||
}
|
||||
ProcessList_Unlock(&g_manager.processList);
|
||||
|
||||
bool originallyDebugged = launchFlags & PMLAUNCHFLAG_QUEUE_DEBUG_APPLICATION;
|
||||
|
||||
@@ -408,11 +414,15 @@ Result LaunchTitleUpdate(const FS_ProgramInfo *programInfo, const FS_ProgramInfo
|
||||
|
||||
Result LaunchApp(const FS_ProgramInfo *programInfo, u32 launchFlags)
|
||||
{
|
||||
ProcessList_Lock(&g_manager.processList);
|
||||
if (g_manager.runningApplicationData != NULL) {
|
||||
ProcessList_Unlock(&g_manager.processList);
|
||||
return 0xC8A05BF0;
|
||||
}
|
||||
|
||||
assertSuccess(setAppCpuTimeLimit(0));
|
||||
ProcessList_Unlock(&g_manager.processList);
|
||||
|
||||
return LaunchTitle(NULL, programInfo, launchFlags | PMLAUNCHFLAG_LOAD_DEPENDENCIES | PMLAUNCHFLAG_NORMAL_APPLICATION);
|
||||
}
|
||||
|
||||
@@ -421,10 +431,13 @@ Result RunQueuedProcess(Handle *outDebug)
|
||||
Result res = 0;
|
||||
StartupInfo si = {0};
|
||||
|
||||
ProcessList_Lock(&g_manager.processList);
|
||||
if (g_manager.debugData == NULL) {
|
||||
ProcessList_Unlock(&g_manager.processList);
|
||||
return 0xD8A05804;
|
||||
} else if ((g_manager.debugData->flags & PROCESSFLAG_NORMAL_APPLICATION) && g_manager.runningApplicationData != NULL) {
|
||||
// Not in official PM
|
||||
ProcessList_Unlock(&g_manager.processList);
|
||||
return 0xC8A05BF0;
|
||||
}
|
||||
|
||||
@@ -455,17 +468,21 @@ Result RunQueuedProcess(Handle *outDebug)
|
||||
}
|
||||
|
||||
ExHeaderInfoHeap_Delete(exheaderInfo);
|
||||
ProcessList_Unlock(&g_manager.processList);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
Result LaunchAppDebug(Handle *outDebug, const FS_ProgramInfo *programInfo, u32 launchFlags)
|
||||
{
|
||||
ProcessList_Lock(&g_manager.processList);
|
||||
if (g_manager.debugData != NULL) {
|
||||
ProcessList_Unlock(&g_manager.processList);
|
||||
return RunQueuedProcess(outDebug);
|
||||
}
|
||||
|
||||
if (g_manager.runningApplicationData != NULL) {
|
||||
ProcessList_Unlock(&g_manager.processList);
|
||||
return 0xC8A05BF0;
|
||||
}
|
||||
|
||||
@@ -473,6 +490,8 @@ Result LaunchAppDebug(Handle *outDebug, const FS_ProgramInfo *programInfo, u32 l
|
||||
g_debugNextApplication = false;
|
||||
|
||||
assertSuccess(setAppCpuTimeLimit(0));
|
||||
ProcessList_Unlock(&g_manager.processList);
|
||||
|
||||
Result res = launchTitleImplWrapper(outDebug, NULL, programInfo, programInfo,
|
||||
(launchFlags & ~PMLAUNCHFLAG_USE_UPDATE_TITLE) | PMLAUNCHFLAG_NORMAL_APPLICATION);
|
||||
|
||||
@@ -509,9 +528,12 @@ Result LaunchTitleDebug(Handle *outDebug, const FS_ProgramInfo *programInfo, u32
|
||||
return LaunchAppDebug(outDebug, programInfo, launchFlags);
|
||||
}
|
||||
|
||||
ProcessList_Lock(&g_manager.processList);
|
||||
if (g_manager.debugData != NULL) {
|
||||
ProcessList_Unlock(&g_manager.processList);
|
||||
return RunQueuedProcess(outDebug);
|
||||
}
|
||||
ProcessList_Unlock(&g_manager.processList);
|
||||
|
||||
return launchTitleImplWrapper(outDebug, NULL, programInfo, programInfo, launchFlags & ~PMLAUNCHFLAG_USE_UPDATE_TITLE);
|
||||
}
|
||||
|
||||
@@ -27,16 +27,18 @@ static void cleanupProcess(ProcessData *process)
|
||||
LOADER_UnregisterProgram(process->programHandle);
|
||||
}
|
||||
|
||||
if (process == g_manager.runningApplicationData) {
|
||||
ProcessList_Lock(&g_manager.processList);
|
||||
if (g_manager.runningApplicationData != NULL && process->handle == g_manager.runningApplicationData->handle) {
|
||||
if (IS_N3DS && APPMEMTYPE == 6) {
|
||||
assertSuccess(resetAppMemLimit());
|
||||
}
|
||||
g_manager.runningApplicationData = NULL;
|
||||
}
|
||||
|
||||
if (process == g_manager.debugData) {
|
||||
if (g_manager.debugData != NULL && process->handle == g_manager.debugData->handle) {
|
||||
g_manager.debugData = NULL;
|
||||
}
|
||||
ProcessList_Unlock(&g_manager.processList);
|
||||
|
||||
if (process->flags & PROCESSFLAG_NOTIFY_TERMINATION) {
|
||||
notifySubscribers(0x110 + process->terminatedNotificationVariation);
|
||||
|
||||
@@ -215,9 +215,11 @@ Result TerminateApplication(s64 timeout)
|
||||
assertSuccess(svcClearEvent(g_manager.allNotifiedTerminationEvent));
|
||||
g_manager.waitingForTermination = true;
|
||||
|
||||
ProcessList_Lock(&g_manager.processList);
|
||||
if (g_manager.runningApplicationData != NULL) {
|
||||
terminateProcessImpl(g_manager.runningApplicationData, exheaderInfo);
|
||||
}
|
||||
ProcessList_Unlock(&g_manager.processList);
|
||||
|
||||
res = commitPendingTerminations(timeout);
|
||||
|
||||
@@ -266,6 +268,7 @@ ProcessData *terminateAllProcesses(u32 callerPid, s64 timeout)
|
||||
ProcessList_Unlock(&g_manager.processList);
|
||||
}
|
||||
|
||||
ProcessList_Lock(&g_manager.processList);
|
||||
// Send notification 0x100 to the currently running application
|
||||
if (g_manager.runningApplicationData != NULL) {
|
||||
g_manager.runningApplicationData->flags &= ~PROCESSFLAG_DEPENDENCIES_LOADED;
|
||||
@@ -274,7 +277,6 @@ ProcessData *terminateAllProcesses(u32 callerPid, s64 timeout)
|
||||
|
||||
// Send notification 0x100 to anything but the caller deps or the caller; and *increase* the refcount of the latter if autoloaded
|
||||
// Ignore KIPs
|
||||
ProcessList_Lock(&g_manager.processList);
|
||||
FOREACH_PROCESS(&g_manager.processList, process) {
|
||||
if (process->flags & PROCESSFLAG_KIP) {
|
||||
continue;
|
||||
|
||||
Reference in New Issue
Block a user