Kernel: Track performance events for context switches

This commit is contained in:
Gunnar Beutner 2021-05-14 07:48:53 +02:00 committed by Andreas Kling
parent c94440860e
commit 8b2ace0326
Notes: sideshowbarker 2024-07-18 17:45:47 +09:00
6 changed files with 29 additions and 2 deletions

View file

@ -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);

View file

@ -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];

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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);