Core/HW: Add time tracking thread in CPU manager
Introduce method to track the time played for a game via time differences and TimePlayed methods. Threads are synchronized via Common::Event.
This commit is contained in:
parent
3c44fe592b
commit
fffb499da2
|
@ -10,12 +10,16 @@
|
|||
#include "AudioCommon/AudioCommon.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/Event.h"
|
||||
#include "Common/Timer.h"
|
||||
#include "Core/CPUThreadConfigCallback.h"
|
||||
#include "Core/Config/MainSettings.h"
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/Core.h"
|
||||
#include "Core/Host.h"
|
||||
#include "Core/PowerPC/GDBStub.h"
|
||||
#include "Core/PowerPC/PowerPC.h"
|
||||
#include "Core/System.h"
|
||||
#include "Core/TimePlayed.h"
|
||||
#include "VideoCommon/Fifo.h"
|
||||
|
||||
namespace CPU
|
||||
|
@ -63,6 +67,41 @@ void CPUManager::ExecutePendingJobs(std::unique_lock<std::mutex>& state_lock)
|
|||
}
|
||||
}
|
||||
|
||||
void CPUManager::StartTimePlayedTimer()
|
||||
{
|
||||
// Steady clock for greater accuracy of timing
|
||||
std::chrono::steady_clock timer;
|
||||
auto prev_time = timer.now();
|
||||
|
||||
while (true)
|
||||
{
|
||||
const std::string game_id = SConfig::GetInstance().GetGameID();
|
||||
TimePlayed time_played(game_id);
|
||||
auto curr_time = timer.now();
|
||||
|
||||
// Check that emulation is not paused
|
||||
// If the emulation is paused, wait for SetStepping() to reactivate
|
||||
if (m_state == State::Running)
|
||||
{
|
||||
const auto diff_time =
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(curr_time - prev_time);
|
||||
time_played.AddTime(diff_time);
|
||||
}
|
||||
else if (m_state == State::Stepping)
|
||||
{
|
||||
m_time_played_finish_sync.Wait();
|
||||
curr_time = timer.now();
|
||||
}
|
||||
|
||||
prev_time = curr_time;
|
||||
|
||||
if (m_state == State::PowerDown)
|
||||
return;
|
||||
|
||||
m_time_played_finish_sync.WaitFor(std::chrono::seconds(30));
|
||||
}
|
||||
}
|
||||
|
||||
void CPUManager::Run()
|
||||
{
|
||||
auto& power_pc = m_system.GetPowerPC();
|
||||
|
@ -71,6 +110,13 @@ void CPUManager::Run()
|
|||
// We can't rely on PowerPC::Init doing it, since it's called from EmuThread.
|
||||
PowerPC::RoundingModeUpdated(power_pc.GetPPCState());
|
||||
|
||||
// Start a separate time tracker thread
|
||||
std::thread timing;
|
||||
if (Config::Get(Config::MAIN_TIME_TRACKING))
|
||||
{
|
||||
timing = std::thread(&CPUManager::StartTimePlayedTimer, this);
|
||||
}
|
||||
|
||||
std::unique_lock state_lock(m_state_change_lock);
|
||||
while (m_state != State::PowerDown)
|
||||
{
|
||||
|
@ -165,6 +211,13 @@ void CPUManager::Run()
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (timing.joinable())
|
||||
{
|
||||
m_time_played_finish_sync.Set();
|
||||
timing.join();
|
||||
}
|
||||
|
||||
state_lock.unlock();
|
||||
Host_UpdateDisasmDialog();
|
||||
}
|
||||
|
@ -266,6 +319,7 @@ void CPUManager::SetStepping(bool stepping)
|
|||
else if (SetStateLocked(State::Running))
|
||||
{
|
||||
m_state_cpu_cvar.notify_one();
|
||||
m_time_played_finish_sync.Set();
|
||||
RunAdjacentSystems(true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#include <mutex>
|
||||
#include <queue>
|
||||
|
||||
#include "Common/Event.h"
|
||||
|
||||
namespace Common
|
||||
{
|
||||
class Event;
|
||||
|
@ -102,6 +104,7 @@ public:
|
|||
private:
|
||||
void FlushStepSyncEventLocked();
|
||||
void ExecutePendingJobs(std::unique_lock<std::mutex>& state_lock);
|
||||
void StartTimePlayedTimer();
|
||||
void RunAdjacentSystems(bool running);
|
||||
bool SetStateLocked(State s);
|
||||
|
||||
|
@ -133,6 +136,7 @@ private:
|
|||
bool m_state_cpu_step_instruction = false;
|
||||
Common::Event* m_state_cpu_step_instruction_sync = nullptr;
|
||||
std::queue<std::function<void()>> m_pending_jobs;
|
||||
Common::Event m_time_played_finish_sync;
|
||||
|
||||
Core::System& m_system;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue