Build transactions at runtime

Drop _xbegin family intrinsics due to bad codegen
Implemented `notifier` class, replacing vm::notify
Minor optimization: detach transactions from global mutex on TSX path
Minor optimization: don't acquire vm::passive_lock on PPU on TSX path
This commit is contained in:
Nekotekina 2018-05-14 23:07:36 +03:00
parent fd525ae1cf
commit 367f039523
14 changed files with 529 additions and 339 deletions

View file

@ -2,6 +2,7 @@
#include "Memory.h"
#include "Emu/System.h"
#include "Utilities/mutex.h"
#include "Utilities/cond.h"
#include "Utilities/Thread.h"
#include "Utilities/VirtualMemory.h"
#include "Emu/CPU/CPUThread.h"
@ -10,6 +11,8 @@
#include <atomic>
#include <deque>
static_assert(sizeof(notifier) == 8, "Unexpected size of notifier");
namespace vm
{
static u8* memory_reserve_4GiB(std::uintptr_t _addr = 0)
@ -38,12 +41,12 @@ namespace vm
// Reservation stats (compressed x16)
u8* const g_reservations = memory_reserve_4GiB((std::uintptr_t)g_stat_addr);
// Reservation sync variables
u8* const g_reservations2 = g_reservations + 0x10000000;
// Memory locations
std::vector<std::shared_ptr<block_t>> g_locations;
// Registered waiters
std::deque<vm::waiter*> g_waiters;
// Memory mutex core
shared_mutex g_mutex;
@ -239,65 +242,6 @@ namespace vm
// Memory pages
std::array<memory_page, 0x100000000 / 4096> g_pages{};
void waiter::init()
{
// Register waiter
vm::writer_lock lock(0);
g_waiters.emplace_back(this);
}
void waiter::test() const
{
if (std::memcmp(data, vm::base(addr), size) == 0)
{
return;
}
if (stamp >= reservation_acquire(addr, size))
{
return;
}
if (owner)
{
owner->notify();
}
}
waiter::~waiter()
{
// Unregister waiter
vm::writer_lock lock(0);
// Find waiter
const auto found = std::find(g_waiters.cbegin(), g_waiters.cend(), this);
if (found != g_waiters.cend())
{
g_waiters.erase(found);
}
}
void notify(u32 addr, u32 size)
{
for (const waiter* ptr : g_waiters)
{
if (ptr->addr / 128 == addr / 128)
{
ptr->test();
}
}
}
void notify_all()
{
for (const waiter* ptr : g_waiters)
{
ptr->test();
}
}
static void _page_map(u32 addr, u8 flags, utils::shm& shm)
{
const u32 size = shm.size();
@ -539,6 +483,7 @@ namespace vm
if (addr != 0xc0000000 && addr != 0xe0000000)
{
utils::memory_commit(g_reservations + addr / 16, size / 16);
utils::memory_commit(g_reservations2 + addr / 16, size / 16);
}
}