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
tls_is_cpu_thread = true;
@ -288,7 +288,7 @@ static void DeclareAsCPUThread()
#endif
}
static void UndeclareAsCPUThread()
void UndeclareAsCPUThread()
{
#ifdef ThreadLocalStorage
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).
g_video_backend->PauseAndLock(doLock, unpauseOnUnlock);
return wasUnpaused;
}

View File

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

View File

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

View File

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