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=…
==============================================================================
--- 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/…
==============================================================================
--- 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=…
==============================================================================
--- 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,