Skip to content

Commit

Permalink
Kernel: Add a syscall to clear the profiling buffer
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
bgianfo authored and awesomekling committed Apr 19, 2021
1 parent cdd9faa commit 4ed682a
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 0 deletions.
1 change: 1 addition & 0 deletions Kernel/API/Syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ namespace Kernel {
S(purge) \
S(profiling_enable) \
S(profiling_disable) \
S(profiling_free_buffer) \
S(futex) \
S(chroot) \
S(pledge) \
Expand Down
6 changes: 6 additions & 0 deletions Kernel/Process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 };
Expand Down
2 changes: 2 additions & 0 deletions Kernel/Process.h
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,7 @@ class Process
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*>);
Expand Down Expand Up @@ -520,6 +521,7 @@ class Process
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);
Expand Down
33 changes: 33 additions & 0 deletions Kernel/Syscalls/profiling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
}
}

0 comments on commit 4ed682a

Please sign in to comment.