mirror of
https://github.com/reactos/reactos.git
synced 2025-02-28 19:32:59 +00:00
[NTOS:KD] In KDBG, move handling of dmesg buffer from screen provider to kdbg provider
dmesg command is now available even if screen output is disabled. CORE-10749
This commit is contained in:
parent
e9bcf72757
commit
aeb843e014
2 changed files with 111 additions and 71 deletions
|
@ -42,14 +42,6 @@ CPPORT SerialPortInfo = {0, DEFAULT_DEBUG_BAUD_RATE, 0};
|
|||
static CHAR KdpScreenLineBuffer[KdpScreenLineLengthDefault + 1] = "";
|
||||
static ULONG KdpScreenLineBufferPos = 0, KdpScreenLineLength = 0;
|
||||
|
||||
const ULONG KdpDmesgBufferSize = 128 * 1024; // 512*1024; // 5*1024*1024;
|
||||
PCHAR KdpDmesgBuffer = NULL;
|
||||
volatile ULONG KdpDmesgCurrentPosition = 0;
|
||||
volatile ULONG KdpDmesgFreeBytes = 0;
|
||||
volatile ULONG KdbDmesgTotalWritten = 0;
|
||||
volatile BOOLEAN KdbpIsInDmesgMode = FALSE;
|
||||
static KSPIN_LOCK KdpDmesgLogSpinLock;
|
||||
|
||||
KDP_DEBUG_MODE KdpDebugMode;
|
||||
LIST_ENTRY KdProviders = {&KdProviders, &KdProviders};
|
||||
KD_DISPATCH_TABLE DispatchTable[KdMax];
|
||||
|
@ -410,20 +402,12 @@ KdpScreenRelease(VOID)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Screen debug logger function KdpScreenPrint() writes text strings into
|
||||
* KdpDmesgBuffer, using it as a circular buffer. KdpDmesgBuffer contents could
|
||||
* be later (re)viewed using dmesg command of kdbg. KdpScreenPrint() protects
|
||||
* KdpDmesgBuffer from simultaneous writes by use of KdpDmesgLogSpinLock.
|
||||
*/
|
||||
static VOID
|
||||
NTAPI
|
||||
KdpScreenPrint(PCHAR String,
|
||||
ULONG Length)
|
||||
{
|
||||
PCHAR pch = String;
|
||||
KIRQL OldIrql;
|
||||
ULONG beg, end, num;
|
||||
|
||||
while (pch < String + Length && *pch)
|
||||
{
|
||||
|
@ -467,47 +451,6 @@ KdpScreenPrint(PCHAR String,
|
|||
HalDisplayString(KdpScreenLineBuffer + KdpScreenLineBufferPos);
|
||||
KdpScreenLineBufferPos = KdpScreenLineLength;
|
||||
}
|
||||
|
||||
/* Dmesg: store the string in the buffer to show it later */
|
||||
if (KdbpIsInDmesgMode)
|
||||
return;
|
||||
|
||||
if (KdpDmesgBuffer == NULL)
|
||||
return;
|
||||
|
||||
/* Acquire the printing spinlock without waiting at raised IRQL */
|
||||
OldIrql = KdpAcquireLock(&KdpDmesgLogSpinLock);
|
||||
|
||||
/* Invariant: always_true(KdpDmesgFreeBytes == KdpDmesgBufferSize);
|
||||
* set num to min(KdpDmesgFreeBytes, Length).
|
||||
*/
|
||||
num = (Length < KdpDmesgFreeBytes) ? Length : KdpDmesgFreeBytes;
|
||||
beg = KdpDmesgCurrentPosition;
|
||||
if (num != 0)
|
||||
{
|
||||
end = (beg + num) % KdpDmesgBufferSize;
|
||||
if (end > beg)
|
||||
{
|
||||
RtlCopyMemory(KdpDmesgBuffer + beg, String, Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
RtlCopyMemory(KdpDmesgBuffer + beg, String, KdpDmesgBufferSize - beg);
|
||||
RtlCopyMemory(KdpDmesgBuffer, String + (KdpDmesgBufferSize - beg), end);
|
||||
}
|
||||
KdpDmesgCurrentPosition = end;
|
||||
|
||||
/* Counting the total bytes written */
|
||||
KdbDmesgTotalWritten += num;
|
||||
}
|
||||
|
||||
/* Release the spinlock */
|
||||
KdpReleaseLock(&KdpDmesgLogSpinLock, OldIrql);
|
||||
|
||||
/* Optional step(?): find out a way to notify about buffer exhaustion,
|
||||
* and possibly fall into kbd to use dmesg command: user will read
|
||||
* debug strings before they will be wiped over by next writes.
|
||||
*/
|
||||
}
|
||||
|
||||
VOID
|
||||
|
@ -528,22 +471,9 @@ KdpScreenInit(PKD_DISPATCH_TABLE DispatchTable,
|
|||
}
|
||||
else if (BootPhase == 1)
|
||||
{
|
||||
/* Allocate a buffer for dmesg log buffer. +1 for terminating null,
|
||||
* see kdbp_cli.c:KdbpCmdDmesg()/2
|
||||
*/
|
||||
KdpDmesgBuffer = ExAllocatePoolZero(NonPagedPool,
|
||||
KdpDmesgBufferSize + 1,
|
||||
TAG_KDBG);
|
||||
/* Ignore failure if KdpDmesgBuffer is NULL */
|
||||
KdpDmesgFreeBytes = KdpDmesgBufferSize;
|
||||
KdbDmesgTotalWritten = 0;
|
||||
|
||||
/* Take control of the display */
|
||||
KdpScreenAcquire();
|
||||
|
||||
/* Initialize spinlock */
|
||||
KeInitializeSpinLock(&KdpDmesgLogSpinLock);
|
||||
|
||||
HalDisplayString("\r\n Screen debugging enabled\r\n\r\n");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,14 @@
|
|||
|
||||
/* GLOBALS ******************************************************************/
|
||||
|
||||
const ULONG KdpDmesgBufferSize = 128 * 1024; // 512*1024; // 5*1024*1024;
|
||||
PCHAR KdpDmesgBuffer = NULL;
|
||||
volatile ULONG KdpDmesgCurrentPosition = 0;
|
||||
volatile ULONG KdpDmesgFreeBytes = 0;
|
||||
volatile ULONG KdbDmesgTotalWritten = 0;
|
||||
volatile BOOLEAN KdbpIsInDmesgMode = FALSE;
|
||||
static KSPIN_LOCK KdpDmesgLogSpinLock;
|
||||
|
||||
typedef struct _IMAGE_SYMBOL_INFO_CACHE
|
||||
{
|
||||
LIST_ENTRY ListEntry;
|
||||
|
@ -31,6 +39,47 @@ static LIST_ENTRY SymbolsToLoad;
|
|||
static KSPIN_LOCK SymbolsToLoadLock;
|
||||
static KEVENT SymbolsToLoadEvent;
|
||||
|
||||
/* LOCKING FUNCTIONS *********************************************************/
|
||||
|
||||
KIRQL
|
||||
NTAPI
|
||||
KdbAcquireLock(IN PKSPIN_LOCK SpinLock)
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
|
||||
/* Acquire the spinlock without waiting at raised IRQL */
|
||||
while (TRUE)
|
||||
{
|
||||
/* Loop until the spinlock becomes available */
|
||||
while (!KeTestSpinLock(SpinLock));
|
||||
|
||||
/* Spinlock is free, raise IRQL to high level */
|
||||
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
||||
|
||||
/* Try to get the spinlock */
|
||||
if (KeTryToAcquireSpinLockAtDpcLevel(SpinLock))
|
||||
break;
|
||||
|
||||
/* Someone else got the spinlock, lower IRQL back */
|
||||
KeLowerIrql(OldIrql);
|
||||
}
|
||||
|
||||
return OldIrql;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KdbReleaseLock(IN PKSPIN_LOCK SpinLock,
|
||||
IN KIRQL OldIrql)
|
||||
{
|
||||
/* Release the spinlock */
|
||||
KiReleaseSpinLock(SpinLock);
|
||||
// KeReleaseSpinLockFromDpcLevel(SpinLock);
|
||||
|
||||
/* Restore the old IRQL */
|
||||
KeLowerIrql(OldIrql);
|
||||
}
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
static
|
||||
|
@ -330,13 +379,61 @@ KdbSymProcessSymbols(
|
|||
KeSetEvent(&SymbolsToLoadEvent, IO_NO_INCREMENT, FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Debug logger function KdbDebugPrint() writes text messages into
|
||||
* KdpDmesgBuffer, using it as a circular buffer. KdpDmesgBuffer contents could
|
||||
* be later (re)viewed using dmesg command of kdbg. KdbDebugPrint() protects
|
||||
* KdpDmesgBuffer from simultaneous writes by use of KdpDmesgLogSpinLock.
|
||||
*/
|
||||
VOID
|
||||
NTAPI
|
||||
KdbDebugPrint(
|
||||
PCH Message,
|
||||
ULONG Length)
|
||||
{
|
||||
/* Nothing here */
|
||||
KIRQL OldIrql;
|
||||
ULONG beg, end, num;
|
||||
|
||||
/* Dmesg: store Message in the buffer to show it later */
|
||||
if (KdbpIsInDmesgMode)
|
||||
return;
|
||||
|
||||
if (KdpDmesgBuffer == NULL)
|
||||
return;
|
||||
|
||||
/* Acquire the printing spinlock without waiting at raised IRQL */
|
||||
OldIrql = KdbAcquireLock(&KdpDmesgLogSpinLock);
|
||||
|
||||
/* Invariant: always_true(KdpDmesgFreeBytes == KdpDmesgBufferSize);
|
||||
* set num to min(KdpDmesgFreeBytes, Length).
|
||||
*/
|
||||
num = (Length < KdpDmesgFreeBytes) ? Length : KdpDmesgFreeBytes;
|
||||
beg = KdpDmesgCurrentPosition;
|
||||
if (num != 0)
|
||||
{
|
||||
end = (beg + num) % KdpDmesgBufferSize;
|
||||
if (end > beg)
|
||||
{
|
||||
RtlCopyMemory(KdpDmesgBuffer + beg, Message, Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
RtlCopyMemory(KdpDmesgBuffer + beg, Message, KdpDmesgBufferSize - beg);
|
||||
RtlCopyMemory(KdpDmesgBuffer, Message + (KdpDmesgBufferSize - beg), end);
|
||||
}
|
||||
KdpDmesgCurrentPosition = end;
|
||||
|
||||
/* Counting the total bytes written */
|
||||
KdbDmesgTotalWritten += num;
|
||||
}
|
||||
|
||||
/* Release the spinlock */
|
||||
KdbReleaseLock(&KdpDmesgLogSpinLock, OldIrql);
|
||||
|
||||
/* Optional step(?): find out a way to notify about buffer exhaustion,
|
||||
* and possibly fall into kbd to use dmesg command: user will read
|
||||
* debug messages before they will be wiped over by next writes.
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
@ -426,6 +523,19 @@ KdbInitialize(
|
|||
NTSTATUS Status;
|
||||
KIRQL OldIrql;
|
||||
|
||||
/* Allocate a buffer for dmesg log buffer. +1 for terminating null,
|
||||
* see kdbp_cli.c:KdbpCmdDmesg()/2
|
||||
*/
|
||||
KdpDmesgBuffer = ExAllocatePoolZero(NonPagedPool,
|
||||
KdpDmesgBufferSize + 1,
|
||||
TAG_KDBG);
|
||||
/* Ignore failure if KdpDmesgBuffer is NULL */
|
||||
KdpDmesgFreeBytes = KdpDmesgBufferSize;
|
||||
KdbDmesgTotalWritten = 0;
|
||||
|
||||
/* Initialize spinlock */
|
||||
KeInitializeSpinLock(&KdpDmesgLogSpinLock);
|
||||
|
||||
/* Launch our worker thread */
|
||||
InitializeListHead(&SymbolsToLoad);
|
||||
KeInitializeSpinLock(&SymbolsToLoadLock);
|
||||
|
|
Loading…
Reference in a new issue