windows-nt/Source/XPSP1/NT/base/tools/pperf/app/calcperf.c
2020-09-26 16:20:57 +08:00

501 lines
9.7 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1990 Microsoft Corporation
Module Name:
CalcPerf.c
Abstract:
calculate perfoemance statistics
Author:
Environment:
Win32
Revision History:
10-20-91 Initial version
--*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <assert.h>
#include "calcperf.h"
#include "..\pstat.h"
//SYSTEM_PERFORMANCE_INFORMATION PerfInfo;
//SYSTEM_PERFORMANCE_INFORMATION PreviousPerfInfo;
#define INFSIZE 60000
HANDLE DriverHandle;
ULONG NumberOfProcessors;
ULONG Buffer[INFSIZE/4];
extern ULONG UseGlobalMax, GlobalMax;
ULONG
InitPerfInfo()
/*++
Routine Description:
Initialize data for perf measurements
Arguments:
None
Return Value:
Number of system processors (0 if error)
Revision History:
10-21-91 Initial code
--*/
{
UNICODE_STRING DriverName;
NTSTATUS status;
OBJECT_ATTRIBUTES ObjA;
IO_STATUS_BLOCK IOSB;
SYSTEM_BASIC_INFORMATION BasicInfo;
PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION PPerfInfo;
int i;
//
// Init Nt performance interface
//
NtQuerySystemInformation(
SystemBasicInformation,
&BasicInfo,
sizeof(BasicInfo),
NULL
);
NumberOfProcessors = BasicInfo.NumberOfProcessors;
if (NumberOfProcessors > MAX_PROCESSORS) {
return(0);
}
//
// Open P5Stat driver
//
RtlInitUnicodeString(&DriverName, L"\\Device\\PStat");
InitializeObjectAttributes(
&ObjA,
&DriverName,
OBJ_CASE_INSENSITIVE,
0,
0 );
status = NtOpenFile (
&DriverHandle, // return handle
SYNCHRONIZE | FILE_READ_DATA, // desired access
&ObjA, // Object
&IOSB, // io status block
FILE_SHARE_READ | FILE_SHARE_WRITE, // share access
FILE_SYNCHRONOUS_IO_ALERT // open options
);
if (!NT_SUCCESS(status)) {
return 0;
}
InitPossibleEventList();
return(NumberOfProcessors);
}
BOOL
CalcPerf(
PDISPLAY_ITEM pPerf1
)
/*++
Routine Description:
calculate and return %cpu time and time periods
Arguments:
None
Return Value:
Revision History:
10-21-91 Initial code
--*/
{
ULONG i;
ULONG TotalDataPoint;
ULONG OldGlobalMax;
PDISPLAY_ITEM pPerf;
//
// get system performance info
//
OldGlobalMax = GlobalMax;
GlobalMax = 0;
UpdateInternalStats();
for (pPerf = pPerf1; pPerf; pPerf = pPerf->Next) {
TotalDataPoint = 0;
pPerf->SnapData (pPerf);
if (pPerf->AutoTotal) {
//
// Automatically calc system total by summing each processor
//
switch (pPerf->DisplayMode) {
case DISPLAY_MODE_TOTAL:
case DISPLAY_MODE_BREAKDOWN:
default:
for (i=0; i < NumberOfProcessors; i++) {
TotalDataPoint += pPerf->CurrentDataPoint[i + 1];
UpdatePerfInfo1 (
pPerf->DataList[i + 1],
pPerf->CurrentDataPoint[i + 1]
);
}
pPerf->ChangeScale = UpdatePerfInfo (
pPerf->DataList[0],
TotalDataPoint,
&pPerf->Max
);
break;
case DISPLAY_MODE_PER_PROCESSOR:
for (i=0; i < NumberOfProcessors; i++) {
TotalDataPoint += pPerf->CurrentDataPoint[i + 1];
pPerf->ChangeScale = UpdatePerfInfo (
pPerf->DataList[i + 1],
pPerf->CurrentDataPoint[i + 1],
&pPerf->Max
);
}
UpdatePerfInfo1 (pPerf->DataList[0], TotalDataPoint);
break;
}
} else {
for (i=0; i < NumberOfProcessors+1; i++) {
pPerf->ChangeScale = UpdatePerfInfo (
pPerf->DataList[i],
pPerf->CurrentDataPoint[i],
&pPerf->Max
);
}
}
}
if (UseGlobalMax && OldGlobalMax != GlobalMax) {
for (pPerf = pPerf1; pPerf; pPerf = pPerf->Next) {
pPerf->ChangeScale = TRUE;
}
}
return(TRUE);
}
VOID
UpdateInternalStats(VOID)
{
IO_STATUS_BLOCK IOSB;
NtDeviceIoControlFile(
DriverHandle,
(HANDLE) NULL, // event
(PIO_APC_ROUTINE) NULL,
(PVOID) NULL,
&IOSB,
PSTAT_READ_STATS,
Buffer, // input buffer
INFSIZE,
NULL, // output buffer
0
);
}
VOID
SetCounterEvents (PVOID Events, ULONG length)
{
IO_STATUS_BLOCK IOSB;
NtDeviceIoControlFile(
DriverHandle,
(HANDLE) NULL, // event
(PIO_APC_ROUTINE) NULL,
(PVOID) NULL,
&IOSB,
PSTAT_SET_CESR,
Events, // input buffer
length,
NULL, // output buffer
0
);
}
VOID
SnapNull (
IN OUT PDISPLAY_ITEM pPerf
)
{
ULONG i;
for (i=0; i < NumberOfProcessors; i++) {
pPerf->CurrentDataPoint[i + 1] = 0;
}
}
VOID
SnapInterrupts (
IN OUT PDISPLAY_ITEM pPerf
)
{
SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION ProcessorInfo[MAX_PROCESSORS];
ULONG i, l;
NtQuerySystemInformation(
SystemProcessorPerformanceInformation,
ProcessorInfo,
sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * MAX_PROCESSORS,
NULL
);
for (i=0; i < NumberOfProcessors; i++) {
l = ProcessorInfo[i].InterruptCount - pPerf->LastAccumulator[i+1];
pPerf->LastAccumulator[i+1] = ProcessorInfo[i].InterruptCount;
pPerf->CurrentDataPoint[i+1] = l / DELAY_SECONDS;
}
}
VOID
SnapPrivateInfo (
IN OUT PDISPLAY_ITEM pPerf
)
{
ULONG i, j, l, len;
PULONG PrivateStat;
len = *((PULONG) Buffer);
PrivateStat = (PULONG) ((PUCHAR) Buffer + sizeof(ULONG) + pPerf->SnapParam1);
// accumlating data, take delta
for (i=0; i < NumberOfProcessors; i++) {
if (pPerf->Mega) {
PULONGLONG li = (PULONGLONG) PrivateStat;
*li = *li >> 10;
}
j = *PrivateStat / DELAY_SECONDS;
l = j - pPerf->LastAccumulator[i+1];
pPerf->LastAccumulator[i+1] = j;
if (l > 0) {
pPerf->CurrentDataPoint[i+1] = l;
} else {
// item wrapped
pPerf->CurrentDataPoint[i+1] = 0 - l;
}
PrivateStat = (PULONG)((PUCHAR)PrivateStat + len);
}
}
BOOL
UpdatePerfInfo(
PULONG DataPointer,
ULONG NewDataValue,
PULONG OldMaxValue
)
/*++
Routine Description:
Shift array of DATA_LIST_LENGTH USORTS and add the new value to the
start of list
Arguments:
DataPointer - Pointer to the start of a DATA_LIST_LENGTH array
NewDataValue - Data element to be added
OldMaxValue - Scale value
Return Value:
TRUE is MaxValue must be increased or decreased
Revision History:
10-21-91 Initial code
--*/
{
ULONG Index;
ULONG ScanMax;
//
// Shift DataArray while keeping track of the max value
//
//
// Set temp max to 100 to init a minimum maximum
//
ScanMax = 100;
for (Index=DATA_LIST_LENGTH-1;Index>=1;Index--) {
DataPointer[Index] = DataPointer[Index-1];
if (DataPointer[Index] > ScanMax) {
ScanMax = DataPointer[Index];
}
}
//
// add and check first value
//
DataPointer[0] = NewDataValue;
if (NewDataValue > ScanMax) {
ScanMax = NewDataValue;
}
//
// If Max values changed then undate the new max
// value and return TRUE.
//
if (ScanMax > GlobalMax) {
GlobalMax = ScanMax;
}
if (ScanMax != *OldMaxValue) {
if (ScanMax < *OldMaxValue &&
*OldMaxValue - ScanMax <= *OldMaxValue / 10) {
//
// New ScanMax is smaller, but only by a tiny amount
//
return (FALSE);
}
*OldMaxValue = ScanMax;
return(TRUE);
}
return(FALSE);
}
VOID
UpdatePerfInfo1(
PULONG DataPointer,
ULONG NewDataValue
)
/*++
Routine Description:
Shift array of DATA_LIST_LENGTH USORTS and add the new value to the
start of list
Arguments:
DataPointer - Pointer to the start of a DATA_LIST_LENGTH array
NewDataValue - Data element to be added
OldMaxValue - Scale value
Return Value:
TRUE is MaxValue must be increased or decreased
Revision History:
10-21-91 Initial code
--*/
{
ULONG Index;
ULONG ScanMax;
//
// Shift DataArray while keeping track of the max value
//
//
// Set temp max to 100 to init a minimum maximum
//
ScanMax = 100;
for (Index=DATA_LIST_LENGTH-1;Index>=1;Index--) {
DataPointer[Index] = DataPointer[Index-1];
}
//
// add and check first value
//
DataPointer[0] = NewDataValue;
return ;
}