mirror of
https://github.com/reactos/reactos.git
synced 2024-10-02 07:26:47 +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 */
|
/* Class 2 - Performance Information */
|
||||||
QSI_DEF(SystemPerformanceInformation)
|
QSI_DEF(SystemPerformanceInformation)
|
||||||
{
|
{
|
||||||
|
ULONG IdleUser, IdleKernel;
|
||||||
PSYSTEM_PERFORMANCE_INFORMATION Spi
|
PSYSTEM_PERFORMANCE_INFORMATION Spi
|
||||||
= (PSYSTEM_PERFORMANCE_INFORMATION) Buffer;
|
= (PSYSTEM_PERFORMANCE_INFORMATION) Buffer;
|
||||||
|
|
||||||
|
@ -554,8 +555,8 @@ QSI_DEF(SystemPerformanceInformation)
|
||||||
|
|
||||||
TheIdleProcess = PsIdleProcess;
|
TheIdleProcess = PsIdleProcess;
|
||||||
|
|
||||||
Spi->IdleProcessTime.QuadPart = TheIdleProcess->Pcb.KernelTime * 100000LL;
|
IdleKernel = KeQueryRuntimeProcess(&TheIdleProcess->Pcb, &IdleUser);
|
||||||
|
Spi->IdleProcessTime.QuadPart = UInt32x32To64(IdleKernel, KeMaximumIncrement);
|
||||||
Spi->IoReadTransferCount = IoReadTransferCount;
|
Spi->IoReadTransferCount = IoReadTransferCount;
|
||||||
Spi->IoWriteTransferCount = IoWriteTransferCount;
|
Spi->IoWriteTransferCount = IoWriteTransferCount;
|
||||||
Spi->IoOtherTransferCount = IoOtherTransferCount;
|
Spi->IoOtherTransferCount = IoOtherTransferCount;
|
||||||
|
@ -699,7 +700,8 @@ QSI_DEF(SystemProcessInformation)
|
||||||
{
|
{
|
||||||
ULONG ovlSize = 0, nThreads;
|
ULONG ovlSize = 0, nThreads;
|
||||||
PEPROCESS pr = NULL, syspr;
|
PEPROCESS pr = NULL, syspr;
|
||||||
unsigned char *pCur;
|
PUCHAR pCur;
|
||||||
|
ULONG TotalUser, TotalKernel;
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
_SEH2_TRY
|
_SEH2_TRY
|
||||||
|
@ -757,8 +759,6 @@ QSI_DEF(SystemProcessInformation)
|
||||||
SpiCur->NextEntryOffset = curSize+inLen; // relative offset to the beginnnig of the next structure
|
SpiCur->NextEntryOffset = curSize+inLen; // relative offset to the beginnnig of the next structure
|
||||||
SpiCur->NumberOfThreads = nThreads;
|
SpiCur->NumberOfThreads = nThreads;
|
||||||
SpiCur->CreateTime = pr->CreateTime;
|
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.Length = strlen(pr->ImageFileName) * sizeof(WCHAR);
|
||||||
SpiCur->ImageName.MaximumLength = (USHORT)inLen;
|
SpiCur->ImageName.MaximumLength = (USHORT)inLen;
|
||||||
SpiCur->ImageName.Buffer = (void*)(pCur+curSize);
|
SpiCur->ImageName.Buffer = (void*)(pCur+curSize);
|
||||||
|
@ -798,8 +798,8 @@ QSI_DEF(SystemProcessInformation)
|
||||||
current = CONTAINING_RECORD(current_entry, ETHREAD,
|
current = CONTAINING_RECORD(current_entry, ETHREAD,
|
||||||
ThreadListEntry);
|
ThreadListEntry);
|
||||||
|
|
||||||
ThreadInfo->KernelTime.QuadPart = current->Tcb.KernelTime * 100000LL;
|
ThreadInfo->KernelTime.QuadPart = UInt32x32To64(current->Tcb.KernelTime, KeMaximumIncrement);
|
||||||
ThreadInfo->UserTime.QuadPart = current->Tcb.UserTime * 100000LL;
|
ThreadInfo->UserTime.QuadPart = UInt32x32To64(current->Tcb.UserTime, KeMaximumIncrement);
|
||||||
ThreadInfo->CreateTime.QuadPart = current->CreateTime.QuadPart;
|
ThreadInfo->CreateTime.QuadPart = current->CreateTime.QuadPart;
|
||||||
ThreadInfo->WaitTime = current->Tcb.WaitTime;
|
ThreadInfo->WaitTime = current->Tcb.WaitTime;
|
||||||
ThreadInfo->StartAddress = (PVOID) current->StartAddress;
|
ThreadInfo->StartAddress = (PVOID) current->StartAddress;
|
||||||
|
@ -809,10 +809,16 @@ QSI_DEF(SystemProcessInformation)
|
||||||
ThreadInfo->ContextSwitches = current->Tcb.ContextSwitches;
|
ThreadInfo->ContextSwitches = current->Tcb.ContextSwitches;
|
||||||
ThreadInfo->ThreadState = current->Tcb.State;
|
ThreadInfo->ThreadState = current->Tcb.State;
|
||||||
ThreadInfo->WaitReason = current->Tcb.WaitReason;
|
ThreadInfo->WaitReason = current->Tcb.WaitReason;
|
||||||
|
|
||||||
ThreadInfo++;
|
ThreadInfo++;
|
||||||
current_entry = current_entry->Flink;
|
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 */
|
/* Handle idle process entry */
|
||||||
if (pr == PsIdleProcess) pr = NULL;
|
if (pr == PsIdleProcess) pr = NULL;
|
||||||
|
|
||||||
|
@ -882,37 +888,39 @@ QSI_DEF(SystemDeviceInformation)
|
||||||
/* Class 8 - Processor Performance Information */
|
/* Class 8 - Processor Performance Information */
|
||||||
QSI_DEF(SystemProcessorPerformanceInformation)
|
QSI_DEF(SystemProcessorPerformanceInformation)
|
||||||
{
|
{
|
||||||
PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION Spi
|
PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION Spi
|
||||||
= (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) Buffer;
|
= (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) Buffer;
|
||||||
|
|
||||||
LONG i;
|
LONG i;
|
||||||
LARGE_INTEGER CurrentTime;
|
ULONG TotalTime;
|
||||||
PKPRCB Prcb;
|
LARGE_INTEGER CurrentTime;
|
||||||
|
PKPRCB Prcb;
|
||||||
|
|
||||||
*ReqSize = KeNumberProcessors * sizeof (SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION);
|
*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();
|
/* Check user buffer's size */
|
||||||
Prcb = KeGetPcr()->Prcb;
|
if (Size < *ReqSize)
|
||||||
for (i = 0; i < KeNumberProcessors; i++)
|
{
|
||||||
{
|
return STATUS_INFO_LENGTH_MISMATCH;
|
||||||
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);
|
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 */
|
/* Class 9 - Flags Information */
|
||||||
|
|
|
@ -716,6 +716,16 @@ VOID
|
||||||
FASTCALL
|
FASTCALL
|
||||||
KiActivateWaiterQueue(IN PKQUEUE Queue);
|
KiActivateWaiterQueue(IN PKQUEUE Queue);
|
||||||
|
|
||||||
|
ULONG
|
||||||
|
NTAPI
|
||||||
|
KeQueryRuntimeProcess(IN PKPROCESS Process,
|
||||||
|
OUT PULONG UserTime);
|
||||||
|
|
||||||
|
ULONG
|
||||||
|
NTAPI
|
||||||
|
KeQueryRuntimeThread(IN PKTHREAD Thread,
|
||||||
|
OUT PULONG UserTime);
|
||||||
|
|
||||||
/* INITIALIZATION FUNCTIONS *************************************************/
|
/* INITIALIZATION FUNCTIONS *************************************************/
|
||||||
|
|
||||||
BOOLEAN
|
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
|
* @implemented
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in a new issue