From ccdcb6a63523c6862c873090c181c9b36e5a5c38 Mon Sep 17 00:00:00 2001 From: Brian Gianforcaro Date: Thu, 6 May 2021 22:29:19 -0700 Subject: [PATCH] Kernel: Add PerformanceManager static class, move perf event APIs there The current method of emitting performance events requires a bit of boiler plate at every invocation, as well as having to ignore the return code which isn't used outside of the perf event syscall. This change attempts to clean that up by exposing high level API's that can be used around the code base. --- Kernel/PerformanceEventBuffer.cpp | 3 +- Kernel/PerformanceEventBuffer.h | 2 +- Kernel/PerformanceManager.h | 47 +++++++++++++++++++++++++++++++ Kernel/Process.h | 1 + Kernel/Syscalls/exit.cpp | 9 +++--- Kernel/Syscalls/mmap.cpp | 28 ++++++++---------- Kernel/Syscalls/thread.cpp | 13 ++++----- 7 files changed, 70 insertions(+), 33 deletions(-) create mode 100644 Kernel/PerformanceManager.h diff --git a/Kernel/PerformanceEventBuffer.cpp b/Kernel/PerformanceEventBuffer.cpp index f7c7983e43..29ce426aec 100644 --- a/Kernel/PerformanceEventBuffer.cpp +++ b/Kernel/PerformanceEventBuffer.cpp @@ -20,12 +20,11 @@ PerformanceEventBuffer::PerformanceEventBuffer(NonnullOwnPtr buffer) { } -NEVER_INLINE KResult PerformanceEventBuffer::append(int type, FlatPtr arg1, FlatPtr arg2, const StringView& arg3) +NEVER_INLINE KResult PerformanceEventBuffer::append(int type, FlatPtr arg1, FlatPtr arg2, const StringView& arg3, Thread* current_thread) { FlatPtr ebp; asm volatile("movl %%ebp, %%eax" : "=a"(ebp)); - auto current_thread = Thread::current(); return append_with_eip_and_ebp(current_thread->pid(), current_thread->tid(), 0, ebp, type, arg1, arg2, arg3); } diff --git a/Kernel/PerformanceEventBuffer.h b/Kernel/PerformanceEventBuffer.h index c6c589bedb..61f1fd1cba 100644 --- a/Kernel/PerformanceEventBuffer.h +++ b/Kernel/PerformanceEventBuffer.h @@ -75,7 +75,7 @@ class PerformanceEventBuffer { public: static OwnPtr try_create_with_size(size_t buffer_size); - KResult append(int type, FlatPtr arg1, FlatPtr arg2, const StringView& arg3); + KResult append(int type, FlatPtr arg1, FlatPtr arg2, const StringView& arg3, Thread* current_thread = Thread::current()); KResult append_with_eip_and_ebp(ProcessID pid, ThreadID tid, u32 eip, u32 ebp, int type, FlatPtr arg1, FlatPtr arg2, const StringView& arg3); diff --git a/Kernel/PerformanceManager.h b/Kernel/PerformanceManager.h new file mode 100644 index 0000000000..c3ffd33723 --- /dev/null +++ b/Kernel/PerformanceManager.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021, Brian Gianforcaro + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include + +namespace Kernel { + +class PerformanceManager { + +public: + inline static void add_thread_created_event(Thread& thread) + { + if (auto* event_buffer = thread.process().current_perf_events_buffer()) { + [[maybe_unused]] auto rc = event_buffer->append(PERF_EVENT_THREAD_CREATE, thread.tid().value(), 0, nullptr, &thread); + } + } + + inline static void add_thread_exit_event(Thread& thread) + { + if (auto* event_buffer = thread.process().current_perf_events_buffer()) { + [[maybe_unused]] auto rc = event_buffer->append(PERF_EVENT_THREAD_EXIT, thread.tid().value(), 0, nullptr, &thread); + } + } + + inline static void add_mmap_perf_event(Process& current_process, Region const& region) + { + if (auto* event_buffer = current_process.current_perf_events_buffer()) { + [[maybe_unused]] auto res = event_buffer->append(PERF_EVENT_MMAP, region.vaddr().get(), region.size(), region.name()); + } + } + + inline static void add_unmap_perf_event(Process& current_process, Range const& region) + { + if (auto* event_buffer = current_process.current_perf_events_buffer()) { + [[maybe_unused]] auto res = event_buffer->append(PERF_EVENT_MUNMAP, region.base().get(), region.size(), nullptr); + } + } +}; + +} diff --git a/Kernel/Process.h b/Kernel/Process.h index bdbfddca41..054bcc1621 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -492,6 +492,7 @@ private: friend class MemoryManager; friend class Scheduler; friend class Region; + friend class PerformanceManager; bool add_thread(Thread&); bool remove_thread(Thread&); diff --git a/Kernel/Syscalls/exit.cpp b/Kernel/Syscalls/exit.cpp index 1f60ae9094..fa2faf357b 100644 --- a/Kernel/Syscalls/exit.cpp +++ b/Kernel/Syscalls/exit.cpp @@ -5,7 +5,7 @@ */ #include -#include +#include #include namespace Kernel { @@ -18,12 +18,11 @@ void Process::sys$exit(int status) m_termination_signal = 0; } - if (auto* event_buffer = current_perf_events_buffer()) { - [[maybe_unused]] auto rc = event_buffer->append(PERF_EVENT_THREAD_EXIT, Thread::current()->tid().value(), 0, nullptr); - } + auto* current_thread = Thread::current(); + PerformanceManager::add_thread_exit_event(*current_thread); die(); - Thread::current()->die_if_needed(); + current_thread->die_if_needed(); VERIFY_NOT_REACHED(); } diff --git a/Kernel/Syscalls/mmap.cpp b/Kernel/Syscalls/mmap.cpp index 6c0f70f191..16bb423f97 100644 --- a/Kernel/Syscalls/mmap.cpp +++ b/Kernel/Syscalls/mmap.cpp @@ -5,10 +5,10 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include #include #include #include +#include #include #include #include @@ -248,11 +248,6 @@ KResultOr Process::sys$mmap(Userspace u if (!region) return ENOMEM; - if (auto* event_buffer = current_perf_events_buffer()) { - [[maybe_unused]] auto res = event_buffer->append(PERF_EVENT_MMAP, region->vaddr().get(), - region->size(), name.is_null() ? region->name() : name); - } - region->set_mmap(true); if (map_shared) region->set_shared(true); @@ -260,6 +255,9 @@ KResultOr Process::sys$mmap(Userspace u region->set_stack(true); if (!name.is_null()) region->set_name(name); + + PerformanceManager::add_mmap_perf_event(*this, *region); + return region->vaddr().get(); } @@ -437,10 +435,10 @@ KResultOr Process::sys$set_mmap_name(Userspaceis_mmap()) return EPERM; - if (auto* event_buffer = current_perf_events_buffer()) { - [[maybe_unused]] auto res = event_buffer->append(PERF_EVENT_MMAP, region->vaddr().get(), region->size(), name.characters()); - } + region->set_name(move(name)); + PerformanceManager::add_mmap_perf_event(*this, *region); + return 0; } @@ -463,13 +461,11 @@ KResultOr Process::sys$munmap(Userspace addr, size_t size) if (auto* whole_region = space().find_region_from_range(range_to_unmap)) { if (!whole_region->is_mmap()) return EPERM; - auto base = whole_region->vaddr(); - auto size = whole_region->size(); + + PerformanceManager::add_unmap_perf_event(*this, whole_region->range()); + bool success = space().deallocate_region(*whole_region); VERIFY(success); - if (auto* event_buffer = current_perf_events_buffer()) { - [[maybe_unused]] auto res = event_buffer->append(PERF_EVENT_MUNMAP, base.get(), size, nullptr); - } return 0; } @@ -542,9 +538,7 @@ KResultOr Process::sys$munmap(Userspace addr, size_t size) new_region->map(space().page_directory()); } - if (auto* event_buffer = current_perf_events_buffer()) { - [[maybe_unused]] auto res = event_buffer->append(PERF_EVENT_MUNMAP, range_to_unmap.base().get(), range_to_unmap.size(), nullptr); - } + PerformanceManager::add_unmap_perf_event(*this, range_to_unmap); return 0; } diff --git a/Kernel/Syscalls/thread.cpp b/Kernel/Syscalls/thread.cpp index bbffef9866..42acab2690 100644 --- a/Kernel/Syscalls/thread.cpp +++ b/Kernel/Syscalls/thread.cpp @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include #include @@ -70,9 +70,7 @@ KResultOr Process::sys$create_thread(void* (*entry)(void*), Userspaceappend(PERF_EVENT_THREAD_CREATE, thread->tid().value(), 0, nullptr); - } + PerformanceManager::add_thread_created_event(*thread); ScopedSpinLock lock(g_scheduler_lock); thread->set_priority(requested_thread_priority); @@ -89,11 +87,10 @@ void Process::sys$exit_thread(Userspace exit_value) this->sys$exit(0); } - if (auto* event_buffer = current_perf_events_buffer()) { - [[maybe_unused]] auto rc = event_buffer->append(PERF_EVENT_THREAD_EXIT, 0, 0, nullptr); - } + auto current_thread = Thread::current(); + PerformanceManager::add_thread_exit_event(*current_thread); - Thread::current()->exit(reinterpret_cast(exit_value.ptr())); + current_thread->exit(reinterpret_cast(exit_value.ptr())); VERIFY_NOT_REACHED(); }