mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-03 21:41:26 +12:00
Savestates: Make locking SPU threads more reasonable
Avoid locking in hopeless cases. Extend waiting time to more than 2 seconds.
This commit is contained in:
parent
3364a46139
commit
a539308545
1 changed files with 36 additions and 7 deletions
|
@ -1425,7 +1425,7 @@ u32 CPUDisAsm::DisAsmBranchTarget(s32 /*imm*/)
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
auto get_spus = [old_counter = u64{umax}, spu_list = std::vector<std::shared_ptr<named_thread<spu_thread>>>()](bool can_collect) mutable
|
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;
|
const u64 new_counter = cpu_thread::g_threads_created + cpu_thread::g_threads_deleted;
|
||||||
|
|
||||||
|
@ -1436,14 +1436,34 @@ extern bool try_lock_spu_threads_in_a_state_compatible_with_savestates(bool reve
|
||||||
return decltype(&spu_list){};
|
return decltype(&spu_list){};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const u64 current = get_system_time();
|
||||||
|
|
||||||
// Fetch SPU contexts
|
// Fetch SPU contexts
|
||||||
spu_list.clear();
|
spu_list.clear();
|
||||||
|
|
||||||
idm::select<named_thread<spu_thread>>([&](u32 id, spu_thread&)
|
bool give_up = false;
|
||||||
|
|
||||||
|
idm::select<named_thread<spu_thread>>([&](u32 id, spu_thread& spu)
|
||||||
{
|
{
|
||||||
spu_list.emplace_back(ensure(idm::get_unlocked<named_thread<spu_thread>>(id)));
|
spu_list.emplace_back(ensure(idm::get_unlocked<named_thread<spu_thread>>(id)));
|
||||||
|
|
||||||
|
if (spu.current_func && spu.unsavable)
|
||||||
|
{
|
||||||
|
const u64 start = spu.start_time;
|
||||||
|
|
||||||
|
// Automatically give up if it is asleep 15 seconds or more
|
||||||
|
if (start && current > start && current - start >= 15'000'000)
|
||||||
|
{
|
||||||
|
give_up = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!force_collect && give_up)
|
||||||
|
{
|
||||||
|
return decltype(&spu_list){};
|
||||||
|
}
|
||||||
|
|
||||||
old_counter = new_counter;
|
old_counter = new_counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1451,7 +1471,7 @@ extern bool try_lock_spu_threads_in_a_state_compatible_with_savestates(bool reve
|
||||||
};
|
};
|
||||||
|
|
||||||
// Attempt to lock for a second, if somehow takes longer abort it
|
// Attempt to lock for a second, if somehow takes longer abort it
|
||||||
for (u64 start = 0, passed_count = 0; passed_count < 10;)
|
for (u64 start = 0, passed_count = 0; passed_count < 15;)
|
||||||
{
|
{
|
||||||
if (revert_lock)
|
if (revert_lock)
|
||||||
{
|
{
|
||||||
|
@ -1463,7 +1483,7 @@ extern bool try_lock_spu_threads_in_a_state_compatible_with_savestates(bool reve
|
||||||
{
|
{
|
||||||
start = get_system_time();
|
start = get_system_time();
|
||||||
}
|
}
|
||||||
else if (get_system_time() - start >= 100'000)
|
else if (get_system_time() - start >= 150'000)
|
||||||
{
|
{
|
||||||
passed_count++;
|
passed_count++;
|
||||||
start = 0;
|
start = 0;
|
||||||
|
@ -1471,7 +1491,16 @@ extern bool try_lock_spu_threads_in_a_state_compatible_with_savestates(bool reve
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to fetch SPUs out of critical section
|
// Try to fetch SPUs out of critical section
|
||||||
const auto spu_list = get_spus(true);
|
const auto spu_list = get_spus(true, false);
|
||||||
|
|
||||||
|
if (!spu_list)
|
||||||
|
{
|
||||||
|
// Give up for now
|
||||||
|
std::this_thread::sleep_for(10ms);
|
||||||
|
passed_count++;
|
||||||
|
start = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Avoid using suspend_all when more than 2 threads known to be unsavable
|
// Avoid using suspend_all when more than 2 threads known to be unsavable
|
||||||
u32 unsavable_threads = 0;
|
u32 unsavable_threads = 0;
|
||||||
|
@ -1500,7 +1529,7 @@ extern bool try_lock_spu_threads_in_a_state_compatible_with_savestates(bool reve
|
||||||
|
|
||||||
if (cpu_thread::suspend_all(nullptr, {}, [&]()
|
if (cpu_thread::suspend_all(nullptr, {}, [&]()
|
||||||
{
|
{
|
||||||
if (!get_spus(false))
|
if (!get_spus(false, true))
|
||||||
{
|
{
|
||||||
// Avoid locking IDM here because this is a critical section
|
// Avoid locking IDM here because this is a critical section
|
||||||
return true;
|
return true;
|
||||||
|
@ -1572,7 +1601,7 @@ extern bool try_lock_spu_threads_in_a_state_compatible_with_savestates(bool reve
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& spu : *get_spus(true))
|
for (auto& spu : *get_spus(true, true))
|
||||||
{
|
{
|
||||||
if (spu->state.test_and_reset(cpu_flag::dbg_global_pause))
|
if (spu->state.test_and_reset(cpu_flag::dbg_global_pause))
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue