mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-26 09:30:24 +00:00
Kernel: Add syscall performance event type
This allows tracing the syscalls made by a thread through the kernel's performance event framework, which is similar in principle to strace. Currently, this merely logs a stack backtrace to the current thread's performance event buffer whenever a syscall is made, if profiling is enabled. Future improvements could include tracing the arguments and the return value, for example.
This commit is contained in:
parent
4c4b8ea443
commit
0286160b62
Notes:
sideshowbarker
2024-07-18 07:09:05 +09:00
Author: https://github.com/boricj Commit: https://github.com/SerenityOS/serenity/commit/0286160b62d Pull-request: https://github.com/SerenityOS/serenity/pull/9329 Reviewed-by: https://github.com/gunnarbeutner ✅
6 changed files with 24 additions and 1 deletions
|
@ -135,6 +135,8 @@ KResult PerformanceEventBuffer::append_with_ip_and_bp(ProcessID pid, ThreadID ti
|
||||||
break;
|
break;
|
||||||
case PERF_EVENT_PAGE_FAULT:
|
case PERF_EVENT_PAGE_FAULT:
|
||||||
break;
|
break;
|
||||||
|
case PERF_EVENT_SYSCALL:
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -226,6 +228,9 @@ bool PerformanceEventBuffer::to_json_impl(Serializer& object) const
|
||||||
case PERF_EVENT_PAGE_FAULT:
|
case PERF_EVENT_PAGE_FAULT:
|
||||||
event_object.add("type", "page_fault");
|
event_object.add("type", "page_fault");
|
||||||
break;
|
break;
|
||||||
|
case PERF_EVENT_SYSCALL:
|
||||||
|
event_object.add("type", "syscall");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
event_object.add("pid", event.pid);
|
event_object.add("pid", event.pid);
|
||||||
event_object.add("tid", event.tid);
|
event_object.add("tid", event.tid);
|
||||||
|
|
|
@ -119,6 +119,17 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline static void add_syscall_event(Thread& thread, const RegisterState& regs)
|
||||||
|
{
|
||||||
|
if (thread.is_profiling_suppressed())
|
||||||
|
return;
|
||||||
|
if (auto* event_buffer = thread.process().current_perf_events_buffer()) {
|
||||||
|
[[maybe_unused]] auto rc = event_buffer->append_with_ip_and_bp(
|
||||||
|
thread.pid(), thread.tid(),
|
||||||
|
regs.ip(), regs.bp(), PERF_EVENT_SYSCALL, 0, 0, 0, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline static void timer_tick(RegisterState const& regs)
|
inline static void timer_tick(RegisterState const& regs)
|
||||||
{
|
{
|
||||||
static Time last_wakeup;
|
static Time last_wakeup;
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <Kernel/Arch/x86/TrapFrame.h>
|
#include <Kernel/Arch/x86/TrapFrame.h>
|
||||||
#include <Kernel/Memory/MemoryManager.h>
|
#include <Kernel/Memory/MemoryManager.h>
|
||||||
#include <Kernel/Panic.h>
|
#include <Kernel/Panic.h>
|
||||||
|
#include <Kernel/PerformanceManager.h>
|
||||||
#include <Kernel/Process.h>
|
#include <Kernel/Process.h>
|
||||||
#include <Kernel/Sections.h>
|
#include <Kernel/Sections.h>
|
||||||
#include <Kernel/ThreadTracer.h>
|
#include <Kernel/ThreadTracer.h>
|
||||||
|
@ -108,6 +109,8 @@ KResultOr<FlatPtr> handle(RegisterState& regs, FlatPtr function, FlatPtr arg1, F
|
||||||
auto& process = current_thread->process();
|
auto& process = current_thread->process();
|
||||||
current_thread->did_syscall();
|
current_thread->did_syscall();
|
||||||
|
|
||||||
|
PerformanceManager::add_syscall_event(*current_thread, regs);
|
||||||
|
|
||||||
if (function >= Function::__Count) {
|
if (function >= Function::__Count) {
|
||||||
dbgln("Unknown syscall {} requested ({:p}, {:p}, {:p}, {:p})", function, arg1, arg2, arg3, arg4);
|
dbgln("Unknown syscall {} requested ({:p}, {:p}, {:p}, {:p})", function, arg1, arg2, arg3, arg4);
|
||||||
return ENOSYS;
|
return ENOSYS;
|
||||||
|
|
|
@ -62,6 +62,7 @@ enum {
|
||||||
PERF_EVENT_KMALLOC = 2048,
|
PERF_EVENT_KMALLOC = 2048,
|
||||||
PERF_EVENT_KFREE = 4096,
|
PERF_EVENT_KFREE = 4096,
|
||||||
PERF_EVENT_PAGE_FAULT = 8192,
|
PERF_EVENT_PAGE_FAULT = 8192,
|
||||||
|
PERF_EVENT_SYSCALL = 16384,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define WNOHANG 1
|
#define WNOHANG 1
|
||||||
|
|
|
@ -112,6 +112,7 @@ enum {
|
||||||
PERF_EVENT_KMALLOC = 2048,
|
PERF_EVENT_KMALLOC = 2048,
|
||||||
PERF_EVENT_KFREE = 4096,
|
PERF_EVENT_KFREE = 4096,
|
||||||
PERF_EVENT_PAGE_FAULT = 8192,
|
PERF_EVENT_PAGE_FAULT = 8192,
|
||||||
|
PERF_EVENT_SYSCALL = 16384,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PERF_EVENT_MASK_ALL (~0ull)
|
#define PERF_EVENT_MASK_ALL (~0ull)
|
||||||
|
|
|
@ -45,6 +45,8 @@ int main(int argc, char** argv)
|
||||||
event_mask |= PERF_EVENT_KFREE;
|
event_mask |= PERF_EVENT_KFREE;
|
||||||
else if (event_type == "page_fault")
|
else if (event_type == "page_fault")
|
||||||
event_mask |= PERF_EVENT_PAGE_FAULT;
|
event_mask |= PERF_EVENT_PAGE_FAULT;
|
||||||
|
else if (event_type == "syscall")
|
||||||
|
event_mask |= PERF_EVENT_SYSCALL;
|
||||||
else {
|
else {
|
||||||
warnln("Unknown event type '{}' specified.", event_type);
|
warnln("Unknown event type '{}' specified.", event_type);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -54,7 +56,7 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
auto print_types = [] {
|
auto print_types = [] {
|
||||||
outln();
|
outln();
|
||||||
outln("Event type can be one of: sample, context_switch, page_fault, kmalloc and kfree.");
|
outln("Event type can be one of: sample, context_switch, page_fault, syscall, kmalloc and kfree.");
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!args_parser.parse(argc, argv, Core::ArgsParser::FailureBehavior::PrintUsage)) {
|
if (!args_parser.parse(argc, argv, Core::ArgsParser::FailureBehavior::PrintUsage)) {
|
||||||
|
|
Loading…
Reference in a new issue