mirror of
https://github.com/reactos/reactos.git
synced 2025-01-03 21:09:19 +00:00
Fix logging to a file.
In spite of limitations, it remains the only way to obtain desired logs for some people. svn path=/trunk/; revision=43331
This commit is contained in:
parent
ffbb3fd184
commit
07dc415f89
1 changed files with 131 additions and 54 deletions
|
@ -14,16 +14,17 @@
|
||||||
|
|
||||||
/* GLOBALS *******************************************************************/
|
/* GLOBALS *******************************************************************/
|
||||||
|
|
||||||
#define BufferSize 32*1024
|
#define KdpBufferSize (1024 * 512)
|
||||||
|
BOOLEAN KdpLoggingEnabled = FALSE;
|
||||||
|
PCHAR KdpDebugBuffer = NULL;
|
||||||
|
volatile ULONG KdpCurrentPosition = 0;
|
||||||
|
volatile ULONG KdpFreeBytes = 0;
|
||||||
|
KSPIN_LOCK KdpDebugLogSpinLock;
|
||||||
|
KEVENT KdpLoggerThreadEvent;
|
||||||
|
HANDLE KdpLogFileHandle;
|
||||||
|
|
||||||
HANDLE KdbLogFileHandle;
|
|
||||||
BOOLEAN KdpLogInitialized;
|
|
||||||
CHAR DebugBuffer[BufferSize];
|
|
||||||
ULONG CurrentPosition;
|
|
||||||
WORK_QUEUE_ITEM KdpDebugLogQueue;
|
|
||||||
KSPIN_LOCK KdpSerialSpinLock;
|
KSPIN_LOCK KdpSerialSpinLock;
|
||||||
BOOLEAN ItemQueued;
|
KD_PORT_INFORMATION SerialPortInfo = { DEFAULT_DEBUG_PORT, DEFAULT_DEBUG_BAUD_RATE, 0 };
|
||||||
KD_PORT_INFORMATION SerialPortInfo = {DEFAULT_DEBUG_PORT, DEFAULT_DEBUG_BAUD_RATE, 0};
|
|
||||||
|
|
||||||
/* Current Port in use. FIXME: Do we support more then one? */
|
/* Current Port in use. FIXME: Do we support more then one? */
|
||||||
ULONG KdpPort;
|
ULONG KdpPort;
|
||||||
|
@ -32,56 +33,103 @@ ULONG KdpPort;
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
KdpPrintToLogInternal(PVOID Context)
|
KdpLoggerThread(PVOID Context)
|
||||||
{
|
{
|
||||||
|
ULONG beg, end, num;
|
||||||
IO_STATUS_BLOCK Iosb;
|
IO_STATUS_BLOCK Iosb;
|
||||||
|
|
||||||
/* Write to the Debug Log */
|
KdpLoggingEnabled = TRUE;
|
||||||
NtWriteFile(KdbLogFileHandle,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
&Iosb,
|
|
||||||
DebugBuffer,
|
|
||||||
CurrentPosition,
|
|
||||||
NULL,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
/* Clear the Current Position */
|
while (TRUE)
|
||||||
CurrentPosition = 0;
|
{
|
||||||
|
KeWaitForSingleObject(&KdpLoggerThreadEvent, 0, KernelMode, FALSE, NULL);
|
||||||
|
|
||||||
/* A new item can be queued now */
|
/* Bug */
|
||||||
ItemQueued = FALSE;
|
end = KdpCurrentPosition;
|
||||||
|
num = KdpFreeBytes;
|
||||||
|
beg = (end + num) % KdpBufferSize;
|
||||||
|
num = KdpBufferSize - num;
|
||||||
|
|
||||||
|
/* Nothing to do? */
|
||||||
|
if (num == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (end > beg)
|
||||||
|
{
|
||||||
|
NtWriteFile(KdpLogFileHandle, NULL, NULL, NULL, &Iosb,
|
||||||
|
KdpDebugBuffer + beg, num, NULL, NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NtWriteFile(KdpLogFileHandle, NULL, NULL, NULL, &Iosb,
|
||||||
|
KdpDebugBuffer + beg, KdpBufferSize - beg, NULL, NULL);
|
||||||
|
|
||||||
|
NtWriteFile(KdpLogFileHandle, NULL, NULL, NULL, &Iosb,
|
||||||
|
KdpDebugBuffer, end, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
InterlockedExchangeAddUL(&KdpFreeBytes, num);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
KdpPrintToLog(PCH String,
|
KdpPrintToLogFile(PCH String,
|
||||||
ULONG StringLength)
|
ULONG StringLength)
|
||||||
{
|
{
|
||||||
/* Don't overflow */
|
ULONG beg, end, num;
|
||||||
if ((CurrentPosition + StringLength) > BufferSize) return;
|
KIRQL OldIrql;
|
||||||
|
|
||||||
/* Add the string to the buffer */
|
if (KdpDebugBuffer == NULL) return;
|
||||||
RtlCopyMemory(&DebugBuffer[CurrentPosition], String, StringLength);
|
|
||||||
|
|
||||||
/* Update the Current Position */
|
/* Acquire the printing spinlock without waiting at raised IRQL */
|
||||||
CurrentPosition += StringLength;
|
while (TRUE)
|
||||||
|
|
||||||
/* Make sure we are initialized and can queue */
|
|
||||||
if (!KdpLogInitialized || (ItemQueued)) return;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Queue the work item
|
|
||||||
* Note that we don't want to queue if we are > DISPATCH_LEVEL...
|
|
||||||
* The message is in the buffer and will simply be taken care of at
|
|
||||||
* the next time we are at <= DISPATCH, so it won't be lost.
|
|
||||||
*/
|
|
||||||
if (KeGetCurrentIrql() <= DISPATCH_LEVEL)
|
|
||||||
{
|
{
|
||||||
ExQueueWorkItem(&KdpDebugLogQueue, HyperCriticalWorkQueue);
|
/* Wait when the spinlock becomes available */
|
||||||
ItemQueued = TRUE;
|
while (!KeTestSpinLock(&KdpDebugLogSpinLock));
|
||||||
|
|
||||||
|
/* Spinlock was free, raise IRQL */
|
||||||
|
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
||||||
|
|
||||||
|
/* Try to get the spinlock */
|
||||||
|
if (KeTryToAcquireSpinLockAtDpcLevel(&KdpDebugLogSpinLock))
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Someone else got the spinlock, lower IRQL back */
|
||||||
|
KeLowerIrql(OldIrql);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
beg = KdpCurrentPosition;
|
||||||
|
num = KdpFreeBytes;
|
||||||
|
if (StringLength < num)
|
||||||
|
num = StringLength;
|
||||||
|
|
||||||
|
if (num != 0)
|
||||||
|
{
|
||||||
|
end = (beg + num) % KdpBufferSize;
|
||||||
|
KdpCurrentPosition = end;
|
||||||
|
KdpFreeBytes -= num;
|
||||||
|
|
||||||
|
if (end > beg)
|
||||||
|
{
|
||||||
|
RtlCopyMemory(KdpDebugBuffer + beg, String, num);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RtlCopyMemory(KdpDebugBuffer + beg, String, KdpBufferSize - beg);
|
||||||
|
RtlCopyMemory(KdpDebugBuffer, String + KdpBufferSize - beg, end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release spinlock */
|
||||||
|
KiReleaseSpinLock(&KdpDebugLogSpinLock);
|
||||||
|
|
||||||
|
/* Lower IRQL */
|
||||||
|
KeLowerIrql(OldIrql);
|
||||||
|
|
||||||
|
/* Signal the logger thread */
|
||||||
|
if (OldIrql <= DISPATCH_LEVEL && KdpLoggingEnabled)
|
||||||
|
KeSetEvent(&KdpLoggerThreadEvent, 0, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
@ -90,9 +138,11 @@ KdpInitDebugLog(PKD_DISPATCH_TABLE DispatchTable,
|
||||||
ULONG BootPhase)
|
ULONG BootPhase)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
||||||
UNICODE_STRING FileName;
|
UNICODE_STRING FileName;
|
||||||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
IO_STATUS_BLOCK Iosb;
|
IO_STATUS_BLOCK Iosb;
|
||||||
|
HANDLE ThreadHandle;
|
||||||
|
KPRIORITY Priority;
|
||||||
|
|
||||||
if (!KdpDebugMode.File) return;
|
if (!KdpDebugMode.File) return;
|
||||||
|
|
||||||
|
@ -102,11 +152,21 @@ KdpInitDebugLog(PKD_DISPATCH_TABLE DispatchTable,
|
||||||
|
|
||||||
/* Write out the functions that we support for now */
|
/* Write out the functions that we support for now */
|
||||||
DispatchTable->KdpInitRoutine = KdpInitDebugLog;
|
DispatchTable->KdpInitRoutine = KdpInitDebugLog;
|
||||||
DispatchTable->KdpPrintRoutine = KdpPrintToLog;
|
DispatchTable->KdpPrintRoutine = KdpPrintToLogFile;
|
||||||
|
|
||||||
/* Register as a Provider */
|
/* Register as a Provider */
|
||||||
InsertTailList(&KdProviders, &DispatchTable->KdProvidersList);
|
InsertTailList(&KdProviders, &DispatchTable->KdProvidersList);
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (BootPhase == 1)
|
||||||
|
{
|
||||||
|
/* Allocate a buffer for debug log */
|
||||||
|
KdpDebugBuffer = ExAllocatePool(NonPagedPool, KdpBufferSize);
|
||||||
|
KdpFreeBytes = KdpBufferSize;
|
||||||
|
|
||||||
|
/* Initialize spinlock */
|
||||||
|
KeInitializeSpinLock(&KdpDebugLogSpinLock);
|
||||||
|
|
||||||
/* Display separator + ReactOS version at start of the debug log */
|
/* Display separator + ReactOS version at start of the debug log */
|
||||||
DPRINT1("---------------------------------------------------------------\n");
|
DPRINT1("---------------------------------------------------------------\n");
|
||||||
DPRINT1("ReactOS "KERNEL_VERSION_STR" (Build "KERNEL_VERSION_BUILD_STR")\n");
|
DPRINT1("ReactOS "KERNEL_VERSION_STR" (Build "KERNEL_VERSION_BUILD_STR")\n");
|
||||||
|
@ -117,7 +177,7 @@ KdpInitDebugLog(PKD_DISPATCH_TABLE DispatchTable,
|
||||||
}
|
}
|
||||||
else if (BootPhase == 3)
|
else if (BootPhase == 3)
|
||||||
{
|
{
|
||||||
/* Setup the Log Name */
|
/* Setup the log name */
|
||||||
RtlInitUnicodeString(&FileName, L"\\SystemRoot\\debug.log");
|
RtlInitUnicodeString(&FileName, L"\\SystemRoot\\debug.log");
|
||||||
InitializeObjectAttributes(&ObjectAttributes,
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
&FileName,
|
&FileName,
|
||||||
|
@ -125,9 +185,9 @@ KdpInitDebugLog(PKD_DISPATCH_TABLE DispatchTable,
|
||||||
NULL,
|
NULL,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
/* Create the Log File */
|
/* Create the log file */
|
||||||
Status = NtCreateFile(&KdbLogFileHandle,
|
Status = NtCreateFile(&KdpLogFileHandle,
|
||||||
FILE_ALL_ACCESS,
|
FILE_APPEND_DATA | SYNCHRONIZE,
|
||||||
&ObjectAttributes,
|
&ObjectAttributes,
|
||||||
&Iosb,
|
&Iosb,
|
||||||
NULL,
|
NULL,
|
||||||
|
@ -138,9 +198,26 @@ KdpInitDebugLog(PKD_DISPATCH_TABLE DispatchTable,
|
||||||
NULL,
|
NULL,
|
||||||
0);
|
0);
|
||||||
|
|
||||||
/* Allow it to be used */
|
if (!NT_SUCCESS(Status)) return;
|
||||||
ExInitializeWorkItem(&KdpDebugLogQueue, &KdpPrintToLogInternal, NULL);
|
|
||||||
KdpLogInitialized = TRUE;
|
KeInitializeEvent(&KdpLoggerThreadEvent, SynchronizationEvent, TRUE);
|
||||||
|
|
||||||
|
/* Create the logger thread */
|
||||||
|
Status = PsCreateSystemThread(&ThreadHandle,
|
||||||
|
THREAD_ALL_ACCESS,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
KdpLoggerThread,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status)) return;
|
||||||
|
|
||||||
|
Priority = 7;
|
||||||
|
NtSetInformationThread(ThreadHandle,
|
||||||
|
ThreadPriority,
|
||||||
|
&Priority,
|
||||||
|
sizeof(Priority));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,7 +237,7 @@ KdpSerialDebugPrint(LPSTR Message,
|
||||||
/* Wait when the spinlock becomes available */
|
/* Wait when the spinlock becomes available */
|
||||||
while (!KeTestSpinLock(&KdpSerialSpinLock));
|
while (!KeTestSpinLock(&KdpSerialSpinLock));
|
||||||
|
|
||||||
/* Spinlock was free, raise irql */
|
/* Spinlock was free, raise IRQL */
|
||||||
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
||||||
|
|
||||||
/* Try to get the spinlock */
|
/* Try to get the spinlock */
|
||||||
|
|
Loading…
Reference in a new issue