Rewrite vm::reservation

Use flat virtual memory area
This commit is contained in:
Nekotekina 2018-04-07 17:43:47 +03:00
parent 2b5cf2455f
commit 3681507136
3 changed files with 27 additions and 51 deletions

View File

@ -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++;

View File

@ -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);
}
}

View File

@ -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);