23 #include "../libiec/i_iec.h"
32 #undef PERFEVAL_WRITE_TO_MEMORY
37 #define DBG_PRINT_REG( _xxx ) DBG_PRINT( _xxx )
38 #define DBG_PRINT_FILE( _xxx ) DBG_PRINT( _xxx )
42 #define DBG_PRINT_REG( _xxx )
43 #define DBG_PRINT_FILE( _xxx )
49 #define MAX_PERFORMANCE_EVAL_ENTRIES 0xffff
52 static PPERFORMANCE_EVAL_ENTRY PerformanceEvalEntries = NULL;
57 static ULONG CurrentPerformanceEvalEntry = -1;
62 static ULONG ProcessorFrequency = -1;
81 #pragma warning(disable:4035)
83 __forceinline __int64 RDTSC(
void)
94 li = KeQueryPerformanceCounter(NULL);
115 DBG_ASSERT(CurrentPerformanceEvalEntry == -1);
119 PerformanceEvalEntries = (PPERFORMANCE_EVAL_ENTRY) ExAllocatePoolWithTag(NonPagedPool,
120 MAX_PERFORMANCE_EVAL_ENTRIES *
sizeof(*PerformanceEvalEntries),
MTAG_PERFEVAL);
122 if (PerformanceEvalEntries)
126 UNICODE_STRING registryPath;
128 HANDLE handleRegistry;
134 RtlInitUnicodeString(®istryPath,
135 L
"\\REGISTRY\\MACHINE\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0");
137 DBG_PRINT_REG((
DBG_PREFIX "trying to open %wZ", ®istryPath));
141 if (NT_SUCCESS(ntStatus))
144 DBG_PRINT_REG((
DBG_PREFIX "cbm_registry_read() returned %s, value = %u",
154 KeQueryPerformanceCounter(&li);
157 ProcessorFrequency = li.LowPart;
162 unsigned int waitPeriod = 100;
200 PerfEvent(IN ULONG_PTR Event, IN ULONG_PTR Data)
208 if (PerformanceEvalEntries)
215 currentEntry = InterlockedIncrement(&CurrentPerformanceEvalEntry);
217 if (currentEntry < MAX_PERFORMANCE_EVAL_ENTRIES)
219 PerformanceEvalEntries[currentEntry].Timestamp = RDTSC();
221 PerformanceEvalEntries[currentEntry].PeThread = PsGetCurrentThread();
222 PerformanceEvalEntries[currentEntry].Event = Event;
223 PerformanceEvalEntries[currentEntry].Data = Data;
231 InterlockedDecrement(&CurrentPerformanceEvalEntry);
241 struct PERFEVAL_FILE_HEADER
248 ULONG ProcessorFrequency;
253 } PERFEVAL_FILE_HEADER, *PPERFEVAL_FILE_HEADER;
266 PerfSynchronize(VOID)
272 DBG_ASSERT(((LONG)CurrentPerformanceEvalEntry) >= 0);
274 if (PerformanceEvalEntries)
277 #ifdef PERFEVAL_WRITE_TO_MEMORY
279 __int64 FirstTimestamp;
280 __int64 LastTimestamp;
283 FirstTimestamp = PerformanceEvalEntries[0].Timestamp;
284 LastTimestamp = FirstTimestamp;
286 for (i = 0; i < CurrentPerformanceEvalEntry; i++)
294 tempTimeAbs = (PerformanceEvalEntries[i].Timestamp - FirstTimestamp) / ProcessorFrequency;
295 tempTimeRel = (PerformanceEvalEntries[i].Timestamp - LastTimestamp) / ProcessorFrequency;
297 LastTimestamp = PerformanceEvalEntries[i].Timestamp;
299 usTime = (ULONG) (tempTimeAbs % 1000);
300 msTime = (ULONG) ((tempTimeAbs / 1000) % 1000);
301 sTime = (ULONG) ((tempTimeAbs / 1000000) % 1000);
304 "%6u - Time: %3u.%03u.%03u us (+%7I64u us) - Event = %08x, Data = %08x"
305 " on processur %u in thread %p",
307 sTime, msTime, usTime,
309 PerformanceEvalEntries[i].Event,
310 PerformanceEvalEntries[i].Data,
311 PerformanceEvalEntries[i].Processor,
312 PerformanceEvalEntries[i].PeThread));
318 InterlockedExchange(&CurrentPerformanceEvalEntry, -1);
322 IO_STATUS_BLOCK ioStatusBlock;
323 OBJECT_ATTRIBUTES objectAttributes;
324 UNICODE_STRING fileName;
328 RtlZeroMemory(&objectAttributes,
sizeof(objectAttributes));
329 RtlInitUnicodeString(&fileName, L
"\\??\\c:\\opencbm\\timing\\timing.dat");
331 DBG_IRQL( == PASSIVE_LEVEL);
332 InitializeObjectAttributes(&objectAttributes,
334 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
339 ntStatus = ZwCreateFile(
341 FILE_APPEND_DATA | SYNCHRONIZE,
345 FILE_ATTRIBUTE_NORMAL,
348 FILE_NON_DIRECTORY_FILE | FILE_SEQUENTIAL_ONLY | FILE_SYNCHRONOUS_IO_NONALERT,
355 if (NT_SUCCESS(ntStatus))
357 PERFEVAL_FILE_HEADER fileHeader;
359 fileHeader.FileVersion = 2
365 fileHeader.ProcessorFrequency = ProcessorFrequency;
366 fileHeader.CountEntries = CurrentPerformanceEvalEntry + 1;
370 ntStatus = ZwWriteFile(fileHandle,
380 DBG_PRINT_FILE((
DBG_PREFIX "ZwWriteFile (header) returned %s",
383 ntStatus = ZwWriteFile(fileHandle,
388 PerformanceEvalEntries,
389 fileHeader.CountEntries *
sizeof(*PerformanceEvalEntries),
393 DBG_PRINT_FILE((
DBG_PREFIX "ZwWriteFile (data) returned %s",
396 ntStatus = ZwClose(fileHandle);
398 DBG_PRINT_FILE((
DBG_PREFIX "ZwCloseFile returned %s",
404 InterlockedExchange(&CurrentPerformanceEvalEntry, -1);
430 if (PerformanceEvalEntries)
440 buffer = InterlockedExchangePointer(&PerformanceEvalEntries, NULL);
441 InterlockedExchange(&CurrentPerformanceEvalEntry, -1);
VOID cbmiec_udelay(IN ULONG howlong)
Wait for a timeout.
ULONG CbmGetCurrentProcessorNumber(VOID)
Wrapper for KeGetCurrentProcessorNumber()
NTSTATUS cbm_registry_close(IN HANDLE HandleKey)
Close a registry key.
#define PERF_EVENT_MEASURE_TIME(_x_)
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.
Definitions for the opencbm driver.
NTSTATUS cbm_registry_open_for_read(OUT PHANDLE HandleKey, IN PUNICODE_STRING Path)
Open a registry path for reading.