00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00020 #include <wdm.h>
00021
00022 #include "cbm_driver.h"
00023
00024 #include "../libiec/i_iec.h"
00025
00026 #ifdef PERFEVAL
00027
00029 #undef PERFEVAL_DEBUG
00030
00033 #undef PERFEVAL_WRITE_TO_MEMORY
00034
00035
00036 #ifdef PERFEVAL_DEBUG
00037
00038 #define DBG_PRINT_REG( _xxx ) DBG_PRINT( _xxx )
00039 #define DBG_PRINT_FILE( _xxx ) DBG_PRINT( _xxx )
00040
00041 #else
00042
00043 #define DBG_PRINT_REG( _xxx )
00044 #define DBG_PRINT_FILE( _xxx )
00045
00046 #endif
00047
00050 #define MAX_PERFORMANCE_EVAL_ENTRIES 0xffff
00051
00053 static PPERFORMANCE_EVAL_ENTRY PerformanceEvalEntries = NULL;
00054
00058 static ULONG CurrentPerformanceEvalEntry = -1;
00059
00063 static ULONG ProcessorFrequency = -1;
00064
00081 #pragma warning(push)
00082 #pragma warning(disable:4035)
00083
00084 __forceinline __int64 RDTSC(void)
00085 {
00086 #ifdef USE_RDTSC
00087 __asm {
00088
00089 _emit 0x0F
00090 _emit 0x31
00091 }
00092 #else
00093 LARGE_INTEGER li;
00094
00095 li = KeQueryPerformanceCounter(NULL);
00096
00097 return li.QuadPart;
00098 #endif
00099 }
00100 #pragma warning(pop)
00101
00110 VOID
00111 PerfInit(VOID)
00112 {
00113 FUNC_ENTER();
00114
00115 DBG_ASSERT(PerformanceEvalEntries == NULL);
00116 DBG_ASSERT(CurrentPerformanceEvalEntry == -1);
00117
00118
00119
00120 PerformanceEvalEntries = (PPERFORMANCE_EVAL_ENTRY) ExAllocatePoolWithTag(NonPagedPool,
00121 MAX_PERFORMANCE_EVAL_ENTRIES * sizeof(*PerformanceEvalEntries), MTAG_PERFEVAL);
00122
00123 if (PerformanceEvalEntries)
00124 {
00125 #ifdef USE_RDTSC
00126
00127 UNICODE_STRING registryPath;
00128 NTSTATUS ntStatus;
00129 HANDLE handleRegistry;
00130
00131
00132
00133
00134
00135 RtlInitUnicodeString(®istryPath,
00136 L"\\REGISTRY\\MACHINE\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0");
00137
00138 DBG_PRINT_REG((DBG_PREFIX "trying to open %wZ", ®istryPath));
00139 ntStatus = cbm_registry_open_for_read(&handleRegistry, ®istryPath);
00140 DBG_PRINT_REG((DBG_PREFIX "cbm_registry_open() returned %s", DebugNtStatus(ntStatus)));
00141
00142 if (NT_SUCCESS(ntStatus))
00143 {
00144 ntStatus = cbm_registry_read_ulong(handleRegistry, L"~MHz", &ProcessorFrequency);
00145 DBG_PRINT_REG((DBG_PREFIX "cbm_registry_read() returned %s, value = %u",
00146 DebugNtStatus(ntStatus), ProcessorFrequency));
00147
00148 ntStatus = cbm_registry_close(handleRegistry);
00149 DBG_PRINT_REG((DBG_PREFIX "cbm_registry_close() returned %s", DebugNtStatus(ntStatus)));
00150 }
00151
00152 #else
00153 LARGE_INTEGER li;
00154
00155 KeQueryPerformanceCounter(&li);
00156
00157 DBG_ASSERT(li.HighPart == 0);
00158 ProcessorFrequency = li.LowPart;
00159
00160 #endif
00161
00162 {
00163 unsigned int waitPeriod = 100;
00164
00165 DBG_PRINT((DBG_PREFIX "Measuring time:"));
00166 PERF_EVENT_MEASURE_TIME(0);
00167 cbmiec_udelay(waitPeriod);
00168 PERF_EVENT_MEASURE_TIME(waitPeriod);
00169 DBG_PRINT((DBG_PREFIX "We waited %u us.", waitPeriod));
00170 }
00171 }
00172
00173 FUNC_LEAVE();
00174 }
00175
00200 VOID
00201 PerfEvent(IN ULONG_PTR Event, IN ULONG_PTR Data)
00202 {
00203 ULONG currentEntry;
00204
00205 FUNC_ENTER();
00206
00207
00208
00209 if (PerformanceEvalEntries)
00210 {
00211
00212
00213
00214
00215
00216 currentEntry = InterlockedIncrement(&CurrentPerformanceEvalEntry);
00217
00218 if (currentEntry < MAX_PERFORMANCE_EVAL_ENTRIES)
00219 {
00220 PerformanceEvalEntries[currentEntry].Timestamp = RDTSC();
00221 PerformanceEvalEntries[currentEntry].Processor = CbmGetCurrentProcessorNumber();
00222 PerformanceEvalEntries[currentEntry].PeThread = PsGetCurrentThread();
00223 PerformanceEvalEntries[currentEntry].Event = Event;
00224 PerformanceEvalEntries[currentEntry].Data = Data;
00225 }
00226 else
00227 {
00228
00229
00230
00231
00232 InterlockedDecrement(&CurrentPerformanceEvalEntry);
00233 }
00234 }
00235
00236 FUNC_LEAVE();
00237 }
00238
00241 typedef
00242 struct PERFEVAL_FILE_HEADER
00243 {
00245 ULONG FileVersion;
00246
00249 ULONG ProcessorFrequency;
00250
00252 ULONG CountEntries;
00253
00254 } PERFEVAL_FILE_HEADER, *PPERFEVAL_FILE_HEADER;
00255
00266 VOID
00267 PerfSynchronize(VOID)
00268 {
00269 FUNC_ENTER();
00270
00271
00272
00273 DBG_ASSERT(((LONG)CurrentPerformanceEvalEntry) >= 0);
00274
00275 if (PerformanceEvalEntries)
00276 {
00277
00278 #ifdef PERFEVAL_WRITE_TO_MEMORY
00279
00280 __int64 FirstTimestamp;
00281 __int64 LastTimestamp;
00282 ULONG i;
00283
00284 FirstTimestamp = PerformanceEvalEntries[0].Timestamp;
00285 LastTimestamp = FirstTimestamp;
00286
00287 for (i = 0; i < CurrentPerformanceEvalEntry; i++)
00288 {
00289 __int64 tempTimeAbs;
00290 __int64 tempTimeRel;
00291 ULONG usTime;
00292 ULONG msTime;
00293 ULONG sTime;
00294
00295 tempTimeAbs = (PerformanceEvalEntries[i].Timestamp - FirstTimestamp) / ProcessorFrequency;
00296 tempTimeRel = (PerformanceEvalEntries[i].Timestamp - LastTimestamp) / ProcessorFrequency;
00297
00298 LastTimestamp = PerformanceEvalEntries[i].Timestamp;
00299
00300 usTime = (ULONG) (tempTimeAbs % 1000);
00301 msTime = (ULONG) ((tempTimeAbs / 1000) % 1000);
00302 sTime = (ULONG) ((tempTimeAbs / 1000000) % 1000);
00303
00304 DBG_PRINT((DBG_PREFIX
00305 "%6u - Time: %3u.%03u.%03u us (+%7I64u us) - Event = %08x, Data = %08x"
00306 " on processur %u in thread %p",
00307 i,
00308 sTime, msTime, usTime,
00309 tempTimeRel,
00310 PerformanceEvalEntries[i].Event,
00311 PerformanceEvalEntries[i].Data,
00312 PerformanceEvalEntries[i].Processor,
00313 PerformanceEvalEntries[i].PeThread));
00314 }
00315
00316
00317
00318
00319 InterlockedExchange(&CurrentPerformanceEvalEntry, -1);
00320
00321 #else
00322
00323 IO_STATUS_BLOCK ioStatusBlock;
00324 OBJECT_ATTRIBUTES objectAttributes;
00325 UNICODE_STRING fileName;
00326 NTSTATUS ntStatus;
00327 HANDLE fileHandle;
00328
00329 RtlZeroMemory(&objectAttributes, sizeof(objectAttributes));
00330 RtlInitUnicodeString(&fileName, L"\\??\\c:\\opencbm\\timing\\timing.dat");
00331
00332 DBG_IRQL( == PASSIVE_LEVEL);
00333 InitializeObjectAttributes(&objectAttributes,
00334 &fileName,
00335 OBJ_CASE_INSENSITIVE ,
00336 NULL,
00337 NULL
00338 );
00339
00340 ntStatus = ZwCreateFile(
00341 &fileHandle,
00342 FILE_APPEND_DATA | SYNCHRONIZE,
00343 &objectAttributes,
00344 &ioStatusBlock,
00345 NULL,
00346 FILE_ATTRIBUTE_NORMAL,
00347 0,
00348 FILE_OPEN_IF,
00349 FILE_NON_DIRECTORY_FILE | FILE_SEQUENTIAL_ONLY | FILE_SYNCHRONOUS_IO_NONALERT,
00350 NULL,
00351 0
00352 );
00353
00354 DBG_PRINT_FILE((DBG_PREFIX "ZwCreateFile returned %s", DebugNtStatus(ntStatus)));
00355
00356 if (NT_SUCCESS(ntStatus))
00357 {
00358 PERFEVAL_FILE_HEADER fileHeader;
00359
00360 fileHeader.FileVersion = 2
00361 #ifndef _X86_
00362 | (1<<31);
00363 #endif
00364 ;
00365
00366 fileHeader.ProcessorFrequency = ProcessorFrequency;
00367 fileHeader.CountEntries = CurrentPerformanceEvalEntry + 1;
00368
00369
00370
00371 ntStatus = ZwWriteFile(fileHandle,
00372 NULL,
00373 NULL,
00374 NULL,
00375 &ioStatusBlock,
00376 &fileHeader,
00377 sizeof(fileHeader),
00378 NULL,
00379 NULL);
00380
00381 DBG_PRINT_FILE((DBG_PREFIX "ZwWriteFile (header) returned %s",
00382 DebugNtStatus(ntStatus)));
00383
00384 ntStatus = ZwWriteFile(fileHandle,
00385 NULL,
00386 NULL,
00387 NULL,
00388 &ioStatusBlock,
00389 PerformanceEvalEntries,
00390 fileHeader.CountEntries * sizeof(*PerformanceEvalEntries),
00391 NULL,
00392 NULL);
00393
00394 DBG_PRINT_FILE((DBG_PREFIX "ZwWriteFile (data) returned %s",
00395 DebugNtStatus(ntStatus)));
00396
00397 ntStatus = ZwClose(fileHandle);
00398
00399 DBG_PRINT_FILE((DBG_PREFIX "ZwCloseFile returned %s",
00400 DebugNtStatus(ntStatus)));
00401
00402
00403
00404
00405 InterlockedExchange(&CurrentPerformanceEvalEntry, -1);
00406 }
00407
00408 #endif
00409
00410 }
00411
00412 FUNC_LEAVE();
00413 }
00414
00426 VOID
00427 PerfSave(VOID)
00428 {
00429 FUNC_ENTER();
00430
00431 if (PerformanceEvalEntries)
00432 {
00433 PVOID buffer;
00434
00435
00436
00437 PerfSynchronize();
00438
00439
00440
00441 buffer = InterlockedExchangePointer(&PerformanceEvalEntries, NULL);
00442 InterlockedExchange(&CurrentPerformanceEvalEntry, -1);
00443
00444
00445
00446 ExFreePool(buffer);
00447 }
00448
00449 FUNC_LEAVE();
00450 }
00451
00452 #endif