summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-05-08 22:10:47 +0200
committerAndreas Kling <kling@serenityos.org>2020-05-08 22:10:47 +0200
commit55f61c00049e928f1eb2e14c6509372591849991 (patch)
treeb2462d727863ef9b625a3ff5a3302ed1e184e165
parent239fd334059823619e0af199e9b5618a320e15f9 (diff)
downloadserenity-55f61c00049e928f1eb2e14c6509372591849991.zip
Kernel: Add for_each_vmobject_of_type<T>
This makes iterating over a specific type of VMObjects a bit nicer.
-rw-r--r--Kernel/Process.cpp10
-rw-r--r--Kernel/VM/AnonymousVMObject.h6
-rw-r--r--Kernel/VM/ContiguousVMObject.h7
-rw-r--r--Kernel/VM/InodeVMObject.h6
-rw-r--r--Kernel/VM/MemoryManager.cpp17
-rw-r--r--Kernel/VM/MemoryManager.h11
-rw-r--r--Kernel/VM/PurgeableVMObject.h6
-rw-r--r--Kernel/VM/VMObject.h10
8 files changed, 57 insertions, 16 deletions
diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp
index cd46574a95..9e292dc043 100644
--- a/Kernel/Process.cpp
+++ b/Kernel/Process.cpp
@@ -671,9 +671,8 @@ int Process::sys$purge(int mode)
NonnullRefPtrVector<PurgeableVMObject> vmobjects;
{
InterruptDisabler disabler;
- MM.for_each_vmobject([&](auto& vmobject) {
- if (vmobject.is_purgeable())
- vmobjects.append(static_cast<PurgeableVMObject&>(vmobject));
+ MM.for_each_vmobject_of_type<PurgeableVMObject>([&](auto& vmobject) {
+ vmobjects.append(vmobject);
return IterationDecision::Continue;
});
}
@@ -685,9 +684,8 @@ int Process::sys$purge(int mode)
NonnullRefPtrVector<InodeVMObject> vmobjects;
{
InterruptDisabler disabler;
- MM.for_each_vmobject([&](auto& vmobject) {
- if (vmobject.is_inode())
- vmobjects.append(static_cast<InodeVMObject&>(vmobject));
+ MM.for_each_vmobject_of_type<InodeVMObject>([&](auto& vmobject) {
+ vmobjects.append(vmobject);
return IterationDecision::Continue;
});
}
diff --git a/Kernel/VM/AnonymousVMObject.h b/Kernel/VM/AnonymousVMObject.h
index 9972bab1a4..12da99df43 100644
--- a/Kernel/VM/AnonymousVMObject.h
+++ b/Kernel/VM/AnonymousVMObject.h
@@ -56,4 +56,10 @@ private:
virtual bool is_anonymous() const override { return true; }
};
+template<>
+inline bool is<AnonymousVMObject>(const VMObject& vmobject)
+{
+ return vmobject.is_anonymous();
+}
+
}
diff --git a/Kernel/VM/ContiguousVMObject.h b/Kernel/VM/ContiguousVMObject.h
index b25d6dc1c0..58de60c944 100644
--- a/Kernel/VM/ContiguousVMObject.h
+++ b/Kernel/VM/ContiguousVMObject.h
@@ -50,4 +50,11 @@ private:
virtual bool is_contiguous() const override { return true; }
};
+
+template<>
+inline bool is<ContiguousVMObject>(const VMObject& vmobject)
+{
+ return vmobject.is_contiguous();
+}
+
}
diff --git a/Kernel/VM/InodeVMObject.h b/Kernel/VM/InodeVMObject.h
index 5ec9013bac..ca5f0af6e7 100644
--- a/Kernel/VM/InodeVMObject.h
+++ b/Kernel/VM/InodeVMObject.h
@@ -66,4 +66,10 @@ protected:
Bitmap m_dirty_pages;
};
+template<>
+inline bool is<InodeVMObject>(const VMObject& vmobject)
+{
+ return vmobject.is_inode();
+}
+
}
diff --git a/Kernel/VM/MemoryManager.cpp b/Kernel/VM/MemoryManager.cpp
index 7268a652df..aa3f7dccc7 100644
--- a/Kernel/VM/MemoryManager.cpp
+++ b/Kernel/VM/MemoryManager.cpp
@@ -441,16 +441,13 @@ RefPtr<PhysicalPage> MemoryManager::allocate_user_physical_page(ShouldZeroFill s
klog() << "MM: no user physical regions available (?)";
}
- for_each_vmobject([&](auto& vmobject) {
- if (vmobject.is_purgeable()) {
- auto& purgeable_vmobject = static_cast<PurgeableVMObject&>(vmobject);
- int purged_page_count = purgeable_vmobject.purge_with_interrupts_disabled({});
- if (purged_page_count) {
- klog() << "MM: Purge saved the day! Purged " << purged_page_count << " pages from PurgeableVMObject{" << &purgeable_vmobject << "}";
- page = find_free_user_physical_page();
- ASSERT(page);
- return IterationDecision::Break;
- }
+ for_each_vmobject_of_type<PurgeableVMObject>([&](auto& vmobject) {
+ int purged_page_count = vmobject.purge_with_interrupts_disabled({});
+ if (purged_page_count) {
+ klog() << "MM: Purge saved the day! Purged " << purged_page_count << " pages from PurgeableVMObject{" << &vmobject << "}";
+ page = find_free_user_physical_page();
+ ASSERT(page);
+ return IterationDecision::Break;
}
return IterationDecision::Continue;
});
diff --git a/Kernel/VM/MemoryManager.h b/Kernel/VM/MemoryManager.h
index 322a9facc9..f4293fff35 100644
--- a/Kernel/VM/MemoryManager.h
+++ b/Kernel/VM/MemoryManager.h
@@ -125,6 +125,17 @@ public:
}
}
+ template<typename T, typename Callback>
+ static void for_each_vmobject_of_type(Callback callback)
+ {
+ for (auto& vmobject : MM.m_vmobjects) {
+ if (!is<T>(vmobject))
+ continue;
+ if (callback(static_cast<T&>(vmobject)) == IterationDecision::Break)
+ break;
+ }
+ }
+
static Region* region_from_vaddr(Process&, VirtualAddress);
static const Region* region_from_vaddr(const Process&, VirtualAddress);
diff --git a/Kernel/VM/PurgeableVMObject.h b/Kernel/VM/PurgeableVMObject.h
index 5e100aa5f0..0b63801284 100644
--- a/Kernel/VM/PurgeableVMObject.h
+++ b/Kernel/VM/PurgeableVMObject.h
@@ -64,4 +64,10 @@ private:
bool m_volatile { false };
};
+template<>
+inline bool is<PurgeableVMObject>(const VMObject& vmobject)
+{
+ return vmobject.is_purgeable();
+}
+
}
diff --git a/Kernel/VM/VMObject.h b/Kernel/VM/VMObject.h
index 79ee9dadad..bb0314301c 100644
--- a/Kernel/VM/VMObject.h
+++ b/Kernel/VM/VMObject.h
@@ -84,4 +84,14 @@ private:
VMObject(VMObject&&) = delete;
};
+template<typename T>
+inline bool is(const VMObject&) { return false; }
+
+template<typename T>
+inline T& to(VMObject& object)
+{
+ ASSERT(is<typename RemoveConst<T>::Type>(object));
+ return static_cast<T&>(object);
+}
+
}