diff --git a/Kernel/PerformanceEventBuffer.cpp b/Kernel/PerformanceEventBuffer.cpp index 0e5e3cb3a41..f461ad8db9d 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 7157d0e655e..c05ad84d290 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 58f6e80f1ad..6c71c0b94e3 100644 --- a/Kernel/Syscall.cpp +++ b/Kernel/Syscall.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -108,6 +109,8 @@ KResultOr 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 44a3351a8a3..9ebc56bca81 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 649c0914eb2..a2533479d6a 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 d1362ef8da8..e11eac5d15e 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)) {