Serenity Operating System
at master 93 lines 3.7 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#pragma once 8 9#include <Kernel/Memory/AllocationStrategy.h> 10#include <Kernel/Memory/MemoryManager.h> 11#include <Kernel/Memory/PageFaultResponse.h> 12#include <Kernel/Memory/VMObject.h> 13#include <Kernel/PhysicalAddress.h> 14 15namespace Kernel::Memory { 16 17class AnonymousVMObject final : public VMObject { 18public: 19 virtual ~AnonymousVMObject() override; 20 21 static ErrorOr<NonnullLockRefPtr<AnonymousVMObject>> try_create_with_size(size_t, AllocationStrategy); 22 static ErrorOr<NonnullLockRefPtr<AnonymousVMObject>> try_create_for_physical_range(PhysicalAddress paddr, size_t size); 23 static ErrorOr<NonnullLockRefPtr<AnonymousVMObject>> try_create_with_physical_pages(Span<NonnullRefPtr<PhysicalPage>>); 24 static ErrorOr<NonnullLockRefPtr<AnonymousVMObject>> try_create_purgeable_with_size(size_t, AllocationStrategy); 25 static ErrorOr<NonnullLockRefPtr<AnonymousVMObject>> try_create_physically_contiguous_with_size(size_t); 26 virtual ErrorOr<NonnullLockRefPtr<VMObject>> try_clone() override; 27 28 [[nodiscard]] NonnullRefPtr<PhysicalPage> allocate_committed_page(Badge<Region>); 29 PageFaultResponse handle_cow_fault(size_t, VirtualAddress); 30 size_t cow_pages() const; 31 bool should_cow(size_t page_index, bool) const; 32 ErrorOr<void> set_should_cow(size_t page_index, bool); 33 34 bool is_purgeable() const { return m_purgeable; } 35 bool is_volatile() const { return m_volatile; } 36 37 ErrorOr<void> set_volatile(bool is_volatile, bool& was_purged); 38 39 size_t purge(); 40 41private: 42 class SharedCommittedCowPages; 43 44 static ErrorOr<NonnullLockRefPtr<AnonymousVMObject>> try_create_with_shared_cow(AnonymousVMObject const&, NonnullLockRefPtr<SharedCommittedCowPages>, FixedArray<RefPtr<PhysicalPage>>&&); 45 46 explicit AnonymousVMObject(FixedArray<RefPtr<PhysicalPage>>&&, AllocationStrategy, Optional<CommittedPhysicalPageSet>); 47 explicit AnonymousVMObject(PhysicalAddress, FixedArray<RefPtr<PhysicalPage>>&&); 48 explicit AnonymousVMObject(FixedArray<RefPtr<PhysicalPage>>&&); 49 explicit AnonymousVMObject(LockWeakPtr<AnonymousVMObject>, NonnullLockRefPtr<SharedCommittedCowPages>, FixedArray<RefPtr<PhysicalPage>>&&); 50 51 virtual StringView class_name() const override { return "AnonymousVMObject"sv; } 52 53 AnonymousVMObject& operator=(AnonymousVMObject const&) = delete; 54 AnonymousVMObject& operator=(AnonymousVMObject&&) = delete; 55 AnonymousVMObject(AnonymousVMObject&&) = delete; 56 57 virtual bool is_anonymous() const override { return true; } 58 59 ErrorOr<void> ensure_cow_map(); 60 ErrorOr<void> ensure_or_reset_cow_map(); 61 62 Optional<CommittedPhysicalPageSet> m_unused_committed_pages; 63 Bitmap m_cow_map; 64 65 // AnonymousVMObject shares committed COW pages with cloned children (happens on fork) 66 class SharedCommittedCowPages final : public AtomicRefCounted<SharedCommittedCowPages> { 67 AK_MAKE_NONCOPYABLE(SharedCommittedCowPages); 68 69 public: 70 SharedCommittedCowPages() = delete; 71 72 explicit SharedCommittedCowPages(CommittedPhysicalPageSet&&); 73 ~SharedCommittedCowPages(); 74 75 [[nodiscard]] bool is_empty() const { return m_committed_pages.is_empty(); } 76 77 [[nodiscard]] NonnullRefPtr<PhysicalPage> take_one(); 78 void uncommit_one(); 79 80 private: 81 Spinlock<LockRank::None> m_lock {}; 82 CommittedPhysicalPageSet m_committed_pages; 83 }; 84 85 LockWeakPtr<AnonymousVMObject> m_cow_parent; 86 LockRefPtr<SharedCommittedCowPages> m_shared_committed_cow_pages; 87 88 bool m_purgeable { false }; 89 bool m_volatile { false }; 90 bool m_was_purged { false }; 91}; 92 93}