summaryrefslogtreecommitdiff
path: root/Kernel/Scheduler.cpp
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2021-03-02 17:19:35 +0100
committerAndreas Kling <kling@serenityos.org>2021-03-02 22:38:06 +0100
commitea500dd3e31f531212af2e9a33ff40f26de48594 (patch)
treed70115636c4445ca450a68ea2107427275e1e7f7 /Kernel/Scheduler.cpp
parentb425c2602c6dd10b5509fcd8d81c765b9c76993a (diff)
downloadserenity-ea500dd3e31f531212af2e9a33ff40f26de48594.zip
Kernel: Start work on full system profiling :^)
The superuser can now call sys$profiling_enable() with PID -1 to enable profiling of all running threads in the system. The perf events are collected in a global PerformanceEventBuffer (currently 32 MiB in size.) The events can be accessed via /proc/profile
Diffstat (limited to 'Kernel/Scheduler.cpp')
-rw-r--r--Kernel/Scheduler.cpp21
1 files changed, 18 insertions, 3 deletions
diff --git a/Kernel/Scheduler.cpp b/Kernel/Scheduler.cpp
index 0bf6e0b6e0..fb71b6af28 100644
--- a/Kernel/Scheduler.cpp
+++ b/Kernel/Scheduler.cpp
@@ -42,6 +42,9 @@
namespace Kernel {
+extern bool g_profiling_all_threads;
+extern PerformanceEventBuffer* g_global_perf_events;
+
class SchedulerPerProcessorData {
AK_MAKE_NONCOPYABLE(SchedulerPerProcessorData);
AK_MAKE_NONMOVABLE(SchedulerPerProcessorData);
@@ -542,10 +545,22 @@ void Scheduler::timer_tick(const RegisterState& regs)
if (!is_bsp)
return; // TODO: This prevents scheduling on other CPUs!
#endif
- if (current_thread->process().is_profiling()) {
+
+ PerformanceEventBuffer* perf_events = nullptr;
+
+ if (g_profiling_all_threads) {
+ VERIFY(g_global_perf_events);
+ // FIXME: We currently don't collect samples while idle.
+ // That will be an interesting mode to add in the future. :^)
+ if (current_thread != Processor::current().idle_thread())
+ perf_events = g_global_perf_events;
+ } else if (current_thread->process().is_profiling()) {
VERIFY(current_thread->process().perf_events());
- auto& perf_events = *current_thread->process().perf_events();
- [[maybe_unused]] auto rc = perf_events.append_with_eip_and_ebp(regs.eip, regs.ebp, PERF_EVENT_SAMPLE, 0, 0);
+ perf_events = current_thread->process().perf_events();
+ }
+
+ if (perf_events) {
+ [[maybe_unused]] auto rc = perf_events->append_with_eip_and_ebp(regs.eip, regs.ebp, PERF_EVENT_SAMPLE, 0, 0);
}
if (current_thread->tick())