1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-25 12:12:50 +01:00

SPURS limiter tweaks

This commit is contained in:
Elad Ashkenazi 2024-10-07 12:54:08 +03:00 committed by Elad
parent 36da83592a
commit d51d5ce86d
2 changed files with 70 additions and 30 deletions

View File

@ -1839,12 +1839,8 @@ void spu_thread::cpu_task()
if (group->name.ends_with("CellSpursKernelGroup"sv) && vm::check_addr(arg))
{
spurs_addr = arg;
if (group->max_run != group->max_num)
{
group->spurs_running++;
}
}
else
{
spurs_addr = invalid_spurs;
@ -1900,7 +1896,7 @@ void spu_thread::cpu_task()
allow_interrupts_in_cpu_work = false;
}
if (spurs_addr != invalid_spurs && group->max_run != group->max_num)
if (spurs_addr != invalid_spurs)
{
if (group->spurs_running.exchange(0))
{
@ -4894,20 +4890,54 @@ bool spu_thread::process_mfc_cmd()
// Avoid logging useless commands if there is no reservation
const bool dump = g_cfg.core.mfc_debug && raddr;
const bool is_spurs_task_wait = pc == 0x11e4 && spurs_addr == raddr && group->max_run != group->max_num && !spurs_waited;
const bool is_spurs_task_wait = pc == 0x11e4 && spurs_addr == raddr && g_cfg.core.max_spurs_threads != g_cfg.core.max_spurs_threads.def && !spurs_waited;
if (is_spurs_task_wait)
{
// Wait for other threads to complete their tasks (temporarily)
u32 max_run = group->max_run;
u32 prev_running = group->spurs_running;
u32 prev_running = group->spurs_running.fetch_op([max_run](u32& x)
{
if (x >= max_run)
{
x--;
return true;
}
if (prev_running > max_run)
return false;
}).first;
if (prev_running == max_run && prev_running != group->max_num)
{
group->spurs_running.notify_one();
if (group->spurs_running == max_run - 1)
{
// Try to let another thread slip in and take over execution
thread_ctrl::wait_for(300);
// Try to quit waiting
prev_running = group->spurs_running.fetch_op([max_run](u32& x)
{
if (x < max_run)
{
x++;
return true;
}
return false;
}).first;
}
}
if (prev_running >= max_run)
{
const u64 before = get_system_time();
u64 current = before;
lv2_obj::prepare_for_sleep(*this);
while (true)
{
if (is_stopped())
@ -4915,24 +4945,37 @@ bool spu_thread::process_mfc_cmd()
break;
}
thread_ctrl::wait_on(group->spurs_running, prev_running, 5000 - (current - before));
thread_ctrl::wait_on(group->spurs_running, prev_running, 10000 - (current - before));
max_run = group->max_run;
prev_running = group->spurs_running;
if (prev_running <= max_run)
prev_running = group->spurs_running.fetch_op([max_run](u32& x)
{
if (x < max_run)
{
x++;
return true;
}
return false;
}).first;
if (prev_running < max_run)
{
break;
}
current = get_system_time();
if (current - before >= 5000u)
if (current - before >= 10000u)
{
// Timed-out
break;
}
}
state += cpu_flag::temp;
static_cast<void>(test_stopped());
}
}
@ -5545,7 +5588,7 @@ s64 spu_thread::get_ch_value(u32 ch)
return events.events & mask1;
}
const bool is_spurs_task_wait = pc == 0x11a8 && spurs_addr == raddr && group->max_run != group->max_num && !spurs_waited;
const bool is_spurs_task_wait = pc == 0x11a8 && spurs_addr == raddr && g_cfg.core.max_spurs_threads != g_cfg.core.max_spurs_threads.def && !spurs_waited;
const auto wait_spurs_task = [&]
{
@ -5572,6 +5615,8 @@ s64 spu_thread::get_ch_value(u32 ch)
const u64 before = get_system_time();
u64 current = before;
lv2_obj::prepare_for_sleep(*this);
spurs_waited = true;
while (true)
@ -5581,7 +5626,7 @@ s64 spu_thread::get_ch_value(u32 ch)
break;
}
thread_ctrl::wait_on(group->spurs_running, prev_running, 5000 - (current - before));
thread_ctrl::wait_on(group->spurs_running, prev_running, 10000u - (current - before));
max_run = group->max_run;
@ -5603,7 +5648,7 @@ s64 spu_thread::get_ch_value(u32 ch)
current = get_system_time();
if (current - before >= 5000u)
if (current - before >= 10000u)
{
// Timed-out
group->spurs_running++;
@ -5628,9 +5673,17 @@ s64 spu_thread::get_ch_value(u32 ch)
return false;
}).first;
if (prev_running == group->max_run)
if (prev_running == group->max_run && prev_running < group->max_num)
{
group->spurs_running.notify_one();
spurs_waited = true;
if (group->spurs_running == prev_running - 1)
{
// Try to let another thread slip in and take over execution
thread_ctrl::wait_for(300);
}
}
}

View File

@ -731,19 +731,6 @@ error_code sys_spu_thread_initialize(ppu_thread& ppu, vm::ptr<u32> thread, u32 g
if (++group->init == group->max_num)
{
if (u32 max_threads = std::min<u32>(g_cfg.core.max_spurs_threads, group->max_num); group->max_num > max_threads)
{
constexpr std::string_view spurs_suffix = "CellSpursKernelGroup"sv;
if (group->name.ends_with(spurs_suffix) && !group->name.substr(0, group->name.size() - spurs_suffix.size()).ends_with("_libsail"))
{
// Hack: don't run more SPURS threads than specified.
group->max_run = max_threads;
spu_log.success("HACK: '%s' (0x%x) limited to %u threads.", group->name, group_id, max_threads);
}
}
const auto old = group->run_state.compare_and_swap(SPU_THREAD_GROUP_STATUS_NOT_INITIALIZED, SPU_THREAD_GROUP_STATUS_INITIALIZED);
if (old == SPU_THREAD_GROUP_STATUS_DESTROYED)