Synchronize DVDInterface::ChangeDisc with the CPU thread properly.

This addresses a bit of thread unsafety mentioned in a comment, and
fixes a 'ScheduleEvent_Threadsafe from main thread' message.

To make this work nicely, make PauseAndLock call DeclareAsCPUThread -
i.e. while you have the CPU thread locked, you can consider yourself the
CPU thread.
This commit is contained in:
comex 2015-06-06 01:41:26 -04:00 committed by JosJuice
parent 3de1ec384a
commit e602eac4f9
4 changed files with 27 additions and 6 deletions

View File

@ -276,7 +276,7 @@ void Stop() // - Hammertime!
} }
} }
static void DeclareAsCPUThread() void DeclareAsCPUThread()
{ {
#ifdef ThreadLocalStorage #ifdef ThreadLocalStorage
tls_is_cpu_thread = true; tls_is_cpu_thread = true;
@ -288,7 +288,7 @@ static void DeclareAsCPUThread()
#endif #endif
} }
static void UndeclareAsCPUThread() void UndeclareAsCPUThread()
{ {
#ifdef ThreadLocalStorage #ifdef ThreadLocalStorage
tls_is_cpu_thread = false; tls_is_cpu_thread = false;
@ -715,6 +715,7 @@ bool PauseAndLock(bool doLock, bool unpauseOnUnlock)
// video has to come after CPU, because CPU thread can wait for video thread (s_efbAccessRequested). // video has to come after CPU, because CPU thread can wait for video thread (s_efbAccessRequested).
g_video_backend->PauseAndLock(doLock, unpauseOnUnlock); g_video_backend->PauseAndLock(doLock, unpauseOnUnlock);
return wasUnpaused; return wasUnpaused;
} }

View File

@ -41,6 +41,9 @@ bool Init();
void Stop(); void Stop();
void Shutdown(); void Shutdown();
void DeclareAsCPUThread();
void UndeclareAsCPUThread();
std::string StopMessage(bool, const std::string&); std::string StopMessage(bool, const std::string&);
bool IsRunning(); bool IsRunning();

View File

@ -149,13 +149,22 @@ void Break()
bool PauseAndLock(bool do_lock, bool unpause_on_unlock) bool PauseAndLock(bool do_lock, bool unpause_on_unlock)
{ {
static bool s_have_fake_cpu_thread;
bool wasUnpaused = !IsStepping(); bool wasUnpaused = !IsStepping();
if (do_lock) if (do_lock)
{ {
// we can't use EnableStepping, that would causes deadlocks with both audio and video // we can't use EnableStepping, that would causes deadlocks with both audio and video
PowerPC::Pause(); PowerPC::Pause();
if (!Core::IsCPUThread()) if (!Core::IsCPUThread())
{
m_csCpuOccupied.lock(); m_csCpuOccupied.lock();
s_have_fake_cpu_thread = true;
Core::DeclareAsCPUThread();
}
else
{
s_have_fake_cpu_thread = false;
}
} }
else else
{ {
@ -165,8 +174,12 @@ bool PauseAndLock(bool do_lock, bool unpause_on_unlock)
m_StepEvent.Set(); m_StepEvent.Set();
} }
if (!Core::IsCPUThread()) if (s_have_fake_cpu_thread)
{
Core::UndeclareAsCPUThread();
m_csCpuOccupied.unlock(); m_csCpuOccupied.unlock();
s_have_fake_cpu_thread = false;
}
} }
return wasUnpaused; return wasUnpaused;
} }

View File

@ -14,6 +14,7 @@
#include "Common/MathUtil.h" #include "Common/MathUtil.h"
#include "Core/ConfigManager.h" #include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/CoreTiming.h" #include "Core/CoreTiming.h"
#include "Core/Movie.h" #include "Core/Movie.h"
#include "Core/HW/AudioInterface.h" #include "Core/HW/AudioInterface.h"
@ -522,10 +523,11 @@ void InsertDiscCallback(u64 userdata, int cyclesLate)
void ChangeDisc(const std::string& newFileName) void ChangeDisc(const std::string& newFileName)
{ {
bool is_cpu = Core::IsCPUThread();
bool was_unpaused = is_cpu ? false : Core::PauseAndLock(true);
std::string* _FileName = new std::string(newFileName); std::string* _FileName = new std::string(newFileName);
CoreTiming::ScheduleEvent_Threadsafe(0, ejectDisc); CoreTiming::ScheduleEvent(0, ejectDisc);
CoreTiming::ScheduleEvent_Threadsafe(500000000, insertDisc, (u64)_FileName); CoreTiming::ScheduleEvent(500000000, insertDisc, (u64)_FileName);
// TODO: We shouldn't be modifying movie state from the GUI thread.
if (Movie::IsRecordingInput()) if (Movie::IsRecordingInput())
{ {
Movie::g_bDiscChange = true; Movie::g_bDiscChange = true;
@ -538,6 +540,8 @@ void ChangeDisc(const std::string& newFileName)
} }
Movie::g_discChange = fileName.substr(sizeofpath); Movie::g_discChange = fileName.substr(sizeofpath);
} }
if (!is_cpu)
Core::PauseAndLock(false, was_unpaused);
} }
void SetLidOpen(bool _bOpen) void SetLidOpen(bool _bOpen)