34 #undef PERFEVAL_WRITE_TO_MEMORY
39 #define DBG_PRINT_REG( _xxx ) DBG_PRINT( _xxx )
40 #define DBG_PRINT_FILE( _xxx ) DBG_PRINT( _xxx )
44 #define DBG_PRINT_REG( _xxx )
45 #define DBG_PRINT_FILE( _xxx )
51 #define MAX_PERFORMANCE_EVAL_ENTRIES 0xffff
54 static PPERFORMANCE_EVAL_ENTRY PerformanceEvalEntries = NULL;
59 static ULONG CurrentPerformanceEvalEntry = -1;
64 static ULONG ProcessorFrequency = -1;
83 #pragma warning(disable:4035)
85 __forceinline __int64 RDTSC(
void)
96 QueryPerformanceCounter(&li);
117 DBG_ASSERT(CurrentPerformanceEvalEntry == -1);
121 PerformanceEvalEntries = (PPERFORMANCE_EVAL_ENTRY) malloc(
122 MAX_PERFORMANCE_EVAL_ENTRIES *
sizeof(*PerformanceEvalEntries));
124 if (PerformanceEvalEntries)
128 UNICODE_STRING registryPath;
130 HANDLE handleRegistry;
136 RtlInitUnicodeString(®istryPath,
137 L
"\\REGISTRY\\MACHINE\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0");
139 DBG_PRINT_REG((
DBG_PREFIX "trying to open %wZ", ®istryPath));
143 if (NT_SUCCESS(ntStatus))
146 DBG_PRINT_REG((
DBG_PREFIX "cbm_registry_read() returned %s, value = %u",
156 QueryPerformanceCounter(&li);
159 ProcessorFrequency = li.LowPart;
192 PerfEvent(IN ULONG_PTR Event, IN ULONG_PTR Data)
200 if (PerformanceEvalEntries)
207 currentEntry = InterlockedIncrement(&CurrentPerformanceEvalEntry);
209 if (currentEntry < MAX_PERFORMANCE_EVAL_ENTRIES)
211 PerformanceEvalEntries[currentEntry].Timestamp = RDTSC();
212 PerformanceEvalEntries[currentEntry].Processor = 0;
213 PerformanceEvalEntries[currentEntry].PeThread = GetCurrentThread();
214 PerformanceEvalEntries[currentEntry].Event = Event;
215 PerformanceEvalEntries[currentEntry].Data = Data;
223 InterlockedDecrement(&CurrentPerformanceEvalEntry);
233 struct PERFEVAL_FILE_HEADER
240 ULONG ProcessorFrequency;
245 } PERFEVAL_FILE_HEADER, *PPERFEVAL_FILE_HEADER;
258 PerfSynchronize(VOID)
264 DBG_ASSERT(((LONG)CurrentPerformanceEvalEntry) >= 0);
266 if (PerformanceEvalEntries)
269 #ifdef PERFEVAL_WRITE_TO_MEMORY
271 __int64 FirstTimestamp;
272 __int64 LastTimestamp;
275 FirstTimestamp = PerformanceEvalEntries[0].Timestamp;
276 LastTimestamp = FirstTimestamp;
278 for (i = 0; i < CurrentPerformanceEvalEntry; i++)
286 tempTimeAbs = (PerformanceEvalEntries[i].Timestamp - FirstTimestamp) / ProcessorFrequency;
287 tempTimeRel = (PerformanceEvalEntries[i].Timestamp - LastTimestamp) / ProcessorFrequency;
289 LastTimestamp = PerformanceEvalEntries[i].Timestamp;
291 usTime = (ULONG) (tempTimeAbs % 1000);
292 msTime = (ULONG) ((tempTimeAbs / 1000) % 1000);
293 sTime = (ULONG) ((tempTimeAbs / 1000000) % 1000);
296 "%6u - Time: %3u.%03u.%03u us (+%7I64u us) - Event = %08x, Data = %08x"
297 " on processur %u in thread %p",
299 sTime, msTime, usTime,
301 PerformanceEvalEntries[i].Event,
302 PerformanceEvalEntries[i].Data,
303 PerformanceEvalEntries[i].Processor,
304 PerformanceEvalEntries[i].PeThread));
310 InterlockedExchange(&CurrentPerformanceEvalEntry, -1);
314 HANDLE fileHandle = CreateFile(
"time.perfeval", GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
316 if (fileHandle != INVALID_HANDLE_VALUE)
318 PERFEVAL_FILE_HEADER fileHeader;
321 fileHeader.FileVersion = 2
327 fileHeader.ProcessorFrequency = ProcessorFrequency;
328 fileHeader.CountEntries = CurrentPerformanceEvalEntry + 1;
332 WriteFile(fileHandle, &fileHeader,
sizeof(fileHeader), &byteWritten, NULL);
334 WriteFile(fileHandle, PerformanceEvalEntries, fileHeader.CountEntries *
sizeof(*PerformanceEvalEntries), &byteWritten, NULL);
336 CloseHandle(fileHandle);
341 InterlockedExchange(&CurrentPerformanceEvalEntry, -1);
362 #ifndef InterlockedExchangePointer
363 # define InterlockedExchangePointer(_x, _y) (void*) InterlockedExchange( (void*) (_x), (_y))
371 if (PerformanceEvalEntries)
381 buffer = InterlockedExchangePointer(&PerformanceEvalEntries, 0);
382 InterlockedExchange(&CurrentPerformanceEvalEntry, -1);
NTSTATUS cbm_registry_close(IN HANDLE HandleKey)
Close a registry key.
NTSTATUS cbm_registry_read_ulong(IN HANDLE HandleKey, IN PCWSTR KeyName, OUT PULONG Value)
Read a ULONG value out of a registry key.
const UCHAR * DebugNtStatus(NTSTATUS Value)
Return the description of an NTSTATUS code.
Functions and macros for performance evaluation purposes.
NTSTATUS cbm_registry_open_for_read(OUT PHANDLE HandleKey, IN PUNICODE_STRING Path)
Open a registry path for reading.