/* * Copyright (c) 2018-2021, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include #include #include namespace Kernel::Memory { class VMObject : public ListedRefCounted , public Weakable { friend class MemoryManager; friend class Region; public: virtual ~VMObject(); virtual ErrorOr> try_clone() = 0; virtual bool is_anonymous() const { return false; } virtual bool is_inode() const { return false; } virtual bool is_shared_inode() const { return false; } virtual bool is_private_inode() const { return false; } size_t page_count() const { return m_physical_pages.size(); } virtual Span const> physical_pages() const { return m_physical_pages.span(); } virtual Span> physical_pages() { return m_physical_pages.span(); } size_t size() const { return m_physical_pages.size() * PAGE_SIZE; } virtual StringView class_name() const = 0; ALWAYS_INLINE void add_region(Region& region) { SpinlockLocker locker(m_lock); m_regions.append(region); } ALWAYS_INLINE void remove_region(Region& region) { SpinlockLocker locker(m_lock); m_regions.remove(region); } protected: static ErrorOr>> try_create_physical_pages(size_t); ErrorOr>> try_clone_physical_pages() const; explicit VMObject(FixedArray>&&); template void for_each_region(Callback); IntrusiveListNode m_list_node; FixedArray> m_physical_pages; mutable RecursiveSpinlock m_lock; private: VMObject& operator=(VMObject const&) = delete; VMObject& operator=(VMObject&&) = delete; VMObject(VMObject&&) = delete; Region::ListInVMObject m_regions; public: using AllInstancesList = IntrusiveList<&VMObject::m_list_node>; static SpinlockProtected& all_instances(); }; template inline void VMObject::for_each_region(Callback callback) { SpinlockLocker lock(m_lock); for (auto& region : m_regions) { callback(region); } } inline PhysicalPage const* Region::physical_page(size_t index) const { VERIFY(index < page_count()); return vmobject().physical_pages()[first_page_index() + index]; } inline RefPtr& Region::physical_page_slot(size_t index) { VERIFY(index < page_count()); return vmobject().physical_pages()[first_page_index() + index]; } }