diff options
author | Jean-Baptiste Boric <jblbeurope@gmail.com> | 2021-08-10 21:02:59 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-08-10 21:55:48 +0200 |
commit | 0286160b62dd4871ddddd89276398739d7d737b0 (patch) | |
tree | 020c7d332ce12f51e92a9625584799a161660968 | |
parent | 4c4b8ea443bceb14e041e6d4e6b6a56988aad0c7 (diff) | |
download | serenity-0286160b62dd4871ddddd89276398739d7d737b0.zip |
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.
-rw-r--r-- | Kernel/PerformanceEventBuffer.cpp | 5 | ||||
-rw-r--r-- | Kernel/PerformanceManager.h | 11 | ||||
-rw-r--r-- | Kernel/Syscall.cpp | 3 | ||||
-rw-r--r-- | Kernel/UnixTypes.h | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibC/serenity.h | 1 | ||||
-rw-r--r-- | Userland/Utilities/profile.cpp | 4 |
6 files changed, 24 insertions, 1 deletions
diff --git a/Kernel/PerformanceEventBuffer.cpp b/Kernel/PerformanceEventBuffer.cpp index 0e5e3cb3a4..f461ad8db9 100644 --- a/Kernel/PerformanceEventBuffer.cpp +++ b/Kernel/PerformanceEventBuffer.cpp @@ -135,6 +135,8 @@ KResult PerformanceEventBuffer::append_with_ip_and_bp(ProcessID pid, ThreadID ti break; case PERF_EVENT_PAGE_FAULT: break; + case PERF_EVENT_SYSCALL: + break; default: return EINVAL; } @@ -226,6 +228,9 @@ bool PerformanceEventBuffer::to_json_impl(Serializer& object) const case PERF_EVENT_PAGE_FAULT: event_object.add("type", "page_fault"); break; + case PERF_EVENT_SYSCALL: + event_object.add("type", "syscall"); + break; } event_object.add("pid", event.pid); event_object.add("tid", event.tid); diff --git a/Kernel/PerformanceManager.h b/Kernel/PerformanceManager.h index 7157d0e655..c05ad84d29 100644 --- a/Kernel/PerformanceManager.h +++ b/Kernel/PerformanceManager.h @@ -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) { static Time last_wakeup; diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp index 58f6e80f1a..6c71c0b94e 100644 --- a/Kernel/Syscall.cpp +++ b/Kernel/Syscall.cpp @@ -9,6 +9,7 @@ #include <Kernel/Arch/x86/TrapFrame.h> #include <Kernel/Memory/MemoryManager.h> #include <Kernel/Panic.h> +#include <Kernel/PerformanceManager.h> #include <Kernel/Process.h> #include <Kernel/Sections.h> #include <Kernel/ThreadTracer.h> @@ -108,6 +109,8 @@ KResultOr<FlatPtr> handle(RegisterState& regs, FlatPtr function, FlatPtr arg1, F auto& process = current_thread->process(); current_thread->did_syscall(); + PerformanceManager::add_syscall_event(*current_thread, regs); + if (function >= Function::__Count) { dbgln("Unknown syscall {} requested ({:p}, {:p}, {:p}, {:p})", function, arg1, arg2, arg3, arg4); return ENOSYS; diff --git a/Kernel/UnixTypes.h b/Kernel/UnixTypes.h index 44a3351a8a..9ebc56bca8 100644 --- a/Kernel/UnixTypes.h +++ b/Kernel/UnixTypes.h @@ -62,6 +62,7 @@ enum { PERF_EVENT_KMALLOC = 2048, PERF_EVENT_KFREE = 4096, PERF_EVENT_PAGE_FAULT = 8192, + PERF_EVENT_SYSCALL = 16384, }; #define WNOHANG 1 diff --git a/Userland/Libraries/LibC/serenity.h b/Userland/Libraries/LibC/serenity.h index 649c0914eb..a2533479d6 100644 --- a/Userland/Libraries/LibC/serenity.h +++ b/Userland/Libraries/LibC/serenity.h @@ -112,6 +112,7 @@ enum { PERF_EVENT_KMALLOC = 2048, PERF_EVENT_KFREE = 4096, PERF_EVENT_PAGE_FAULT = 8192, + PERF_EVENT_SYSCALL = 16384, }; #define PERF_EVENT_MASK_ALL (~0ull) diff --git a/Userland/Utilities/profile.cpp b/Userland/Utilities/profile.cpp index d1362ef8da..e11eac5d15 100644 --- a/Userland/Utilities/profile.cpp +++ b/Userland/Utilities/profile.cpp @@ -45,6 +45,8 @@ int main(int argc, char** argv) event_mask |= PERF_EVENT_KFREE; else if (event_type == "page_fault") event_mask |= PERF_EVENT_PAGE_FAULT; + else if (event_type == "syscall") + event_mask |= PERF_EVENT_SYSCALL; else { warnln("Unknown event type '{}' specified.", event_type); exit(1); @@ -54,7 +56,7 @@ int main(int argc, char** argv) auto print_types = [] { 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)) { |