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.
This commit is contained in:
Brian Gianforcaro 2021-04-18 21:10:05 -07:00 committed by Andreas Kling
parent cdd9faaf39
commit 4ed682aebc
Notes: sideshowbarker 2024-07-18 19:23:05 +09:00
4 changed files with 42 additions and 0 deletions

View file

@ -171,6 +171,7 @@ namespace Kernel {
S(purge) \
S(profiling_enable) \
S(profiling_disable) \
S(profiling_free_buffer) \
S(futex) \
S(chroot) \
S(pledge) \

View file

@ -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 };

View file

@ -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);

View file

@ -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;
}
}