Attempt to workaround some stop hangs by using MsgWait instead of Wait. change order of dsp / video shutdown. some comments.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2379 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
a32e29aaa5
commit
68f5cc1873
|
@ -133,18 +133,60 @@ void Event::Shutdown()
|
|||
m_hEvent = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Event::Set()
|
||||
{
|
||||
SetEvent(m_hEvent);
|
||||
}
|
||||
|
||||
|
||||
void Event::Wait()
|
||||
{
|
||||
WaitForSingleObject(m_hEvent, INFINITE);
|
||||
}
|
||||
|
||||
inline HRESULT MsgWaitForSingleObject(HANDLE handle, DWORD timeout)
|
||||
{
|
||||
return MsgWaitForMultipleObjects(1, &handle, FALSE, timeout, 0);
|
||||
}
|
||||
|
||||
void Event::MsgWait()
|
||||
{
|
||||
// Adapted from MSDN example http://msdn.microsoft.com/en-us/library/ms687060.aspx
|
||||
while (true)
|
||||
{
|
||||
DWORD result;
|
||||
MSG msg;
|
||||
// Read all of the messages in this next loop,
|
||||
// removing each message as we read it.
|
||||
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
|
||||
{
|
||||
// If it is a quit message, exit.
|
||||
if (msg.message == WM_QUIT)
|
||||
return;
|
||||
// Otherwise, dispatch the message.
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
|
||||
// Wait for any message sent or posted to this queue
|
||||
// or for one of the passed handles be set to signaled.
|
||||
result = MsgWaitForSingleObject(m_hEvent, INFINITE);
|
||||
|
||||
// The result tells us the type of event we have.
|
||||
if (result == (WAIT_OBJECT_0 + 1))
|
||||
{
|
||||
// New messages have arrived.
|
||||
// Continue to the top of the always while loop to
|
||||
// dispatch them and resume waiting.
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// result == WAIT_OBJECT_0
|
||||
// Our event got signaled
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////
|
||||
|
||||
|
||||
|
|
|
@ -98,6 +98,11 @@ public:
|
|||
|
||||
void Set();
|
||||
void Wait();
|
||||
#ifdef _WIN32
|
||||
void MsgWait();
|
||||
#else
|
||||
void MsgWait() {Wait();}
|
||||
#endif
|
||||
|
||||
// -----------------------------------------
|
||||
#ifdef SETUP_TIMER_WAITING
|
||||
|
|
|
@ -227,7 +227,7 @@ bool Init()
|
|||
emuThreadGoing.Init();
|
||||
// This will execute EmuThread() further down in this file
|
||||
g_EmuThread = new Common::Thread(EmuThread, NULL);
|
||||
emuThreadGoing.Wait();
|
||||
emuThreadGoing.MsgWait();
|
||||
emuThreadGoing.Shutdown();
|
||||
#ifdef SETUP_TIMER_WAITING
|
||||
VideoThreadRunning = true;
|
||||
|
@ -254,29 +254,27 @@ void Stop()
|
|||
StopReachedEnd = false;
|
||||
EmuThreadReachedEnd = false;
|
||||
#endif
|
||||
|
||||
Host_SetWaitCursor(true);
|
||||
Host_SetWaitCursor(true); // hourglass!
|
||||
if (PowerPC::GetState() == PowerPC::CPU_POWERDOWN)
|
||||
return;
|
||||
|
||||
// Stop the CPU
|
||||
PowerPC::Stop();
|
||||
CCPU::StepOpcode(); // Kick it if it's waiting
|
||||
CCPU::StepOpcode(); // Kick it if it's waiting (code stepping wait loop)
|
||||
|
||||
// Wait until the CPU finishes exiting the main run loop
|
||||
cpuRunloopQuit.Wait();
|
||||
cpuRunloopQuit.Shutdown();
|
||||
// At this point, we must be out of the CPU:s runloop.
|
||||
|
||||
// Silence audio - stops audio thread.
|
||||
// Stop audio thread.
|
||||
CPluginManager::GetInstance().GetDSP()->DSP_StopSoundStream();
|
||||
|
||||
// If dual core mode, the CPU thread should immediately exit here.
|
||||
|
||||
Console::Print("Stop [Main Thread]: Wait for Video Loop...\n");
|
||||
|
||||
// Should be moved inside the plugin.
|
||||
if (_CoreParameter.bUseDualCore)
|
||||
if (_CoreParameter.bUseDualCore) {
|
||||
Console::Print("Stop [Main Thread]: Wait for Video Loop to exit...\n");
|
||||
CPluginManager::GetInstance().GetVideo()->Video_ExitLoop();
|
||||
}
|
||||
|
||||
#ifdef SETUP_TIMER_WAITING
|
||||
StopUpToVideoDone = true;
|
||||
|
@ -288,15 +286,8 @@ void Stop()
|
|||
//Console::Print("Stop() will continue\n");
|
||||
#endif
|
||||
|
||||
/* Video_EnterLoop() should now exit so that EmuThread() will continue concurrently with the rest
|
||||
of the commands in this function */
|
||||
|
||||
/* The quit is to get it out of its message loop. There is no guarantee of when this will occur though.
|
||||
And since we have no while(GetMessage()) loop we can't wait for this to happen, or say exactly when
|
||||
the loop has ended */
|
||||
#ifdef _WIN32
|
||||
//PostMessage((HWND)g_pWindowHandle, WM_QUIT, 0, 0);
|
||||
#endif
|
||||
// Video_EnterLoop() should now exit so that EmuThread() will continue concurrently with the rest
|
||||
// of the commands in this function. We no longer rely on Postmessage. */
|
||||
|
||||
// Close the trace file
|
||||
Core::StopTrace();
|
||||
|
@ -530,7 +521,6 @@ THREAD_RETURN EmuThread(void *pArg)
|
|||
cpuThread = new Common::Thread(CpuThread, pArg);
|
||||
Common::SetCurrentThreadName("Video thread");
|
||||
|
||||
// I bet that many of our stopping problems come from this loop not properly exiting.
|
||||
Plugins.GetVideo()->Video_EnterLoop();
|
||||
}
|
||||
#ifdef SETUP_TIMER_WAITING
|
||||
|
|
|
@ -82,9 +82,10 @@ bool SCoreStartupParameter::AutoSetup(EBootBios _BootBios)
|
|||
DiscIO::IVolume* pVolume = DiscIO::CreateVolumeFromFilename(m_strFilename.c_str());
|
||||
if (pVolume == NULL)
|
||||
{
|
||||
|
||||
PanicAlert(bootDrive ? "Drive could not be mounted" :
|
||||
"Your GCM/ISO file seems to be invalid, or not a GC/Wii ISO." );
|
||||
PanicAlert(bootDrive ?
|
||||
"Disc in %s could not be read - no disc, or not a GC/Wii backup.\n"
|
||||
"Please note that original Gamecube and Wii discs cannot be read by most PC DVD drives.":
|
||||
"Your GCM/ISO file seems to be invalid, or not a GC/Wii ISO.", m_strFilename.c_str());
|
||||
return false;
|
||||
}
|
||||
m_strName = pVolume->GetName();
|
||||
|
|
|
@ -208,17 +208,6 @@ void CPluginManager::ShutdownPlugins()
|
|||
//m_wiimote[i] = NULL;
|
||||
}
|
||||
|
||||
if (m_video)
|
||||
{
|
||||
m_video->Shutdown();
|
||||
// With this option, this is done on boot instead
|
||||
#ifndef SETUP_DONT_FREE_PLUGIN_ON_STOP
|
||||
delete m_video;
|
||||
m_video = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
if (m_dsp)
|
||||
{
|
||||
m_dsp->Shutdown();
|
||||
|
@ -228,6 +217,16 @@ void CPluginManager::ShutdownPlugins()
|
|||
m_dsp = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (m_video)
|
||||
{
|
||||
m_video->Shutdown();
|
||||
// With this option, this is done on boot instead
|
||||
#ifndef SETUP_DONT_FREE_PLUGIN_ON_STOP
|
||||
delete m_video;
|
||||
m_video = NULL;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
//////////////////////////////////////////////
|
||||
|
||||
|
|
|
@ -72,7 +72,6 @@ EDiscType GetDiscType(IBlobReader& _rReader);
|
|||
IVolume* CreateVolumeFromFilename(const std::string& _rFilename)
|
||||
{
|
||||
IBlobReader* pReader = CreateBlobReader(_rFilename.c_str());
|
||||
|
||||
if (pReader == NULL)
|
||||
return NULL;
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ extern u8* g_pVideoData;
|
|||
|
||||
namespace {
|
||||
|
||||
static bool fifoStateRun = false;
|
||||
static volatile bool fifoStateRun = false;
|
||||
static u8 *videoBuffer;
|
||||
static Common::Event fifo_exit_event;
|
||||
// STATE_TO_SAVE
|
||||
|
@ -97,11 +97,16 @@ void Video_SendFifoData(u8* _uData, u32 len)
|
|||
OpcodeDecoder_Run();
|
||||
}
|
||||
|
||||
// Executed from another thread, no the graphics thread!
|
||||
// Basically, all it does is set a flag so that the loop will eventually exit, then
|
||||
// waits for the event to be set, which happens when the loop does exit.
|
||||
// If we look stuck in here, then the video thread is stuck in something and won't exit
|
||||
// the loop. Switch to the video thread and investigate.
|
||||
void Fifo_ExitLoop()
|
||||
{
|
||||
fifoStateRun = false;
|
||||
#ifndef SETUP_TIMER_WAITING
|
||||
fifo_exit_event.Wait();
|
||||
fifo_exit_event.MsgWait();
|
||||
fifo_exit_event.Shutdown();
|
||||
#else
|
||||
//Console::Print("Video: Fifo_ExitLoop: Done:%i\n", fifo_exit_event.DoneWait());
|
||||
|
@ -114,6 +119,7 @@ void Fifo_ExitLoop()
|
|||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
void Fifo_EnterLoop(const SVideoInitialize &video_initialize)
|
||||
{
|
||||
fifoStateRun = true;
|
||||
|
|
|
@ -306,8 +306,8 @@ HWND OpenWindow(HWND parent, HINSTANCE hInstance, int width, int height, const T
|
|||
|
||||
m_hWnd = CreateWindow(m_szClassName, title,
|
||||
WS_CHILD,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
parent, NULL, hInstance, NULL );
|
||||
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
parent, NULL, hInstance, NULL);
|
||||
|
||||
ShowWindow(m_hWnd, SW_SHOWMAXIMIZED);
|
||||
}
|
||||
|
|
|
@ -134,7 +134,7 @@ FRAGMENTSHADER& GetOrCreateEncodingShader(u32 format)
|
|||
|
||||
void Init()
|
||||
{
|
||||
glGenFramebuffersEXT( 1, &s_texConvFrameBuffer);
|
||||
glGenFramebuffersEXT(1, &s_texConvFrameBuffer);
|
||||
|
||||
glGenRenderbuffersEXT(1, &s_dstRenderBuffer);
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, s_dstRenderBuffer);
|
||||
|
@ -154,6 +154,9 @@ void Shutdown()
|
|||
glDeleteTextures(1, &s_srcTexture);
|
||||
glDeleteRenderbuffersEXT(1, &s_dstRenderBuffer);
|
||||
glDeleteFramebuffersEXT(1, &s_texConvFrameBuffer);
|
||||
s_srcTexture = 0;
|
||||
s_dstRenderBuffer = 0;
|
||||
s_texConvFrameBuffer = 0;
|
||||
}
|
||||
|
||||
void EncodeToRam(GLuint srcTexture, const TRectangle& sourceRc,
|
||||
|
|
Loading…
Reference in New Issue