Core: Wait for background CPU load on exit.

This prevents crashes when exiting a game while loading is still in
progress.  See #11516.
This commit is contained in:
Unknown W. Brackets 2018-11-01 21:27:01 -07:00
parent 5ea935f4bf
commit 670e207c57
5 changed files with 41 additions and 1 deletions

View File

@ -258,6 +258,7 @@ bool LoadFile(FileLoader **fileLoaderPtr, std::string *error_string) {
}
else if (ebootType == IdentifiedFileType::PSP_PS1_PBP) {
*error_string = "PS1 EBOOTs are not supported by PPSSPP.";
coreState = CORE_ERROR;
return false;
}
std::string path = fileLoader->Path();
@ -269,6 +270,7 @@ bool LoadFile(FileLoader **fileLoaderPtr, std::string *error_string) {
return Load_PSP_ELF_PBP(fileLoader, error_string);
} else {
*error_string = "No EBOOT.PBP, misidentified game";
coreState = CORE_ERROR;
return false;
}
}
@ -347,5 +349,7 @@ bool LoadFile(FileLoader **fileLoaderPtr, std::string *error_string) {
*error_string = "Failed to identify file";
break;
}
coreState = CORE_ERROR;
return false;
}

View File

@ -247,6 +247,7 @@ bool Load_PSP_ISO(FileLoader *fileLoader, std::string *error_string) {
} else {
*error_string = "A PSP game couldn't be found on the disc.";
}
coreState = CORE_ERROR;
return false;
}
@ -257,6 +258,10 @@ bool Load_PSP_ISO(FileLoader *fileLoader, std::string *error_string) {
std::thread th([bootpath] {
setCurrentThreadName("ExecLoader");
PSP_LoadingLock guard;
if (coreState != CORE_POWERUP)
return;
PSP_SetLoading("Loading executable...");
// TODO: We can't use the initial error_string pointer.
bool success = __KernelLoadExec(bootpath.c_str(), 0, &PSP_CoreParameter().errorString);
@ -327,6 +332,7 @@ bool Load_PSP_ELF_PBP(FileLoader *fileLoader, std::string *error_string) {
// If root is not a subpath of path, we can't boot the game.
if (!startsWith(pathNorm, rootNorm)) {
*error_string = "Cannot boot ELF located outside mountRoot.";
coreState = CORE_ERROR;
return false;
}
@ -374,6 +380,11 @@ bool Load_PSP_ELF_PBP(FileLoader *fileLoader, std::string *error_string) {
// End of temporary code
std::thread th([finalName] {
setCurrentThreadName("ExecLoader");
PSP_LoadingLock guard;
if (coreState != CORE_POWERUP)
return;
bool success = __KernelLoadExec(finalName.c_str(), 0, &PSP_CoreParameter().errorString);
if (success && coreState == CORE_POWERUP) {
coreState = PSP_CoreParameter().startBreak ? CORE_STEPPING : CORE_RUNNING;
@ -392,6 +403,11 @@ bool Load_PSP_GE_Dump(FileLoader *fileLoader, std::string *error_string) {
pspFileSystem.Mount("disc0:", umd);
std::thread th([] {
setCurrentThreadName("ExecLoader");
PSP_LoadingLock guard;
if (coreState != CORE_POWERUP)
return;
bool success = __KernelLoadGEDump("disc0:/data.ppdmp", &PSP_CoreParameter().errorString);
if (success && coreState == CORE_POWERUP) {
coreState = PSP_CoreParameter().startBreak ? CORE_STEPPING : CORE_RUNNING;

View File

@ -82,6 +82,9 @@ ParamSFOData g_paramSFO;
static GlobalUIState globalUIState;
static CoreParameter coreParameter;
static FileLoader *loadedFile;
// For background loading thread.
static std::mutex loadingLock;
// For loadingReason updates.
static std::mutex loadingReasonLock;
static std::string loadingReason;
@ -255,7 +258,18 @@ void CPU_Init() {
}
}
PSP_LoadingLock::PSP_LoadingLock() {
loadingLock.lock();
}
PSP_LoadingLock::~PSP_LoadingLock() {
loadingLock.unlock();
}
void CPU_Shutdown() {
// Since we load on a background thread, wait for startup to complete.
PSP_LoadingLock lock;
if (g_Config.bAutoSaveSymbolMap) {
host->SaveSymbolMap();
}

View File

@ -79,6 +79,12 @@ void PSP_RunLoopFor(int cycles);
void PSP_SetLoading(const std::string &reason);
std::string PSP_GetLoading();
// Used to wait for background loading thread.
struct PSP_LoadingLock {
PSP_LoadingLock();
~PSP_LoadingLock();
};
// Call before PSP_BeginHostFrame() in order to not miss any GPU stats.
void Core_UpdateDebugStats(bool collectStats);

View File

@ -334,7 +334,7 @@ void EmuScreen::bootComplete() {
}
EmuScreen::~EmuScreen() {
if (!invalid_) {
if (!invalid_ || bootPending_) {
// If we were invalid, it would already be shutdown.
PSP_Shutdown();
}