Author: fireball Date: Mon Dec 8 06:57:53 2008 New Revision: 37934
URL: http://svn.reactos.org/svn/reactos?rev=37934&view=rev Log: - Implement KeQueryRuntimeProcess for querying total user/kernel times of a process. - Use it for obtaining idle process times, and per-process information in QuerySystemInformation routines. - Fix incorrect multiplier being applied to user/kernel times (should be KeMaximumIncrement instead of 100000). - Slightly rework SystemProcessorPerformanceInformation to provide valid data. - This fixed a bug existing since revision 24148, 2 years ago. See issue #2329 for more details.
Modified: trunk/reactos/ntoskrnl/ex/sysinfo.c trunk/reactos/ntoskrnl/include/internal/ke.h trunk/reactos/ntoskrnl/ke/procobj.c
Modified: trunk/reactos/ntoskrnl/ex/sysinfo.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ex/sysinfo.c?rev=3... ============================================================================== --- trunk/reactos/ntoskrnl/ex/sysinfo.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/ex/sysinfo.c [iso-8859-1] Mon Dec 8 06:57:53 2008 @@ -538,6 +538,7 @@ /* Class 2 - Performance Information */ QSI_DEF(SystemPerformanceInformation) { + ULONG IdleUser, IdleKernel; PSYSTEM_PERFORMANCE_INFORMATION Spi = (PSYSTEM_PERFORMANCE_INFORMATION) Buffer;
@@ -554,8 +555,8 @@
TheIdleProcess = PsIdleProcess;
- Spi->IdleProcessTime.QuadPart = TheIdleProcess->Pcb.KernelTime * 100000LL; - + IdleKernel = KeQueryRuntimeProcess(&TheIdleProcess->Pcb, &IdleUser); + Spi->IdleProcessTime.QuadPart = UInt32x32To64(IdleKernel, KeMaximumIncrement); Spi->IoReadTransferCount = IoReadTransferCount; Spi->IoWriteTransferCount = IoWriteTransferCount; Spi->IoOtherTransferCount = IoOtherTransferCount; @@ -699,7 +700,8 @@ { ULONG ovlSize = 0, nThreads; PEPROCESS pr = NULL, syspr; - unsigned char *pCur; + PUCHAR pCur; + ULONG TotalUser, TotalKernel; NTSTATUS Status = STATUS_SUCCESS;
_SEH2_TRY @@ -757,8 +759,6 @@ SpiCur->NextEntryOffset = curSize+inLen; // relative offset to the beginnnig of the next structure SpiCur->NumberOfThreads = nThreads; SpiCur->CreateTime = pr->CreateTime; - SpiCur->UserTime.QuadPart = pr->Pcb.UserTime * 100000LL; - SpiCur->KernelTime.QuadPart = pr->Pcb.KernelTime * 100000LL; SpiCur->ImageName.Length = strlen(pr->ImageFileName) * sizeof(WCHAR); SpiCur->ImageName.MaximumLength = (USHORT)inLen; SpiCur->ImageName.Buffer = (void*)(pCur+curSize); @@ -798,8 +798,8 @@ current = CONTAINING_RECORD(current_entry, ETHREAD, ThreadListEntry);
- ThreadInfo->KernelTime.QuadPart = current->Tcb.KernelTime * 100000LL; - ThreadInfo->UserTime.QuadPart = current->Tcb.UserTime * 100000LL; + ThreadInfo->KernelTime.QuadPart = UInt32x32To64(current->Tcb.KernelTime, KeMaximumIncrement); + ThreadInfo->UserTime.QuadPart = UInt32x32To64(current->Tcb.UserTime, KeMaximumIncrement); ThreadInfo->CreateTime.QuadPart = current->CreateTime.QuadPart; ThreadInfo->WaitTime = current->Tcb.WaitTime; ThreadInfo->StartAddress = (PVOID) current->StartAddress; @@ -809,9 +809,15 @@ ThreadInfo->ContextSwitches = current->Tcb.ContextSwitches; ThreadInfo->ThreadState = current->Tcb.State; ThreadInfo->WaitReason = current->Tcb.WaitReason; + ThreadInfo++; current_entry = current_entry->Flink; } + + /* Query total user/kernel times of a process */ + TotalKernel = KeQueryRuntimeProcess(&pr->Pcb, &TotalUser); + SpiCur->UserTime.QuadPart = UInt32x32To64(TotalUser, KeMaximumIncrement); + SpiCur->KernelTime.QuadPart = UInt32x32To64(TotalKernel, KeMaximumIncrement);
/* Handle idle process entry */ if (pr == PsIdleProcess) pr = NULL; @@ -882,37 +888,39 @@ /* Class 8 - Processor Performance Information */ QSI_DEF(SystemProcessorPerformanceInformation) { - PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION Spi - = (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) Buffer; - - LONG i; - LARGE_INTEGER CurrentTime; - PKPRCB Prcb; - - *ReqSize = KeNumberProcessors * sizeof (SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION); - /* - * Check user buffer's size - */ - if (Size < KeNumberProcessors * sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)) - { - return (STATUS_INFO_LENGTH_MISMATCH); - } - - CurrentTime.QuadPart = KeQueryInterruptTime(); - Prcb = KeGetPcr()->Prcb; - for (i = 0; i < KeNumberProcessors; i++) - { - Spi->IdleTime.QuadPart = (Prcb->IdleThread->KernelTime + Prcb->IdleThread->UserTime) * 100000LL; - Spi->KernelTime.QuadPart = Prcb->KernelTime * 100000LL; - Spi->UserTime.QuadPart = Prcb->UserTime * 100000LL; - Spi->DpcTime.QuadPart = Prcb->DpcTime * 100000LL; - Spi->InterruptTime.QuadPart = Prcb->InterruptTime * 100000LL; - Spi->InterruptCount = Prcb->InterruptCount; - Spi++; - Prcb = (PKPRCB)((ULONG_PTR)Prcb + PAGE_SIZE); - } - - return (STATUS_SUCCESS); + PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION Spi + = (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) Buffer; + + LONG i; + ULONG TotalTime; + LARGE_INTEGER CurrentTime; + PKPRCB Prcb; + + *ReqSize = KeNumberProcessors * sizeof (SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION); + + /* Check user buffer's size */ + if (Size < *ReqSize) + { + return STATUS_INFO_LENGTH_MISMATCH; + } + + CurrentTime.QuadPart = KeQueryInterruptTime(); + Prcb = KeGetPcr()->Prcb; + for (i = 0; i < KeNumberProcessors; i++) + { + /* Calculate total user and kernel times */ + TotalTime = Prcb->IdleThread->KernelTime + Prcb->IdleThread->UserTime; + Spi->IdleTime.QuadPart = UInt32x32To64(TotalTime, KeMaximumIncrement); + Spi->KernelTime.QuadPart = UInt32x32To64(Prcb->KernelTime, KeMaximumIncrement); + Spi->UserTime.QuadPart = UInt32x32To64(Prcb->UserTime, KeMaximumIncrement); + Spi->DpcTime.QuadPart = UInt32x32To64(Prcb->DpcTime, KeMaximumIncrement); + Spi->InterruptTime.QuadPart = UInt32x32To64(Prcb->InterruptTime, KeMaximumIncrement); + Spi->InterruptCount = Prcb->InterruptCount; + Spi++; + Prcb = (PKPRCB)((ULONG_PTR)Prcb + PAGE_SIZE); + } + + return STATUS_SUCCESS; }
/* Class 9 - Flags Information */
Modified: trunk/reactos/ntoskrnl/include/internal/ke.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/k... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/ke.h [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/include/internal/ke.h [iso-8859-1] Mon Dec 8 06:57:53 2008 @@ -716,6 +716,16 @@ FASTCALL KiActivateWaiterQueue(IN PKQUEUE Queue);
+ULONG +NTAPI +KeQueryRuntimeProcess(IN PKPROCESS Process, + OUT PULONG UserTime); + +ULONG +NTAPI +KeQueryRuntimeThread(IN PKTHREAD Thread, + OUT PULONG UserTime); + /* INITIALIZATION FUNCTIONS *************************************************/
BOOLEAN
Modified: trunk/reactos/ntoskrnl/ke/procobj.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/procobj.c?rev=3... ============================================================================== --- trunk/reactos/ntoskrnl/ke/procobj.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/ke/procobj.c [iso-8859-1] Mon Dec 8 06:57:53 2008 @@ -722,6 +722,54 @@ /* * @implemented */ +ULONG +NTAPI +KeQueryRuntimeProcess(IN PKPROCESS Process, + OUT PULONG UserTime) +{ + ULONG TotalUser, TotalKernel; + KLOCK_QUEUE_HANDLE ProcessLock; + PLIST_ENTRY NextEntry, ListHead; + PKTHREAD Thread; + + ASSERT_PROCESS(Process); + + /* Initialize user and kernel times */ + TotalUser = Process->UserTime; + TotalKernel = Process->KernelTime; + + /* Lock the process */ + KiAcquireProcessLock(Process, &ProcessLock); + + /* Loop all child threads and sum up their times */ + ListHead = &Process->ThreadListHead; + NextEntry = ListHead->Flink; + while (ListHead != NextEntry) + { + /* Get the thread */ + Thread = CONTAINING_RECORD(NextEntry, KTHREAD, ThreadListEntry); + + /* Sum up times */ + TotalKernel += Thread->KernelTime; + TotalUser += Thread->UserTime; + + /* Go to the next one */ + NextEntry = NextEntry->Flink; + } + + /* Release lock */ + KiReleaseProcessLock(&ProcessLock); + + /* Return the user time */ + *UserTime = TotalUser; + + /* Return the kernel time */ + return TotalKernel; +} + +/* + * @implemented + */ BOOLEAN NTAPI KeAddSystemServiceTable(IN PULONG_PTR Base,