summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Gianforcaro <b.gianfo@gmail.com>2021-04-18 21:10:05 -0700
committerAndreas Kling <kling@serenityos.org>2021-04-19 18:30:37 +0200
commit4ed682aebc36febc6bff9738ac4e97be02c928a9 (patch)
tree8e499feb28f8fa878763445908a0deb9ead2b029
parentcdd9faaf39d711071d22777ed581590234781407 (diff)
downloadserenity-4ed682aebc36febc6bff9738ac4e97be02c928a9.zip
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.
-rw-r--r--Kernel/API/Syscall.h1
-rw-r--r--Kernel/Process.cpp6
-rw-r--r--Kernel/Process.h2
-rw-r--r--Kernel/Syscalls/profiling.cpp33
4 files changed, 42 insertions, 0 deletions
diff --git a/Kernel/API/Syscall.h b/Kernel/API/Syscall.h
index 11d6807302..db876d786d 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 fb18f73796..c3eba414ff 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 8a4f4f7653..7f2d64d458 100644
--- a/Kernel/Process.h
+++ b/Kernel/Process.h
@@ -394,6 +394,7 @@ public:
KResultOr<int> sys$module_unload(Userspace<const char*> name, size_t name_length);
KResultOr<int> sys$profiling_enable(pid_t);
KResultOr<int> sys$profiling_disable(pid_t);
+ KResultOr<int> sys$profiling_free_buffer(pid_t);
KResultOr<int> sys$futex(Userspace<const Syscall::SC_futex_params*>);
KResultOr<int> sys$chroot(Userspace<const char*> path, size_t path_length, int mount_flags);
KResultOr<int> sys$pledge(Userspace<const Syscall::SC_pledge_params*>);
@@ -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<FileDescription> main_program_description, Vector<String> arguments, Vector<String> environment, RefPtr<FileDescription> interpreter_description, Thread*& new_main_thread, u32& prev_flags, const Elf32_Ehdr& main_program_header);
KResultOr<ssize_t> do_write(FileDescription&, const UserOrKernelBuffer&, size_t);
diff --git a/Kernel/Syscalls/profiling.cpp b/Kernel/Syscalls/profiling.cpp
index 62aa46a443..182fa09285 100644
--- a/Kernel/Syscalls/profiling.cpp
+++ b/Kernel/Syscalls/profiling.cpp
@@ -67,6 +67,8 @@ KResultOr<int> Process::sys$profiling_enable(pid_t pid)
KResultOr<int> Process::sys$profiling_disable(pid_t pid)
{
+ REQUIRE_NO_PROMISES;
+
if (pid == -1) {
if (!is_superuser())
return EPERM;
@@ -87,4 +89,35 @@ KResultOr<int> Process::sys$profiling_disable(pid_t pid)
return 0;
}
+KResultOr<int> Process::sys$profiling_free_buffer(pid_t pid)
+{
+ REQUIRE_NO_PROMISES;
+
+ if (pid == -1) {
+ if (!is_superuser())
+ return EPERM;
+
+ OwnPtr<PerformanceEventBuffer> 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;
+}
}