summaryrefslogtreecommitdiff
path: root/Kernel
diff options
context:
space:
mode:
authorNicholas Baron <nicholas.baron.ten@gmail.com>2021-05-16 02:36:52 -0700
committerGitHub <noreply@github.com>2021-05-16 10:36:52 +0100
commitaa4d41fe2c473c3bb78327a1dbe8ec85530259ca (patch)
tree925d408b37ab1f7750a3af37adfb2949fcafa836 /Kernel
parentbbaa4630323c20e37e2a0ead478987cb5f02fc53 (diff)
downloadserenity-aa4d41fe2c473c3bb78327a1dbe8ec85530259ca.zip
AK+Kernel+LibELF: Remove the need for `IteratorDecision::Continue`
By constraining two implementations, the compiler will select the best fitting one. All this will require is duplicating the implementation and simplifying for the `void` case. This constraining also informs both the caller and compiler by passing the callback parameter types as part of the constraint (e.g.: `IterationFunction<int>`). Some `for_each` functions in LibELF only take functions which return `void`. This is a minimal correctness check, as it removes one way for a function to incompletely do something. There seems to be a possible idiom where inside a lambda, a `return;` is the same as `continue;` in a for-loop.
Diffstat (limited to 'Kernel')
-rw-r--r--Kernel/Arch/i386/CPU.cpp6
-rw-r--r--Kernel/Arch/x86/CPU.h13
-rw-r--r--Kernel/FileSystem/ProcFS.cpp7
-rw-r--r--Kernel/PerformanceEventBuffer.cpp1
-rw-r--r--Kernel/Process.cpp13
-rw-r--r--Kernel/Process.h80
-rw-r--r--Kernel/Scheduler.cpp4
-rw-r--r--Kernel/Syscalls/execve.cpp3
-rw-r--r--Kernel/Syscalls/kill.cpp2
-rw-r--r--Kernel/Syscalls/module.cpp10
-rw-r--r--Kernel/TTY/TTY.cpp1
-rw-r--r--Kernel/Thread.cpp16
-rw-r--r--Kernel/Thread.h32
-rw-r--r--Kernel/VM/AnonymousVMObject.cpp14
-rw-r--r--Kernel/VM/AnonymousVMObject.h26
-rw-r--r--Kernel/VM/MemoryManager.h10
16 files changed, 169 insertions, 69 deletions
diff --git a/Kernel/Arch/i386/CPU.cpp b/Kernel/Arch/i386/CPU.cpp
index b33e48f659..661eb8653c 100644
--- a/Kernel/Arch/i386/CPU.cpp
+++ b/Kernel/Arch/i386/CPU.cpp
@@ -2090,12 +2090,11 @@ void Processor::smp_broadcast_message(ProcessorMessage& msg)
VERIFY(msg.refs > 0);
bool need_broadcast = false;
for_each(
- [&](Processor& proc) -> IterationDecision {
+ [&](Processor& proc) {
if (&proc != &cur_proc) {
if (proc.smp_queue_message(msg))
need_broadcast = true;
}
- return IterationDecision::Continue;
});
// Now trigger an IPI on all other APs (unless all targets already had messages queued)
@@ -2215,9 +2214,8 @@ void Processor::smp_broadcast_halt()
// We don't want to use a message, because this could have been triggered
// by being out of memory and we might not be able to get a message
for_each(
- [&](Processor& proc) -> IterationDecision {
+ [&](Processor& proc) {
proc.m_halt_requested.store(true, AK::MemoryOrder::memory_order_release);
- return IterationDecision::Continue;
});
// Now trigger an IPI on all other APs
diff --git a/Kernel/Arch/x86/CPU.h b/Kernel/Arch/x86/CPU.h
index 159a64876f..488443a7fc 100644
--- a/Kernel/Arch/x86/CPU.h
+++ b/Kernel/Arch/x86/CPU.h
@@ -8,6 +8,7 @@
#include <AK/Atomic.h>
#include <AK/Badge.h>
+#include <AK/Concepts.h>
#include <AK/Noncopyable.h>
#include <AK/Vector.h>
@@ -733,7 +734,7 @@ public:
static size_t processor_count() { return processors().size(); }
- template<typename Callback>
+ template<IteratorFunction<Processor&> Callback>
static inline IterationDecision for_each(Callback callback)
{
auto& procs = processors();
@@ -745,6 +746,16 @@ public:
return IterationDecision::Continue;
}
+ template<VoidFunction<Processor&> Callback>
+ static inline IterationDecision for_each(Callback callback)
+ {
+ auto& procs = processors();
+ size_t count = procs.size();
+ for (size_t i = 0; i < count; i++)
+ callback(*procs[i]);
+ return IterationDecision::Continue;
+ }
+
ALWAYS_INLINE u8 physical_address_bit_width() const { return m_physical_address_bit_width; }
ALWAYS_INLINE ProcessorInfo& info() { return *m_info; }
diff --git a/Kernel/FileSystem/ProcFS.cpp b/Kernel/FileSystem/ProcFS.cpp
index 777bb5b936..805f852293 100644
--- a/Kernel/FileSystem/ProcFS.cpp
+++ b/Kernel/FileSystem/ProcFS.cpp
@@ -688,7 +688,7 @@ static bool procfs$cpuinfo(InodeIdentifier, KBufferBuilder& builder)
{
JsonArraySerializer array { builder };
Processor::for_each(
- [&](Processor& proc) -> IterationDecision {
+ [&](Processor& proc) {
auto& info = proc.info();
auto obj = array.add_object();
JsonArray features;
@@ -702,7 +702,6 @@ static bool procfs$cpuinfo(InodeIdentifier, KBufferBuilder& builder)
obj.add("stepping", info.stepping());
obj.add("type", info.type());
obj.add("brandstr", info.brandstr());
- return IterationDecision::Continue;
});
array.finish();
return true;
@@ -826,7 +825,6 @@ static bool procfs$all(InodeIdentifier, KBufferBuilder& builder)
thread_object.add("unix_socket_write_bytes", thread.unix_socket_write_bytes());
thread_object.add("ipv4_socket_read_bytes", thread.ipv4_socket_read_bytes());
thread_object.add("ipv4_socket_write_bytes", thread.ipv4_socket_write_bytes());
- return IterationDecision::Continue;
});
};
@@ -1328,10 +1326,9 @@ KResult ProcFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntr
auto process = Process::from_pid(pid);
if (!process)
return ENOENT;
- process->for_each_thread([&](const Thread& thread) -> IterationDecision {
+ process->for_each_thread([&](const Thread& thread) {
int tid = thread.tid().value();
callback({ String::number(tid), to_identifier_with_stack(fsid(), tid), 0 });
- return IterationDecision::Continue;
});
} break;
diff --git a/Kernel/PerformanceEventBuffer.cpp b/Kernel/PerformanceEventBuffer.cpp
index 730c19304a..8b1c7a11a5 100644
--- a/Kernel/PerformanceEventBuffer.cpp
+++ b/Kernel/PerformanceEventBuffer.cpp
@@ -230,7 +230,6 @@ void PerformanceEventBuffer::add_process(const Process& process, ProcessEventTyp
process.for_each_thread([&](auto& thread) {
[[maybe_unused]] auto rc = append_with_eip_and_ebp(process.pid(), thread.tid().value(),
0, 0, PERF_EVENT_THREAD_CREATE, 0, 0, 0, nullptr);
- return IterationDecision::Continue;
});
for (auto& region : process.space().regions()) {
diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp
index bc92dc94e4..b6d922f7a0 100644
--- a/Kernel/Process.cpp
+++ b/Kernel/Process.cpp
@@ -103,15 +103,16 @@ void Process::kill_threads_except_self()
auto current_thread = Thread::current();
for_each_thread([&](Thread& thread) {
- if (&thread == current_thread
- || thread.state() == Thread::State::Dead
- || thread.state() == Thread::State::Dying)
- return IterationDecision::Continue;
+ if (&thread == current_thread)
+ return;
+
+ if (auto state = thread.state(); state == Thread::State::Dead
+ || state == Thread::State::Dying)
+ return;
// We need to detach this thread in case it hasn't been joined
thread.detach();
thread.set_should_die();
- return IterationDecision::Continue;
});
big_lock().clear_waiters();
@@ -123,7 +124,6 @@ void Process::kill_all_threads()
// We need to detach this thread in case it hasn't been joined
thread.detach();
thread.set_should_die();
- return IterationDecision::Continue;
});
}
@@ -562,7 +562,6 @@ void Process::die()
for_each_thread([&](auto& thread) {
m_threads_for_coredump.append(thread);
- return IterationDecision::Continue;
});
{
diff --git a/Kernel/Process.h b/Kernel/Process.h
index 5ffcc47c2b..537528a149 100644
--- a/Kernel/Process.h
+++ b/Kernel/Process.h
@@ -7,6 +7,7 @@
#pragma once
#include <AK/Checked.h>
+#include <AK/Concepts.h>
#include <AK/HashMap.h>
#include <AK/InlineLinkedList.h>
#include <AK/NonnullOwnPtrVector.h>
@@ -224,16 +225,30 @@ public:
RefPtr<FileDescription> file_description(int fd) const;
int fd_flags(int fd) const;
- template<typename Callback>
+ // Breakable iteration functions
+ template<IteratorFunction<Process&> Callback>
static void for_each(Callback);
- template<typename Callback>
+ template<IteratorFunction<Process&> Callback>
static void for_each_in_pgrp(ProcessGroupID, Callback);
- template<typename Callback>
+ template<IteratorFunction<Process&> Callback>
void for_each_child(Callback);
- template<typename Callback>
+ template<IteratorFunction<Thread&> Callback>
IterationDecision for_each_thread(Callback);
- template<typename Callback>
+ template<IteratorFunction<Thread&> Callback>
+ IterationDecision for_each_thread(Callback callback) const;
+
+ // Non-breakable iteration functions
+ template<VoidFunction<Process&> Callback>
+ static void for_each(Callback);
+ template<VoidFunction<Process&> Callback>
+ static void for_each_in_pgrp(ProcessGroupID, Callback);
+ template<VoidFunction<Process&> Callback>
+ void for_each_child(Callback);
+
+ template<VoidFunction<Thread&> Callback>
+ IterationDecision for_each_thread(Callback);
+ template<VoidFunction<Thread&> Callback>
IterationDecision for_each_thread(Callback callback) const;
void die();
@@ -628,7 +643,7 @@ private:
extern InlineLinkedList<Process>* g_processes;
extern RecursiveSpinLock g_processes_lock;
-template<typename Callback>
+template<IteratorFunction<Process&> Callback>
inline void Process::for_each(Callback callback)
{
VERIFY_INTERRUPTS_DISABLED();
@@ -641,7 +656,7 @@ inline void Process::for_each(Callback callback)
}
}
-template<typename Callback>
+template<IteratorFunction<Process&> Callback>
inline void Process::for_each_child(Callback callback)
{
VERIFY_INTERRUPTS_DISABLED();
@@ -657,7 +672,7 @@ inline void Process::for_each_child(Callback callback)
}
}
-template<typename Callback>
+template<IteratorFunction<Thread&> Callback>
inline IterationDecision Process::for_each_thread(Callback callback) const
{
ScopedSpinLock thread_list_lock(m_thread_list_lock);
@@ -669,7 +684,7 @@ inline IterationDecision Process::for_each_thread(Callback callback) const
return IterationDecision::Continue;
}
-template<typename Callback>
+template<IteratorFunction<Thread&> Callback>
inline IterationDecision Process::for_each_thread(Callback callback)
{
ScopedSpinLock thread_list_lock(m_thread_list_lock);
@@ -681,7 +696,7 @@ inline IterationDecision Process::for_each_thread(Callback callback)
return IterationDecision::Continue;
}
-template<typename Callback>
+template<IteratorFunction<Process&> Callback>
inline void Process::for_each_in_pgrp(ProcessGroupID pgid, Callback callback)
{
VERIFY_INTERRUPTS_DISABLED();
@@ -696,6 +711,51 @@ inline void Process::for_each_in_pgrp(ProcessGroupID pgid, Callback callback)
}
}
+template<VoidFunction<Process&> Callback>
+inline void Process::for_each(Callback callback)
+{
+ return for_each([&](auto& item) {
+ callback(item);
+ return IterationDecision::Continue;
+ });
+}
+
+template<VoidFunction<Process&> Callback>
+inline void Process::for_each_child(Callback callback)
+{
+ return for_each_child([&](auto& item) {
+ callback(item);
+ return IterationDecision::Continue;
+ });
+}
+
+template<VoidFunction<Thread&> Callback>
+inline IterationDecision Process::for_each_thread(Callback callback) const
+{
+ ScopedSpinLock thread_list_lock(m_thread_list_lock);
+ for (auto& thread : m_thread_list)
+ callback(thread);
+ return IterationDecision::Continue;
+}
+
+template<VoidFunction<Thread&> Callback>
+inline IterationDecision Process::for_each_thread(Callback callback)
+{
+ ScopedSpinLock thread_list_lock(m_thread_list_lock);
+ for (auto& thread : m_thread_list)
+ callback(thread);
+ return IterationDecision::Continue;
+}
+
+template<VoidFunction<Process&> Callback>
+inline void Process::for_each_in_pgrp(ProcessGroupID pgid, Callback callback)
+{
+ return for_each_in_pgrp(pgid, [&](auto& item) {
+ callback(item);
+ return IterationDecision::Continue;
+ });
+}
+
inline bool InodeMetadata::may_read(const Process& process) const
{
return may_read(process.euid(), process.egid(), process.extra_gids());
diff --git a/Kernel/Scheduler.cpp b/Kernel/Scheduler.cpp
index 8417719bc3..8c1dad9379 100644
--- a/Kernel/Scheduler.cpp
+++ b/Kernel/Scheduler.cpp
@@ -584,7 +584,7 @@ void dump_thread_list()
return thread.get_register_dump_from_stack().eip;
};
- Thread::for_each([&](Thread& thread) -> IterationDecision {
+ Thread::for_each([&](Thread& thread) {
switch (thread.state()) {
case Thread::Dying:
dbgln(" {:14} {:30} @ {:04x}:{:08x} Finalizable: {}, (nsched: {})",
@@ -605,8 +605,6 @@ void dump_thread_list()
thread.times_scheduled());
break;
}
-
- return IterationDecision::Continue;
});
}
diff --git a/Kernel/Syscalls/execve.cpp b/Kernel/Syscalls/execve.cpp
index f8917ede36..7abfba809e 100644
--- a/Kernel/Syscalls/execve.cpp
+++ b/Kernel/Syscalls/execve.cpp
@@ -172,7 +172,7 @@ static KResultOr<RequiredLoadRange> get_required_load_range(FileDescription& pro
RequiredLoadRange range {};
elf_image.for_each_program_header([&range](const auto& pheader) {
if (pheader.type() != PT_LOAD)
- return IterationDecision::Continue;
+ return;
auto region_start = (FlatPtr)pheader.vaddr().as_ptr();
auto region_end = region_start + pheader.size_in_memory();
@@ -180,7 +180,6 @@ static KResultOr<RequiredLoadRange> get_required_load_range(FileDescription& pro
range.start = region_start;
if (range.end == 0 || region_end > range.end)
range.end = region_end;
- return IterationDecision::Continue;
});
VERIFY(range.end > range.start);
diff --git a/Kernel/Syscalls/kill.cpp b/Kernel/Syscalls/kill.cpp
index 6ce69b7217..d1a4181a3d 100644
--- a/Kernel/Syscalls/kill.cpp
+++ b/Kernel/Syscalls/kill.cpp
@@ -47,8 +47,6 @@ KResult Process::do_killpg(ProcessGroupID pgrp, int signal)
any_succeeded = true;
else
error = res;
-
- return IterationDecision::Continue;
});
if (group_was_empty)
diff --git a/Kernel/Syscalls/module.cpp b/Kernel/Syscalls/module.cpp
index 1389cb8f16..8b1ad64833 100644
--- a/Kernel/Syscalls/module.cpp
+++ b/Kernel/Syscalls/module.cpp
@@ -51,18 +51,18 @@ KResultOr<int> Process::sys$module_load(Userspace<const char*> user_path, size_t
elf_image->for_each_section_of_type(SHT_PROGBITS, [&](const ELF::Image::Section& section) {
if (!section.size())
- return IterationDecision::Continue;
+ return;
auto section_storage = KBuffer::copy(section.raw_data(), section.size(), Region::Access::Read | Region::Access::Write | Region::Access::Execute);
section_storage_by_name.set(section.name(), section_storage.data());
module->sections.append(move(section_storage));
- return IterationDecision::Continue;
});
bool missing_symbols = false;
elf_image->for_each_section_of_type(SHT_PROGBITS, [&](const ELF::Image::Section& section) {
if (!section.size())
- return IterationDecision::Continue;
+ return;
+
auto* section_storage = section_storage_by_name.get(section.name()).value_or(nullptr);
VERIFY(section_storage);
auto relocations = section.relocations();
@@ -103,10 +103,7 @@ KResultOr<int> Process::sys$module_load(Userspace<const char*> user_path, size_t
}
break;
}
- return IterationDecision::Continue;
});
-
- return IterationDecision::Continue;
});
if (missing_symbols)
@@ -129,7 +126,6 @@ KResultOr<int> Process::sys$module_load(Userspace<const char*> user_path, size_t
if (storage)
module->name = String((const char*)(storage + symbol.value()));
}
- return IterationDecision::Continue;
});
if (!module->module_init)
diff --git a/Kernel/TTY/TTY.cpp b/Kernel/TTY/TTY.cpp
index 516b255e4d..9ffc018b54 100644
--- a/Kernel/TTY/TTY.cpp
+++ b/Kernel/TTY/TTY.cpp
@@ -286,7 +286,6 @@ void TTY::generate_signal(int signal)
dbgln_if(TTY_DEBUG, "{}: Send signal {} to {}", tty_name(), signal, process);
// FIXME: Should this error be propagated somehow?
[[maybe_unused]] auto rc = process.send_signal(signal, nullptr);
- return IterationDecision::Continue;
});
}
diff --git a/Kernel/Thread.cpp b/Kernel/Thread.cpp
index 8696ec8e3c..beeee29472 100644
--- a/Kernel/Thread.cpp
+++ b/Kernel/Thread.cpp
@@ -404,7 +404,6 @@ void Thread::finalize_dying_threads()
for_each_in_state(Thread::State::Dying, [&](Thread& thread) {
if (thread.is_finalizable())
dying_threads.append(&thread);
- return IterationDecision::Continue;
});
}
for (auto* thread : dying_threads) {
@@ -740,7 +739,6 @@ DispatchSignalResult Thread::dispatch_signal(u8 signal)
process.set_dump_core(true);
process.for_each_thread([](auto& thread) {
thread.set_dump_backtrace_on_finalization();
- return IterationDecision::Continue;
});
[[fallthrough]];
case DefaultSignalAction::Terminate:
@@ -891,11 +889,12 @@ void Thread::set_state(State new_state, u8 stop_signal)
auto& process = this->process();
if (process.set_stopped(false) == true) {
process.for_each_thread([&](auto& thread) {
- if (&thread == this || !thread.is_stopped())
- return IterationDecision::Continue;
+ if (&thread == this)
+ return;
+ if (!thread.is_stopped())
+ return;
dbgln_if(THREAD_DEBUG, "Resuming peer thread {}", thread);
thread.resume_from_stopped();
- return IterationDecision::Continue;
});
process.unblock_waiters(Thread::WaitBlocker::UnblockFlags::Continued);
// Tell the parent process (if any) about this change.
@@ -914,11 +913,12 @@ void Thread::set_state(State new_state, u8 stop_signal)
auto& process = this->process();
if (process.set_stopped(true) == false) {
process.for_each_thread([&](auto& thread) {
- if (&thread == this || thread.is_stopped())
- return IterationDecision::Continue;
+ if (&thread == this)
+ return;
+ if (thread.is_stopped())
+ return;
dbgln_if(THREAD_DEBUG, "Stopping peer thread {}", thread);
thread.set_state(Stopped, stop_signal);
- return IterationDecision::Continue;
});
process.unblock_waiters(Thread::WaitBlocker::UnblockFlags::Stopped, stop_signal);
// Tell the parent process (if any) about this change.
diff --git a/Kernel/Thread.h b/Kernel/Thread.h
index 446b34eda8..d288d6e07f 100644
--- a/Kernel/Thread.h
+++ b/Kernel/Thread.h
@@ -6,6 +6,7 @@
#pragma once
+#include <AK/Concepts.h>
#include <AK/EnumBits.h>
#include <AK/Function.h>
#include <AK/HashMap.h>
@@ -1044,9 +1045,14 @@ public:
RefPtr<Thread> clone(Process&);
- template<typename Callback>
+ template<IteratorFunction<Thread&> Callback>
static IterationDecision for_each_in_state(State, Callback);
- template<typename Callback>
+ template<IteratorFunction<Thread&> Callback>
+ static IterationDecision for_each(Callback);
+
+ template<VoidFunction<Thread&> Callback>
+ static IterationDecision for_each_in_state(State, Callback);
+ template<VoidFunction<Thread&> Callback>
static IterationDecision for_each(Callback);
static constexpr u32 default_kernel_stack_size = 65536;
@@ -1260,7 +1266,7 @@ private:
AK_ENUM_BITWISE_OPERATORS(Thread::FileBlocker::BlockFlags);
-template<typename Callback>
+template<IteratorFunction<Thread&> Callback>
inline IterationDecision Thread::for_each(Callback callback)
{
ScopedSpinLock lock(g_tid_map_lock);
@@ -1272,7 +1278,7 @@ inline IterationDecision Thread::for_each(Callback callback)
return IterationDecision::Continue;
}
-template<typename Callback>
+template<IteratorFunction<Thread&> Callback>
inline IterationDecision Thread::for_each_in_state(State state, Callback callback)
{
ScopedSpinLock lock(g_tid_map_lock);
@@ -1287,6 +1293,24 @@ inline IterationDecision Thread::for_each_in_state(State state, Callback callbac
return IterationDecision::Continue;
}
+template<VoidFunction<Thread&> Callback>
+inline IterationDecision Thread::for_each(Callback callback)
+{
+ ScopedSpinLock lock(g_tid_map_lock);
+ for (auto& it : *g_tid_map)
+ callback(*it.value);
+ return IterationDecision::Continue;
+}
+
+template<VoidFunction<Thread&> Callback>
+inline IterationDecision Thread::for_each_in_state(State state, Callback callback)
+{
+ return for_each_in_state(state, [&](auto& thread) {
+ callback(thread);
+ return IterationDecision::Continue;
+ });
+}
+
}
template<>
diff --git a/Kernel/VM/AnonymousVMObject.cpp b/Kernel/VM/AnonymousVMObject.cpp
index 912e4cb275..576c040ae5 100644
--- a/Kernel/VM/AnonymousVMObject.cpp
+++ b/Kernel/VM/AnonymousVMObject.cpp
@@ -23,13 +23,11 @@ RefPtr<VMObject> AnonymousVMObject::clone()
// so that the parent is still guaranteed to be able to have all
// non-volatile memory available.
size_t need_cow_pages = 0;
- {
- // We definitely need to commit non-volatile areas
- for_each_nonvolatile_range([&](const VolatilePageRange& nonvolatile_range) {
- need_cow_pages += nonvolatile_range.count;
- return IterationDecision::Continue;
- });
- }
+
+ // We definitely need to commit non-volatile areas
+ for_each_nonvolatile_range([&](const VolatilePageRange& nonvolatile_range) {
+ need_cow_pages += nonvolatile_range.count;
+ });
dbgln_if(COMMIT_DEBUG, "Cloning {:p}, need {} committed cow pages", this, need_cow_pages);
@@ -220,7 +218,6 @@ int AnonymousVMObject::purge_impl()
}
});
}
- return IterationDecision::Continue;
});
return purged_page_count;
}
@@ -284,7 +281,6 @@ void AnonymousVMObject::update_volatile_cache()
m_volatile_ranges_cache.clear();
for_each_nonvolatile_range([&](const VolatilePageRange& range) {
m_volatile_ranges_cache.add_unchecked(range);
- return IterationDecision::Continue;
});
m_volatile_ranges_cache_dirty = false;
diff --git a/Kernel/VM/AnonymousVMObject.h b/Kernel/VM/AnonymousVMObject.h
index bdca7c0336..85afc0d53a 100644
--- a/Kernel/VM/AnonymousVMObject.h
+++ b/Kernel/VM/AnonymousVMObject.h
@@ -40,7 +40,7 @@ public:
bool is_any_volatile() const;
- template<typename F>
+ template<IteratorFunction<const VolatilePageRange&> F>
IterationDecision for_each_volatile_range(F f) const
{
VERIFY(m_lock.is_locked());
@@ -78,24 +78,42 @@ public:
return IterationDecision::Continue;
}
- template<typename F>
+ template<IteratorFunction<const VolatilePageRange&> F>
IterationDecision for_each_nonvolatile_range(F f) const
{
size_t base = 0;
for_each_volatile_range([&](const VolatilePageRange& volatile_range) {
if (volatile_range.base == base)
return IterationDecision::Continue;
- IterationDecision decision = f({ base, volatile_range.base - base });
+ IterationDecision decision = f(VolatilePageRange { base, volatile_range.base - base });
if (decision != IterationDecision::Continue)
return decision;
base = volatile_range.base + volatile_range.count;
return IterationDecision::Continue;
});
if (base < page_count())
- return f({ base, page_count() - base });
+ return f(VolatilePageRange { base, page_count() - base });
return IterationDecision::Continue;
}
+ template<VoidFunction<const VolatilePageRange&> F>
+ IterationDecision for_each_volatile_range(F f) const
+ {
+ return for_each_volatile_range([&](auto& range) {
+ f(range);
+ return IterationDecision::Continue;
+ });
+ }
+
+ template<VoidFunction<const VolatilePageRange&> F>
+ IterationDecision for_each_nonvolatile_range(F f) const
+ {
+ return for_each_nonvolatile_range([&](auto range) {
+ f(move(range));
+ return IterationDecision::Continue;
+ });
+ }
+
private:
explicit AnonymousVMObject(size_t, AllocationStrategy);
explicit AnonymousVMObject(PhysicalAddress, size_t);
diff --git a/Kernel/VM/MemoryManager.h b/Kernel/VM/MemoryManager.h
index af3db1243a..cb6b860b17 100644
--- a/Kernel/VM/MemoryManager.h
+++ b/Kernel/VM/MemoryManager.h
@@ -6,6 +6,7 @@
#pragma once
+#include <AK/Concepts.h>
#include <AK/HashTable.h>
#include <AK/NonnullRefPtrVector.h>
#include <AK/String.h>
@@ -157,7 +158,7 @@ public:
unsigned super_physical_pages() const { return m_super_physical_pages; }
unsigned super_physical_pages_used() const { return m_super_physical_pages_used; }
- template<typename Callback>
+ template<IteratorFunction<VMObject&> Callback>
static void for_each_vmobject(Callback callback)
{
for (auto& vmobject : MM.m_vmobjects) {
@@ -166,6 +167,13 @@ public:
}
}
+ template<VoidFunction<VMObject&> Callback>
+ static void for_each_vmobject(Callback callback)
+ {
+ for (auto& vmobject : MM.m_vmobjects)
+ callback(vmobject);
+ }
+
static Region* find_region_from_vaddr(Space&, VirtualAddress);
static Region* find_user_region_from_vaddr(Space&, VirtualAddress);