mirror of
https://github.com/SerenityOS/serenity.git
synced 2025-01-22 17:31:58 -05:00
Kernel: Track performance events for context switches
This commit is contained in:
parent
c94440860e
commit
8b2ace0326
6 changed files with 29 additions and 2 deletions
|
@ -107,6 +107,10 @@ KResult PerformanceEventBuffer::append_with_eip_and_ebp(ProcessID pid, ThreadID
|
||||||
break;
|
break;
|
||||||
case PERF_EVENT_THREAD_EXIT:
|
case PERF_EVENT_THREAD_EXIT:
|
||||||
break;
|
break;
|
||||||
|
case PERF_EVENT_CONTEXT_SWITCH:
|
||||||
|
event.data.context_switch.next_pid = arg1;
|
||||||
|
event.data.context_switch.next_tid = arg2;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -180,6 +184,11 @@ bool PerformanceEventBuffer::to_json_impl(Serializer& object) const
|
||||||
case PERF_EVENT_THREAD_EXIT:
|
case PERF_EVENT_THREAD_EXIT:
|
||||||
event_object.add("type", "thread_exit");
|
event_object.add("type", "thread_exit");
|
||||||
break;
|
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("pid", event.pid);
|
||||||
event_object.add("tid", event.tid);
|
event_object.add("tid", event.tid);
|
||||||
|
|
|
@ -47,6 +47,11 @@ struct [[gnu::packed]] ThreadCreatePerformanceEvent {
|
||||||
pid_t parent_tid;
|
pid_t parent_tid;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct [[gnu::packed]] ContextSwitchPerformanceEvent {
|
||||||
|
pid_t next_pid;
|
||||||
|
u32 next_tid;
|
||||||
|
};
|
||||||
|
|
||||||
struct [[gnu::packed]] PerformanceEvent {
|
struct [[gnu::packed]] PerformanceEvent {
|
||||||
u8 type { 0 };
|
u8 type { 0 };
|
||||||
u8 stack_size { 0 };
|
u8 stack_size { 0 };
|
||||||
|
@ -62,6 +67,7 @@ struct [[gnu::packed]] PerformanceEvent {
|
||||||
ProcessCreatePerformanceEvent process_create;
|
ProcessCreatePerformanceEvent process_create;
|
||||||
ProcessExecPerformanceEvent process_exec;
|
ProcessExecPerformanceEvent process_exec;
|
||||||
ThreadCreatePerformanceEvent thread_create;
|
ThreadCreatePerformanceEvent thread_create;
|
||||||
|
ContextSwitchPerformanceEvent context_switch;
|
||||||
} data;
|
} data;
|
||||||
static constexpr size_t max_stack_frame_count = 64;
|
static constexpr size_t max_stack_frame_count = 64;
|
||||||
FlatPtr stack[max_stack_frame_count];
|
FlatPtr stack[max_stack_frame_count];
|
||||||
|
|
|
@ -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)
|
inline static void timer_tick(RegisterState const& regs)
|
||||||
{
|
{
|
||||||
static Time last_wakeup;
|
static Time last_wakeup;
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <AK/Time.h>
|
#include <AK/Time.h>
|
||||||
#include <Kernel/Debug.h>
|
#include <Kernel/Debug.h>
|
||||||
#include <Kernel/Panic.h>
|
#include <Kernel/Panic.h>
|
||||||
|
#include <Kernel/PerformanceManager.h>
|
||||||
#include <Kernel/Process.h>
|
#include <Kernel/Process.h>
|
||||||
#include <Kernel/RTC.h>
|
#include <Kernel/RTC.h>
|
||||||
#include <Kernel/Scheduler.h>
|
#include <Kernel/Scheduler.h>
|
||||||
|
@ -365,6 +366,8 @@ bool Scheduler::context_switch(Thread* thread)
|
||||||
}
|
}
|
||||||
thread->set_state(Thread::Running);
|
thread->set_state(Thread::Running);
|
||||||
|
|
||||||
|
PerformanceManager::add_context_switch_perf_event(*from_thread, *thread);
|
||||||
|
|
||||||
proc.switch_context(from_thread, thread);
|
proc.switch_context(from_thread, thread);
|
||||||
|
|
||||||
// NOTE: from_thread at this point reflects the thread we were
|
// NOTE: from_thread at this point reflects the thread we were
|
||||||
|
|
|
@ -56,7 +56,8 @@ enum {
|
||||||
PERF_EVENT_PROCESS_EXEC,
|
PERF_EVENT_PROCESS_EXEC,
|
||||||
PERF_EVENT_PROCESS_EXIT,
|
PERF_EVENT_PROCESS_EXIT,
|
||||||
PERF_EVENT_THREAD_CREATE,
|
PERF_EVENT_THREAD_CREATE,
|
||||||
PERF_EVENT_THREAD_EXIT
|
PERF_EVENT_THREAD_EXIT,
|
||||||
|
PERF_EVENT_CONTEXT_SWITCH,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define WNOHANG 1
|
#define WNOHANG 1
|
||||||
|
|
|
@ -85,7 +85,8 @@ enum {
|
||||||
PERF_EVENT_PROCESS_EXEC,
|
PERF_EVENT_PROCESS_EXEC,
|
||||||
PERF_EVENT_PROCESS_EXIT,
|
PERF_EVENT_PROCESS_EXIT,
|
||||||
PERF_EVENT_THREAD_CREATE,
|
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);
|
int perf_event(int type, uintptr_t arg1, uintptr_t arg2);
|
||||||
|
|
Loading…
Reference in a new issue