Merge pull request #4936 from lioncash/page

page_table: Allow page tables to be moved
This commit is contained in:
bunnei 2020-11-18 20:40:10 -08:00 committed by GitHub
commit 92344da20c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 37 additions and 12 deletions

View file

@ -8,7 +8,7 @@ namespace Common {
PageTable::PageTable() = default; PageTable::PageTable() = default;
PageTable::~PageTable() = default; PageTable::~PageTable() noexcept = default;
void PageTable::Resize(std::size_t address_space_width_in_bits, std::size_t page_size_in_bits, void PageTable::Resize(std::size_t address_space_width_in_bits, std::size_t page_size_in_bits,
bool has_attribute) { bool has_attribute) {

View file

@ -4,9 +4,7 @@
#pragma once #pragma once
#include <vector> #include <tuple>
#include <boost/icl/interval_map.hpp>
#include "common/common_types.h" #include "common/common_types.h"
#include "common/memory_hook.h" #include "common/memory_hook.h"
@ -51,13 +49,21 @@ struct SpecialRegion {
*/ */
struct PageTable { struct PageTable {
PageTable(); PageTable();
~PageTable(); ~PageTable() noexcept;
PageTable(const PageTable&) = delete;
PageTable& operator=(const PageTable&) = delete;
PageTable(PageTable&&) noexcept = default;
PageTable& operator=(PageTable&&) noexcept = default;
/** /**
* Resizes the page table to be able to accomodate enough pages within * Resizes the page table to be able to accomodate enough pages within
* a given address space. * a given address space.
* *
* @param address_space_width_in_bits The address size width in bits. * @param address_space_width_in_bits The address size width in bits.
* @param page_size_in_bits The page size in bits.
* @param has_attribute Whether or not this page has any backing attributes.
*/ */
void Resize(std::size_t address_space_width_in_bits, std::size_t page_size_in_bits, void Resize(std::size_t address_space_width_in_bits, std::size_t page_size_in_bits,
bool has_attribute); bool has_attribute);

View file

@ -13,7 +13,7 @@
namespace Common { namespace Common {
void* AllocateMemoryPages(std::size_t size) { void* AllocateMemoryPages(std::size_t size) noexcept {
#ifdef _WIN32 #ifdef _WIN32
void* base{VirtualAlloc(nullptr, size, MEM_COMMIT, PAGE_READWRITE)}; void* base{VirtualAlloc(nullptr, size, MEM_COMMIT, PAGE_READWRITE)};
#else #else
@ -29,7 +29,7 @@ void* AllocateMemoryPages(std::size_t size) {
return base; return base;
} }
void FreeMemoryPages(void* base, [[maybe_unused]] std::size_t size) { void FreeMemoryPages(void* base, [[maybe_unused]] std::size_t size) noexcept {
if (!base) { if (!base) {
return; return;
} }

View file

@ -4,25 +4,44 @@
#pragma once #pragma once
#include "common/common_funcs.h" #include <type_traits>
#include <utility>
namespace Common { namespace Common {
void* AllocateMemoryPages(std::size_t size); void* AllocateMemoryPages(std::size_t size) noexcept;
void FreeMemoryPages(void* base, std::size_t size); void FreeMemoryPages(void* base, std::size_t size) noexcept;
template <typename T> template <typename T>
class VirtualBuffer final : NonCopyable { class VirtualBuffer final {
public: public:
static_assert(
std::is_trivially_constructible_v<T>,
"T must be trivially constructible, as non-trivial constructors will not be executed "
"with the current allocator");
constexpr VirtualBuffer() = default; constexpr VirtualBuffer() = default;
explicit VirtualBuffer(std::size_t count) : alloc_size{count * sizeof(T)} { explicit VirtualBuffer(std::size_t count) : alloc_size{count * sizeof(T)} {
base_ptr = reinterpret_cast<T*>(AllocateMemoryPages(alloc_size)); base_ptr = reinterpret_cast<T*>(AllocateMemoryPages(alloc_size));
} }
~VirtualBuffer() { ~VirtualBuffer() noexcept {
FreeMemoryPages(base_ptr, alloc_size); FreeMemoryPages(base_ptr, alloc_size);
} }
VirtualBuffer(const VirtualBuffer&) = delete;
VirtualBuffer& operator=(const VirtualBuffer&) = delete;
VirtualBuffer(VirtualBuffer&& other) noexcept
: alloc_size{std::exchange(other.alloc_size, 0)}, base_ptr{std::exchange(other.base_ptr),
nullptr} {}
VirtualBuffer& operator=(VirtualBuffer&& other) noexcept {
alloc_size = std::exchange(other.alloc_size, 0);
base_ptr = std::exchange(other.base_ptr, nullptr);
return *this;
}
void resize(std::size_t count) { void resize(std::size_t count) {
FreeMemoryPages(base_ptr, alloc_size); FreeMemoryPages(base_ptr, alloc_size);