mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 10:42:36 +01:00
sys_game_watchdog minor fixups
This commit is contained in:
parent
035d410a89
commit
7ea0a6d642
@ -5,53 +5,107 @@
|
|||||||
#include "Emu/System.h"
|
#include "Emu/System.h"
|
||||||
#include "Emu/system_config.h"
|
#include "Emu/system_config.h"
|
||||||
|
|
||||||
#include <thread>
|
#include "Emu/IdManager.h"
|
||||||
|
#include "Utilities/Thread.h"
|
||||||
|
|
||||||
#include "sys_game.h"
|
#include "sys_game.h"
|
||||||
|
|
||||||
LOG_CHANNEL(sys_game);
|
LOG_CHANNEL(sys_game);
|
||||||
|
|
||||||
atomic_t<bool> watchdog_stopped = true;
|
struct watchdog_t
|
||||||
atomic_t<u64> watchdog_last_clear;
|
|
||||||
u64 get_timestamp()
|
|
||||||
{
|
{
|
||||||
return (get_system_time() - Emu.GetPauseTime());
|
struct alignas(8) control_t
|
||||||
}
|
{
|
||||||
|
bool needs_restart = false;
|
||||||
|
bool active = false;
|
||||||
|
char pad[sizeof(u32) - sizeof(bool) * 2]{};
|
||||||
|
u32 timeout = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
atomic_t<control_t> control;
|
||||||
|
|
||||||
|
void operator()()
|
||||||
|
{
|
||||||
|
u64 start_time = get_system_time();
|
||||||
|
u64 old_time = start_time;
|
||||||
|
u64 current_time = old_time;
|
||||||
|
|
||||||
|
constexpr u64 sleep_time = 50'000;
|
||||||
|
|
||||||
|
while (thread_ctrl::state() != thread_state::aborting)
|
||||||
|
{
|
||||||
|
if (Emu.GetStatus(false) == system_state::paused)
|
||||||
|
{
|
||||||
|
start_time += current_time - old_time;
|
||||||
|
old_time = current_time;
|
||||||
|
thread_ctrl::wait_for(sleep_time);
|
||||||
|
current_time = get_system_time();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
old_time = std::exchange(current_time, get_system_time());
|
||||||
|
|
||||||
|
const auto old = control.fetch_op([&](control_t& data)
|
||||||
|
{
|
||||||
|
if (data.needs_restart)
|
||||||
|
{
|
||||||
|
data.needs_restart = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}).first;
|
||||||
|
|
||||||
|
if (old.active && old.needs_restart)
|
||||||
|
{
|
||||||
|
start_time = current_time;
|
||||||
|
old_time = current_time;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (old.active && current_time - start_time >= old.timeout)
|
||||||
|
{
|
||||||
|
sys_game.warning("Watchdog timeout! Restarting the game...");
|
||||||
|
|
||||||
|
Emu.CallFromMainThread([]()
|
||||||
|
{
|
||||||
|
Emu.Restart();
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
thread_ctrl::wait_for(sleep_time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr auto thread_name = "LV2 Watchdog Thread"sv;
|
||||||
|
};
|
||||||
|
|
||||||
error_code _sys_game_watchdog_start(u32 timeout)
|
error_code _sys_game_watchdog_start(u32 timeout)
|
||||||
{
|
{
|
||||||
sys_game.trace("sys_game_watchdog_start(timeout=%d)", timeout);
|
sys_game.trace("sys_game_watchdog_start(timeout=%d)", timeout);
|
||||||
|
|
||||||
if (!watchdog_stopped)
|
// According to disassembly
|
||||||
|
timeout *= 1'000'000;
|
||||||
|
timeout &= -64;
|
||||||
|
|
||||||
|
if (!g_fxo->get<named_thread<watchdog_t>>().control.fetch_op([&](watchdog_t::control_t& data)
|
||||||
|
{
|
||||||
|
if (data.active)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
data.needs_restart = true;
|
||||||
|
data.active = true;
|
||||||
|
data.timeout = timeout;
|
||||||
|
return true;
|
||||||
|
}).second)
|
||||||
{
|
{
|
||||||
return CELL_EABORT;
|
return CELL_EABORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto watchdog = [=]()
|
|
||||||
{
|
|
||||||
while (!watchdog_stopped)
|
|
||||||
{
|
|
||||||
if (Emu.IsStopped() || get_timestamp() - watchdog_last_clear > timeout * 1000000)
|
|
||||||
{
|
|
||||||
watchdog_stopped = true;
|
|
||||||
if (!Emu.IsStopped())
|
|
||||||
{
|
|
||||||
sys_game.warning("Watchdog timeout! Restarting the game...");
|
|
||||||
Emu.CallFromMainThread([]()
|
|
||||||
{
|
|
||||||
Emu.Restart();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
std::this_thread::sleep_for(1s);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
watchdog_stopped = false;
|
|
||||||
watchdog_last_clear = get_timestamp();
|
|
||||||
std::thread(watchdog).detach();
|
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +113,16 @@ error_code _sys_game_watchdog_stop()
|
|||||||
{
|
{
|
||||||
sys_game.trace("sys_game_watchdog_stop()");
|
sys_game.trace("sys_game_watchdog_stop()");
|
||||||
|
|
||||||
watchdog_stopped = true;
|
g_fxo->get<named_thread<watchdog_t>>().control.fetch_op([](watchdog_t::control_t& data)
|
||||||
|
{
|
||||||
|
if (!data.active)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
data.active = false;
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
@ -68,7 +131,16 @@ error_code _sys_game_watchdog_clear()
|
|||||||
{
|
{
|
||||||
sys_game.trace("sys_game_watchdog_clear()");
|
sys_game.trace("sys_game_watchdog_clear()");
|
||||||
|
|
||||||
watchdog_last_clear = get_timestamp();
|
g_fxo->get<named_thread<watchdog_t>>().control.fetch_op([](watchdog_t::control_t& data)
|
||||||
|
{
|
||||||
|
if (!data.active || data.needs_restart)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
data.needs_restart = true;
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
@ -314,7 +314,7 @@ public:
|
|||||||
bool IsStopped() const { return m_state == system_state::stopped; }
|
bool IsStopped() const { return m_state == system_state::stopped; }
|
||||||
bool IsReady() const { return m_state == system_state::ready; }
|
bool IsReady() const { return m_state == system_state::ready; }
|
||||||
bool IsStarting() const { return m_state == system_state::starting; }
|
bool IsStarting() const { return m_state == system_state::starting; }
|
||||||
auto GetStatus() const { system_state state = m_state; return state == system_state::frozen ? system_state::paused : state; }
|
auto GetStatus(bool fixup = true) const { system_state state = m_state; return fixup && state == system_state::frozen ? system_state::paused : state; }
|
||||||
|
|
||||||
bool HasGui() const { return m_has_gui; }
|
bool HasGui() const { return m_has_gui; }
|
||||||
void SetHasGui(bool has_gui) { m_has_gui = has_gui; }
|
void SetHasGui(bool has_gui) { m_has_gui = has_gui; }
|
||||||
|
Loading…
Reference in New Issue
Block a user