diff options
author | Andreas Kling <kling@serenityos.org> | 2021-04-18 19:57:17 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-04-18 20:00:10 +0200 |
commit | 24dcd99e4b3a0538e12c9975b03c9cbfb7ff226e (patch) | |
tree | f104007178682a343973e9336e8867d843fa867b | |
parent | 685556ae84036fb84a363cbb8872264e8e54dbfc (diff) | |
download | serenity-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.
-rw-r--r-- | Kernel/Devices/HID/PS2KeyboardDevice.cpp | 5 | ||||
-rw-r--r-- | Kernel/Scheduler.cpp | 72 | ||||
-rw-r--r-- | Kernel/Scheduler.h | 1 |
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(); }; } |