VOID UpdateNodeInformation() { UINT32 j; D3DKMT_QUERYSTATISTICS queryStatistics; UINT64 totalRunningTime; UINT64 systemRunningTime; LARGE_INTEGER performanceCounter; static BOOLEAN initialized = FALSE; //check if initialized if (!initialized) { D3DKMTInitialize(); initialized = TRUE; } totalRunningTime = 0; systemRunningTime = 0; if (D3dkmt_GpuAdapter == NULL) { return; } for (j = 0; j < D3dkmt_GpuAdapter->NodeCount; j++) { memset(&queryStatistics, 0, sizeof(D3DKMT_QUERYSTATISTICS)); queryStatistics.Type = D3DKMT_QUERYSTATISTICS_NODE; queryStatistics.AdapterLuid = D3dkmt_GpuAdapter->AdapterLuid; queryStatistics.QueryNode.NodeId = j; if (NT_SUCCESS(D3DKMTQueryStatistics(&queryStatistics))) { UINT32 nodeIndex; nodeIndex = D3dkmt_GpuAdapter->FirstNodeIndex + j; PhUpdateDelta( &EtGpuNodesTotalRunningTimeDelta[nodeIndex], queryStatistics.QueryResult.NodeInformation.GlobalInformation.RunningTime.QuadPart ); totalRunningTime += queryStatistics.QueryResult.NodeInformation.GlobalInformation.RunningTime.QuadPart; systemRunningTime += queryStatistics.QueryResult.NodeInformation.SystemInformation.RunningTime.QuadPart; } } NtQueryPerformanceCounter(&performanceCounter, &EtClockTotalRunningTimeFrequency); PhUpdateDelta(&EtClockTotalRunningTimeDelta, performanceCounter.QuadPart); PhUpdateDelta(&EtGpuTotalRunningTimeDelta, totalRunningTime); PhUpdateDelta(&EtGpuSystemRunningTimeDelta, systemRunningTime); }
VOID PhSipTickCpuDialog( VOID ) { ULONG64 dpcCount; ULONG i; dpcCount = 0; if (NT_SUCCESS(NtQuerySystemInformation( SystemInterruptInformation, InterruptInformation, sizeof(SYSTEM_INTERRUPT_INFORMATION) * NumberOfProcessors, NULL ))) { for (i = 0; i < NumberOfProcessors; i++) dpcCount += InterruptInformation[i].DpcCount; } PhUpdateDelta(&ContextSwitchesDelta, PhPerfInformation.ContextSwitches); PhUpdateDelta(&InterruptsDelta, PhCpuTotals.InterruptCount); PhUpdateDelta(&DpcsDelta, dpcCount); PhUpdateDelta(&SystemCallsDelta, PhPerfInformation.SystemCalls); if (!NT_SUCCESS(NtPowerInformation( ProcessorInformation, NULL, 0, PowerInformation, sizeof(PROCESSOR_POWER_INFORMATION) * NumberOfProcessors ))) { memset(PowerInformation, 0, sizeof(PROCESSOR_POWER_INFORMATION) * NumberOfProcessors); } if (WindowsVersion >= WINDOWS_7) { if (PreviousPerformanceDistribution) PhFree(PreviousPerformanceDistribution); PreviousPerformanceDistribution = CurrentPerformanceDistribution; CurrentPerformanceDistribution = NULL; PhSipQueryProcessorPerformanceDistribution(&CurrentPerformanceDistribution); } CpuTicked++; if (CpuTicked > 2) CpuTicked = 2; PhSipUpdateCpuGraphs(); PhSipUpdateCpuPanel(); }
static VOID NTAPI ProcessesUpdatedCallback( __in_opt PVOID Parameter, __in_opt PVOID Context ) { PLIST_ENTRY listEntry; // Note: no lock is needed because we only ever modify the list on this same thread. listEntry = EtProcessBlockListHead.Flink; while (listEntry != &EtProcessBlockListHead) { PET_PROCESS_BLOCK block; block = CONTAINING_RECORD(listEntry, ET_PROCESS_BLOCK, ListEntry); PhUpdateDelta(&block->HardFaultsDelta, block->ProcessItem->HardFaultCount); // Invalidate all text. PhAcquireQueuedLockExclusive(&block->TextCacheLock); memset(block->TextCacheValid, 0, sizeof(block->TextCacheValid)); PhReleaseQueuedLockExclusive(&block->TextCacheLock); listEntry = listEntry->Flink; } }
VOID NTAPI EtEtwNetworkItemsUpdatedCallback( _In_opt_ PVOID Parameter, _In_opt_ PVOID Context ) { PLIST_ENTRY listEntry; // ETW is flushed in the processes-updated callback above. This may cause us the network // blocks to all fall one update interval behind, however. // Update per-connection statistics. // Note: no lock is needed because we only ever modify the list on this same thread. listEntry = EtNetworkBlockListHead.Flink; while (listEntry != &EtNetworkBlockListHead) { PET_NETWORK_BLOCK block; PH_UINT64_DELTA oldDeltas[4]; block = CONTAINING_RECORD(listEntry, ET_NETWORK_BLOCK, ListEntry); memcpy(oldDeltas, block->Deltas, sizeof(block->Deltas)); PhUpdateDelta(&block->ReceiveDelta, block->ReceiveCount); PhUpdateDelta(&block->ReceiveRawDelta, block->ReceiveRaw); PhUpdateDelta(&block->SendDelta, block->SendCount); PhUpdateDelta(&block->SendRawDelta, block->SendRaw); if (memcmp(oldDeltas, block->Deltas, sizeof(block->Deltas))) { // Values have changed. Invalidate the network node. PhReferenceObject(block->NetworkItem); ProcessHacker_Invoke(PhMainWndHandle, EtpInvalidateNetworkNode, block->NetworkItem); } listEntry = listEntry->Flink; } }
VOID PhSipTickMemoryDialog( VOID ) { PhUpdateDelta(&PagedAllocsDelta, PhPerfInformation.PagedPoolAllocs); PhUpdateDelta(&PagedFreesDelta, PhPerfInformation.PagedPoolFrees); PhUpdateDelta(&NonPagedAllocsDelta, PhPerfInformation.NonPagedPoolAllocs); PhUpdateDelta(&NonPagedFreesDelta, PhPerfInformation.NonPagedPoolFrees); PhUpdateDelta(&PageFaultsDelta, PhPerfInformation.PageFaultCount); PhUpdateDelta(&PageReadsDelta, PhPerfInformation.PageReadCount); PhUpdateDelta(&PagefileWritesDelta, PhPerfInformation.DirtyPagesWriteCount); PhUpdateDelta(&MappedWritesDelta, PhPerfInformation.MappedPagesWriteCount); MemoryTicked++; if (MemoryTicked > 2) MemoryTicked = 2; PhSipUpdateMemoryGraphs(); PhSipUpdateMemoryPanel(); }
VOID DiskDrivesUpdate( VOID ) { static ULONG runCount = 0; // MUST keep in sync with runCount in process provider PhAcquireQueuedLockShared(&DiskDrivesListLock); for (ULONG i = 0; i < DiskDrivesList->Count; i++) { HANDLE deviceHandle; PDV_DISK_ENTRY entry; entry = PhReferenceObjectSafe(DiskDrivesList->Items[i]); if (!entry) continue; if (NT_SUCCESS(DiskDriveCreateHandle(&deviceHandle, entry->Id.DevicePath))) { DISK_PERFORMANCE diskPerformance; if (NT_SUCCESS(DiskDriveQueryStatistics(deviceHandle, &diskPerformance))) { ULONG64 readTime; ULONG64 writeTime; ULONG64 idleTime; ULONG readCount; ULONG writeCount; ULONG64 queryTime; PhUpdateDelta(&entry->BytesReadDelta, diskPerformance.BytesRead.QuadPart); PhUpdateDelta(&entry->BytesWrittenDelta, diskPerformance.BytesWritten.QuadPart); PhUpdateDelta(&entry->ReadTimeDelta, diskPerformance.ReadTime.QuadPart); PhUpdateDelta(&entry->WriteTimeDelta, diskPerformance.WriteTime.QuadPart); PhUpdateDelta(&entry->IdleTimeDelta, diskPerformance.IdleTime.QuadPart); PhUpdateDelta(&entry->ReadCountDelta, diskPerformance.ReadCount); PhUpdateDelta(&entry->WriteCountDelta, diskPerformance.WriteCount); PhUpdateDelta(&entry->QueryTimeDelta, diskPerformance.QueryTime.QuadPart); readTime = entry->ReadTimeDelta.Delta; writeTime = entry->WriteTimeDelta.Delta; idleTime = entry->IdleTimeDelta.Delta; readCount = entry->ReadCountDelta.Delta; writeCount = entry->WriteCountDelta.Delta; queryTime = entry->QueryTimeDelta.Delta; if (readCount + writeCount != 0) entry->ResponseTime = ((FLOAT)readTime + (FLOAT)writeTime) / (readCount + writeCount); else entry->ResponseTime = 0; if (queryTime != 0) entry->ActiveTime = (FLOAT)(queryTime - idleTime) / queryTime * 100; else entry->ActiveTime = 0.0f; if (entry->ActiveTime > 100.f) entry->ActiveTime = 0.f; if (entry->ActiveTime < 0.f) entry->ActiveTime = 0.f; entry->QueueDepth = diskPerformance.QueueDepth; entry->SplitCount = diskPerformance.SplitCount; entry->DiskIndex = diskPerformance.StorageDeviceNumber; entry->DevicePresent = TRUE; } else { // Disk has been disconnected or dismounted. PhInitializeDelta(&entry->BytesReadDelta); PhInitializeDelta(&entry->BytesWrittenDelta); PhInitializeDelta(&entry->ReadTimeDelta); PhInitializeDelta(&entry->WriteTimeDelta); PhInitializeDelta(&entry->IdleTimeDelta); PhInitializeDelta(&entry->ReadCountDelta); PhInitializeDelta(&entry->WriteCountDelta); PhInitializeDelta(&entry->QueryTimeDelta); entry->ResponseTime = 0; entry->ActiveTime = 0.0f; entry->QueueDepth = 0; entry->SplitCount = 0; entry->DiskIndex = ULONG_MAX; entry->DevicePresent = FALSE; PhClearReference(&entry->DiskIndexName); } if (runCount > 1) { // Delay the first query for the disk name, index and type. // 1) This information is not needed until the user opens the sysinfo window. // 2) Try not to query this information while opening the sysinfo window (e.g. delay). // 3) Try not to query this information during startup (e.g. delay). // // Note: If the user opens the Sysinfo window before we query the disk info, // we have a second check in diskgraph.c that queries the information on demand. DiskDriveUpdateDeviceInfo(deviceHandle, entry); } NtClose(deviceHandle); } else { // Disk has been disconnected or dismounted. PhInitializeDelta(&entry->BytesReadDelta); PhInitializeDelta(&entry->BytesWrittenDelta); PhInitializeDelta(&entry->ReadTimeDelta); PhInitializeDelta(&entry->WriteTimeDelta); PhInitializeDelta(&entry->IdleTimeDelta); PhInitializeDelta(&entry->ReadCountDelta); PhInitializeDelta(&entry->WriteCountDelta); PhInitializeDelta(&entry->QueryTimeDelta); entry->ResponseTime = 0; entry->ActiveTime = 0.0f; entry->QueueDepth = 0; entry->SplitCount = 0; entry->DiskIndex = ULONG_MAX; entry->DevicePresent = FALSE; PhClearReference(&entry->DiskIndexName); } if (!entry->HaveFirstSample) { // The first sample must be zero. entry->BytesReadDelta.Delta = 0; entry->BytesWrittenDelta.Delta = 0; entry->HaveFirstSample = TRUE; } if (runCount != 0) { PhAddItemCircularBuffer_ULONG64(&entry->ReadBuffer, entry->BytesReadDelta.Delta); PhAddItemCircularBuffer_ULONG64(&entry->WriteBuffer, entry->BytesWrittenDelta.Delta); } PhDereferenceObjectDeferDelete(entry); } PhReleaseQueuedLockShared(&DiskDrivesListLock); runCount++; }
VOID NTAPI EtEtwProcessesUpdatedCallback( _In_opt_ PVOID Parameter, _In_opt_ PVOID Context ) { static ULONG runCount = 0; // MUST keep in sync with runCount in process provider PLIST_ENTRY listEntry; ULONG64 maxDiskValue = 0; PET_PROCESS_BLOCK maxDiskBlock = NULL; ULONG64 maxNetworkValue = 0; PET_PROCESS_BLOCK maxNetworkBlock = NULL; // Since Windows 8, we no longer get the correct process/thread IDs in the // event headers for disk events. We need to update our process information since // etwmon uses our EtThreadIdToProcessId function. if (WindowsVersion >= WINDOWS_8) EtUpdateProcessInformation(); // ETW is extremely lazy when it comes to flushing buffers, so we must do it // manually. EtFlushEtwSession(); // Update global statistics. PhUpdateDelta(&EtDiskReadDelta, EtpDiskReadRaw); PhUpdateDelta(&EtDiskWriteDelta, EtpDiskWriteRaw); PhUpdateDelta(&EtNetworkReceiveDelta, EtpNetworkReceiveRaw); PhUpdateDelta(&EtNetworkSendDelta, EtpNetworkSendRaw); PhUpdateDelta(&EtDiskReadCountDelta, EtDiskReadCount); PhUpdateDelta(&EtDiskWriteCountDelta, EtDiskWriteCount); PhUpdateDelta(&EtNetworkReceiveCountDelta, EtNetworkReceiveCount); PhUpdateDelta(&EtNetworkSendCountDelta, EtNetworkSendCount); // Update per-process statistics. // Note: no lock is needed because we only ever modify the list on this same thread. listEntry = EtProcessBlockListHead.Flink; while (listEntry != &EtProcessBlockListHead) { PET_PROCESS_BLOCK block; block = CONTAINING_RECORD(listEntry, ET_PROCESS_BLOCK, ListEntry); PhUpdateDelta(&block->DiskReadDelta, block->DiskReadCount); PhUpdateDelta(&block->DiskReadRawDelta, block->DiskReadRaw); PhUpdateDelta(&block->DiskWriteDelta, block->DiskWriteCount); PhUpdateDelta(&block->DiskWriteRawDelta, block->DiskWriteRaw); PhUpdateDelta(&block->NetworkReceiveDelta, block->NetworkReceiveCount); PhUpdateDelta(&block->NetworkReceiveRawDelta, block->NetworkReceiveRaw); PhUpdateDelta(&block->NetworkSendDelta, block->NetworkSendCount); PhUpdateDelta(&block->NetworkSendRawDelta, block->NetworkSendRaw); if (maxDiskValue < block->DiskReadRawDelta.Delta + block->DiskWriteRawDelta.Delta) { maxDiskValue = block->DiskReadRawDelta.Delta + block->DiskWriteRawDelta.Delta; maxDiskBlock = block; } if (maxNetworkValue < block->NetworkReceiveRawDelta.Delta + block->NetworkSendRawDelta.Delta) { maxNetworkValue = block->NetworkReceiveRawDelta.Delta + block->NetworkSendRawDelta.Delta; maxNetworkBlock = block; } listEntry = listEntry->Flink; } // Update history buffers. if (runCount != 0) { PhAddItemCircularBuffer_ULONG(&EtDiskReadHistory, EtDiskReadDelta.Delta); PhAddItemCircularBuffer_ULONG(&EtDiskWriteHistory, EtDiskWriteDelta.Delta); PhAddItemCircularBuffer_ULONG(&EtNetworkReceiveHistory, EtNetworkReceiveDelta.Delta); PhAddItemCircularBuffer_ULONG(&EtNetworkSendHistory, EtNetworkSendDelta.Delta); if (maxDiskBlock) { PhAddItemCircularBuffer_ULONG(&EtMaxDiskHistory, HandleToUlong(maxDiskBlock->ProcessItem->ProcessId)); PhReferenceProcessRecordForStatistics(maxDiskBlock->ProcessItem->Record); } else { PhAddItemCircularBuffer_ULONG(&EtMaxDiskHistory, 0); } if (maxNetworkBlock) { PhAddItemCircularBuffer_ULONG(&EtMaxNetworkHistory, HandleToUlong(maxNetworkBlock->ProcessItem->ProcessId)); PhReferenceProcessRecordForStatistics(maxNetworkBlock->ProcessItem->Record); } else { PhAddItemCircularBuffer_ULONG(&EtMaxNetworkHistory, 0); } } runCount++; }
VOID PhpThreadProviderUpdate( __in PPH_THREAD_PROVIDER ThreadProvider, __in PVOID ProcessInformation ) { PPH_THREAD_PROVIDER threadProvider = ThreadProvider; PSYSTEM_PROCESS_INFORMATION process; SYSTEM_PROCESS_INFORMATION localProcess; PSYSTEM_THREAD_INFORMATION threads; ULONG numberOfThreads; ULONG i; process = PhFindProcessInformation(ProcessInformation, threadProvider->ProcessId); if (!process) { // The process doesn't exist anymore. Pretend it does but // has no threads. process = &localProcess; process->NumberOfThreads = 0; } threads = process->Threads; numberOfThreads = process->NumberOfThreads; // System Idle Process has one thread per CPU. // They all have a TID of 0, but we can't have // multiple TIDs, so we'll assign unique TIDs. if (threadProvider->ProcessId == SYSTEM_IDLE_PROCESS_ID) { for (i = 0; i < numberOfThreads; i++) { threads[i].ClientId.UniqueThread = (HANDLE)i; } } // Look for dead threads. { PPH_LIST threadsToRemove = NULL; ULONG enumerationKey = 0; PPH_THREAD_ITEM *threadItem; while (PhEnumHashtable(threadProvider->ThreadHashtable, (PPVOID)&threadItem, &enumerationKey)) { BOOLEAN found = FALSE; // Check if the thread still exists. for (i = 0; i < numberOfThreads; i++) { PSYSTEM_THREAD_INFORMATION thread = &threads[i]; if ((*threadItem)->ThreadId == thread->ClientId.UniqueThread) { found = TRUE; break; } } if (!found) { // Raise the thread removed event. PhInvokeCallback(&threadProvider->ThreadRemovedEvent, *threadItem); if (!threadsToRemove) threadsToRemove = PhCreateList(2); PhAddItemList(threadsToRemove, *threadItem); } } if (threadsToRemove) { PhAcquireFastLockExclusive(&threadProvider->ThreadHashtableLock); for (i = 0; i < threadsToRemove->Count; i++) { PhpRemoveThreadItem( threadProvider, (PPH_THREAD_ITEM)threadsToRemove->Items[i] ); } PhReleaseFastLockExclusive(&threadProvider->ThreadHashtableLock); PhDereferenceObject(threadsToRemove); } } // Go through the queued thread query data. { PSLIST_ENTRY entry; PPH_THREAD_QUERY_DATA data; entry = RtlInterlockedFlushSList(&threadProvider->QueryListHead); while (entry) { data = CONTAINING_RECORD(entry, PH_THREAD_QUERY_DATA, ListEntry); entry = entry->Next; if (data->StartAddressResolveLevel == PhsrlFunction && data->StartAddressString) { PhSwapReference(&data->ThreadItem->StartAddressString, data->StartAddressString); data->ThreadItem->StartAddressResolveLevel = data->StartAddressResolveLevel; } PhSwapReference2(&data->ThreadItem->ServiceName, data->ServiceName); data->ThreadItem->JustResolved = TRUE; if (data->StartAddressString) PhDereferenceObject(data->StartAddressString); PhDereferenceObject(data->ThreadItem); PhFree(data); } } // Look for new threads and update existing ones. for (i = 0; i < numberOfThreads; i++) { PSYSTEM_THREAD_INFORMATION thread = &threads[i]; PPH_THREAD_ITEM threadItem; threadItem = PhReferenceThreadItem(threadProvider, thread->ClientId.UniqueThread); if (!threadItem) { ULONG64 cycles; PVOID startAddress = NULL; threadItem = PhCreateThreadItem(thread->ClientId.UniqueThread); threadItem->CreateTime = thread->CreateTime; threadItem->KernelTime = thread->KernelTime; threadItem->UserTime = thread->UserTime; PhUpdateDelta(&threadItem->ContextSwitchesDelta, thread->ContextSwitches); threadItem->Priority = thread->Priority; threadItem->BasePriority = thread->BasePriority; threadItem->State = (KTHREAD_STATE)thread->ThreadState; threadItem->WaitReason = thread->WaitReason; // Try to open a handle to the thread. if (!NT_SUCCESS(PhOpenThread( &threadItem->ThreadHandle, THREAD_QUERY_INFORMATION, threadItem->ThreadId ))) { PhOpenThread( &threadItem->ThreadHandle, ThreadQueryAccess, threadItem->ThreadId ); } // Get the cycle count. if (NT_SUCCESS(PhpGetThreadCycleTime( threadProvider, threadItem, &cycles ))) { PhUpdateDelta(&threadItem->CyclesDelta, cycles); } // Initialize the CPU time deltas. PhUpdateDelta(&threadItem->CpuKernelDelta, threadItem->KernelTime.QuadPart); PhUpdateDelta(&threadItem->CpuUserDelta, threadItem->UserTime.QuadPart); // Try to get the start address. if (threadItem->ThreadHandle) { NtQueryInformationThread( threadItem->ThreadHandle, ThreadQuerySetWin32StartAddress, &startAddress, sizeof(PVOID), NULL ); } if (!startAddress) startAddress = thread->StartAddress; threadItem->StartAddress = (ULONG64)startAddress; // Get the Win32 priority. threadItem->PriorityWin32 = GetThreadPriority(threadItem->ThreadHandle); if (PhTestEvent(&threadProvider->SymbolsLoadedEvent)) { threadItem->StartAddressString = PhpGetThreadBasicStartAddress( threadProvider, threadItem->StartAddress, &threadItem->StartAddressResolveLevel ); } if (!threadItem->StartAddressString) { threadItem->StartAddressResolveLevel = PhsrlAddress; threadItem->StartAddressString = PhCreateStringEx(NULL, PH_PTR_STR_LEN * 2); PhPrintPointer( threadItem->StartAddressString->Buffer, (PVOID)threadItem->StartAddress ); PhTrimToNullTerminatorString(threadItem->StartAddressString); } PhpQueueThreadQuery(threadProvider, threadItem); // Is it a GUI thread? if (threadItem->ThreadHandle && KphIsConnected()) { PVOID win32Thread; if (NT_SUCCESS(KphQueryInformationThread( threadItem->ThreadHandle, KphThreadWin32Thread, &win32Thread, sizeof(PVOID), NULL ))) { threadItem->IsGuiThread = win32Thread != NULL; } } // Add the thread item to the hashtable. PhAcquireFastLockExclusive(&threadProvider->ThreadHashtableLock); PhAddEntryHashtable(threadProvider->ThreadHashtable, &threadItem); PhReleaseFastLockExclusive(&threadProvider->ThreadHashtableLock); // Raise the thread added event. PhInvokeCallback(&threadProvider->ThreadAddedEvent, threadItem); } else { BOOLEAN modified = FALSE; if (threadItem->JustResolved) modified = TRUE; threadItem->KernelTime = thread->KernelTime; threadItem->UserTime = thread->UserTime; threadItem->Priority = thread->Priority; threadItem->BasePriority = thread->BasePriority; threadItem->State = (KTHREAD_STATE)thread->ThreadState; if (threadItem->WaitReason != thread->WaitReason) { threadItem->WaitReason = thread->WaitReason; modified = TRUE; } // If the resolve level is only at address, it probably // means symbols weren't loaded the last time we // tried to get the start address. Try again. if (threadItem->StartAddressResolveLevel == PhsrlAddress) { if (PhTestEvent(&threadProvider->SymbolsLoadedEvent)) { PPH_STRING newStartAddressString; newStartAddressString = PhpGetThreadBasicStartAddress( threadProvider, threadItem->StartAddress, &threadItem->StartAddressResolveLevel ); PhSwapReference2( &threadItem->StartAddressString, newStartAddressString ); modified = TRUE; } } // If we couldn't resolve the start address to a // module+offset, use the StartAddress instead // of the Win32StartAddress and try again. // Note that we check the resolve level again // because we may have changed it in the previous // block. if ( threadItem->JustResolved && threadItem->StartAddressResolveLevel == PhsrlAddress ) { if (threadItem->StartAddress != (ULONG64)thread->StartAddress) { threadItem->StartAddress = (ULONG64)thread->StartAddress; PhpQueueThreadQuery(threadProvider, threadItem); } } // Update the context switch count. { ULONG oldDelta; oldDelta = threadItem->ContextSwitchesDelta.Delta; PhUpdateDelta(&threadItem->ContextSwitchesDelta, thread->ContextSwitches); if (threadItem->ContextSwitchesDelta.Delta != oldDelta) { modified = TRUE; } } // Update the cycle count. { ULONG64 cycles; ULONG64 oldDelta; oldDelta = threadItem->CyclesDelta.Delta; if (NT_SUCCESS(PhpGetThreadCycleTime( threadProvider, threadItem, &cycles ))) { PhUpdateDelta(&threadItem->CyclesDelta, cycles); if (threadItem->CyclesDelta.Delta != oldDelta) { modified = TRUE; } } } // Update the CPU time deltas. PhUpdateDelta(&threadItem->CpuKernelDelta, threadItem->KernelTime.QuadPart); PhUpdateDelta(&threadItem->CpuUserDelta, threadItem->UserTime.QuadPart); // Update the CPU usage. // If the cycle time isn't available, we'll fall back to using the CPU time. if (PhEnableCycleCpuUsage && (threadProvider->ProcessId == SYSTEM_IDLE_PROCESS_ID || threadItem->ThreadHandle)) { threadItem->CpuUsage = (FLOAT)threadItem->CyclesDelta.Delta / PhCpuTotalCycleDelta; } else { threadItem->CpuUsage = (FLOAT)(threadItem->CpuKernelDelta.Delta + threadItem->CpuUserDelta.Delta) / (PhCpuKernelDelta.Delta + PhCpuUserDelta.Delta + PhCpuIdleDelta.Delta); } // Update the Win32 priority. { LONG oldPriorityWin32 = threadItem->PriorityWin32; threadItem->PriorityWin32 = GetThreadPriority(threadItem->ThreadHandle); if (threadItem->PriorityWin32 != oldPriorityWin32) { modified = TRUE; } } // Update the GUI thread status. if (threadItem->ThreadHandle && KphIsConnected()) { PVOID win32Thread; if (NT_SUCCESS(KphQueryInformationThread( threadItem->ThreadHandle, KphThreadWin32Thread, &win32Thread, sizeof(PVOID), NULL ))) { BOOLEAN oldIsGuiThread = threadItem->IsGuiThread; threadItem->IsGuiThread = win32Thread != NULL; if (threadItem->IsGuiThread != oldIsGuiThread) modified = TRUE; } } threadItem->JustResolved = FALSE; if (modified) { // Raise the thread modified event. PhInvokeCallback(&threadProvider->ThreadModifiedEvent, threadItem); } PhDereferenceObject(threadItem); } } PhInvokeCallback(&threadProvider->UpdatedEvent, NULL); threadProvider->RunId++; }
static VOID EtpUpdateNodeInformation( _In_opt_ PET_PROCESS_BLOCK Block ) { ULONG i; ULONG j; PETP_GPU_ADAPTER gpuAdapter; D3DKMT_QUERYSTATISTICS queryStatistics; ULONG64 totalRunningTime; ULONG64 systemRunningTime; if (Block && !Block->ProcessItem->QueryHandle) return; totalRunningTime = 0; systemRunningTime = 0; for (i = 0; i < EtpGpuAdapterList->Count; i++) { gpuAdapter = EtpGpuAdapterList->Items[i]; for (j = 0; j < gpuAdapter->NodeCount; j++) { if (Block && !RtlCheckBit(&EtGpuNodeBitMap, gpuAdapter->FirstNodeIndex + j)) continue; memset(&queryStatistics, 0, sizeof(D3DKMT_QUERYSTATISTICS)); if (Block) queryStatistics.Type = D3DKMT_QUERYSTATISTICS_PROCESS_NODE; else queryStatistics.Type = D3DKMT_QUERYSTATISTICS_NODE; queryStatistics.AdapterLuid = gpuAdapter->AdapterLuid; if (Block) { queryStatistics.hProcess = Block->ProcessItem->QueryHandle; queryStatistics.QueryProcessNode.NodeId = j; } else { queryStatistics.QueryNode.NodeId = j; } if (NT_SUCCESS(D3DKMTQueryStatistics_I(&queryStatistics))) { if (Block) { totalRunningTime += queryStatistics.QueryResult.ProcessNodeInformation.RunningTime.QuadPart; } else { ULONG nodeIndex; nodeIndex = gpuAdapter->FirstNodeIndex + j; PhUpdateDelta(&EtGpuNodesTotalRunningTimeDelta[nodeIndex], queryStatistics.QueryResult.NodeInformation.GlobalInformation.RunningTime.QuadPart); if (RtlCheckBit(&EtGpuNodeBitMap, gpuAdapter->FirstNodeIndex + j)) { totalRunningTime += queryStatistics.QueryResult.NodeInformation.GlobalInformation.RunningTime.QuadPart; systemRunningTime += queryStatistics.QueryResult.NodeInformation.SystemInformation.RunningTime.QuadPart; } } } } } if (Block) { PhUpdateDelta(&Block->GpuRunningTimeDelta, totalRunningTime); } else { LARGE_INTEGER performanceCounter; NtQueryPerformanceCounter(&performanceCounter, &EtClockTotalRunningTimeFrequency); PhUpdateDelta(&EtClockTotalRunningTimeDelta, performanceCounter.QuadPart); PhUpdateDelta(&EtGpuTotalRunningTimeDelta, totalRunningTime); PhUpdateDelta(&EtGpuSystemRunningTimeDelta, systemRunningTime); } }
VOID DiskDrivesUpdate( VOID ) { static ULONG runCount = 0; // MUST keep in sync with runCount in process provider PhAcquireQueuedLockShared(&DiskDrivesListLock); for (ULONG i = 0; i < DiskDrivesList->Count; i++) { HANDLE deviceHandle = NULL; PDV_DISK_ENTRY entry; entry = PhReferenceObjectSafe(DiskDrivesList->Items[i]); if (!entry) continue; if (NT_SUCCESS(DiskDriveCreateHandle( &deviceHandle, entry->Id.DevicePath ))) { DISK_PERFORMANCE diskPerformance; if (NT_SUCCESS(DiskDriveQueryStatistics( deviceHandle, &diskPerformance ))) { ULONG64 readTime; ULONG64 writeTime; ULONG64 idleTime; ULONG readCount; ULONG writeCount; ULONG64 queryTime; PhUpdateDelta(&entry->BytesReadDelta, diskPerformance.BytesRead.QuadPart); PhUpdateDelta(&entry->BytesWrittenDelta, diskPerformance.BytesWritten.QuadPart); PhUpdateDelta(&entry->ReadTimeDelta, diskPerformance.ReadTime.QuadPart); PhUpdateDelta(&entry->WriteTimeDelta, diskPerformance.WriteTime.QuadPart); PhUpdateDelta(&entry->IdleTimeDelta, diskPerformance.IdleTime.QuadPart); PhUpdateDelta(&entry->ReadCountDelta, diskPerformance.ReadCount); PhUpdateDelta(&entry->WriteCountDelta, diskPerformance.WriteCount); PhUpdateDelta(&entry->QueryTimeDelta, diskPerformance.QueryTime.QuadPart); readTime = entry->ReadTimeDelta.Delta; writeTime = entry->WriteTimeDelta.Delta; idleTime = entry->IdleTimeDelta.Delta; readCount = entry->ReadCountDelta.Delta; writeCount = entry->WriteCountDelta.Delta; queryTime = entry->QueryTimeDelta.Delta; if (readCount + writeCount != 0) entry->ResponseTime = ((FLOAT)readTime + (FLOAT)writeTime) / (readCount + writeCount); else entry->ResponseTime = 0; if (queryTime != 0) entry->ActiveTime = (FLOAT)(queryTime - idleTime) / queryTime * 100; else entry->ActiveTime = 0.0f; if (entry->ActiveTime > 100.f) entry->ActiveTime = 0.f; if (entry->ActiveTime < 0.f) entry->ActiveTime = 0.f; entry->QueueDepth = diskPerformance.QueueDepth; entry->SplitCount = diskPerformance.SplitCount; } else { // Disk has been disconnected or dismounted. PhInitializeDelta(&entry->BytesReadDelta); PhInitializeDelta(&entry->BytesWrittenDelta); PhInitializeDelta(&entry->ReadTimeDelta); PhInitializeDelta(&entry->WriteTimeDelta); PhInitializeDelta(&entry->IdleTimeDelta); PhInitializeDelta(&entry->ReadCountDelta); PhInitializeDelta(&entry->WriteCountDelta); PhInitializeDelta(&entry->QueryTimeDelta); entry->ResponseTime = 0; entry->ActiveTime = 0.0f; entry->QueueDepth = 0; entry->SplitCount = 0; } // HACK: Pull the Disk name from the current query. if (!entry->DiskName) { DiskDriveQueryDeviceInformation(deviceHandle, NULL, &entry->DiskName, NULL, NULL); } // HACK: Pull the Disk index from the current query. if (entry->DiskIndex == ULONG_MAX) { ULONG diskIndex = ULONG_MAX; // Note: Do not initialize to zero. if (NT_SUCCESS(DiskDriveQueryDeviceTypeAndNumber(deviceHandle, &diskIndex, NULL))) { entry->DiskIndex = diskIndex; } } NtClose(deviceHandle); } else { // Disk has been disconnected or dismounted. PhInitializeDelta(&entry->BytesReadDelta); PhInitializeDelta(&entry->BytesWrittenDelta); PhInitializeDelta(&entry->ReadTimeDelta); PhInitializeDelta(&entry->WriteTimeDelta); PhInitializeDelta(&entry->IdleTimeDelta); PhInitializeDelta(&entry->ReadCountDelta); PhInitializeDelta(&entry->WriteCountDelta); PhInitializeDelta(&entry->QueryTimeDelta); entry->ResponseTime = 0; entry->ActiveTime = 0.0f; entry->QueueDepth = 0; entry->SplitCount = 0; } if (!entry->HaveFirstSample) { // The first sample must be zero. entry->BytesReadDelta.Delta = 0; entry->BytesWrittenDelta.Delta = 0; entry->HaveFirstSample = TRUE; } if (runCount != 0) { PhAddItemCircularBuffer_ULONG64(&entry->ReadBuffer, entry->BytesReadDelta.Delta); PhAddItemCircularBuffer_ULONG64(&entry->WriteBuffer, entry->BytesWrittenDelta.Delta); } PhDereferenceObjectDeferDelete(entry); } PhReleaseQueuedLockShared(&DiskDrivesListLock); runCount++; }