0886a89d39f65d66098644042a61629029180df4
[reactos.git] / reactos / ntoskrnl / kd / dlog.c
1 /* $Id: dlog.c,v 1.15 2004/08/15 16:39:04 chorns Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/kd/kdebug.c
6 * PURPOSE: Kernel debugger
7 * PROGRAMMER: Eric Kohl (ekohl@abo.rhein-zeitung.de)
8 * UPDATE HISTORY:
9 * 21/10/99: Created
10 */
11
12 /* INCLUDES ******************************************************************/
13
14 #include <ntoskrnl.h>
15
16 /* GLOBALS *******************************************************************/
17
18 #define DEBUGLOG_SIZE (32*1024)
19
20 static CHAR DebugLog[DEBUGLOG_SIZE];
21 static ULONG DebugLogStart;
22 static ULONG DebugLogEnd;
23 static ULONG DebugLogCount;
24 static KSPIN_LOCK DebugLogLock;
25 static ULONG DebugLogOverflow;
26 static HANDLE DebugLogThreadHandle;
27 static CLIENT_ID DebugLogThreadCid;
28 static HANDLE DebugLogFile;
29 static KEVENT DebugLogEvent;
30
31 /* FUNCTIONS *****************************************************************/
32
33 VOID
34 DebugLogDumpMessages(VOID)
35 {
36 static CHAR Buffer[256];
37 ULONG Offset;
38 ULONG Length;
39
40 if (!(KdDebugState & KD_DEBUG_BOOTLOG))
41 {
42 return;
43 }
44 KdDebugState &= ~KD_DEBUG_BOOTLOG;
45
46 Offset = (DebugLogEnd + 1) % DEBUGLOG_SIZE;
47 do
48 {
49 if (Offset <= DebugLogEnd)
50 {
51 Length = min(255, DebugLogEnd - Offset);
52 }
53 else
54 {
55 Length = min(255, DEBUGLOG_SIZE - Offset);
56 }
57 memcpy(Buffer, DebugLog + Offset, Length);
58 Buffer[Length] = 0;
59 DbgPrint(Buffer);
60 Offset = (Offset + Length) % DEBUGLOG_SIZE;
61 }
62 while (Length > 0);
63 }
64
65 VOID INIT_FUNCTION
66 DebugLogInit(VOID)
67 {
68 KeInitializeSpinLock(&DebugLogLock);
69 DebugLogStart = 0;
70 DebugLogEnd = 0;
71 DebugLogOverflow = 0;
72 DebugLogCount = 0;
73 KeInitializeEvent(&DebugLogEvent, NotificationEvent, FALSE);
74 }
75
76 VOID STDCALL
77 DebugLogThreadMain(PVOID Context)
78 {
79 KIRQL oldIrql;
80 IO_STATUS_BLOCK Iosb;
81 static CHAR Buffer[256];
82 ULONG WLen;
83
84 for (;;)
85 {
86 LARGE_INTEGER TimeOut;
87 TimeOut.QuadPart = -5000000; /* Half a second. */
88 KeWaitForSingleObject(&DebugLogEvent,
89 0,
90 KernelMode,
91 FALSE,
92 &TimeOut);
93 KeAcquireSpinLock(&DebugLogLock, &oldIrql);
94 while (DebugLogCount > 0)
95 {
96 if (DebugLogStart > DebugLogEnd)
97 {
98 WLen = min(256, DEBUGLOG_SIZE - DebugLogStart);
99 memcpy(Buffer, &DebugLog[DebugLogStart], WLen);
100 Buffer[WLen + 1] = '\n';
101 DebugLogStart =
102 (DebugLogStart + WLen) % DEBUGLOG_SIZE;
103 DebugLogCount = DebugLogCount - WLen;
104 KeReleaseSpinLock(&DebugLogLock, oldIrql);
105 NtWriteFile(DebugLogFile,
106 NULL,
107 NULL,
108 NULL,
109 &Iosb,
110 Buffer,
111 WLen + 1,
112 NULL,
113 NULL);
114 }
115 else
116 {
117 WLen = min(255, DebugLogEnd - DebugLogStart);
118 memcpy(Buffer, &DebugLog[DebugLogStart], WLen);
119 DebugLogStart =
120 (DebugLogStart + WLen) % DEBUGLOG_SIZE;
121 DebugLogCount = DebugLogCount - WLen;
122 KeReleaseSpinLock(&DebugLogLock, oldIrql);
123 NtWriteFile(DebugLogFile,
124 NULL,
125 NULL,
126 NULL,
127 &Iosb,
128 Buffer,
129 WLen,
130 NULL,
131 NULL);
132 }
133 KeAcquireSpinLock(&DebugLogLock, &oldIrql);
134 }
135 KeResetEvent(&DebugLogEvent);
136 KeReleaseSpinLock(&DebugLogLock, oldIrql);
137 }
138 }
139
140 VOID INIT_FUNCTION
141 DebugLogInit2(VOID)
142 {
143 NTSTATUS Status;
144 OBJECT_ATTRIBUTES ObjectAttributes;
145 UNICODE_STRING FileName;
146 IO_STATUS_BLOCK Iosb;
147
148 RtlInitUnicodeString(&FileName, L"\\SystemRoot\\debug.log");
149 InitializeObjectAttributes(&ObjectAttributes,
150 &FileName,
151 0,
152 NULL,
153 NULL);
154
155 Status = NtCreateFile(&DebugLogFile,
156 FILE_ALL_ACCESS,
157 &ObjectAttributes,
158 &Iosb,
159 NULL,
160 FILE_ATTRIBUTE_NORMAL,
161 0,
162 FILE_SUPERSEDE,
163 FILE_WRITE_THROUGH | FILE_SYNCHRONOUS_IO_NONALERT,
164 NULL,
165 0);
166 if (!NT_SUCCESS(Status))
167 {
168 DbgPrint("Failed to create debug log file\n");
169 return;
170 }
171
172 Status = PsCreateSystemThread(&DebugLogThreadHandle,
173 THREAD_ALL_ACCESS,
174 NULL,
175 NULL,
176 &DebugLogThreadCid,
177 DebugLogThreadMain,
178 NULL);
179 }
180
181 VOID
182 DebugLogWrite(PCH String)
183 {
184 KIRQL oldIrql;
185
186 if (KeGetCurrentIrql() > DISPATCH_LEVEL)
187 {
188 DebugLogOverflow++;
189 return;
190 }
191
192 KeAcquireSpinLock(&DebugLogLock, &oldIrql);
193
194 if (DebugLogCount == DEBUGLOG_SIZE)
195 {
196 DebugLogOverflow++;
197 KeReleaseSpinLock(&DebugLogLock, oldIrql);
198 if (oldIrql < DISPATCH_LEVEL)
199 {
200 KeSetEvent(&DebugLogEvent, IO_NO_INCREMENT, FALSE);
201 }
202 return;
203 }
204
205 while ((*String) != 0)
206 {
207 DebugLog[DebugLogEnd] = *String;
208 String++;
209 DebugLogCount++;
210
211 if (DebugLogCount == DEBUGLOG_SIZE)
212 {
213 DebugLogOverflow++;
214 KeReleaseSpinLock(&DebugLogLock, oldIrql);
215 if (oldIrql < DISPATCH_LEVEL)
216 {
217 KeSetEvent(&DebugLogEvent, IO_NO_INCREMENT, FALSE);
218 }
219 return;
220 }
221 DebugLogEnd = (DebugLogEnd + 1) % DEBUGLOG_SIZE;
222 }
223
224 KeReleaseSpinLock(&DebugLogLock, oldIrql);
225
226 if (oldIrql < DISPATCH_LEVEL)
227 {
228 KeSetEvent(&DebugLogEvent, IO_NO_INCREMENT, FALSE);
229 }
230 }
231