From 4ed682aebc36febc6bff9738ac4e97be02c928a9 Mon Sep 17 00:00:00 2001 From: Brian Gianforcaro Date: Sun, 18 Apr 2021 21:10:05 -0700 Subject: [PATCH] Kernel: Add a syscall to clear the profiling buffer While profiling all processes the profile buffer lives forever. Once you have copied the profile to disk, there's no need to keep it in memory. This syscall surfaces the ability to clear that buffer. --- Kernel/API/Syscall.h | 1 + Kernel/Process.cpp | 6 ++++++ Kernel/Process.h | 2 ++ Kernel/Syscalls/profiling.cpp | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 42 insertions(+) diff --git a/Kernel/API/Syscall.h b/Kernel/API/Syscall.h index 11d68073027..db876d786d0 100644 --- a/Kernel/API/Syscall.h +++ b/Kernel/API/Syscall.h @@ -171,6 +171,7 @@ namespace Kernel { S(purge) \ S(profiling_enable) \ S(profiling_disable) \ + S(profiling_free_buffer) \ S(futex) \ S(chroot) \ S(pledge) \ diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index fb18f737961..c3eba414ffc 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -700,6 +700,12 @@ bool Process::create_perf_events_buffer_if_needed() return !!m_perf_event_buffer; } +void Process::delete_perf_events_buffer() +{ + if (m_perf_event_buffer) + m_perf_event_buffer = nullptr; +} + bool Process::remove_thread(Thread& thread) { ProtectedDataMutationScope scope { *this }; diff --git a/Kernel/Process.h b/Kernel/Process.h index 8a4f4f76539..7f2d64d458a 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -394,6 +394,7 @@ public: KResultOr sys$module_unload(Userspace name, size_t name_length); KResultOr sys$profiling_enable(pid_t); KResultOr sys$profiling_disable(pid_t); + KResultOr sys$profiling_free_buffer(pid_t); KResultOr sys$futex(Userspace); KResultOr sys$chroot(Userspace path, size_t path_length, int mount_flags); KResultOr sys$pledge(Userspace); @@ -520,6 +521,7 @@ private: bool dump_core(); bool dump_perfcore(); bool create_perf_events_buffer_if_needed(); + void delete_perf_events_buffer(); KResult do_exec(NonnullRefPtr main_program_description, Vector arguments, Vector environment, RefPtr interpreter_description, Thread*& new_main_thread, u32& prev_flags, const Elf32_Ehdr& main_program_header); KResultOr do_write(FileDescription&, const UserOrKernelBuffer&, size_t); diff --git a/Kernel/Syscalls/profiling.cpp b/Kernel/Syscalls/profiling.cpp index 62aa46a4436..182fa092853 100644 --- a/Kernel/Syscalls/profiling.cpp +++ b/Kernel/Syscalls/profiling.cpp @@ -67,6 +67,8 @@ KResultOr Process::sys$profiling_enable(pid_t pid) KResultOr Process::sys$profiling_disable(pid_t pid) { + REQUIRE_NO_PROMISES; + if (pid == -1) { if (!is_superuser()) return EPERM; @@ -87,4 +89,35 @@ KResultOr Process::sys$profiling_disable(pid_t pid) return 0; } +KResultOr Process::sys$profiling_free_buffer(pid_t pid) +{ + REQUIRE_NO_PROMISES; + + if (pid == -1) { + if (!is_superuser()) + return EPERM; + + OwnPtr perf_events; + + { + ScopedCritical critical; + + perf_events = g_global_perf_events; + g_global_perf_events = nullptr; + } + + return 0; + } + + ScopedSpinLock lock(g_processes_lock); + auto process = Process::from_pid(pid); + if (!process) + return ESRCH; + if (!is_superuser() && process->uid() != euid()) + return EPERM; + if (process->is_profiling()) + return EINVAL; + process->delete_perf_events_buffer(); + return 0; +} }