mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-01-30 21:32:50 +00:00
SPU: Task-based SPURS limiter
This commit is contained in:
parent
c4334f5142
commit
ad42a2b89a
@ -1837,6 +1837,11 @@ void spu_thread::cpu_task()
|
||||
}
|
||||
}
|
||||
|
||||
if (spurs_addr && group->max_run != 6)
|
||||
{
|
||||
group->spurs_running++;
|
||||
}
|
||||
|
||||
if (jit)
|
||||
{
|
||||
while (true)
|
||||
@ -1884,6 +1889,14 @@ void spu_thread::cpu_task()
|
||||
|
||||
allow_interrupts_in_cpu_work = false;
|
||||
}
|
||||
|
||||
if (spurs_addr && group->max_run != 6)
|
||||
{
|
||||
if (group->spurs_running.exchange(0))
|
||||
{
|
||||
group->spurs_running.notify_all();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void spu_thread::cpu_work()
|
||||
@ -5469,12 +5482,71 @@ s64 spu_thread::get_ch_value(u32 ch)
|
||||
|
||||
case SPU_RdEventStat:
|
||||
{
|
||||
const bool is_spurs_task_wait = pc == 0x11a8 && group->max_run != 6 && spurs_addr;
|
||||
|
||||
if (is_spurs_task_wait)
|
||||
{
|
||||
const u32 prev_running = group->spurs_running.fetch_op([](u32& x)
|
||||
{
|
||||
if (x)
|
||||
{
|
||||
x--;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}).first;
|
||||
|
||||
if (prev_running == group->max_run)
|
||||
{
|
||||
group->spurs_running.notify_all();
|
||||
}
|
||||
}
|
||||
|
||||
const u32 mask1 = ch_events.load().mask;
|
||||
|
||||
auto events = get_events(mask1, false, true);
|
||||
|
||||
const auto wait_spurs_task = [&]
|
||||
{
|
||||
if (is_spurs_task_wait)
|
||||
{
|
||||
// Wait for other threads to complete their tasks (temporarily)
|
||||
if (!is_stopped())
|
||||
{
|
||||
const u32 prev_running = group->spurs_running.fetch_op([max = group->max_run](u32& x)
|
||||
{
|
||||
if (x < max)
|
||||
{
|
||||
x++;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}).first;
|
||||
|
||||
if (prev_running >= group->max_run)
|
||||
{
|
||||
const u64 before = get_system_time();
|
||||
thread_ctrl::wait_on(group->spurs_running, prev_running, 10000);
|
||||
|
||||
// Check for missed waiting (due to thread-state notification or value change)
|
||||
const u32 new_running = group->spurs_running;
|
||||
|
||||
if (!is_stopped() && new_running >= group->max_run && get_system_time() - before < 1500)
|
||||
{
|
||||
thread_ctrl::wait_on(group->spurs_running, new_running, 10000);
|
||||
}
|
||||
|
||||
group->spurs_running++;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (events.count)
|
||||
{
|
||||
wait_spurs_task();
|
||||
return events.events & mask1;
|
||||
}
|
||||
|
||||
@ -5490,7 +5562,7 @@ s64 spu_thread::get_ch_value(u32 ch)
|
||||
const u32 old_raddr = raddr;
|
||||
|
||||
// Does not need to safe-access reservation if LR is the only event masked
|
||||
// Because it's either an access violation or a livelock if an invalid memory is passed
|
||||
// Because it's either an access violation or a live-lock if an invalid memory is passed
|
||||
if (raddr && mask1 > SPU_EVENT_LR)
|
||||
{
|
||||
auto area = vm::get(vm::any, raddr);
|
||||
@ -5504,7 +5576,7 @@ s64 spu_thread::get_ch_value(u32 ch)
|
||||
}
|
||||
else if (area)
|
||||
{
|
||||
// Ensure possesion over reservation memory so it won't be deallocated
|
||||
// Ensure possession over reservation memory so it won't be de-allocated
|
||||
auto [base_addr, shm_] = area->peek(raddr);
|
||||
|
||||
if (shm_)
|
||||
@ -5690,6 +5762,7 @@ s64 spu_thread::get_ch_value(u32 ch)
|
||||
thread_ctrl::wait_on(state, old, 100);
|
||||
}
|
||||
|
||||
wait_spurs_task();
|
||||
wakeup_delay();
|
||||
|
||||
if (is_paused(state - cpu_flag::suspend))
|
||||
|
@ -1057,7 +1057,7 @@ error_code sys_spu_thread_group_start(ppu_thread& ppu, u32 id)
|
||||
default: return CELL_ESTAT;
|
||||
}
|
||||
|
||||
const u32 max_threads = group->max_run;
|
||||
const u32 max_threads = group->max_num;
|
||||
|
||||
group->join_state = 0;
|
||||
group->exit_status = 0;
|
||||
|
@ -289,6 +289,7 @@ struct lv2_spu_group
|
||||
atomic_t<s32> exit_status; // SPU Thread Group Exit Status
|
||||
atomic_t<u32> join_state; // flags used to detect exit cause and signal
|
||||
atomic_t<u32> running = 0; // Number of running threads
|
||||
atomic_t<u32> spurs_running = 0;
|
||||
atomic_t<u32> stop_count = 0;
|
||||
atomic_t<u32> wait_term_count = 0;
|
||||
u32 waiter_spu_index = -1; // Index of SPU executing a waiting syscall
|
||||
|
Loading…
x
Reference in New Issue
Block a user