mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-12-06 07:12:28 +01:00
SaveStates: Improve try_lock_spu_threads_in_a_state_compatible_with_savestates
This commit is contained in:
parent
a053abfba4
commit
1c0fa2ad58
|
|
@ -1585,22 +1585,30 @@ extern bool try_lock_spu_threads_in_a_state_compatible_with_savestates(bool reve
|
|||
|
||||
idm::select<named_thread<spu_thread>>([&](u32 id, spu_thread& spu)
|
||||
{
|
||||
spu_list.emplace_back(ensure(idm::get_unlocked<named_thread<spu_thread>>(id)));
|
||||
if (give_up)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (spu.current_func && spu.unsavable)
|
||||
if (spu.current_func && spu.unsavable && !force_collect)
|
||||
{
|
||||
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)
|
||||
// Automatically give up if it is asleep 5 seconds or more
|
||||
if (start && current > start && current - start >= 5'000'000)
|
||||
{
|
||||
give_up = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
spu_list.emplace_back(ensure(idm::get_unlocked<named_thread<spu_thread>>(id)));
|
||||
});
|
||||
|
||||
if (!force_collect && give_up)
|
||||
if (give_up)
|
||||
{
|
||||
spu_list.clear();
|
||||
old_counter = umax;
|
||||
return decltype(&spu_list){};
|
||||
}
|
||||
|
||||
|
|
@ -1625,6 +1633,7 @@ extern bool try_lock_spu_threads_in_a_state_compatible_with_savestates(bool reve
|
|||
}
|
||||
else if (get_system_time() - start >= 150'000)
|
||||
{
|
||||
std::this_thread::sleep_for(1ms);
|
||||
passed_count++;
|
||||
start = 0;
|
||||
continue;
|
||||
|
|
@ -1636,37 +1645,29 @@ extern bool try_lock_spu_threads_in_a_state_compatible_with_savestates(bool reve
|
|||
if (!spu_list)
|
||||
{
|
||||
// Give up for now
|
||||
std::this_thread::sleep_for(10ms);
|
||||
std::this_thread::sleep_for(50ms);
|
||||
passed_count++;
|
||||
start = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Avoid using suspend_all when more than 2 threads known to be unsavable
|
||||
u32 unsavable_threads = 0;
|
||||
u32 savable_threads = 0;
|
||||
|
||||
for (auto& spu : *spu_list)
|
||||
{
|
||||
if (spu->unsavable)
|
||||
if (!spu->unsavable)
|
||||
{
|
||||
unsavable_threads++;
|
||||
|
||||
if (unsavable_threads >= 3)
|
||||
{
|
||||
break;
|
||||
}
|
||||
savable_threads++;
|
||||
}
|
||||
}
|
||||
|
||||
if (unsavable_threads >= 3)
|
||||
if (!savable_threads)
|
||||
{
|
||||
std::this_thread::yield();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Flag for optimization
|
||||
bool paused_anyone = false;
|
||||
|
||||
if (cpu_thread::suspend_all(nullptr, {}, [&]()
|
||||
{
|
||||
if (!get_spus(false, true))
|
||||
|
|
@ -1695,19 +1696,13 @@ extern bool try_lock_spu_threads_in_a_state_compatible_with_savestates(bool reve
|
|||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
paused_anyone = true;
|
||||
ensure(!spu->state.test_and_set(cpu_flag::dbg_global_pause));
|
||||
}
|
||||
}
|
||||
|
||||
if (failed && paused_anyone)
|
||||
{
|
||||
// For faster signalling, first remove state flags then batch notifications
|
||||
for (auto& spu : *spu_list)
|
||||
{
|
||||
spu->state -= cpu_flag::dbg_global_pause;
|
||||
if (!failed && !is_emu_paused)
|
||||
{
|
||||
ensure(!spu->state.test_and_set(cpu_flag::dbg_global_pause));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1719,13 +1714,6 @@ extern bool try_lock_spu_threads_in_a_state_compatible_with_savestates(bool reve
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!paused_anyone)
|
||||
{
|
||||
// Need not do anything
|
||||
std::this_thread::yield();
|
||||
continue;
|
||||
}
|
||||
|
||||
for (auto& spu : *spu_list)
|
||||
{
|
||||
if (spu->state & cpu_flag::wait)
|
||||
|
|
@ -1755,7 +1743,7 @@ extern bool try_lock_spu_threads_in_a_state_compatible_with_savestates(bool reve
|
|||
{
|
||||
spu->state.notify_one();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue