mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-07 07:21:25 +12:00
Rewrite vm::reservation
Use flat virtual memory area
This commit is contained in:
parent
2b5cf2455f
commit
3681507136
3 changed files with 27 additions and 51 deletions
|
@ -314,6 +314,7 @@ std::string SPUThread::dump() const
|
||||||
|
|
||||||
// Print some transaction statistics
|
// Print some transaction statistics
|
||||||
fmt::append(ret, "\nTX: %u; Fail: %u", tx_success, tx_failure);
|
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, "\nTag Mask: 0x%08x", ch_tag_mask);
|
||||||
fmt::append(ret, "\nMFC Stall: 0x%08x", ch_stall_mask);
|
fmt::append(ret, "\nMFC Stall: 0x%08x", ch_stall_mask);
|
||||||
fmt::append(ret, "\nMFC Queue Size: %u", mfc_size);
|
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
|
// Second transaction attempt
|
||||||
vm::reader_lock lock;
|
vm::reader_lock lock;
|
||||||
|
|
||||||
|
// Touch reservation memory area as well
|
||||||
|
vm::reservation_acquire(raddr, 128) += 0;
|
||||||
|
|
||||||
if (utils::transaction_enter())
|
if (utils::transaction_enter())
|
||||||
{
|
{
|
||||||
if (rtime == vm::reservation_acquire(raddr, 128) && rdata == data)
|
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);
|
vm::reservation_update(raddr, 128);
|
||||||
}
|
}
|
||||||
|
|
||||||
_xend();
|
_xend();
|
||||||
tx_success++;
|
tx_success++;
|
||||||
|
|
||||||
|
|
|
@ -36,12 +36,12 @@ namespace vm
|
||||||
// Stats for debugging
|
// Stats for debugging
|
||||||
u8* const g_stat_addr = memory_reserve_4GiB((std::uintptr_t)g_exec_addr);
|
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
|
// Memory locations
|
||||||
std::vector<std::shared_ptr<block_t>> g_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
|
// Registered waiters
|
||||||
std::deque<vm::waiter*> g_waiters;
|
std::deque<vm::waiter*> g_waiters;
|
||||||
|
|
||||||
|
@ -235,48 +235,11 @@ namespace vm
|
||||||
{
|
{
|
||||||
// Memory flags
|
// Memory flags
|
||||||
atomic_t<u8> 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
|
// Memory pages
|
||||||
std::array<memory_page, 0x100000000 / 4096> g_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()
|
void waiter::init()
|
||||||
{
|
{
|
||||||
// Register waiter
|
// Register waiter
|
||||||
|
@ -292,14 +255,7 @@ namespace vm
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
memory_page& page = g_pages[addr >> 12];
|
if (stamp >= reservation_acquire(addr, size))
|
||||||
|
|
||||||
if (page.reservations == nullptr)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stamp >= (*page.reservations)[(addr & 0xfff) >> 7].load())
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -563,6 +519,11 @@ namespace vm
|
||||||
, size(size)
|
, size(size)
|
||||||
, flags(flags)
|
, 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()
|
block_t::~block_t()
|
||||||
|
@ -826,6 +787,7 @@ namespace vm
|
||||||
utils::memory_decommit(g_base_addr, 0x100000000);
|
utils::memory_decommit(g_base_addr, 0x100000000);
|
||||||
utils::memory_decommit(g_exec_addr, 0x100000000);
|
utils::memory_decommit(g_exec_addr, 0x100000000);
|
||||||
utils::memory_decommit(g_stat_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_base_addr;
|
||||||
extern u8* const g_exec_addr;
|
extern u8* const g_exec_addr;
|
||||||
extern u8* const g_stat_addr;
|
extern u8* const g_stat_addr;
|
||||||
|
extern u8* const g_reservations;
|
||||||
|
|
||||||
enum memory_location_t : uint
|
enum memory_location_t : uint
|
||||||
{
|
{
|
||||||
|
@ -100,10 +101,18 @@ namespace vm
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get reservation status for further atomic update: last update timestamp
|
// 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
|
// Update reservation status
|
||||||
void reservation_update(u32 addr, u32 size, bool lsb = false);
|
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
|
// Check and notify memory changes at address
|
||||||
void notify(u32 addr, u32 size);
|
void notify(u32 addr, u32 size);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue