mirror of
https://github.com/reactos/reactos.git
synced 2024-06-30 09:50:07 +00:00
- 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. svn path=/trunk/; revision=37934
This commit is contained in:
parent
0e162bfb0b
commit
7b11a5fcdb
|
@ -538,6 +538,7 @@ QSI_DEF(SystemProcessorInformation)
|
|||
/* Class 2 - Performance Information */
|
||||
QSI_DEF(SystemPerformanceInformation)
|
||||
{
|
||||
ULONG IdleUser, IdleKernel;
|
||||
PSYSTEM_PERFORMANCE_INFORMATION Spi
|
||||
= (PSYSTEM_PERFORMANCE_INFORMATION) Buffer;
|
||||
|
||||
|
@ -554,8 +555,8 @@ QSI_DEF(SystemPerformanceInformation)
|
|||
|
||||
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 @@ QSI_DEF(SystemProcessInformation)
|
|||
{
|
||||
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 @@ QSI_DEF(SystemProcessInformation)
|
|||
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 @@ QSI_DEF(SystemProcessInformation)
|
|||
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,10 +809,16 @@ QSI_DEF(SystemProcessInformation)
|
|||
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 @@ QSI_DEF(SystemDeviceInformation)
|
|||
/* Class 8 - Processor Performance Information */
|
||||
QSI_DEF(SystemProcessorPerformanceInformation)
|
||||
{
|
||||
PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION Spi
|
||||
= (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) Buffer;
|
||||
PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION Spi
|
||||
= (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) Buffer;
|
||||
|
||||
LONG i;
|
||||
LARGE_INTEGER CurrentTime;
|
||||
PKPRCB Prcb;
|
||||
LONG i;
|
||||
ULONG TotalTime;
|
||||
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);
|
||||
}
|
||||
*ReqSize = KeNumberProcessors * sizeof (SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION);
|
||||
|
||||
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);
|
||||
}
|
||||
/* Check user buffer's size */
|
||||
if (Size < *ReqSize)
|
||||
{
|
||||
return STATUS_INFO_LENGTH_MISMATCH;
|
||||
}
|
||||
|
||||
return (STATUS_SUCCESS);
|
||||
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 */
|
||||
|
|
|
@ -716,6 +716,16 @@ VOID
|
|||
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
|
||||
|
|
|
@ -719,6 +719,54 @@ KeUnstackDetachProcess(IN PRKAPC_STATE ApcState)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @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
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue