mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-09-07 05:03:35 +02:00
Fix/prevent crashes when MainWindow is closed before LoadFile() completes, or when it gets certain messages before TheThread completes initialization.
Fix missing ppsspp.ini loading log (only 1 unimportant line though). Fix loading ui_atlas.zim failure when [General]Browse = True is set in ppsspp.ini. Some other minor fixes as well.
This commit is contained in:
+71
-8
@@ -7,6 +7,8 @@
|
||||
#include "StringUtils.h"
|
||||
#include "../Globals.h"
|
||||
#include "EmuThread.h"
|
||||
#include "WndMainWindow.h"
|
||||
#include "resource.h"
|
||||
#include "../Core/Reporting.h"
|
||||
#include "../Core/MemMap.h"
|
||||
#include "../Core/Core.h"
|
||||
@@ -17,34 +19,79 @@
|
||||
|
||||
#include <tchar.h>
|
||||
#include <process.h>
|
||||
#include <intrin.h>
|
||||
#pragma intrinsic(_InterlockedExchange)
|
||||
|
||||
class EmuThreadLockGuard
|
||||
{
|
||||
public:
|
||||
EmuThreadLockGuard() { emuThreadCS_.Enter(); }
|
||||
~EmuThreadLockGuard() { emuThreadCS_.Leave(); }
|
||||
private:
|
||||
static struct EmuThreadCS
|
||||
{
|
||||
EmuThreadCS() { InitializeCriticalSection(&TheCS_); }
|
||||
~EmuThreadCS() { DeleteCriticalSection(&TheCS_); }
|
||||
void Enter() { EnterCriticalSection(&TheCS_); }
|
||||
void Leave() { LeaveCriticalSection(&TheCS_); }
|
||||
CRITICAL_SECTION TheCS_;
|
||||
} emuThreadCS_;
|
||||
};
|
||||
|
||||
EmuThreadLockGuard::EmuThreadCS EmuThreadLockGuard::emuThreadCS_;
|
||||
static HANDLE emuThread;
|
||||
static long emuThreadReady;
|
||||
|
||||
enum EmuTreadStatus : long
|
||||
{
|
||||
THREAD_NONE = 0,
|
||||
THREAD_INIT,
|
||||
THREAD_CORE_LOOP,
|
||||
THREAD_SHUTDOWN,
|
||||
THREAD_END,
|
||||
};
|
||||
|
||||
HANDLE EmuThread_GetThreadHandle()
|
||||
{
|
||||
EmuThreadLockGuard lock;
|
||||
return emuThread;
|
||||
}
|
||||
|
||||
DWORD TheThread(LPVOID x);
|
||||
unsigned int WINAPI TheThread(void *);
|
||||
|
||||
void EmuThread_Start()
|
||||
{
|
||||
unsigned int i;
|
||||
emuThread = (HANDLE)_beginthreadex(0,0,(unsigned int (__stdcall *)(void *))TheThread,(LPVOID)0,0,&i);
|
||||
EmuThreadLockGuard lock;
|
||||
emuThread = (HANDLE)_beginthreadex(0, 0, &TheThread, 0, 0, 0);
|
||||
}
|
||||
|
||||
void EmuThread_Stop()
|
||||
{
|
||||
// DSound_UpdateSound();
|
||||
Core_Stop();
|
||||
if (WAIT_TIMEOUT == WaitForSingleObject(EmuThread_GetThreadHandle(),300))
|
||||
Core_WaitInactive(800);
|
||||
if (WAIT_TIMEOUT == WaitForSingleObject(emuThread, 800))
|
||||
{
|
||||
//MessageBox(0,"Wait for emuthread timed out, please alert the developer to possible deadlock or infinite loop in emuthread :(.",0,0);
|
||||
MessageBox(MainWindow::GetHWND(),"Wait for emuthread timed out! :(\n"
|
||||
"please alert the developer to possible deadlock or infinite loop in emuthread!", 0, 0);
|
||||
}
|
||||
{
|
||||
EmuThreadLockGuard lock;
|
||||
CloseHandle(emuThread);
|
||||
emuThread = 0;
|
||||
}
|
||||
host->UpdateUI();
|
||||
}
|
||||
|
||||
DWORD TheThread(LPVOID x) {
|
||||
bool EmuThread_Ready()
|
||||
{
|
||||
return emuThreadReady == THREAD_CORE_LOOP;
|
||||
}
|
||||
|
||||
unsigned int WINAPI TheThread(void *)
|
||||
{
|
||||
_InterlockedExchange(&emuThreadReady, THREAD_INIT);
|
||||
|
||||
setCurrentThreadName("EmuThread");
|
||||
|
||||
std::string memstick, flash0;
|
||||
@@ -75,20 +122,36 @@ DWORD TheThread(LPVOID x) {
|
||||
INFO_LOG(BOOT, "Done.");
|
||||
_dbg_update_();
|
||||
|
||||
if (coreState == CORE_POWERDOWN) {
|
||||
INFO_LOG(BOOT, "Exit before core loop.");
|
||||
goto shutdown;
|
||||
}
|
||||
|
||||
_InterlockedExchange(&emuThreadReady, THREAD_CORE_LOOP);
|
||||
|
||||
if (g_Config.bBrowse)
|
||||
{
|
||||
PostMessage(MainWindow::GetHWND(), WM_COMMAND, ID_FILE_LOAD, 0);
|
||||
//MainWindow::BrowseAndBoot("");
|
||||
}
|
||||
|
||||
Core_EnableStepping(FALSE);
|
||||
|
||||
Core_Run();
|
||||
|
||||
shutdown:
|
||||
_InterlockedExchange(&emuThreadReady, THREAD_SHUTDOWN);
|
||||
|
||||
host = nativeHost;
|
||||
NativeShutdownGraphics();
|
||||
NativeShutdown();
|
||||
host = oldHost;
|
||||
|
||||
host->ShutdownGL();
|
||||
|
||||
_InterlockedExchange(&emuThreadReady, THREAD_END);
|
||||
|
||||
//The CPU should return when a game is stopped and cleanup should be done here,
|
||||
//so we can restart the plugins (or load new ones) for the next game
|
||||
_endthreadex(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user