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(); }