forked from eden-emu/eden
[heap_tracker] use std::set instead of inhouse rbtree (depends on #374)
Signed-off-by: lizzie <lizzie@eden-emu.dev>
This commit is contained in:
parent
18f2a1abe5
commit
163187e91b
2 changed files with 21 additions and 49 deletions
|
@ -1,9 +1,7 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <fstream>
|
#include "common/assert.h"
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "common/heap_tracker.h"
|
#include "common/heap_tracker.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
|
|
||||||
|
@ -23,6 +21,8 @@ inline s64 GetMaxPermissibleResidentMapCount() {
|
||||||
HeapTracker::HeapTracker(Common::HostMemory& buffer)
|
HeapTracker::HeapTracker(Common::HostMemory& buffer)
|
||||||
: m_buffer(buffer), m_max_resident_map_count(GetMaxPermissibleResidentMapCount()) {}
|
: m_buffer(buffer), m_max_resident_map_count(GetMaxPermissibleResidentMapCount()) {}
|
||||||
|
|
||||||
|
HeapTracker::~HeapTracker() = default;
|
||||||
|
|
||||||
void HeapTracker::Map(size_t virtual_offset, size_t host_offset, size_t length,
|
void HeapTracker::Map(size_t virtual_offset, size_t host_offset, size_t length,
|
||||||
MemoryPermission perm, bool is_separate_heap) {
|
MemoryPermission perm, bool is_separate_heap) {
|
||||||
bool rebuild_required = false;
|
bool rebuild_required = false;
|
||||||
|
@ -48,10 +48,10 @@ void HeapTracker::Map(size_t virtual_offset, size_t host_offset, size_t length,
|
||||||
|
|
||||||
// Insert into mappings.
|
// Insert into mappings.
|
||||||
m_map_count++;
|
m_map_count++;
|
||||||
const auto it = m_mappings.insert(*map);
|
auto const [it, _] = m_mappings.insert(*map);
|
||||||
|
|
||||||
// Update tick before possible rebuild.
|
// Update tick before possible rebuild.
|
||||||
it->tick = m_tick++;
|
const_cast<SeparateHeapMap&>(*it).tick = m_tick++;
|
||||||
|
|
||||||
// Check if we need to rebuild.
|
// Check if we need to rebuild.
|
||||||
if (m_resident_map_count >= m_max_resident_map_count) {
|
if (m_resident_map_count >= m_max_resident_map_count) {
|
||||||
|
@ -62,7 +62,7 @@ void HeapTracker::Map(size_t virtual_offset, size_t host_offset, size_t length,
|
||||||
m_buffer.Map(it->vaddr, it->paddr, it->size, it->perm, false);
|
m_buffer.Map(it->vaddr, it->paddr, it->size, it->perm, false);
|
||||||
|
|
||||||
// This map is now resident.
|
// This map is now resident.
|
||||||
it->is_resident = true;
|
const_cast<SeparateHeapMap&>(*it).is_resident = true;
|
||||||
m_resident_map_count++;
|
m_resident_map_count++;
|
||||||
m_resident_mappings.insert(*it);
|
m_resident_mappings.insert(*it);
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@ void HeapTracker::Unmap(size_t virtual_offset, size_t size, bool is_separate_hea
|
||||||
// If resident, erase from resident map.
|
// If resident, erase from resident map.
|
||||||
if (item->is_resident) {
|
if (item->is_resident) {
|
||||||
ASSERT(--m_resident_map_count >= 0);
|
ASSERT(--m_resident_map_count >= 0);
|
||||||
m_resident_mappings.erase(m_resident_mappings.iterator_to(*item));
|
m_resident_mappings.erase(m_resident_mappings.find(*item));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Erase from map.
|
// Erase from map.
|
||||||
|
@ -134,8 +134,7 @@ void HeapTracker::Protect(size_t virtual_offset, size_t size, MemoryPermission p
|
||||||
};
|
};
|
||||||
|
|
||||||
// Try to get the next mapping corresponding to this address.
|
// Try to get the next mapping corresponding to this address.
|
||||||
const auto it = m_mappings.nfind(key);
|
const auto it = m_mappings.find(key);
|
||||||
|
|
||||||
if (it == m_mappings.end()) {
|
if (it == m_mappings.end()) {
|
||||||
// There are no separate heap mappings remaining.
|
// There are no separate heap mappings remaining.
|
||||||
next = end;
|
next = end;
|
||||||
|
@ -143,7 +142,7 @@ void HeapTracker::Protect(size_t virtual_offset, size_t size, MemoryPermission p
|
||||||
} else if (it->vaddr == cur) {
|
} else if (it->vaddr == cur) {
|
||||||
// We are in range.
|
// We are in range.
|
||||||
// Update permission bits.
|
// Update permission bits.
|
||||||
it->perm = perm;
|
const_cast<SeparateHeapMap&>(*it).perm = perm;
|
||||||
|
|
||||||
// Determine next address and whether we should protect.
|
// Determine next address and whether we should protect.
|
||||||
next = cur + it->size;
|
next = cur + it->size;
|
||||||
|
@ -184,7 +183,7 @@ void HeapTracker::RebuildSeparateHeapAddressSpace() {
|
||||||
|
|
||||||
for (size_t i = 0; i < evict_count && it != m_resident_mappings.end(); i++) {
|
for (size_t i = 0; i < evict_count && it != m_resident_mappings.end(); i++) {
|
||||||
// Unmark and unmap.
|
// Unmark and unmap.
|
||||||
it->is_resident = false;
|
const_cast<SeparateHeapMap&>(*it).is_resident = false;
|
||||||
m_buffer.Unmap(it->vaddr, it->size, false);
|
m_buffer.Unmap(it->vaddr, it->size, false);
|
||||||
|
|
||||||
// Advance.
|
// Advance.
|
||||||
|
@ -215,7 +214,7 @@ void HeapTracker::SplitHeapMapLocked(VAddr offset) {
|
||||||
|
|
||||||
// Adjust the left map.
|
// Adjust the left map.
|
||||||
const size_t left_size = offset - left->vaddr;
|
const size_t left_size = offset - left->vaddr;
|
||||||
left->size = left_size;
|
const_cast<SeparateHeapMap&>(*left).size = left_size;
|
||||||
|
|
||||||
// Create the new right map.
|
// Create the new right map.
|
||||||
auto* const right = new SeparateHeapMap{
|
auto* const right = new SeparateHeapMap{
|
||||||
|
|
|
@ -3,19 +3,15 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <atomic>
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <set>
|
|
||||||
#include <shared_mutex>
|
#include <shared_mutex>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
#include "common/host_memory.h"
|
#include "common/host_memory.h"
|
||||||
#include "common/intrusive_red_black_tree.h"
|
|
||||||
|
|
||||||
namespace Common {
|
namespace Common {
|
||||||
|
|
||||||
struct SeparateHeapMap {
|
struct SeparateHeapMap {
|
||||||
Common::IntrusiveRedBlackTreeNode addr_node{};
|
|
||||||
Common::IntrusiveRedBlackTreeNode tick_node{};
|
|
||||||
VAddr vaddr{};
|
VAddr vaddr{};
|
||||||
PAddr paddr{};
|
PAddr paddr{};
|
||||||
size_t size{};
|
size_t size{};
|
||||||
|
@ -25,33 +21,22 @@ struct SeparateHeapMap {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SeparateHeapMapAddrComparator {
|
struct SeparateHeapMapAddrComparator {
|
||||||
static constexpr int Compare(const SeparateHeapMap& lhs, const SeparateHeapMap& rhs) {
|
constexpr bool operator()(const SeparateHeapMap& lhs, const SeparateHeapMap& rhs) const noexcept {
|
||||||
if (lhs.vaddr < rhs.vaddr) {
|
return lhs.vaddr < rhs.vaddr;
|
||||||
return -1;
|
|
||||||
} else if (lhs.vaddr <= (rhs.vaddr + rhs.size - 1)) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SeparateHeapMapTickComparator {
|
struct SeparateHeapMapTickComparator {
|
||||||
static constexpr int Compare(const SeparateHeapMap& lhs, const SeparateHeapMap& rhs) {
|
constexpr bool operator()(const SeparateHeapMap& lhs, const SeparateHeapMap& rhs) const noexcept {
|
||||||
if (lhs.tick < rhs.tick) {
|
if (lhs.tick != rhs.tick)
|
||||||
return -1;
|
return lhs.tick < rhs.tick;
|
||||||
} else if (lhs.tick > rhs.tick) {
|
return SeparateHeapMapAddrComparator()(lhs, rhs);
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
return SeparateHeapMapAddrComparator::Compare(lhs, rhs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class HeapTracker {
|
class HeapTracker {
|
||||||
public:
|
public:
|
||||||
explicit HeapTracker(Common::HostMemory& buffer);
|
explicit HeapTracker(Common::HostMemory& buffer);
|
||||||
~HeapTracker() = default;
|
~HeapTracker();
|
||||||
|
|
||||||
void Map(size_t virtual_offset, size_t host_offset, size_t length, MemoryPermission perm,
|
void Map(size_t virtual_offset, size_t host_offset, size_t length, MemoryPermission perm,
|
||||||
bool is_separate_heap);
|
bool is_separate_heap);
|
||||||
|
@ -60,24 +45,12 @@ public:
|
||||||
inline u8* VirtualBasePointer() noexcept {
|
inline u8* VirtualBasePointer() noexcept {
|
||||||
return m_buffer.VirtualBasePointer();
|
return m_buffer.VirtualBasePointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
using AddrTreeTraits =
|
|
||||||
Common::IntrusiveRedBlackTreeMemberTraitsDeferredAssert<&SeparateHeapMap::addr_node>;
|
|
||||||
using AddrTree = AddrTreeTraits::TreeType<SeparateHeapMapAddrComparator>;
|
|
||||||
|
|
||||||
using TickTreeTraits =
|
|
||||||
Common::IntrusiveRedBlackTreeMemberTraitsDeferredAssert<&SeparateHeapMap::tick_node>;
|
|
||||||
using TickTree = TickTreeTraits::TreeType<SeparateHeapMapTickComparator>;
|
|
||||||
|
|
||||||
AddrTree m_mappings{};
|
|
||||||
TickTree m_resident_mappings{};
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void SplitHeapMap(VAddr offset, size_t size);
|
void SplitHeapMap(VAddr offset, size_t size);
|
||||||
void SplitHeapMapLocked(VAddr offset);
|
void SplitHeapMapLocked(VAddr offset);
|
||||||
void RebuildSeparateHeapAddressSpace();
|
void RebuildSeparateHeapAddressSpace();
|
||||||
private:
|
std::set<SeparateHeapMap, SeparateHeapMapAddrComparator> m_mappings{};
|
||||||
|
std::set<SeparateHeapMap, SeparateHeapMapTickComparator> m_resident_mappings{};
|
||||||
Common::HostMemory& m_buffer;
|
Common::HostMemory& m_buffer;
|
||||||
const s64 m_max_resident_map_count;
|
const s64 m_max_resident_map_count;
|
||||||
std::shared_mutex m_rebuild_lock{};
|
std::shared_mutex m_rebuild_lock{};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue