From 29e7d79a869090a39127442cb9553bf46a8cd009 Mon Sep 17 00:00:00 2001 From: --author=Liam Date: Fri, 17 Nov 2023 20:25:23 +0200 Subject: [PATCH] common: Add free region manager * Abstraction for placeholder region tracking in host_memory --- src/common/CMakeLists.txt | 1 + src/common/free_region_manager.h | 55 ++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 src/common/free_region_manager.h diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 7107f4f78..98fd5f1e4 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -52,6 +52,7 @@ add_library(common STATIC fiber.cpp fiber.h fixed_point.h + free_region_manager.h fs/file.cpp fs/file.h fs/fs.cpp diff --git a/src/common/free_region_manager.h b/src/common/free_region_manager.h new file mode 100644 index 000000000..2e590d609 --- /dev/null +++ b/src/common/free_region_manager.h @@ -0,0 +1,55 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include + +namespace Common { + +class FreeRegionManager { +public: + explicit FreeRegionManager() = default; + ~FreeRegionManager() = default; + + void SetAddressSpace(void* start, size_t size) { + this->FreeBlock(start, size); + } + + std::pair FreeBlock(void* block_ptr, size_t size) { + std::scoped_lock lk(m_mutex); + + // Check to see if we are adjacent to any regions. + auto start_address = reinterpret_cast(block_ptr); + auto end_address = start_address + size; + auto it = m_free_regions.find({start_address - 1, end_address + 1}); + + // If we are, join with them, ensuring we stay in bounds. + if (it != m_free_regions.end()) { + start_address = std::min(start_address, it->lower()); + end_address = std::max(end_address, it->upper()); + } + + // Free the relevant region. + m_free_regions.insert({start_address, end_address}); + + // Return the adjusted pointers. + block_ptr = reinterpret_cast(start_address); + size = end_address - start_address; + return {block_ptr, size}; + } + + void AllocateBlock(void* block_ptr, size_t size) { + std::scoped_lock lk(m_mutex); + + auto address = reinterpret_cast(block_ptr); + m_free_regions.subtract({address, address + size}); + } + +private: + std::mutex m_mutex; + boost::icl::interval_set m_free_regions; +}; + +} // namespace Common