Skip to content

Commit

Permalink
SPU: Power consumption reduction when using SPU inaccurate reservations
Browse files Browse the repository at this point in the history
  • Loading branch information
elad335 authored and Nekotekina committed Sep 13, 2022
1 parent 92514e3 commit cfdc852
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 1 deletion.
9 changes: 9 additions & 0 deletions rpcs3/Emu/CPU/CPUThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "Emu/System.h"
#include "Emu/system_config.h"
#include "Emu/Memory/vm_locking.h"
#include "Emu/Memory/vm_reservation.h"
#include "Emu/IdManager.h"
#include "Emu/GDB.h"
#include "Emu/Cell/PPUThread.h"
Expand Down Expand Up @@ -892,6 +893,14 @@ cpu_thread& cpu_thread::operator=(thread_state)
if (old & cpu_flag::wait && old.none_of(cpu_flag::again + cpu_flag::exit))
{
state.notify_one(cpu_flag::exit);

if (auto thread = try_get<spu_thread>())
{
if (u32 resv = atomic_storage<u32>::load(thread->raddr))
{
vm::reservation_notifier(resv).notify_one();
}
}
}

return *this;
Expand Down
28 changes: 27 additions & 1 deletion rpcs3/Emu/Cell/SPUThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4336,6 +4336,14 @@ s64 spu_thread::get_ch_value(u32 ch)
return true;
});

if (raddr - spurs_addr <= 0x80 && !g_cfg.core.spu_accurate_reservations && mask1 == SPU_EVENT_LR)
{
// Wait without timeout, in this situation we have notifications for all writes making it possible
// Abort notifications are handled specially for performance reasons
vm::reservation_notifier(raddr).wait(rtime, -128);
continue;
}

vm::reservation_notifier(raddr).wait(rtime, -128, atomic_wait_timeout{80'000});
}
else
Expand Down Expand Up @@ -5219,6 +5227,8 @@ bool spu_thread::stop_and_signal(u32 code)
break;
}

u32 prev_resv = 0;

for (auto& thread : group->threads)
{
if (thread)
Expand All @@ -5227,10 +5237,26 @@ bool spu_thread::stop_and_signal(u32 code)
if (thread.get() != this && thread->state & cpu_flag::ret)
{
thread_ctrl::notify(*thread);

if (u32 resv = atomic_storage<u32>::load(thread->raddr))
{
if (prev_resv && prev_resv != resv)
{
// Batch reservation notifications if possible
vm::reservation_notifier(prev_resv).notify_all();
}

prev_resv = resv;
}
}
}
}


if (prev_resv)
{
vm::reservation_notifier(prev_resv).notify_all();
}

check_state();
return true;
}
Expand Down
19 changes: 19 additions & 0 deletions rpcs3/Emu/Cell/lv2/sys_spu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "Emu/Cell/PPUThread.h"
#include "Emu/Cell/RawSPUThread.h"
#include "Emu/Cell/timers.hpp"
#include "Emu/Memory/vm_reservation.h"
#include "sys_interrupt.h"
#include "sys_process.h"
#include "sys_memory.h"
Expand Down Expand Up @@ -1365,14 +1366,32 @@ error_code sys_spu_thread_group_terminate(ppu_thread& ppu, u32 id, s32 value)
}
}

u32 prev_resv = 0;

for (auto& thread : group->threads)
{
while (thread && group->running && thread->state & cpu_flag::wait)
{
thread_ctrl::notify(*thread);

if (u32 resv = atomic_storage<u32>::load(thread->raddr))
{
if (prev_resv && prev_resv != resv)
{
// Batch reservation notifications if possible
vm::reservation_notifier(prev_resv).notify_all();
}

prev_resv = resv;
}
}
}

if (prev_resv)
{
vm::reservation_notifier(prev_resv).notify_all();
}

group->exit_status = value;
group->join_state = SYS_SPU_THREAD_GROUP_JOIN_TERMINATED;

Expand Down

0 comments on commit cfdc852

Please sign in to comment.