20 #include "pedigree/kernel/debugger/commands/LocksCommand.h" 21 #include "pedigree/kernel/Log.h" 22 #include "pedigree/kernel/Spinlock.h" 23 #include "pedigree/kernel/linker/KernelElf.h" 24 #include "pedigree/kernel/processor/Processor.h" 25 #include "pedigree/kernel/utilities/demangle.h" 27 #if LOCKS_COMMAND_DO_BACKTRACES && !defined(TESTSUITE) 28 #include "pedigree/kernel/debugger/Backtrace.h" 29 #include "pedigree/kernel/linker/KernelElf.h" 39 static bool g_bReady =
false;
41 #define ERROR_OR_FATAL(x) \ 51 :
DebuggerCommand(), m_pDescriptors(), m_bAcquiring(false), m_LockIndex(0),
52 m_bFatal(true), m_SelectedLine(0)
54 for (
size_t i = 0; i < LOCKS_COMMAND_NUM_CPU; ++i)
56 #if LOCKS_COMMAND_DO_BACKTRACES 57 m_bTracing[i] =
false;
77 output +=
"Sorry, this kernel was not built with TRACK_LOCKS enabled.";
83 output +=
"Lock tracking has not yet been enabled.";
88 pScreen->disableCli();
92 resize(pScreen->
getWidth(), pScreen->getHeight() - 2);
93 setScrollKeys(
'j',
'k');
96 ' ', 0, 0, pScreen->
getWidth() - 1, DebuggerIO::White,
99 ' ', pScreen->getHeight() - 1, 0, pScreen->
getWidth() - 1,
100 DebuggerIO::White, DebuggerIO::Green);
102 "Pedigree debugger - Lock tracker", 0, 0, DebuggerIO::White,
106 "backspace: Page up. space: Page down. q: Quit.",
107 pScreen->getHeight() - 1, 0, DebuggerIO::White, DebuggerIO::Green);
109 "backspace", pScreen->getHeight() - 1, 0, DebuggerIO::Yellow,
112 "space", pScreen->getHeight() - 1, 20, DebuggerIO::Yellow,
115 "q", pScreen->getHeight() - 1, 38, DebuggerIO::Yellow,
126 while (!(in = pScreen->
getChar()))
133 if (static_cast<ssize_t>(m_SelectedLine) - 1 >= 0)
139 if (m_SelectedLine + 1 < getLineCount())
145 if (m_SelectedLine + 5 < getLineCount())
148 m_SelectedLine = getLineCount() - 1;
153 if (static_cast<ssize_t>(m_SelectedLine) - 5 >= 0)
168 pScreen->
drawString(
" ", 1, 0, DebuggerIO::White, DebuggerIO::Black);
173 const char *LocksCommand::getLine1(
183 for (nCpu = 0; nCpu < LOCKS_COMMAND_NUM_CPU; ++nCpu)
185 if (nLock++ == index)
196 for (
size_t j = 0; j < MAX_DESCRIPTORS; ++j)
198 pD = &m_pDescriptors[nCpu][j];
204 else if (nLock == index)
208 #if LOCKS_COMMAND_DO_BACKTRACES 209 else if ((nLock < index) && (nLock + pD->n >= index))
227 if ((nLock - 1) > index)
245 colour = DebuggerIO::White;
246 if (index == m_SelectedLine)
247 bgColour = DebuggerIO::Blue;
249 bgColour = DebuggerIO::Black;
254 const char *LocksCommand::getLine2(
265 bool doBacktrace =
false;
266 for (nCpu = 0; nCpu < LOCKS_COMMAND_NUM_CPU; ++nCpu)
273 if (nLock++ == index)
279 for (
size_t j = 0; j < MAX_DESCRIPTORS; ++j)
281 pD = &m_pDescriptors[nCpu][j];
291 #if LOCKS_COMMAND_DO_BACKTRACES 292 else if ((nLock < index) && (nLock + pD->n >= index))
317 colOffset = nDepth + 3;
319 #if LOCKS_COMMAND_DO_BACKTRACES 320 if (doBacktrace && pD->n)
325 size_t backtraceFrame = index - nLock - 1;
327 if (backtraceFrame > pD->n)
329 ERROR_OR_FATAL(
"wtf");
332 uintptr_t addr = pD->ra[backtraceFrame];
335 Line.append(addr, 16);
339 uintptr_t symStart = 0;
350 Line +=
static_cast<const char *
>(symbol.name);
354 else if (!doBacktrace)
357 Line.append(reinterpret_cast<uintptr_t>(pD->pLock), 16);
359 Line += stateName(pD->state);
361 Line.append(pD->pLock->m_Ra, 16);
364 uintptr_t symStart = 0;
366 pD->pLock->m_Ra, &symStart);
375 Line +=
static_cast<const char *
>(symbol.name);
380 colour = DebuggerIO::White;
381 if (index == m_SelectedLine)
382 bgColour = DebuggerIO::Blue;
384 bgColour = DebuggerIO::Black;
389 size_t LocksCommand::getLineCount()
392 for (
size_t i = 0; i < LOCKS_COMMAND_NUM_CPU; ++i)
401 #if LOCKS_COMMAND_DO_BACKTRACES 403 for (
size_t j = 0; j < nextPos; ++j)
405 numLocks += m_pDescriptors[i][j].n;
415 void LocksCommand::setReady()
425 void LocksCommand::clearFatal()
430 bool LocksCommand::lockAttempted(
431 const Spinlock *pLock,
size_t nCpu,
bool intState)
435 if (pLock->m_bAvoidTracking)
441 if (pos > MAX_DESCRIPTORS)
444 "Spinlock " <<
Hex << pLock <<
" ran out of room for locks [" <<
Dec 453 "Spinlock " <<
Hex << pLock <<
" attempted at level " <<
Dec << pos
454 <<
Hex <<
" with interrupts enabled on CPU" <<
Dec 463 ERROR_OR_FATAL(
"LocksCommand tracking state is corrupt.");
471 #if LOCKS_COMMAND_DO_BACKTRACES 479 m_bTracing[nCpu].compareAndSwap(
false,
true))
485 if (numFrames > NUM_BT_FRAMES)
487 numFrames = NUM_BT_FRAMES;
489 for (
size_t i = 0; i < numFrames; ++i)
495 m_bTracing[nCpu] =
false;
503 bool LocksCommand::lockAcquired(
504 const Spinlock *pLock,
size_t nCpu,
bool intState)
508 if (pLock->m_bAvoidTracking)
514 if (back > MAX_DESCRIPTORS)
517 "Spinlock " <<
Hex << pLock
518 <<
" acquired unexpectedly (no tracked locks).");
522 if (back && intState)
526 "Spinlock " <<
Hex << pLock <<
" acquired at level " <<
Dec << back
527 <<
Hex <<
" with interrupts enabled on CPU" <<
Dec 534 if (pD->state !=
Attempted || pD->pLock != pLock)
537 "Spinlock " <<
Hex << pLock <<
" acquired unexpectedly.");
550 if (pLock->m_bAvoidTracking)
559 if (pD->state !=
Acquired || pD->pLock != pLock)
564 for (
size_t i = 0; i < LOCKS_COMMAND_NUM_CPU; ++i)
570 if (back < MAX_DESCRIPTORS)
573 if (pCheckD->state ==
Acquired && pCheckD->pLock == pLock)
587 <<
Hex << pLock <<
" released out-of-order [expected lock " 588 << (pD ? pD->pLock : 0) << (pD ?
"" :
" (no lock)")
589 <<
", state " << (pD ? stateName(pD->state) :
"(no state)")
614 "Rescheduling CPU" << nCpu <<
" is not allowed, as there are still " 615 << pos <<
" acquired locks.");
626 if (pLock->m_bAvoidTracking)
634 while (!m_bAcquiring.compareAndSwap(
false,
true))
638 for (
size_t i = 0; i < LOCKS_COMMAND_NUM_CPU; ++i)
643 bool foundLock =
false;
647 pD = &m_pDescriptors[i][j];
654 if (pD->pLock == pLock && pD->state ==
Acquired)
661 if (!foundLock || !pD || pD->pLock == pLock)
672 for (
size_t j = 0; j < m_NextPosition[nCpu]; ++j)
680 if (pMyD->pLock == pD->pLock && pMyD->state ==
Acquired)
685 "Detected lock dependency inversion (deadlock) between " 686 <<
Hex << pLock <<
" and " << pD->pLock <<
"!");
694 m_bAcquiring =
false;
virtual size_t getWidth()=0
The lock is about to be attempted.
virtual void enableCli()=0
static size_t isInitialised()
bool lockReleased(const Spinlock *pLock, size_t nCpu=~0U)
Atomic< uint8_t > m_NextPosition[LOCKS_COMMAND_NUM_CPU]
static KernelElf & instance()
uintptr_t globalLookupSymbol(const char *pName)
bool checkState(const Spinlock *pLock, size_t nCpu=~0U)
bool execute(const HugeStaticString &input, HugeStaticString &output, InterruptState &state, DebuggerIO *screen)
virtual void drawString(const char *str, size_t row, size_t col, Colour foreColour, Colour backColour)=0
void autocomplete(const HugeStaticString &input, HugeStaticString &output)
bool checkSchedule(size_t nCpu=~0U)
void performBpBacktrace(uintptr_t base, uintptr_t instruction)
virtual void drawHorizontalLine(char c, size_t row, size_t colStart, size_t colEnd, Colour foreColour, Colour backColour)=0
uintptr_t getReturnAddress(size_t n)
This entry is no longer active.