diff options
author | liamwhite <liamwhite@users.noreply.github.com> | 2023-11-30 15:20:55 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-30 15:20:55 +0100 |
commit | 57a391e71db13ade7a3d96f59d53781eff18d2ac (patch) | |
tree | 0b4223de40a2d77598ac9095b1374353c2e9da7c /src/common/free_region_manager.h | |
parent | Merge pull request #12223 from liamwhite/fruit-company (diff) | |
parent | core: Rename patcher file (diff) | |
download | yuzu-57a391e71db13ade7a3d96f59d53781eff18d2ac.tar yuzu-57a391e71db13ade7a3d96f59d53781eff18d2ac.tar.gz yuzu-57a391e71db13ade7a3d96f59d53781eff18d2ac.tar.bz2 yuzu-57a391e71db13ade7a3d96f59d53781eff18d2ac.tar.lz yuzu-57a391e71db13ade7a3d96f59d53781eff18d2ac.tar.xz yuzu-57a391e71db13ade7a3d96f59d53781eff18d2ac.tar.zst yuzu-57a391e71db13ade7a3d96f59d53781eff18d2ac.zip |
Diffstat (limited to 'src/common/free_region_manager.h')
-rw-r--r-- | src/common/free_region_manager.h | 55 |
1 files changed, 55 insertions, 0 deletions
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 |