mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 02:32:36 +01:00
Savestates: Warn on invalid SPU save state
This commit is contained in:
parent
32e01b5f1a
commit
6d8575d0d0
@ -1459,8 +1459,13 @@ u32 CPUDisAsm::DisAsmBranchTarget(s32 /*imm*/)
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern bool try_lock_spu_threads_in_a_state_compatible_with_savestates(bool revert_lock)
|
||||
extern bool try_lock_spu_threads_in_a_state_compatible_with_savestates(bool revert_lock, std::vector<std::pair<std::shared_ptr<named_thread<spu_thread>>, u32>>* out_list)
|
||||
{
|
||||
if (out_list)
|
||||
{
|
||||
out_list->clear();
|
||||
}
|
||||
|
||||
auto get_spus = [old_counter = u64{umax}, spu_list = std::vector<std::shared_ptr<named_thread<spu_thread>>>()](bool can_collect, bool force_collect) mutable
|
||||
{
|
||||
const u64 new_counter = cpu_thread::g_threads_created + cpu_thread::g_threads_deleted;
|
||||
@ -1634,6 +1639,14 @@ extern bool try_lock_spu_threads_in_a_state_compatible_with_savestates(bool reve
|
||||
continue;
|
||||
}
|
||||
|
||||
if (out_list)
|
||||
{
|
||||
for (auto& spu : *spu_list)
|
||||
{
|
||||
out_list->emplace_back(spu, spu->pc);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1813,7 +1813,10 @@ void spu_thread::cpu_task()
|
||||
spu_runtime::g_gateway(*this, _ptr<u8>(0), nullptr);
|
||||
}
|
||||
|
||||
unsavable = false;
|
||||
if (unsavable && is_stopped(state - cpu_flag::stop))
|
||||
{
|
||||
spu_log.warning("Aborting unsaveable state");
|
||||
}
|
||||
|
||||
// Print some stats
|
||||
(!group || group->stop_count < 5 ? spu_log.notice : spu_log.trace)("Stats: Block Weight: %u (Retreats: %u);", block_counter, block_failure);
|
||||
|
@ -2872,7 +2872,7 @@ void Emulator::GracefulShutdown(bool allow_autoexit, bool async_op, bool savesta
|
||||
}
|
||||
|
||||
extern bool check_if_vdec_contexts_exist();
|
||||
extern bool try_lock_spu_threads_in_a_state_compatible_with_savestates(bool revert_lock = false);
|
||||
extern bool try_lock_spu_threads_in_a_state_compatible_with_savestates(bool revert_lock = false, std::vector<std::pair<std::shared_ptr<named_thread<spu_thread>>, u32>>* out_list = nullptr);
|
||||
|
||||
void Emulator::Kill(bool allow_autoexit, bool savestate, savestate_stage* save_stage)
|
||||
{
|
||||
@ -2894,7 +2894,9 @@ void Emulator::Kill(bool allow_autoexit, bool savestate, savestate_stage* save_s
|
||||
|
||||
*pause_thread = make_ptr(new named_thread("Savestate Prepare Thread"sv, [pause_thread, allow_autoexit, this]() mutable
|
||||
{
|
||||
if (!try_lock_spu_threads_in_a_state_compatible_with_savestates())
|
||||
std::vector<std::pair<std::shared_ptr<named_thread<spu_thread>>, u32>> paused_spus;
|
||||
|
||||
if (!try_lock_spu_threads_in_a_state_compatible_with_savestates(false, &paused_spus))
|
||||
{
|
||||
sys_log.error("Failed to savestate: failed to lock SPU threads execution.");
|
||||
|
||||
@ -2962,10 +2964,11 @@ void Emulator::Kill(bool allow_autoexit, bool savestate, savestate_stage* save_s
|
||||
return;
|
||||
}
|
||||
|
||||
CallFromMainThread([allow_autoexit, this]()
|
||||
CallFromMainThread([allow_autoexit, this, paused_spus]()
|
||||
{
|
||||
savestate_stage stage{};
|
||||
stage.prepared = true;
|
||||
stage.paused_spus = paused_spus;
|
||||
Kill(allow_autoexit, true, &stage);
|
||||
});
|
||||
|
||||
@ -3071,7 +3074,7 @@ void Emulator::Kill(bool allow_autoexit, bool savestate, savestate_stage* save_s
|
||||
// There is no race condition because it is only accessed by the same thread
|
||||
std::shared_ptr<std::shared_ptr<void>> join_thread = std::make_shared<std::shared_ptr<void>>();
|
||||
|
||||
*join_thread = make_ptr(new named_thread("Emulation Join Thread"sv, [join_thread, savestate, allow_autoexit, this]() mutable
|
||||
*join_thread = make_ptr(new named_thread("Emulation Join Thread"sv, [join_thread, savestate, allow_autoexit, save_stage = save_stage ? *save_stage : savestate_stage{}, this]() mutable
|
||||
{
|
||||
fs::pending_file file;
|
||||
|
||||
@ -3142,6 +3145,14 @@ void Emulator::Kill(bool allow_autoexit, bool savestate, savestate_stage* save_s
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& spu : save_stage.paused_spus)
|
||||
{
|
||||
if (spu.first->pc != spu.second)
|
||||
{
|
||||
sys_log.error("SPU thread continued after being paused. (old_pc=0x%x, pc=0x%x, unsavable=%d)", spu.second, spu.first->pc, spu.first->unsavable);
|
||||
|
||||
}
|
||||
}
|
||||
// Save it first for maximum timing accuracy
|
||||
const u64 timestamp = get_timebased_time();
|
||||
const u64 start_time = get_system_time();
|
||||
|
@ -19,6 +19,11 @@ void init_fxo_for_exec(utils::serial*, bool);
|
||||
enum class localized_string_id;
|
||||
enum class video_renderer;
|
||||
|
||||
class spu_thread;
|
||||
|
||||
template <typename T>
|
||||
class named_thread;
|
||||
|
||||
enum class system_state : u32
|
||||
{
|
||||
stopped,
|
||||
@ -351,6 +356,7 @@ private:
|
||||
struct savestate_stage
|
||||
{
|
||||
bool prepared = false;
|
||||
std::vector<std::pair<std::shared_ptr<named_thread<spu_thread>>, u32>> paused_spus;
|
||||
};
|
||||
public:
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user