summaryrefslogtreecommitdiff
path: root/Kernel
diff options
context:
space:
mode:
Diffstat (limited to 'Kernel')
-rw-r--r--Kernel/PerformanceEventBuffer.cpp9
-rw-r--r--Kernel/PerformanceEventBuffer.h6
-rw-r--r--Kernel/PerformanceManager.h7
-rw-r--r--Kernel/Scheduler.cpp3
-rw-r--r--Kernel/UnixTypes.h3
5 files changed, 27 insertions, 1 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