Skip to content

Commit 4cc9e51

Browse files
committed
PPPPPPPUUUUUUUU
1 parent 65fd004 commit 4cc9e51

File tree

3 files changed

+115
-14
lines changed

3 files changed

+115
-14
lines changed

rpcs3/Emu/Cell/SPUThread.cpp

Lines changed: 65 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,28 @@ extern void mov_rdata_nt(spu_rdata_t& _dst, const spu_rdata_t& _src)
425425
#endif
426426
}
427427

428+
static inline u32 cmp16_rdata(const decltype(spu_thread::rdata)& rdata, const decltype(spu_thread::rdata)& to_write)
429+
{
430+
u32 diffcnt = 0;
431+
u32 pos = 0;
432+
433+
for (u32 i = 0; i < 8; i++)
434+
{
435+
if (std::memcmp(rdata + (i * 16), to_write + (i * 16), 16))
436+
{
437+
diffcnt++;
438+
pos = i;
439+
}
440+
};
441+
442+
if (diffcnt == 1)
443+
{
444+
return pos;
445+
}
446+
447+
return -1;
448+
}
449+
428450
#if defined(_MSC_VER)
429451
#define mwaitx_func
430452
#define waitpkg_func
@@ -3968,17 +3990,52 @@ bool spu_thread::do_putllc(const spu_mfc_cmd& args)
39683990
auto& super_data = *vm::get_super_ptr<spu_rdata_t>(addr);
39693991
const bool success = [&]()
39703992
{
3971-
// Full lock (heavyweight)
3972-
// TODO: vm::check_addr
3973-
vm::writer_lock lock(addr, range_lock);
3974-
3975-
if (cmp_rdata(rdata, super_data))
3993+
if (int pos = cmp16_rdata(rdata, to_write); addr != spurs_addr && pos != -1)
39763994
{
3977-
mov_rdata(super_data, to_write);
3978-
return true;
3995+
auto& bits = *utils::bless<atomic_t<u64>>(vm::g_reservations + ((addr & 0xff80) / 2 + 32));
3996+
const auto bits_val = +bits;
3997+
3998+
// Full lock (heavyweight)
3999+
// TODO: vm::check_addr
4000+
const bool halt_ppus = bits_val == umax || bits_val < 0x100000;
4001+
4002+
if (vm::writer_lock lock(addr, range_lock, halt_ppus); cmp_rdata(rdata, super_data))
4003+
{
4004+
auto cast_as = [](void* ptr, usz pos){ return reinterpret_cast<u128*>(ptr) + pos; };
4005+
auto cast_as_const = [](const void* ptr, usz pos){ return reinterpret_cast<const u128*>(ptr) + pos; };
4006+
4007+
if (halt_ppus)
4008+
{
4009+
*cast_as(super_data, pos) = *cast_as_const(to_write, pos);
4010+
bits.try_inc(u64{umax});
4011+
return true;
4012+
}
4013+
else if (atomic_storage<u128>::compare_exchange(*cast_as(super_data, pos), *cast_as(rdata, pos), *cast_as_const(to_write, pos)))
4014+
{
4015+
bits.try_inc(u64{umax});
4016+
*cast_as(rdata, pos) = *cast_as_const(to_write, pos);
4017+
ensure(cmp_rdata(rdata, super_data));
4018+
return true;
4019+
}
4020+
}
4021+
4022+
bits = u64{umax};
4023+
return false;
39794024
}
4025+
else
4026+
{
4027+
// Full lock (heavyweight)
4028+
// TODO: vm::check_addr
4029+
vm::writer_lock lock(addr, range_lock);
39804030

3981-
return false;
4031+
if (cmp_rdata(rdata, super_data))
4032+
{
4033+
mov_rdata(super_data, to_write);
4034+
return true;
4035+
}
4036+
4037+
return false;
4038+
}
39824039
}();
39834040

39844041
res += success ? 64 : 0 - 64;

rpcs3/Emu/Memory/vm.cpp

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "Utilities/address_range.h"
99
#include "Emu/CPU/CPUThread.h"
1010
#include "Emu/RSX/RSXThread.h"
11+
#include "Emu/Cell/PPUThread.h"
1112
#include "Emu/Cell/SPURecompiler.h"
1213
#include "Emu/perf_meter.hpp"
1314
#include <deque>
@@ -402,7 +403,7 @@ namespace vm
402403
return;
403404
}
404405

405-
if (i < 100)
406+
if (1 || i < 100)
406407
busy_wait(200);
407408
else
408409
std::this_thread::yield();
@@ -455,14 +456,57 @@ namespace vm
455456
}
456457
}
457458

459+
void check_locked_ppu()
460+
{
461+
return;
462+
while (true)
463+
{
464+
const u64 tsc = utils::get_tsc();
465+
466+
for (auto lock = g_locks.cbegin(), end = lock + g_cfg.core.ppu_threads; lock != end; lock++)
467+
{
468+
if (auto ptr = static_cast<named_thread<ppu_thread>*>(lock->load()))
469+
{
470+
const u32 cia = ptr->cia;
471+
const u32 ctr = ptr->ctr;
472+
const u32 r0 = ptr->gpr[0];
473+
bool added_temp = false;
474+
475+
for (utils::pause(); cpu_flag::wait - ptr->state && cia == ptr->cia && ctr == ptr->ctr && r0 == ptr->gpr[0]; )
476+
{
477+
if (!added_temp)
478+
{
479+
ptr->state.test_and_set(cpu_flag::measure);
480+
added_temp = true;
481+
}
482+
483+
utils::pause();
484+
485+
if (added_temp && cpu_flag::measure - ptr->state)
486+
{
487+
break;
488+
}
489+
}
490+
}
491+
}
492+
493+
//f (utils::get_tsc() - tsc < 7000)
494+
break;
495+
}
496+
}
497+
458498
writer_lock::writer_lock() noexcept
459499
: writer_lock(0, nullptr, 1)
460500
{
461501
}
462502

463-
writer_lock::writer_lock(u32 const addr, atomic_t<u64, 64>* range_lock, u32 const size, u64 const flags) noexcept
503+
writer_lock::writer_lock(u32 const addr, atomic_t<u64, 64>* range_lock, bool halt_ppus) noexcept
464504
: range_lock(range_lock)
465505
{
506+
// Constant-ized arguments
507+
constexpr u32 size = 128;
508+
constexpr u64 flags = vm::range_locked;
509+
466510
cpu_thread* cpu{};
467511

468512
if (g_tls_locked)
@@ -578,17 +622,17 @@ namespace vm
578622
utils::pause();
579623
}
580624

581-
for (auto lock = g_locks.cbegin(), end = lock + g_cfg.core.ppu_threads; lock != end; lock++)
625+
for (auto lock = g_locks.cbegin(), end = lock + g_cfg.core.ppu_threads; halt_ppus && lock != end; lock++)
582626
{
583627
if (auto ptr = +*lock; ptr && ptr->state.none_of(cpu_flag::wait + cpu_flag::memory))
584628
{
585629
ptr->state.test_and_set(cpu_flag::memory);
586630
}
587631
}
588632

589-
for (auto lock = g_locks.cbegin(), end = lock + g_cfg.core.ppu_threads; lock != end; lock++)
633+
for (auto lock = g_locks.cbegin(), end = lock + g_cfg.core.ppu_threads; halt_ppus && lock != end; lock++)
590634
{
591-
if (auto ptr = +*lock)
635+
if (auto ptr = static_cast<named_thread<ppu_thread>*>(lock->load()))
592636
{
593637
while (!(ptr->state & cpu_flag::wait))
594638
{

rpcs3/Emu/Memory/vm_locking.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ namespace vm
9696
writer_lock(const writer_lock&) = delete;
9797
writer_lock& operator=(const writer_lock&) = delete;
9898
writer_lock() noexcept;
99-
writer_lock(u32 addr, atomic_t<u64, 64>* range_lock = nullptr, u32 size = 128, u64 flags = range_locked) noexcept;
99+
writer_lock(u32 addr, atomic_t<u64, 64>* range_lock = nullptr, bool halt_ppus = true) noexcept;
100100
~writer_lock() noexcept;
101101
};
102102
} // namespace vm

0 commit comments

Comments
 (0)