summaryrefslogtreecommitdiff
path: root/Kernel/Memory/PhysicalPage.h
diff options
context:
space:
mode:
Diffstat (limited to 'Kernel/Memory/PhysicalPage.h')
-rw-r--r--Kernel/Memory/PhysicalPage.h71
1 files changed, 71 insertions, 0 deletions
diff --git a/Kernel/Memory/PhysicalPage.h b/Kernel/Memory/PhysicalPage.h
new file mode 100644
index 0000000000..ab22be3534
--- /dev/null
+++ b/Kernel/Memory/PhysicalPage.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/NonnullRefPtr.h>
+#include <Kernel/PhysicalAddress.h>
+
+namespace Kernel {
+
+enum class MayReturnToFreeList : bool {
+ No,
+ Yes
+};
+
+class PhysicalPage {
+ AK_MAKE_NONCOPYABLE(PhysicalPage);
+ AK_MAKE_NONMOVABLE(PhysicalPage);
+
+ friend class MemoryManager;
+
+public:
+ PhysicalAddress paddr() const;
+
+ void ref()
+ {
+ m_ref_count.fetch_add(1, AK::memory_order_acq_rel);
+ }
+
+ void unref()
+ {
+ if (m_ref_count.fetch_sub(1, AK::memory_order_acq_rel) == 1)
+ free_this();
+ }
+
+ static NonnullRefPtr<PhysicalPage> create(PhysicalAddress, MayReturnToFreeList may_return_to_freelist = MayReturnToFreeList::Yes);
+
+ u32 ref_count() const { return m_ref_count.load(AK::memory_order_consume); }
+
+ bool is_shared_zero_page() const;
+ bool is_lazy_committed_page() const;
+
+private:
+ explicit PhysicalPage(MayReturnToFreeList may_return_to_freelist);
+ ~PhysicalPage() = default;
+
+ void free_this();
+
+ Atomic<u32> m_ref_count { 1 };
+ MayReturnToFreeList m_may_return_to_freelist { MayReturnToFreeList::Yes };
+};
+
+struct PhysicalPageEntry {
+ union {
+ // If it's a live PhysicalPage object:
+ struct {
+ PhysicalPage physical_page;
+ } allocated;
+
+ // If it's an entry in a PhysicalZone::Bucket's freelist.
+ struct {
+ i16 next_index;
+ i16 prev_index;
+ } freelist;
+ };
+};
+
+}