VMObject.h 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /*
  2. * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/FixedArray.h>
  8. #include <AK/IntrusiveList.h>
  9. #include <AK/RefPtr.h>
  10. #include <AK/Weakable.h>
  11. #include <Kernel/Forward.h>
  12. #include <Kernel/Library/ListedRefCounted.h>
  13. #include <Kernel/Locking/Mutex.h>
  14. #include <Kernel/Memory/Region.h>
  15. namespace Kernel::Memory {
  16. class VMObject
  17. : public ListedRefCounted<VMObject, LockType::Spinlock>
  18. , public Weakable<VMObject> {
  19. friend class MemoryManager;
  20. friend class Region;
  21. public:
  22. virtual ~VMObject();
  23. virtual ErrorOr<NonnullRefPtr<VMObject>> try_clone() = 0;
  24. virtual bool is_anonymous() const { return false; }
  25. virtual bool is_inode() const { return false; }
  26. virtual bool is_shared_inode() const { return false; }
  27. virtual bool is_private_inode() const { return false; }
  28. size_t page_count() const { return m_physical_pages.size(); }
  29. virtual Span<RefPtr<PhysicalPage> const> physical_pages() const { return m_physical_pages.span(); }
  30. virtual Span<RefPtr<PhysicalPage>> physical_pages() { return m_physical_pages.span(); }
  31. size_t size() const { return m_physical_pages.size() * PAGE_SIZE; }
  32. virtual StringView class_name() const = 0;
  33. ALWAYS_INLINE void add_region(Region& region)
  34. {
  35. SpinlockLocker locker(m_lock);
  36. m_regions.append(region);
  37. }
  38. ALWAYS_INLINE void remove_region(Region& region)
  39. {
  40. SpinlockLocker locker(m_lock);
  41. m_regions.remove(region);
  42. }
  43. protected:
  44. static ErrorOr<FixedArray<RefPtr<PhysicalPage>>> try_create_physical_pages(size_t);
  45. ErrorOr<FixedArray<RefPtr<PhysicalPage>>> try_clone_physical_pages() const;
  46. explicit VMObject(FixedArray<RefPtr<PhysicalPage>>&&);
  47. template<typename Callback>
  48. void for_each_region(Callback);
  49. IntrusiveListNode<VMObject> m_list_node;
  50. FixedArray<RefPtr<PhysicalPage>> m_physical_pages;
  51. mutable RecursiveSpinlock m_lock;
  52. private:
  53. VMObject& operator=(VMObject const&) = delete;
  54. VMObject& operator=(VMObject&&) = delete;
  55. VMObject(VMObject&&) = delete;
  56. Region::ListInVMObject m_regions;
  57. public:
  58. using AllInstancesList = IntrusiveList<&VMObject::m_list_node>;
  59. static SpinlockProtected<VMObject::AllInstancesList>& all_instances();
  60. };
  61. template<typename Callback>
  62. inline void VMObject::for_each_region(Callback callback)
  63. {
  64. SpinlockLocker lock(m_lock);
  65. for (auto& region : m_regions) {
  66. callback(region);
  67. }
  68. }
  69. inline PhysicalPage const* Region::physical_page(size_t index) const
  70. {
  71. VERIFY(index < page_count());
  72. return vmobject().physical_pages()[first_page_index() + index];
  73. }
  74. inline RefPtr<PhysicalPage>& Region::physical_page_slot(size_t index)
  75. {
  76. VERIFY(index < page_count());
  77. return vmobject().physical_pages()[first_page_index() + index];
  78. }
  79. }