1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 21:08:12 +00:00

Kernel: Start work on full system profiling :^)

The superuser can now call sys$profiling_enable() with PID -1 to enable
profiling of all running threads in the system. The perf events are
collected in a global PerformanceEventBuffer (currently 32 MiB in size.)

The events can be accessed via /proc/profile
This commit is contained in:
Andreas Kling 2021-03-02 17:19:35 +01:00
parent b425c2602c
commit ea500dd3e3
5 changed files with 91 additions and 23 deletions

View file

@ -98,6 +98,7 @@ KResult PerformanceEventBuffer::append_with_eip_and_ebp(u32 eip, u32 ebp, int ty
event.stack_size = min(sizeof(event.stack) / sizeof(FlatPtr), static_cast<size_t>(backtrace.size()));
memcpy(event.stack, backtrace.data(), event.stack_size * sizeof(FlatPtr));
event.tid = Thread::current()->tid().value();
event.timestamp = TimeManagement::the().uptime_ms();
at(m_count++) = event;
return KSuccess;
@ -118,27 +119,9 @@ OwnPtr<KBuffer> PerformanceEventBuffer::to_json(ProcessID pid, const String& exe
return builder.build();
}
bool PerformanceEventBuffer::to_json(KBufferBuilder& builder, ProcessID pid, const String& executable_path) const
template<typename Serializer>
bool PerformanceEventBuffer::to_json_impl(Serializer& object) const
{
auto process = Process::from_pid(pid);
VERIFY(process);
ScopedSpinLock locker(process->space().get_lock());
JsonObjectSerializer object(builder);
object.add("pid", pid.value());
object.add("executable", executable_path);
{
auto region_array = object.add_array("regions");
for (const auto& region : process->space().regions()) {
auto region_object = region_array.add_object();
region_object.add("base", region.vaddr().get());
region_object.add("size", region.size());
region_object.add("name", region.name());
}
region_array.finish();
}
auto array = object.add_array("events");
for (size_t i = 0; i < m_count; ++i) {
auto& event = at(i);
@ -171,6 +154,36 @@ bool PerformanceEventBuffer::to_json(KBufferBuilder& builder, ProcessID pid, con
return true;
}
bool PerformanceEventBuffer::to_json(KBufferBuilder& builder)
{
JsonObjectSerializer object(builder);
return to_json_impl(object);
}
bool PerformanceEventBuffer::to_json(KBufferBuilder& builder, ProcessID pid, const String& executable_path) const
{
auto process = Process::from_pid(pid);
VERIFY(process);
ScopedSpinLock locker(process->space().get_lock());
JsonObjectSerializer object(builder);
object.add("pid", pid.value());
object.add("executable", executable_path);
{
auto region_array = object.add_array("regions");
for (const auto& region : process->space().regions()) {
auto region_object = region_array.add_object();
region_object.add("base", region.vaddr().get());
region_object.add("size", region.size());
region_object.add("name", region.name());
}
region_array.finish();
}
return to_json_impl(object);
}
OwnPtr<PerformanceEventBuffer> PerformanceEventBuffer::try_create_with_size(size_t buffer_size)
{
auto buffer = KBuffer::try_create_with_size(buffer_size, Region::Access::Read | Region::Access::Write, "Performance events", AllocationStrategy::AllocateNow);