summaryrefslogtreecommitdiff
path: root/Kernel
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2021-04-18 19:57:17 +0200
committerAndreas Kling <kling@serenityos.org>2021-04-18 20:00:10 +0200
commit24dcd99e4b3a0538e12c9975b03c9cbfb7ff226e (patch)
treef104007178682a343973e9336e8867d843fa867b /Kernel
parent685556ae84036fb84a363cbb8872264e8e54dbfc (diff)
downloadserenity-24dcd99e4b3a0538e12c9975b03c9cbfb7ff226e.zip
Kernel: Add magic key combo (Alt+Shift+F12) to dump scheduler state
Pressing this combo will dump a list of all threads and their state to the debug console. This might be useful to figure out why the system is not responding.
Diffstat (limited to 'Kernel')
-rw-r--r--Kernel/Devices/HID/PS2KeyboardDevice.cpp5
-rw-r--r--Kernel/Scheduler.cpp72
-rw-r--r--Kernel/Scheduler.h1
3 files changed, 55 insertions, 23 deletions
diff --git a/Kernel/Devices/HID/PS2KeyboardDevice.cpp b/Kernel/Devices/HID/PS2KeyboardDevice.cpp
index f2a822214c..4d68b467fe 100644
--- a/Kernel/Devices/HID/PS2KeyboardDevice.cpp
+++ b/Kernel/Devices/HID/PS2KeyboardDevice.cpp
@@ -53,6 +53,11 @@ void PS2KeyboardDevice::irq_handle_byte_read(u8 byte)
return;
}
+ if (m_modifiers == (Mod_Alt | Mod_Shift) && byte == 0x58) {
+ // Alt+Shift+F12 pressed, dump some kernel state to the debug console.
+ Scheduler::dump_scheduler_state();
+ }
+
dbgln_if(KEYBOARD_DEBUG, "Keyboard::irq_handle_byte_read: {:#02x} {}", ch, (pressed ? "down" : "up"));
switch (ch) {
case 0x38:
diff --git a/Kernel/Scheduler.cpp b/Kernel/Scheduler.cpp
index 4b8e33ee56..99eb042295 100644
--- a/Kernel/Scheduler.cpp
+++ b/Kernel/Scheduler.cpp
@@ -79,6 +79,7 @@ static SpinLock<u8> g_ready_queues_lock;
static u32 g_ready_queues_mask;
static constexpr u32 g_ready_queue_buckets = sizeof(g_ready_queues_mask) * 8;
READONLY_AFTER_INIT static ThreadReadyQueue* g_ready_queues; // g_ready_queue_buckets entries
+static void dump_thread_list();
static inline u32 thread_priority_to_priority_index(u32 thread_priority)
{
@@ -235,29 +236,7 @@ bool Scheduler::pick_next()
}
if constexpr (SCHEDULER_RUNNABLE_DEBUG) {
- dbgln("Scheduler thread list for processor {}:", Processor::id());
- Thread::for_each([&](Thread& thread) -> IterationDecision {
- switch (thread.state()) {
- case Thread::Dying:
- dbgln(" {:12} {} @ {:04x}:{:08x} Finalizable: {}",
- thread.state_string(),
- thread,
- thread.tss().cs,
- thread.tss().eip,
- thread.is_finalizable());
- break;
- default:
- dbgln(" {:12} Pr:{:2} {} @ {:04x}:{:08x}",
- thread.state_string(),
- thread.priority(),
- thread,
- thread.tss().cs,
- thread.tss().eip);
- break;
- }
-
- return IterationDecision::Continue;
- });
+ dump_thread_list();
}
auto pending_beneficiary = scheduler_data.m_pending_beneficiary.strong_ref();
@@ -633,4 +612,51 @@ void Scheduler::idle_loop(void*)
}
}
+void Scheduler::dump_scheduler_state()
+{
+ dump_thread_list();
+}
+
+void dump_thread_list()
+{
+ dbgln("Scheduler thread list for processor {}:", Processor::id());
+
+ auto get_cs = [](Thread& thread) -> u16 {
+ if (!thread.current_trap())
+ return thread.tss().cs;
+ return thread.get_register_dump_from_stack().cs;
+ };
+
+ auto get_eip = [](Thread& thread) -> u32 {
+ if (!thread.current_trap())
+ return thread.tss().eip;
+ return thread.get_register_dump_from_stack().eip;
+ };
+
+ Thread::for_each([&](Thread& thread) -> IterationDecision {
+ switch (thread.state()) {
+ case Thread::Dying:
+ dbgln(" {:14} {:30} @ {:04x}:{:08x} Finalizable: {}, (nsched: {})",
+ thread.state_string(),
+ thread,
+ get_cs(thread),
+ get_eip(thread),
+ thread.is_finalizable(),
+ thread.times_scheduled());
+ break;
+ default:
+ dbgln(" {:14} Pr:{:2} {:30} @ {:04x}:{:08x} (nsched: {})",
+ thread.state_string(),
+ thread.priority(),
+ thread,
+ get_cs(thread),
+ get_eip(thread),
+ thread.times_scheduled());
+ break;
+ }
+
+ return IterationDecision::Continue;
+ });
+}
+
}
diff --git a/Kernel/Scheduler.h b/Kernel/Scheduler.h
index 333821c5dd..f92b0dd1b5 100644
--- a/Kernel/Scheduler.h
+++ b/Kernel/Scheduler.h
@@ -70,6 +70,7 @@ public:
static Thread& pull_next_runnable_thread();
static bool dequeue_runnable_thread(Thread&, bool = false);
static void queue_runnable_thread(Thread&);
+ static void dump_scheduler_state();
};
}