mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-12 13:13:43 +00:00
Rewrite vm::reservation
Use flat virtual memory area
This commit is contained in:
parent
2b5cf2455f
commit
3681507136
@ -314,6 +314,7 @@ std::string SPUThread::dump() const
|
||||
|
||||
// Print some transaction statistics
|
||||
fmt::append(ret, "\nTX: %u; Fail: %u", tx_success, tx_failure);
|
||||
fmt::append(ret, "\nRaddr: 0x%08x; R: 0x%x", raddr, raddr ? +vm::reservation_acquire(raddr, 128) : 0);
|
||||
fmt::append(ret, "\nTag Mask: 0x%08x", ch_tag_mask);
|
||||
fmt::append(ret, "\nMFC Stall: 0x%08x", ch_stall_mask);
|
||||
fmt::append(ret, "\nMFC Queue Size: %u", mfc_size);
|
||||
@ -1174,6 +1175,9 @@ bool SPUThread::process_mfc_cmd(spu_mfc_cmd args)
|
||||
// Second transaction attempt
|
||||
vm::reader_lock lock;
|
||||
|
||||
// Touch reservation memory area as well
|
||||
vm::reservation_acquire(raddr, 128) += 0;
|
||||
|
||||
if (utils::transaction_enter())
|
||||
{
|
||||
if (rtime == vm::reservation_acquire(raddr, 128) && rdata == data)
|
||||
@ -1183,6 +1187,7 @@ bool SPUThread::process_mfc_cmd(spu_mfc_cmd args)
|
||||
|
||||
vm::reservation_update(raddr, 128);
|
||||
}
|
||||
|
||||
_xend();
|
||||
tx_success++;
|
||||
|
||||
|
@ -36,12 +36,12 @@ namespace vm
|
||||
// Stats for debugging
|
||||
u8* const g_stat_addr = memory_reserve_4GiB((std::uintptr_t)g_exec_addr);
|
||||
|
||||
// Reservation stats (compressed x16)
|
||||
u8* const g_reservations = memory_reserve_4GiB((std::uintptr_t)g_stat_addr);
|
||||
|
||||
// Memory locations
|
||||
std::vector<std::shared_ptr<block_t>> g_locations;
|
||||
|
||||
// Reservations (lock lines) in a single memory page
|
||||
using reservation_info = std::array<std::atomic<u64>, 4096 / 128>;
|
||||
|
||||
// Registered waiters
|
||||
std::deque<vm::waiter*> g_waiters;
|
||||
|
||||
@ -235,48 +235,11 @@ namespace vm
|
||||
{
|
||||
// Memory flags
|
||||
atomic_t<u8> flags;
|
||||
|
||||
atomic_t<u32> waiters;
|
||||
|
||||
// Reservations
|
||||
atomic_t<reservation_info*> reservations;
|
||||
|
||||
// Access reservation info
|
||||
std::atomic<u64>& operator [](u32 addr)
|
||||
{
|
||||
auto ptr = reservations.load();
|
||||
|
||||
if (!ptr)
|
||||
{
|
||||
// Opportunistic memory allocation
|
||||
ptr = new reservation_info{};
|
||||
|
||||
if (auto old_ptr = reservations.compare_and_swap(nullptr, ptr))
|
||||
{
|
||||
delete ptr;
|
||||
ptr = old_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
return (*ptr)[(addr & 0xfff) >> 7];
|
||||
}
|
||||
};
|
||||
|
||||
// Memory pages
|
||||
std::array<memory_page, 0x100000000 / 4096> g_pages{};
|
||||
|
||||
u64 reservation_acquire(u32 addr, u32 _size)
|
||||
{
|
||||
// Access reservation info: stamp and the lock bit
|
||||
return g_pages[addr >> 12][addr].load(std::memory_order_acquire);
|
||||
}
|
||||
|
||||
void reservation_update(u32 addr, u32 _size, bool lsb)
|
||||
{
|
||||
// Update reservation info with new timestamp (unsafe, assume allocated)
|
||||
(*g_pages[addr >> 12].reservations)[(addr & 0xfff) >> 7].store((__rdtsc() & -2) | lsb, std::memory_order_release);
|
||||
}
|
||||
|
||||
void waiter::init()
|
||||
{
|
||||
// Register waiter
|
||||
@ -292,14 +255,7 @@ namespace vm
|
||||
return;
|
||||
}
|
||||
|
||||
memory_page& page = g_pages[addr >> 12];
|
||||
|
||||
if (page.reservations == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (stamp >= (*page.reservations)[(addr & 0xfff) >> 7].load())
|
||||
if (stamp >= reservation_acquire(addr, size))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -563,6 +519,11 @@ namespace vm
|
||||
, size(size)
|
||||
, flags(flags)
|
||||
{
|
||||
// Allocate compressed reservation info area (avoid RSX and SPU areas)
|
||||
if (addr != 0xc0000000 && addr != 0xe0000000)
|
||||
{
|
||||
utils::memory_commit(g_reservations + addr / 16, size / 16);
|
||||
}
|
||||
}
|
||||
|
||||
block_t::~block_t()
|
||||
@ -826,6 +787,7 @@ namespace vm
|
||||
utils::memory_decommit(g_base_addr, 0x100000000);
|
||||
utils::memory_decommit(g_exec_addr, 0x100000000);
|
||||
utils::memory_decommit(g_stat_addr, 0x100000000);
|
||||
utils::memory_decommit(g_reservations, 0x100000000);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@ namespace vm
|
||||
extern u8* const g_base_addr;
|
||||
extern u8* const g_exec_addr;
|
||||
extern u8* const g_stat_addr;
|
||||
extern u8* const g_reservations;
|
||||
|
||||
enum memory_location_t : uint
|
||||
{
|
||||
@ -100,10 +101,18 @@ namespace vm
|
||||
};
|
||||
|
||||
// Get reservation status for further atomic update: last update timestamp
|
||||
u64 reservation_acquire(u32 addr, u32 size);
|
||||
inline atomic_t<u64>& reservation_acquire(u32 addr, u32 size)
|
||||
{
|
||||
// Access reservation info: stamp and the lock bit
|
||||
return reinterpret_cast<atomic_t<u64>*>(g_reservations)[addr / 128];
|
||||
}
|
||||
|
||||
// End atomic update
|
||||
void reservation_update(u32 addr, u32 size, bool lsb = false);
|
||||
// Update reservation status
|
||||
inline void reservation_update(u32 addr, u32 size, bool lsb = false)
|
||||
{
|
||||
// Update reservation info with new timestamp
|
||||
reservation_acquire(addr, size) = (__rdtsc() & -2) | lsb;
|
||||
}
|
||||
|
||||
// Check and notify memory changes at address
|
||||
void notify(u32 addr, u32 size);
|
||||
|
Loading…
x
Reference in New Issue
Block a user