heap_tracker.h 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #pragma once
  4. #include <atomic>
  5. #include <mutex>
  6. #include <set>
  7. #include <shared_mutex>
  8. #include "common/host_memory.h"
  9. #include "common/intrusive_red_black_tree.h"
  10. namespace Common {
  11. struct SeparateHeapMap {
  12. Common::IntrusiveRedBlackTreeNode addr_node{};
  13. Common::IntrusiveRedBlackTreeNode tick_node{};
  14. VAddr vaddr{};
  15. PAddr paddr{};
  16. size_t size{};
  17. size_t tick{};
  18. MemoryPermission perm{};
  19. bool is_resident{};
  20. };
  21. struct SeparateHeapMapAddrComparator {
  22. static constexpr int Compare(const SeparateHeapMap& lhs, const SeparateHeapMap& rhs) {
  23. if (lhs.vaddr < rhs.vaddr) {
  24. return -1;
  25. } else if (lhs.vaddr <= (rhs.vaddr + rhs.size - 1)) {
  26. return 0;
  27. } else {
  28. return 1;
  29. }
  30. }
  31. };
  32. struct SeparateHeapMapTickComparator {
  33. static constexpr int Compare(const SeparateHeapMap& lhs, const SeparateHeapMap& rhs) {
  34. if (lhs.tick < rhs.tick) {
  35. return -1;
  36. } else if (lhs.tick > rhs.tick) {
  37. return 1;
  38. } else {
  39. return SeparateHeapMapAddrComparator::Compare(lhs, rhs);
  40. }
  41. }
  42. };
  43. class HeapTracker {
  44. public:
  45. explicit HeapTracker(Common::HostMemory& buffer);
  46. ~HeapTracker();
  47. void Map(size_t virtual_offset, size_t host_offset, size_t length, MemoryPermission perm,
  48. bool is_separate_heap);
  49. void Unmap(size_t virtual_offset, size_t size, bool is_separate_heap);
  50. void Protect(size_t virtual_offset, size_t length, MemoryPermission perm);
  51. u8* VirtualBasePointer() {
  52. return m_buffer.VirtualBasePointer();
  53. }
  54. bool DeferredMapSeparateHeap(u8* fault_address);
  55. bool DeferredMapSeparateHeap(size_t virtual_offset);
  56. private:
  57. using AddrTreeTraits =
  58. Common::IntrusiveRedBlackTreeMemberTraitsDeferredAssert<&SeparateHeapMap::addr_node>;
  59. using AddrTree = AddrTreeTraits::TreeType<SeparateHeapMapAddrComparator>;
  60. using TickTreeTraits =
  61. Common::IntrusiveRedBlackTreeMemberTraitsDeferredAssert<&SeparateHeapMap::tick_node>;
  62. using TickTree = TickTreeTraits::TreeType<SeparateHeapMapTickComparator>;
  63. AddrTree m_mappings{};
  64. TickTree m_resident_mappings{};
  65. private:
  66. void SplitHeapMap(VAddr offset, size_t size);
  67. void SplitHeapMapLocked(VAddr offset);
  68. AddrTree::iterator GetNearestHeapMapLocked(VAddr offset);
  69. void RebuildSeparateHeapAddressSpace();
  70. private:
  71. Common::HostMemory& m_buffer;
  72. const s64 m_max_resident_map_count;
  73. std::shared_mutex m_rebuild_lock{};
  74. std::mutex m_lock{};
  75. s64 m_map_count{};
  76. s64 m_resident_map_count{};
  77. size_t m_tick{};
  78. };
  79. } // namespace Common