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:
parent
3de1ec384a
commit
e602eac4f9
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue