24#include "pedigree/kernel/debugger/DebuggerIO.h"
25#include "pedigree/kernel/debugger/commands/ThreadWaitDiagnostic.h"
26#include "pedigree/kernel/debugger/commands/ThreadsCommand.h"
27#include "pedigree/kernel/linker/KernelElf.h"
28#include "pedigree/kernel/process/Process.h"
29#include "pedigree/kernel/process/Scheduler.h"
30#include "pedigree/kernel/process/Semaphore.h"
31#include "pedigree/kernel/process/Thread.h"
32#include "pedigree/kernel/processor/Processor.h"
33#include "pedigree/kernel/processor/ProcessorInformation.h"
34#include "pedigree/kernel/processor/state.h"
35#include "pedigree/kernel/utilities/demangle.h"
36#include "pedigree/kernel/utilities/utility.h"
47 case Thread::CondWait:
51 case Thread::FutexWait:
53 case Thread::EventWait:
55 case Thread::ProcessWait:
56 return "Process-Wait";
57 case Thread::CallbackDrain:
58 return "Callback-Drain";
62 return "<unknown DebugState>";
67 diagnostic.sleeping = thread->
getStatus() == Thread::Sleeping;
71 appendThreadWaitDiagnostic(diagnostic, line);
75 diagnostic.hasWait =
true;
76 diagnostic.queue =
reinterpret_cast<uintptr_t
>(wait.queue);
77 diagnostic.channelOwner =
reinterpret_cast<uintptr_t
>(wait.channelOwner);
78 diagnostic.channelValue = wait.channelValue;
79 diagnostic.reason = wait.reason;
80 diagnostic.stateLevel = wait.stateLevel;
81 diagnostic.queued = wait.queued;
83 uintptr_t debugAddress = 0;
84 if (thread->
getDebugState(debugAddress) == Thread::SemWait && wait.channelOwner) {
88 diagnostic.mutexOwner =
reinterpret_cast<uintptr_t
>(owner);
92 appendThreadWaitDiagnostic(diagnostic, line);
105 selectedProcess = pedigree_std::move(process);
112 const bool threadAcquired = process->
acquireThread(thread, j);
114 if (threadAcquired) {
115 selectedProcess = pedigree_std::move(process);
116 selectedThread = pedigree_std::move(thread);
141 pScreen->disableCli();
145 resize(pScreen->
getWidth(), pScreen->getHeight() - 2);
146 setScrollKeys(
'j',
'k');
153 pScreen->
drawString(
"Pedigree debugger - Thread selector", 0, 0, DebuggerIO::White,
161 DebuggerIO::White, DebuggerIO::Green);
166 "backspace: Page up. space: Page down. q: Quit. enter: Switch to "
168 pScreen->getHeight() - 1, 0, DebuggerIO::White, DebuggerIO::Green);
169 pScreen->
drawString(
"backspace", pScreen->getHeight() - 1, 0, DebuggerIO::Yellow,
171 pScreen->
drawString(
"space", pScreen->getHeight() - 1, 20, DebuggerIO::Yellow, DebuggerIO::Green);
172 pScreen->
drawString(
"q", pScreen->getHeight() - 1, 38, DebuggerIO::Yellow, DebuggerIO::Green);
173 pScreen->
drawString(
"enter", pScreen->getHeight() - 1, 47, DebuggerIO::Yellow, DebuggerIO::Green);
183 while (!(c = pScreen->
getChar()))
189 if (
static_cast<ssize_t
>(m_SelectedLine) - 1 >= 0)
191 }
else if (c ==
'k') {
193 if (m_SelectedLine + 1 < getLineCount())
195 }
else if (c ==
' ') {
196 scroll(
static_cast<ssize_t
>(height()));
197 if (m_SelectedLine + height() < getLineCount())
198 m_SelectedLine += height();
200 m_SelectedLine = getLineCount() - 1;
201 }
else if (c == 0x08) {
202 scroll(-
static_cast<ssize_t
>(height()));
203 if (
static_cast<ssize_t
>(m_SelectedLine) -
static_cast<ssize_t
>(height()) >= 0)
204 m_SelectedLine -= height();
207 }
else if (c ==
'\n' || c ==
'\r') {
221 pScreen->
drawString(
" ", 1, 0, DebuggerIO::White, DebuggerIO::Black);
233 selectLine(index, process, thread);
234 Process* tehProcess = process.get();
235 Thread* tehThread = thread.get();
243 colour = DebuggerIO::Yellow;
244 if (index == m_SelectedLine)
245 bgColour = DebuggerIO::Blue;
247 bgColour = DebuggerIO::Black;
248 if (tehThread == 0) {
250 Line += tehProcess->
getId();
259const char* ThreadsCommand::getLine2(
size_t index,
size_t& colOffset,
DebuggerIO::Colour& colour,
266 selectLine(index, process, thread);
267 Thread* tehThread = thread.get();
272 case Thread::Created:
275 case Thread::Running:
281 case Thread::Sleeping:
287 case Thread::AwaitingJoin:
296 Line += tehThread->
getId();
301 if (state != Thread::None) {
302 Line += debugStateName(state);
316 const SchedulerState& state = tehThread->
state();
317 ip = state.getInstructionPointer();
331 appendWaitState(tehThread, Line);
332 colour = DebuggerIO::LightGrey;
333 }
else if (tehThread != 0)
337 case Thread::Created:
340 case Thread::Running:
346 case Thread::Sleeping:
352 case Thread::AwaitingJoin:
360 Line += tehThread->
getId();
361 Line +=
"] - CURRENT ";
365 if (state != Thread::None) {
366 Line += debugStateName(state);
379 appendWaitState(tehThread, Line);
381 colour = DebuggerIO::Yellow;
384 if (index == m_SelectedLine)
385 bgColour = DebuggerIO::Blue;
387 bgColour = DebuggerIO::Black;
392size_t ThreadsCommand::getLineCount() {
396bool ThreadsCommand::swapThread(InterruptState& state,
DebuggerIO* pScreen) {
399 selectLine(m_SelectedLine, process, thread);
400 Thread* tehThread = thread.get();
virtual void enableCli()=0
virtual void drawString(const char *str, size_t row, size_t col, Colour foreColour, Colour backColour)=0
virtual size_t getWidth()=0
virtual void drawHorizontalLine(char c, size_t row, size_t colStart, size_t colEnd, Colour foreColour, Colour backColour)=0
static KernelElf & instance()
uintptr_t globalLookupSymbol(const char *pName)
LargeStaticString & description()
MUST_USE_RESULT bool acquireThread(ThreadLease &lease, size_t n)
static ProcessorInformation & information()
static Scheduler & instance()
MUST_USE_RESULT bool acquireProcess(ProcessLease &lease, size_t n)
const void * getDebugMutexOwner() const
bool getWaitDebugInfo(WaitDebugInfo &info)
DebugState getDebugState(uintptr_t &address)
void autocomplete(const HugeStaticString &input, HugeStaticString &output)
bool execute(const HugeStaticString &input, HugeStaticString &output, InterruptState &state, DebuggerIO *screen)