summaryrefslogtreecommitdiffstats
path: root/src/core/hle/kernel/k_memory_manager.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel/k_memory_manager.h')
-rw-r--r--src/core/hle/kernel/k_memory_manager.h259
1 files changed, 177 insertions, 82 deletions
diff --git a/src/core/hle/kernel/k_memory_manager.h b/src/core/hle/kernel/k_memory_manager.h
index dcb9b6348..401d4e644 100644
--- a/src/core/hle/kernel/k_memory_manager.h
+++ b/src/core/hle/kernel/k_memory_manager.h
@@ -21,11 +21,8 @@ namespace Kernel {
class KPageGroup;
-class KMemoryManager final {
+class KMemoryManager {
public:
- YUZU_NON_COPYABLE(KMemoryManager);
- YUZU_NON_MOVEABLE(KMemoryManager);
-
enum class Pool : u32 {
Application = 0,
Applet = 1,
@@ -45,16 +42,85 @@ public:
enum class Direction : u32 {
FromFront = 0,
FromBack = 1,
-
Shift = 0,
Mask = (0xF << Shift),
};
- explicit KMemoryManager(Core::System& system_);
+ static constexpr size_t MaxManagerCount = 10;
+
+ explicit KMemoryManager(Core::System& system);
void Initialize(VAddr management_region, size_t management_region_size);
- constexpr size_t GetSize(Pool pool) const {
+ Result InitializeOptimizedMemory(u64 process_id, Pool pool);
+ void FinalizeOptimizedMemory(u64 process_id, Pool pool);
+
+ PAddr AllocateAndOpenContinuous(size_t num_pages, size_t align_pages, u32 option);
+ Result AllocateAndOpen(KPageGroup* out, size_t num_pages, u32 option);
+ Result AllocateForProcess(KPageGroup* out, size_t num_pages, u32 option, u64 process_id,
+ u8 fill_pattern);
+
+ Pool GetPool(PAddr address) const {
+ return this->GetManager(address).GetPool();
+ }
+
+ void Open(PAddr address, size_t num_pages) {
+ // Repeatedly open references until we've done so for all pages.
+ while (num_pages) {
+ auto& manager = this->GetManager(address);
+ const size_t cur_pages = std::min(num_pages, manager.GetPageOffsetToEnd(address));
+
+ {
+ KScopedLightLock lk(m_pool_locks[static_cast<size_t>(manager.GetPool())]);
+ manager.Open(address, cur_pages);
+ }
+
+ num_pages -= cur_pages;
+ address += cur_pages * PageSize;
+ }
+ }
+
+ void OpenFirst(PAddr address, size_t num_pages) {
+ // Repeatedly open references until we've done so for all pages.
+ while (num_pages) {
+ auto& manager = this->GetManager(address);
+ const size_t cur_pages = std::min(num_pages, manager.GetPageOffsetToEnd(address));
+
+ {
+ KScopedLightLock lk(m_pool_locks[static_cast<size_t>(manager.GetPool())]);
+ manager.OpenFirst(address, cur_pages);
+ }
+
+ num_pages -= cur_pages;
+ address += cur_pages * PageSize;
+ }
+ }
+
+ void Close(PAddr address, size_t num_pages) {
+ // Repeatedly close references until we've done so for all pages.
+ while (num_pages) {
+ auto& manager = this->GetManager(address);
+ const size_t cur_pages = std::min(num_pages, manager.GetPageOffsetToEnd(address));
+
+ {
+ KScopedLightLock lk(m_pool_locks[static_cast<size_t>(manager.GetPool())]);
+ manager.Close(address, cur_pages);
+ }
+
+ num_pages -= cur_pages;
+ address += cur_pages * PageSize;
+ }
+ }
+
+ size_t GetSize() {
+ size_t total = 0;
+ for (size_t i = 0; i < m_num_managers; i++) {
+ total += m_managers[i].GetSize();
+ }
+ return total;
+ }
+
+ size_t GetSize(Pool pool) {
constexpr Direction GetSizeDirection = Direction::FromFront;
size_t total = 0;
for (auto* manager = this->GetFirstManager(pool, GetSizeDirection); manager != nullptr;
@@ -64,18 +130,36 @@ public:
return total;
}
- PAddr AllocateAndOpenContinuous(size_t num_pages, size_t align_pages, u32 option);
- Result AllocateAndOpen(KPageGroup* out, size_t num_pages, u32 option);
- Result AllocateAndOpenForProcess(KPageGroup* out, size_t num_pages, u32 option, u64 process_id,
- u8 fill_pattern);
+ size_t GetFreeSize() {
+ size_t total = 0;
+ for (size_t i = 0; i < m_num_managers; i++) {
+ KScopedLightLock lk(m_pool_locks[static_cast<size_t>(m_managers[i].GetPool())]);
+ total += m_managers[i].GetFreeSize();
+ }
+ return total;
+ }
- static constexpr size_t MaxManagerCount = 10;
+ size_t GetFreeSize(Pool pool) {
+ KScopedLightLock lk(m_pool_locks[static_cast<size_t>(pool)]);
+
+ constexpr Direction GetSizeDirection = Direction::FromFront;
+ size_t total = 0;
+ for (auto* manager = this->GetFirstManager(pool, GetSizeDirection); manager != nullptr;
+ manager = this->GetNextManager(manager, GetSizeDirection)) {
+ total += manager->GetFreeSize();
+ }
+ return total;
+ }
- void Close(PAddr address, size_t num_pages);
- void Close(const KPageGroup& pg);
+ void DumpFreeList(Pool pool) {
+ KScopedLightLock lk(m_pool_locks[static_cast<size_t>(pool)]);
- void Open(PAddr address, size_t num_pages);
- void Open(const KPageGroup& pg);
+ constexpr Direction DumpDirection = Direction::FromFront;
+ for (auto* manager = this->GetFirstManager(pool, DumpDirection); manager != nullptr;
+ manager = this->GetNextManager(manager, DumpDirection)) {
+ manager->DumpFreeList();
+ }
+ }
public:
static size_t CalculateManagementOverheadSize(size_t region_size) {
@@ -88,14 +172,13 @@ public:
}
static constexpr Pool GetPool(u32 option) {
- return static_cast<Pool>((static_cast<u32>(option) & static_cast<u32>(Pool::Mask)) >>
+ return static_cast<Pool>((option & static_cast<u32>(Pool::Mask)) >>
static_cast<u32>(Pool::Shift));
}
static constexpr Direction GetDirection(u32 option) {
- return static_cast<Direction>(
- (static_cast<u32>(option) & static_cast<u32>(Direction::Mask)) >>
- static_cast<u32>(Direction::Shift));
+ return static_cast<Direction>((option & static_cast<u32>(Direction::Mask)) >>
+ static_cast<u32>(Direction::Shift));
}
static constexpr std::tuple<Pool, Direction> DecodeOption(u32 option) {
@@ -103,74 +186,88 @@ public:
}
private:
- class Impl final {
+ class Impl {
public:
- YUZU_NON_COPYABLE(Impl);
- YUZU_NON_MOVEABLE(Impl);
+ static size_t CalculateManagementOverheadSize(size_t region_size);
+
+ static constexpr size_t CalculateOptimizedProcessOverheadSize(size_t region_size) {
+ return (Common::AlignUp((region_size / PageSize), Common::BitSize<u64>()) /
+ Common::BitSize<u64>()) *
+ sizeof(u64);
+ }
+ public:
Impl() = default;
- ~Impl() = default;
size_t Initialize(PAddr address, size_t size, VAddr management, VAddr management_end,
Pool p);
- VAddr AllocateBlock(s32 index, bool random) {
- return heap.AllocateBlock(index, random);
+ PAddr AllocateBlock(s32 index, bool random) {
+ return m_heap.AllocateBlock(index, random);
}
-
- void Free(VAddr addr, size_t num_pages) {
- heap.Free(addr, num_pages);
+ PAddr AllocateAligned(s32 index, size_t num_pages, size_t align_pages) {
+ return m_heap.AllocateAligned(index, num_pages, align_pages);
+ }
+ void Free(PAddr addr, size_t num_pages) {
+ m_heap.Free(addr, num_pages);
}
void SetInitialUsedHeapSize(size_t reserved_size) {
- heap.SetInitialUsedSize(reserved_size);
+ m_heap.SetInitialUsedSize(reserved_size);
}
- constexpr Pool GetPool() const {
- return pool;
+ void InitializeOptimizedMemory() {
+ UNIMPLEMENTED();
}
+ void TrackUnoptimizedAllocation(PAddr block, size_t num_pages);
+ void TrackOptimizedAllocation(PAddr block, size_t num_pages);
+
+ bool ProcessOptimizedAllocation(PAddr block, size_t num_pages, u8 fill_pattern);
+
+ constexpr Pool GetPool() const {
+ return m_pool;
+ }
constexpr size_t GetSize() const {
- return heap.GetSize();
+ return m_heap.GetSize();
+ }
+ constexpr PAddr GetEndAddress() const {
+ return m_heap.GetEndAddress();
}
- constexpr VAddr GetAddress() const {
- return heap.GetAddress();
+ size_t GetFreeSize() const {
+ return m_heap.GetFreeSize();
}
- constexpr VAddr GetEndAddress() const {
- return heap.GetEndAddress();
+ void DumpFreeList() const {
+ UNIMPLEMENTED();
}
constexpr size_t GetPageOffset(PAddr address) const {
- return heap.GetPageOffset(address);
+ return m_heap.GetPageOffset(address);
}
-
constexpr size_t GetPageOffsetToEnd(PAddr address) const {
- return heap.GetPageOffsetToEnd(address);
+ return m_heap.GetPageOffsetToEnd(address);
}
constexpr void SetNext(Impl* n) {
- next = n;
+ m_next = n;
}
-
constexpr void SetPrev(Impl* n) {
- prev = n;
+ m_prev = n;
}
-
constexpr Impl* GetNext() const {
- return next;
+ return m_next;
}
-
constexpr Impl* GetPrev() const {
- return prev;
+ return m_prev;
}
void OpenFirst(PAddr address, size_t num_pages) {
size_t index = this->GetPageOffset(address);
const size_t end = index + num_pages;
while (index < end) {
- const RefCount ref_count = (++page_reference_counts[index]);
+ const RefCount ref_count = (++m_page_reference_counts[index]);
ASSERT(ref_count == 1);
index++;
@@ -181,7 +278,7 @@ private:
size_t index = this->GetPageOffset(address);
const size_t end = index + num_pages;
while (index < end) {
- const RefCount ref_count = (++page_reference_counts[index]);
+ const RefCount ref_count = (++m_page_reference_counts[index]);
ASSERT(ref_count > 1);
index++;
@@ -195,8 +292,8 @@ private:
size_t free_start = 0;
size_t free_count = 0;
while (index < end) {
- ASSERT(page_reference_counts[index] > 0);
- const RefCount ref_count = (--page_reference_counts[index]);
+ ASSERT(m_page_reference_counts[index] > 0);
+ const RefCount ref_count = (--m_page_reference_counts[index]);
// Keep track of how many zero refcounts we see in a row, to minimize calls to free.
if (ref_count == 0) {
@@ -208,7 +305,7 @@ private:
}
} else {
if (free_count > 0) {
- this->Free(heap.GetAddress() + free_start * PageSize, free_count);
+ this->Free(m_heap.GetAddress() + free_start * PageSize, free_count);
free_count = 0;
}
}
@@ -217,44 +314,36 @@ private:
}
if (free_count > 0) {
- this->Free(heap.GetAddress() + free_start * PageSize, free_count);
+ this->Free(m_heap.GetAddress() + free_start * PageSize, free_count);
}
}
- static size_t CalculateManagementOverheadSize(size_t region_size);
-
- static constexpr size_t CalculateOptimizedProcessOverheadSize(size_t region_size) {
- return (Common::AlignUp((region_size / PageSize), Common::BitSize<u64>()) /
- Common::BitSize<u64>()) *
- sizeof(u64);
- }
-
private:
using RefCount = u16;
- KPageHeap heap;
- std::vector<RefCount> page_reference_counts;
- VAddr management_region{};
- Pool pool{};
- Impl* next{};
- Impl* prev{};
+ KPageHeap m_heap;
+ std::vector<RefCount> m_page_reference_counts;
+ VAddr m_management_region{};
+ Pool m_pool{};
+ Impl* m_next{};
+ Impl* m_prev{};
};
private:
- Impl& GetManager(const KMemoryLayout& memory_layout, PAddr address) {
- return managers[memory_layout.GetPhysicalLinearRegion(address).GetAttributes()];
+ Impl& GetManager(PAddr address) {
+ return m_managers[m_memory_layout.GetPhysicalLinearRegion(address).GetAttributes()];
}
- const Impl& GetManager(const KMemoryLayout& memory_layout, PAddr address) const {
- return managers[memory_layout.GetPhysicalLinearRegion(address).GetAttributes()];
+ const Impl& GetManager(PAddr address) const {
+ return m_managers[m_memory_layout.GetPhysicalLinearRegion(address).GetAttributes()];
}
- constexpr Impl* GetFirstManager(Pool pool, Direction dir) const {
- return dir == Direction::FromBack ? pool_managers_tail[static_cast<size_t>(pool)]
- : pool_managers_head[static_cast<size_t>(pool)];
+ constexpr Impl* GetFirstManager(Pool pool, Direction dir) {
+ return dir == Direction::FromBack ? m_pool_managers_tail[static_cast<size_t>(pool)]
+ : m_pool_managers_head[static_cast<size_t>(pool)];
}
- constexpr Impl* GetNextManager(Impl* cur, Direction dir) const {
+ constexpr Impl* GetNextManager(Impl* cur, Direction dir) {
if (dir == Direction::FromBack) {
return cur->GetPrev();
} else {
@@ -263,15 +352,21 @@ private:
}
Result AllocatePageGroupImpl(KPageGroup* out, size_t num_pages, Pool pool, Direction dir,
- bool random);
+ bool unoptimized, bool random);
private:
- Core::System& system;
- std::array<KLightLock, static_cast<size_t>(Pool::Count)> pool_locks;
- std::array<Impl*, MaxManagerCount> pool_managers_head{};
- std::array<Impl*, MaxManagerCount> pool_managers_tail{};
- std::array<Impl, MaxManagerCount> managers;
- size_t num_managers{};
+ template <typename T>
+ using PoolArray = std::array<T, static_cast<size_t>(Pool::Count)>;
+
+ Core::System& m_system;
+ const KMemoryLayout& m_memory_layout;
+ PoolArray<KLightLock> m_pool_locks;
+ std::array<Impl*, MaxManagerCount> m_pool_managers_head{};
+ std::array<Impl*, MaxManagerCount> m_pool_managers_tail{};
+ std::array<Impl, MaxManagerCount> m_managers;
+ size_t m_num_managers{};
+ PoolArray<u64> m_optimized_process_ids{};
+ PoolArray<bool> m_has_optimized_process{};
};
} // namespace Kernel