summaryrefslogtreecommitdiffstats
path: root/src/core/hle/kernel/k_page_group.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel/k_page_group.h')
-rw-r--r--src/core/hle/kernel/k_page_group.h163
1 files changed, 92 insertions, 71 deletions
diff --git a/src/core/hle/kernel/k_page_group.h b/src/core/hle/kernel/k_page_group.h
index 316f172f2..c07f17663 100644
--- a/src/core/hle/kernel/k_page_group.h
+++ b/src/core/hle/kernel/k_page_group.h
@@ -1,4 +1,4 @@
-// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
+// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
@@ -13,24 +13,23 @@
namespace Kernel {
+class KBlockInfoManager;
+class KernelCore;
class KPageGroup;
class KBlockInfo {
-private:
- friend class KPageGroup;
-
public:
- constexpr KBlockInfo() = default;
+ constexpr explicit KBlockInfo() : m_next(nullptr) {}
- constexpr void Initialize(PAddr addr, size_t np) {
+ constexpr void Initialize(KPhysicalAddress addr, size_t np) {
ASSERT(Common::IsAligned(addr, PageSize));
ASSERT(static_cast<u32>(np) == np);
- m_page_index = static_cast<u32>(addr) / PageSize;
+ m_page_index = static_cast<u32>(addr / PageSize);
m_num_pages = static_cast<u32>(np);
}
- constexpr PAddr GetAddress() const {
+ constexpr KPhysicalAddress GetAddress() const {
return m_page_index * PageSize;
}
constexpr size_t GetNumPages() const {
@@ -39,10 +38,10 @@ public:
constexpr size_t GetSize() const {
return this->GetNumPages() * PageSize;
}
- constexpr PAddr GetEndAddress() const {
+ constexpr KPhysicalAddress GetEndAddress() const {
return (m_page_index + m_num_pages) * PageSize;
}
- constexpr PAddr GetLastAddress() const {
+ constexpr KPhysicalAddress GetLastAddress() const {
return this->GetEndAddress() - 1;
}
@@ -62,8 +61,8 @@ public:
return !(*this == rhs);
}
- constexpr bool IsStrictlyBefore(PAddr addr) const {
- const PAddr end = this->GetEndAddress();
+ constexpr bool IsStrictlyBefore(KPhysicalAddress addr) const {
+ const KPhysicalAddress end = this->GetEndAddress();
if (m_page_index != 0 && end == 0) {
return false;
@@ -72,11 +71,11 @@ public:
return end < addr;
}
- constexpr bool operator<(PAddr addr) const {
+ constexpr bool operator<(KPhysicalAddress addr) const {
return this->IsStrictlyBefore(addr);
}
- constexpr bool TryConcatenate(PAddr addr, size_t np) {
+ constexpr bool TryConcatenate(KPhysicalAddress addr, size_t np) {
if (addr != 0 && addr == this->GetEndAddress()) {
m_num_pages += static_cast<u32>(np);
return true;
@@ -90,96 +89,118 @@ private:
}
private:
+ friend class KPageGroup;
+
KBlockInfo* m_next{};
u32 m_page_index{};
u32 m_num_pages{};
};
static_assert(sizeof(KBlockInfo) <= 0x10);
-class KPageGroup final {
+class KPageGroup {
public:
- class Node final {
+ class Iterator {
public:
- constexpr Node(u64 addr_, std::size_t num_pages_) : addr{addr_}, num_pages{num_pages_} {}
+ using iterator_category = std::forward_iterator_tag;
+ using value_type = const KBlockInfo;
+ using difference_type = std::ptrdiff_t;
+ using pointer = value_type*;
+ using reference = value_type&;
+
+ constexpr explicit Iterator(pointer n) : m_node(n) {}
+
+ constexpr bool operator==(const Iterator& rhs) const {
+ return m_node == rhs.m_node;
+ }
+ constexpr bool operator!=(const Iterator& rhs) const {
+ return !(*this == rhs);
+ }
- constexpr u64 GetAddress() const {
- return addr;
+ constexpr pointer operator->() const {
+ return m_node;
+ }
+ constexpr reference operator*() const {
+ return *m_node;
}
- constexpr std::size_t GetNumPages() const {
- return num_pages;
+ constexpr Iterator& operator++() {
+ m_node = m_node->GetNext();
+ return *this;
}
- constexpr std::size_t GetSize() const {
- return GetNumPages() * PageSize;
+ constexpr Iterator operator++(int) {
+ const Iterator it{*this};
+ ++(*this);
+ return it;
}
private:
- u64 addr{};
- std::size_t num_pages{};
+ pointer m_node{};
};
-public:
- KPageGroup() = default;
- KPageGroup(u64 address, u64 num_pages) {
- ASSERT(AddBlock(address, num_pages).IsSuccess());
+ explicit KPageGroup(KernelCore& kernel, KBlockInfoManager* m)
+ : m_kernel{kernel}, m_manager{m} {}
+ ~KPageGroup() {
+ this->Finalize();
}
- constexpr std::list<Node>& Nodes() {
- return nodes;
- }
+ void CloseAndReset();
+ void Finalize();
- constexpr const std::list<Node>& Nodes() const {
- return nodes;
+ Iterator begin() const {
+ return Iterator{m_first_block};
+ }
+ Iterator end() const {
+ return Iterator{nullptr};
+ }
+ bool empty() const {
+ return m_first_block == nullptr;
}
- std::size_t GetNumPages() const {
- std::size_t num_pages = 0;
- for (const Node& node : nodes) {
- num_pages += node.GetNumPages();
- }
- return num_pages;
- }
-
- bool IsEqual(KPageGroup& other) const {
- auto this_node = nodes.begin();
- auto other_node = other.nodes.begin();
- while (this_node != nodes.end() && other_node != other.nodes.end()) {
- if (this_node->GetAddress() != other_node->GetAddress() ||
- this_node->GetNumPages() != other_node->GetNumPages()) {
- return false;
- }
- this_node = std::next(this_node);
- other_node = std::next(other_node);
- }
+ Result AddBlock(KPhysicalAddress addr, size_t num_pages);
+ void Open() const;
+ void OpenFirst() const;
+ void Close() const;
+
+ size_t GetNumPages() const;
+
+ bool IsEquivalentTo(const KPageGroup& rhs) const;
+
+ bool operator==(const KPageGroup& rhs) const {
+ return this->IsEquivalentTo(rhs);
+ }
- return this_node == nodes.end() && other_node == other.nodes.end();
+ bool operator!=(const KPageGroup& rhs) const {
+ return !(*this == rhs);
}
- Result AddBlock(u64 address, u64 num_pages) {
- if (!num_pages) {
- return ResultSuccess;
+private:
+ KernelCore& m_kernel;
+ KBlockInfo* m_first_block{};
+ KBlockInfo* m_last_block{};
+ KBlockInfoManager* m_manager{};
+};
+
+class KScopedPageGroup {
+public:
+ explicit KScopedPageGroup(const KPageGroup* gp) : m_pg(gp) {
+ if (m_pg) {
+ m_pg->Open();
}
- if (!nodes.empty()) {
- const auto node = nodes.back();
- if (node.GetAddress() + node.GetNumPages() * PageSize == address) {
- address = node.GetAddress();
- num_pages += node.GetNumPages();
- nodes.pop_back();
- }
+ }
+ explicit KScopedPageGroup(const KPageGroup& gp) : KScopedPageGroup(std::addressof(gp)) {}
+ ~KScopedPageGroup() {
+ if (m_pg) {
+ m_pg->Close();
}
- nodes.push_back({address, num_pages});
- return ResultSuccess;
}
- bool Empty() const {
- return nodes.empty();
+ void CancelClose() {
+ m_pg = nullptr;
}
- void Finalize() {}
-
private:
- std::list<Node> nodes;
+ const KPageGroup* m_pg{};
};
} // namespace Kernel