diff options
author | Gunnar Beutner <gbeutner@serenityos.org> | 2021-05-14 07:48:53 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-05-19 22:51:42 +0200 |
commit | 8b2ace0326bceb28bdf80c0a09e8297acf39df97 (patch) | |
tree | a1c0cd63cef77a6793035a9ca8a5820c773f6e56 | |
parent | c94440860e46cca9b66afba833c0771515da16fb (diff) | |
download | serenity-8b2ace0326bceb28bdf80c0a09e8297acf39df97.zip |
Kernel: Track performance events for context switches
-rw-r--r-- | Kernel/PerformanceEventBuffer.cpp | 9 | ||||
-rw-r--r-- | Kernel/PerformanceEventBuffer.h | 6 | ||||
-rw-r--r-- | Kernel/PerformanceManager.h | 7 | ||||
-rw-r--r-- | Kernel/Scheduler.cpp | 3 | ||||
-rw-r--r-- | Kernel/UnixTypes.h | 3 | ||||
-rw-r--r-- | Userland/Libraries/LibC/serenity.h | 3 |
6 files changed, 29 insertions, 2 deletions
diff --git a/Kernel/PerformanceEventBuffer.cpp b/Kernel/PerformanceEventBuffer.cpp index 8b1c7a11a5..2fa5b8680d 100644 --- a/Kernel/PerformanceEventBuffer.cpp +++ b/Kernel/PerformanceEventBuffer.cpp @@ -107,6 +107,10 @@ KResult PerformanceEventBuffer::append_with_eip_and_ebp(ProcessID pid, ThreadID break; case PERF_EVENT_THREAD_EXIT: break; + case PERF_EVENT_CONTEXT_SWITCH: + event.data.context_switch.next_pid = arg1; + event.data.context_switch.next_tid = arg2; + break; default: return EINVAL; } @@ -180,6 +184,11 @@ bool PerformanceEventBuffer::to_json_impl(Serializer& object) const case PERF_EVENT_THREAD_EXIT: event_object.add("type", "thread_exit"); break; + case PERF_EVENT_CONTEXT_SWITCH: + event_object.add("type", "context_switch"); + event_object.add("next_pid", static_cast<u64>(event.data.context_switch.next_pid)); + event_object.add("next_tid", static_cast<u64>(event.data.context_switch.next_tid)); + break; } event_object.add("pid", event.pid); event_object.add("tid", event.tid); diff --git a/Kernel/PerformanceEventBuffer.h b/Kernel/PerformanceEventBuffer.h index cfff3ac2e5..4b31b5f516 100644 --- a/Kernel/PerformanceEventBuffer.h +++ b/Kernel/PerformanceEventBuffer.h @@ -47,6 +47,11 @@ struct [[gnu::packed]] ThreadCreatePerformanceEvent { pid_t parent_tid; }; +struct [[gnu::packed]] ContextSwitchPerformanceEvent { + pid_t next_pid; + u32 next_tid; +}; + struct [[gnu::packed]] PerformanceEvent { u8 type { 0 }; u8 stack_size { 0 }; @@ -62,6 +67,7 @@ struct [[gnu::packed]] PerformanceEvent { ProcessCreatePerformanceEvent process_create; ProcessExecPerformanceEvent process_exec; ThreadCreatePerformanceEvent thread_create; + ContextSwitchPerformanceEvent context_switch; } data; static constexpr size_t max_stack_frame_count = 64; FlatPtr stack[max_stack_frame_count]; diff --git a/Kernel/PerformanceManager.h b/Kernel/PerformanceManager.h index ddd21de248..cdf699e61d 100644 --- a/Kernel/PerformanceManager.h +++ b/Kernel/PerformanceManager.h @@ -85,6 +85,13 @@ public: } } + inline static void add_context_switch_perf_event(Thread& current_thread, Thread& next_thread) + { + if (auto* event_buffer = current_thread.process().current_perf_events_buffer()) { + [[maybe_unused]] auto res = event_buffer->append(PERF_EVENT_CONTEXT_SWITCH, next_thread.pid().value(), next_thread.tid().value(), nullptr); + } + } + inline static void timer_tick(RegisterState const& regs) { static Time last_wakeup; diff --git a/Kernel/Scheduler.cpp b/Kernel/Scheduler.cpp index b4df7f8a1e..3642fd8c6f 100644 --- a/Kernel/Scheduler.cpp +++ b/Kernel/Scheduler.cpp @@ -10,6 +10,7 @@ #include <AK/Time.h> #include <Kernel/Debug.h> #include <Kernel/Panic.h> +#include <Kernel/PerformanceManager.h> #include <Kernel/Process.h> #include <Kernel/RTC.h> #include <Kernel/Scheduler.h> @@ -365,6 +366,8 @@ bool Scheduler::context_switch(Thread* thread) } thread->set_state(Thread::Running); + PerformanceManager::add_context_switch_perf_event(*from_thread, *thread); + proc.switch_context(from_thread, thread); // NOTE: from_thread at this point reflects the thread we were diff --git a/Kernel/UnixTypes.h b/Kernel/UnixTypes.h index c981d7727a..f1d2a0a27d 100644 --- a/Kernel/UnixTypes.h +++ b/Kernel/UnixTypes.h @@ -56,7 +56,8 @@ enum { PERF_EVENT_PROCESS_EXEC, PERF_EVENT_PROCESS_EXIT, PERF_EVENT_THREAD_CREATE, - PERF_EVENT_THREAD_EXIT + PERF_EVENT_THREAD_EXIT, + PERF_EVENT_CONTEXT_SWITCH, }; #define WNOHANG 1 diff --git a/Userland/Libraries/LibC/serenity.h b/Userland/Libraries/LibC/serenity.h index 846e4ab6a3..72282cf449 100644 --- a/Userland/Libraries/LibC/serenity.h +++ b/Userland/Libraries/LibC/serenity.h @@ -85,7 +85,8 @@ enum { PERF_EVENT_PROCESS_EXEC, PERF_EVENT_PROCESS_EXIT, PERF_EVENT_THREAD_CREATE, - PERF_EVENT_THREAD_EXIT + PERF_EVENT_THREAD_EXIT, + PERF_EVENT_CONTEXT_SWITCH, }; int perf_event(int type, uintptr_t arg1, uintptr_t arg2); |