k_page_group.cpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "core/hle/kernel/k_dynamic_resource_manager.h"
  4. #include "core/hle/kernel/k_memory_manager.h"
  5. #include "core/hle/kernel/k_page_group.h"
  6. #include "core/hle/kernel/kernel.h"
  7. #include "core/hle/kernel/svc_results.h"
  8. namespace Kernel {
  9. void KPageGroup::Finalize() {
  10. KBlockInfo* cur = m_first_block;
  11. while (cur != nullptr) {
  12. KBlockInfo* next = cur->GetNext();
  13. m_manager->Free(cur);
  14. cur = next;
  15. }
  16. m_first_block = nullptr;
  17. m_last_block = nullptr;
  18. }
  19. void KPageGroup::CloseAndReset() {
  20. auto& mm = m_kernel.MemoryManager();
  21. KBlockInfo* cur = m_first_block;
  22. while (cur != nullptr) {
  23. KBlockInfo* next = cur->GetNext();
  24. mm.Close(cur->GetAddress(), cur->GetNumPages());
  25. m_manager->Free(cur);
  26. cur = next;
  27. }
  28. m_first_block = nullptr;
  29. m_last_block = nullptr;
  30. }
  31. size_t KPageGroup::GetNumPages() const {
  32. size_t num_pages = 0;
  33. for (const auto& it : *this) {
  34. num_pages += it.GetNumPages();
  35. }
  36. return num_pages;
  37. }
  38. Result KPageGroup::AddBlock(KPhysicalAddress addr, size_t num_pages) {
  39. // Succeed immediately if we're adding no pages.
  40. R_SUCCEED_IF(num_pages == 0);
  41. // Check for overflow.
  42. ASSERT(addr < addr + num_pages * PageSize);
  43. // Try to just append to the last block.
  44. if (m_last_block != nullptr) {
  45. R_SUCCEED_IF(m_last_block->TryConcatenate(addr, num_pages));
  46. }
  47. // Allocate a new block.
  48. KBlockInfo* new_block = m_manager->Allocate();
  49. R_UNLESS(new_block != nullptr, ResultOutOfResource);
  50. // Initialize the block.
  51. new_block->Initialize(addr, num_pages);
  52. // Add the block to our list.
  53. if (m_last_block != nullptr) {
  54. m_last_block->SetNext(new_block);
  55. } else {
  56. m_first_block = new_block;
  57. }
  58. m_last_block = new_block;
  59. R_SUCCEED();
  60. }
  61. void KPageGroup::Open() const {
  62. auto& mm = m_kernel.MemoryManager();
  63. for (const auto& it : *this) {
  64. mm.Open(it.GetAddress(), it.GetNumPages());
  65. }
  66. }
  67. void KPageGroup::OpenFirst() const {
  68. auto& mm = m_kernel.MemoryManager();
  69. for (const auto& it : *this) {
  70. mm.OpenFirst(it.GetAddress(), it.GetNumPages());
  71. }
  72. }
  73. void KPageGroup::Close() const {
  74. auto& mm = m_kernel.MemoryManager();
  75. for (const auto& it : *this) {
  76. mm.Close(it.GetAddress(), it.GetNumPages());
  77. }
  78. }
  79. bool KPageGroup::IsEquivalentTo(const KPageGroup& rhs) const {
  80. auto lit = this->begin();
  81. auto rit = rhs.begin();
  82. auto lend = this->end();
  83. auto rend = rhs.end();
  84. while (lit != lend && rit != rend) {
  85. if (*lit != *rit) {
  86. return false;
  87. }
  88. ++lit;
  89. ++rit;
  90. }
  91. return lit == lend && rit == rend;
  92. }
  93. } // namespace Kernel