diff options
-rw-r--r-- | src/common/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/common/free_region_manager.h | 55 |
2 files changed, 56 insertions, 0 deletions
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 <mutex> +#include <boost/icl/interval_set.hpp> + +namespace Common { + +class FreeRegionManager { +public: + explicit FreeRegionManager() = default; + ~FreeRegionManager() = default; + + void SetAddressSpace(void* start, size_t size) { + this->FreeBlock(start, size); + } + + std::pair<void*, size_t> 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<uintptr_t>(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<void*>(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<uintptr_t>(block_ptr); + m_free_regions.subtract({address, address + size}); + } + +private: + std::mutex m_mutex; + boost::icl::interval_set<uintptr_t> m_free_regions; +}; + +} // namespace Common |