free_region_manager.h 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #pragma once
  4. #include <mutex>
  5. #include <boost/icl/interval_set.hpp>
  6. namespace Common {
  7. class FreeRegionManager {
  8. public:
  9. explicit FreeRegionManager() = default;
  10. ~FreeRegionManager() = default;
  11. void SetAddressSpace(void* start, size_t size) {
  12. this->FreeBlock(start, size);
  13. }
  14. std::pair<void*, size_t> FreeBlock(void* block_ptr, size_t size) {
  15. std::scoped_lock lk(m_mutex);
  16. // Check to see if we are adjacent to any regions.
  17. auto start_address = reinterpret_cast<uintptr_t>(block_ptr);
  18. auto end_address = start_address + size;
  19. auto it = m_free_regions.find({start_address - 1, end_address + 1});
  20. // If we are, join with them, ensuring we stay in bounds.
  21. if (it != m_free_regions.end()) {
  22. start_address = std::min(start_address, it->lower());
  23. end_address = std::max(end_address, it->upper());
  24. }
  25. // Free the relevant region.
  26. m_free_regions.insert({start_address, end_address});
  27. // Return the adjusted pointers.
  28. block_ptr = reinterpret_cast<void*>(start_address);
  29. size = end_address - start_address;
  30. return {block_ptr, size};
  31. }
  32. void AllocateBlock(void* block_ptr, size_t size) {
  33. std::scoped_lock lk(m_mutex);
  34. auto address = reinterpret_cast<uintptr_t>(block_ptr);
  35. m_free_regions.subtract({address, address + size});
  36. }
  37. private:
  38. std::mutex m_mutex;
  39. boost::icl::interval_set<uintptr_t> m_free_regions;
  40. };
  41. } // namespace Common