DeviceMemory: Make counter types configurable
This commit is contained in:
parent
aaab11e36f
commit
738e9a79a0
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <bit>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
@ -181,24 +182,28 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
Common::VirtualBuffer<VAddr> cpu_backing_address;
|
Common::VirtualBuffer<VAddr> cpu_backing_address;
|
||||||
static constexpr size_t subentries = 8 / sizeof(u8);
|
using CounterType = u8;
|
||||||
|
using CounterAtomicType = std::atomic_uint8_t;
|
||||||
|
static constexpr size_t subentries = 8 / sizeof(CounterType);
|
||||||
static constexpr size_t subentries_mask = subentries - 1;
|
static constexpr size_t subentries_mask = subentries - 1;
|
||||||
|
static constexpr size_t subentries_shift =
|
||||||
|
std::countr_zero(sizeof(u64)) - std::countr_zero(sizeof(CounterType));
|
||||||
class CounterEntry final {
|
class CounterEntry final {
|
||||||
public:
|
public:
|
||||||
CounterEntry() = default;
|
CounterEntry() = default;
|
||||||
|
|
||||||
std::atomic_uint8_t& Count(std::size_t page) {
|
CounterAtomicType& Count(std::size_t page) {
|
||||||
return values[page & subentries_mask];
|
return values[page & subentries_mask];
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::atomic_uint8_t& Count(std::size_t page) const {
|
const CounterAtomicType& Count(std::size_t page) const {
|
||||||
return values[page & subentries_mask];
|
return values[page & subentries_mask];
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::array<std::atomic_uint8_t, subentries> values{};
|
std::array<CounterAtomicType, subentries> values{};
|
||||||
};
|
};
|
||||||
static_assert(sizeof(CounterEntry) == subentries * sizeof(u8),
|
static_assert(sizeof(CounterEntry) == subentries * sizeof(CounterType),
|
||||||
"CounterEntry should be 8 bytes!");
|
"CounterEntry should be 8 bytes!");
|
||||||
|
|
||||||
static constexpr size_t num_counter_entries =
|
static constexpr size_t num_counter_entries =
|
||||||
|
|
|
@ -213,8 +213,8 @@ void DeviceMemoryManager<Traits>::Free(DAddr start, size_t size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Traits>
|
template <typename Traits>
|
||||||
void DeviceMemoryManager<Traits>::Map(DAddr address, VAddr virtual_address, size_t size,
|
void DeviceMemoryManager<Traits>::Map(DAddr address, VAddr virtual_address, size_t size, Asid asid,
|
||||||
Asid asid, bool track) {
|
bool track) {
|
||||||
Core::Memory::Memory* process_memory = registered_processes[asid.id];
|
Core::Memory::Memory* process_memory = registered_processes[asid.id];
|
||||||
size_t start_page_d = address >> Memory::YUZU_PAGEBITS;
|
size_t start_page_d = address >> Memory::YUZU_PAGEBITS;
|
||||||
size_t num_pages = Common::AlignUp(size, Memory::YUZU_PAGESIZE) >> Memory::YUZU_PAGEBITS;
|
size_t num_pages = Common::AlignUp(size, Memory::YUZU_PAGESIZE) >> Memory::YUZU_PAGEBITS;
|
||||||
|
@ -522,10 +522,10 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size
|
||||||
size_t vpage = base_vaddress >> Memory::YUZU_PAGEBITS;
|
size_t vpage = base_vaddress >> Memory::YUZU_PAGEBITS;
|
||||||
auto* memory_device_inter = registered_processes[asid.id];
|
auto* memory_device_inter = registered_processes[asid.id];
|
||||||
for (; page != page_end; ++page) {
|
for (; page != page_end; ++page) {
|
||||||
std::atomic_uint8_t& count = cached_pages->at(page >> 3).Count(page);
|
CounterAtomicType& count = cached_pages->at(page >> subentries_shift).Count(page);
|
||||||
|
|
||||||
if (delta > 0) {
|
if (delta > 0) {
|
||||||
ASSERT_MSG(count.load(std::memory_order::relaxed) < std::numeric_limits<u8>::max(),
|
ASSERT_MSG(count.load(std::memory_order::relaxed) < std::numeric_limits<CounterType>::max(),
|
||||||
"Count may overflow!");
|
"Count may overflow!");
|
||||||
} else if (delta < 0) {
|
} else if (delta < 0) {
|
||||||
ASSERT_MSG(count.load(std::memory_order::relaxed) > 0, "Count may underflow!");
|
ASSERT_MSG(count.load(std::memory_order::relaxed) > 0, "Count may underflow!");
|
||||||
|
@ -534,7 +534,7 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds or subtracts 1, as count is a unsigned 8-bit value
|
// Adds or subtracts 1, as count is a unsigned 8-bit value
|
||||||
count.fetch_add(static_cast<u8>(delta), std::memory_order_release);
|
count.fetch_add(static_cast<CounterType>(delta), std::memory_order_release);
|
||||||
|
|
||||||
// Assume delta is either -1 or 1
|
// Assume delta is either -1 or 1
|
||||||
if (count.load(std::memory_order::relaxed) == 0) {
|
if (count.load(std::memory_order::relaxed) == 0) {
|
||||||
|
@ -553,15 +553,15 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size
|
||||||
}
|
}
|
||||||
cache_bytes += Memory::YUZU_PAGESIZE;
|
cache_bytes += Memory::YUZU_PAGESIZE;
|
||||||
} else if (cache_bytes > 0) {
|
} else if (cache_bytes > 0) {
|
||||||
MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, cache_bytes,
|
MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS,
|
||||||
true);
|
cache_bytes, true);
|
||||||
cache_bytes = 0;
|
cache_bytes = 0;
|
||||||
}
|
}
|
||||||
vpage++;
|
vpage++;
|
||||||
}
|
}
|
||||||
if (uncache_bytes > 0) {
|
if (uncache_bytes > 0) {
|
||||||
MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS, uncache_bytes,
|
MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS,
|
||||||
false);
|
uncache_bytes, false);
|
||||||
}
|
}
|
||||||
if (cache_bytes > 0) {
|
if (cache_bytes > 0) {
|
||||||
MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, cache_bytes,
|
MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, cache_bytes,
|
||||||
|
|
Loading…
Reference in a new issue