You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
845 lines
29 KiB
845 lines
29 KiB
#include <assert.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <memory.h>
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <windows.h>
|
|
|
|
#include <..\ztools\inc\tools.h>
|
|
|
|
#define NUMBER_SERVICE_TABLES 2
|
|
#define BUFFER_SIZE 1024
|
|
|
|
VOID
|
|
SortUlongData (
|
|
IN ULONG Count,
|
|
IN ULONG Index[],
|
|
IN ULONG Data[]
|
|
);
|
|
|
|
extern UCHAR *CallTable[];
|
|
|
|
ULONG SystemCallBufferStart[BUFFER_SIZE];
|
|
ULONG SystemCallBufferDone[BUFFER_SIZE];
|
|
ULONG Index[BUFFER_SIZE];
|
|
ULONG CallData[BUFFER_SIZE];
|
|
|
|
#define MAX_PROCESSOR 16
|
|
SYSTEM_BASIC_INFORMATION BasicInfo;
|
|
SYSTEM_PERFORMANCE_INFORMATION SystemInfoStart;
|
|
SYSTEM_PERFORMANCE_INFORMATION SystemInfoDone;
|
|
SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION ProcessorInfoStart[MAX_PROCESSOR];
|
|
SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION ProcessorInfoDone[MAX_PROCESSOR];
|
|
|
|
#define vdelta(FLD) (VdmInfoDone.FLD - VdmInfoStart.FLD)
|
|
|
|
#ifdef i386
|
|
SYSTEM_VDM_INSTEMUL_INFO VdmInfoStart;
|
|
SYSTEM_VDM_INSTEMUL_INFO VdmInfoDone;
|
|
#endif
|
|
|
|
HANDLE
|
|
GetServerProcessHandle( VOID )
|
|
{
|
|
HANDLE Process;
|
|
OBJECT_ATTRIBUTES Obja;
|
|
UNICODE_STRING Unicode;
|
|
NTSTATUS Status;
|
|
|
|
RtlInitUnicodeString(&Unicode, L"\\WindowsSS");
|
|
InitializeObjectAttributes(
|
|
&Obja,
|
|
&Unicode,
|
|
0,
|
|
NULL,
|
|
NULL
|
|
);
|
|
Status = NtOpenProcess(
|
|
&Process,
|
|
PROCESS_ALL_ACCESS,
|
|
&Obja,
|
|
NULL
|
|
);
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
printf("OpenProcess Failed %lx\n",Status);
|
|
Process = NULL;
|
|
}
|
|
return Process;
|
|
}
|
|
|
|
BOOL WINAPI
|
|
CtrlcHandler(
|
|
ULONG CtrlType
|
|
)
|
|
{
|
|
//
|
|
// Ignore control C interrupts. Let child process deal with them
|
|
// if it wants. If it doesn't then it will terminate and we will
|
|
// get control and terminate ourselves
|
|
//
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
int
|
|
__cdecl main(
|
|
int argc,
|
|
char *argv[],
|
|
char *envp[]
|
|
)
|
|
{
|
|
LPSTR s;
|
|
BOOL bFull;
|
|
BOOL bOneLine;
|
|
BOOL bSyscall;
|
|
STARTUPINFO StartupInfo;
|
|
PROCESS_INFORMATION ProcessInformation;
|
|
BOOL b;
|
|
VM_COUNTERS ServerVmInfoStart, ServerVmInfoDone, ProcessVmInfoStart, ProcessVmInfoDone;
|
|
KERNEL_USER_TIMES Times, ServerStart, ServerDone, ProcessStart, ProcessDone;
|
|
NTSTATUS Status;
|
|
TIME_FIELDS Etime,Utime,Ktime,Itime;
|
|
LARGE_INTEGER RunTime;
|
|
LARGE_INTEGER IdleTime;
|
|
HANDLE OtherProcess;
|
|
ULONG i;
|
|
CHAR ch;
|
|
ULONG ProcessId;
|
|
HANDLE ProcessHandle;
|
|
ULONG Temp;
|
|
ULONG ContextSwitches;
|
|
ULONG FirstLevelFills;
|
|
ULONG SecondLevelFills;
|
|
PSYSTEM_CALL_COUNT_INFORMATION SystemCallInfoStart;
|
|
PSYSTEM_CALL_COUNT_INFORMATION SystemCallInfoDone;
|
|
PULONG SystemCallTableStart;
|
|
PULONG SystemCallTableDone;
|
|
ULONG NumberOfCounts;
|
|
PULONG p;
|
|
BOOL bShowHelpMsg = FALSE;
|
|
|
|
argv;
|
|
envp;
|
|
|
|
ConvertAppToOem( argc, argv );
|
|
OtherProcess = NULL;
|
|
ProcessHandle = NULL;
|
|
if ( (argc < 2) ) {
|
|
bShowHelpMsg = TRUE;
|
|
}
|
|
|
|
SetConsoleCtrlHandler( CtrlcHandler, TRUE );
|
|
|
|
ProcessId = 0;
|
|
|
|
s = GetCommandLine();
|
|
if( s != NULL ) {
|
|
CharToOem( s, s );
|
|
}
|
|
bFull = FALSE;
|
|
bOneLine = FALSE;
|
|
bSyscall = FALSE;
|
|
|
|
//
|
|
// skip blanks
|
|
//
|
|
while( (NULL != s) && (*s > ' '))s++;
|
|
|
|
//
|
|
// get to next token
|
|
//
|
|
while((NULL != s) && (*s == ' ')) s++;
|
|
|
|
while ((NULL != s) && ( *s == '-' ) || ( *s == '/' )) {
|
|
s++;
|
|
//if "-" or "/" only specified.. display help/usage
|
|
if ( '\0' == *s )
|
|
{
|
|
bShowHelpMsg = TRUE;
|
|
break;
|
|
}
|
|
|
|
while (*s > ' ') {
|
|
switch (*s) {
|
|
case '1' :
|
|
bOneLine = TRUE;
|
|
break;
|
|
|
|
case 'c' :
|
|
case 'C' :
|
|
bSyscall = TRUE;
|
|
break;
|
|
|
|
case 'f' :
|
|
case 'F' :
|
|
bFull = TRUE;
|
|
break;
|
|
|
|
case 's' :
|
|
case 'S' :
|
|
OtherProcess = GetServerProcessHandle();
|
|
break;
|
|
|
|
case 'P':
|
|
case 'p':
|
|
// pid takes decimal argument
|
|
s++;
|
|
do
|
|
ch = *s++;
|
|
while (ch == ' ' || ch == '\t');
|
|
|
|
while (ch >= '0' && ch <= '9') {
|
|
Temp = ProcessId * 10 + ch - '0';
|
|
if (Temp < ProcessId) {
|
|
printf("pid number overflow\n");
|
|
ExitProcess(1);
|
|
}
|
|
ProcessId = Temp;
|
|
ch = *s++;
|
|
}
|
|
if (!ProcessId) {
|
|
printf("bad pid '%ld'\n", ProcessId);
|
|
ExitProcess(1);
|
|
}
|
|
s--;
|
|
if ( *s == ' ' ) s--;
|
|
break;
|
|
|
|
case 'h':
|
|
case 'H':
|
|
case '?':
|
|
bShowHelpMsg = TRUE;
|
|
break;
|
|
|
|
default :
|
|
break;
|
|
}
|
|
s++;
|
|
}
|
|
//
|
|
// get to next token
|
|
//
|
|
while(*s==' ')s++;
|
|
}
|
|
|
|
// see if this is just a request for command line help.
|
|
|
|
if ( bShowHelpMsg ) {
|
|
puts("\n"
|
|
"Usage: ntimer [-1 -f -s] name-of-image [parameters]...\n"
|
|
"\n"
|
|
" Displays the Elapsed, Kernel, User and Idle time of the\n"
|
|
" image specified in the command line\n"
|
|
"\n"
|
|
" -1 displays output on one line\n"
|
|
" -f displays the process page faults, total\n"
|
|
" system interrupts, context switches and system\n"
|
|
" calls\n"
|
|
" -s indicates the name of the image is that of a\n"
|
|
" server process. Press Ctrl-C to get the times.");
|
|
ExitProcess(1);
|
|
}
|
|
|
|
if ( ProcessId ) {
|
|
ProcessHandle = OpenProcess(PROCESS_ALL_ACCESS,FALSE,ProcessId);
|
|
}
|
|
memset(&StartupInfo,0,sizeof(StartupInfo));
|
|
StartupInfo.cb = sizeof(StartupInfo);
|
|
|
|
if (bOneLine) {
|
|
bSyscall = FALSE;
|
|
}
|
|
|
|
if (bSyscall) {
|
|
Status = NtQuerySystemInformation(SystemCallCountInformation,
|
|
(PVOID)SystemCallBufferStart,
|
|
BUFFER_SIZE * sizeof(ULONG),
|
|
NULL);
|
|
|
|
bSyscall = FALSE;
|
|
if (!NT_SUCCESS(Status)) {
|
|
printf("Failed to query system call performance information: %x\n", Status);
|
|
} else {
|
|
|
|
SystemCallInfoStart = (PVOID)SystemCallBufferStart;
|
|
SystemCallInfoDone = (PVOID)SystemCallBufferDone;
|
|
|
|
//
|
|
// Make sure that the number of tables reported by the kernel matches
|
|
// our list.
|
|
//
|
|
|
|
if (SystemCallInfoStart->NumberOfTables != NUMBER_SERVICE_TABLES) {
|
|
printf("System call table count (%d) doesn't match NTIMER's count (%d)\n",
|
|
SystemCallInfoStart->NumberOfTables, NUMBER_SERVICE_TABLES);
|
|
} else {
|
|
|
|
//
|
|
// Make sure call count information is available for base services.
|
|
//
|
|
|
|
p = (PULONG)(SystemCallInfoStart + 1);
|
|
|
|
SystemCallTableStart = (PULONG)(SystemCallInfoStart + 1) + NUMBER_SERVICE_TABLES;
|
|
SystemCallTableDone = (PULONG)(SystemCallInfoDone + 1) + NUMBER_SERVICE_TABLES;
|
|
|
|
if (p[0] == 0) {
|
|
printf("No system call count information available for base services\n");
|
|
} else {
|
|
|
|
//
|
|
// If there is a hole in the count information (i.e., one set of services
|
|
// doesn't have counting enabled, but a subsequent one does, then our
|
|
// indexes will be off, and we'll display the wrong service names.
|
|
//
|
|
|
|
i = 2;
|
|
for ( ; i < NUMBER_SERVICE_TABLES; i++ ) {
|
|
if ((p[i] != 0) && (p[i-1] == 0)) {
|
|
printf("One or more call count tables empty. NTIMER can't report\n");
|
|
break;
|
|
}
|
|
}
|
|
if ( i >= NUMBER_SERVICE_TABLES ) {
|
|
bSyscall = TRUE;
|
|
NumberOfCounts = SystemCallInfoStart->Length
|
|
- sizeof(SYSTEM_CALL_COUNT_INFORMATION)
|
|
- NUMBER_SERVICE_TABLES * sizeof(ULONG);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if ( OtherProcess ) {
|
|
Status = NtQueryInformationProcess(
|
|
OtherProcess,
|
|
ProcessTimes,
|
|
&ServerStart,
|
|
sizeof(Times),
|
|
NULL
|
|
);
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
ExitProcess((DWORD)Status);
|
|
}
|
|
}
|
|
|
|
if ( ProcessHandle ) {
|
|
Status = NtQueryInformationProcess(
|
|
ProcessHandle,
|
|
ProcessTimes,
|
|
&ProcessStart,
|
|
sizeof(Times),
|
|
NULL
|
|
);
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
ExitProcess((DWORD)Status);
|
|
}
|
|
}
|
|
|
|
if ( bFull ) {
|
|
|
|
if ( OtherProcess ) {
|
|
Status = NtQueryInformationProcess(
|
|
OtherProcess,
|
|
ProcessVmCounters,
|
|
&ServerVmInfoStart,
|
|
sizeof(VM_COUNTERS),
|
|
NULL
|
|
);
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
ExitProcess((DWORD)Status);
|
|
}
|
|
}
|
|
|
|
if ( ProcessHandle ) {
|
|
Status = NtQueryInformationProcess(
|
|
ProcessHandle,
|
|
ProcessVmCounters,
|
|
&ProcessVmInfoStart,
|
|
sizeof(VM_COUNTERS),
|
|
NULL
|
|
);
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
ExitProcess((DWORD)Status);
|
|
}
|
|
}
|
|
else {
|
|
ZeroMemory(&ProcessVmInfoStart,sizeof(VM_COUNTERS));
|
|
}
|
|
#ifdef i386
|
|
Status = NtQuerySystemInformation(
|
|
SystemVdmInstemulInformation,
|
|
&VdmInfoStart,
|
|
sizeof(VdmInfoStart),
|
|
NULL
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
printf("Failed to query vdm information\n");
|
|
ExitProcess((DWORD)Status);
|
|
}
|
|
#endif
|
|
Status = NtQuerySystemInformation(
|
|
SystemBasicInformation,
|
|
&BasicInfo,
|
|
sizeof(BasicInfo),
|
|
NULL
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
printf("Failed to query basic information\n");
|
|
ExitProcess((DWORD)Status);
|
|
}
|
|
|
|
Status = NtQuerySystemInformation(SystemProcessorPerformanceInformation,
|
|
(PVOID)&ProcessorInfoStart,
|
|
sizeof (SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * MAX_PROCESSOR,
|
|
NULL);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
printf("Failed to query preocessor performance information\n");
|
|
ExitProcess((DWORD)Status);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
Status = NtQuerySystemInformation(SystemPerformanceInformation,
|
|
(PVOID)&SystemInfoStart,
|
|
sizeof(SYSTEM_PERFORMANCE_INFORMATION),
|
|
NULL);
|
|
|
|
ContextSwitches = SystemInfoStart.ContextSwitches;
|
|
FirstLevelFills = SystemInfoStart.FirstLevelTbFills;
|
|
SecondLevelFills = SystemInfoStart.SecondLevelTbFills;
|
|
b = CreateProcess(
|
|
NULL,
|
|
s,
|
|
NULL,
|
|
NULL,
|
|
TRUE,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
&StartupInfo,
|
|
&ProcessInformation
|
|
);
|
|
|
|
if ( !b ) {
|
|
printf("CreateProcess(%s) failed %d\n",s,GetLastError());
|
|
ExitProcess(GetLastError());
|
|
}
|
|
|
|
WaitForSingleObject(ProcessInformation.hProcess,(DWORD)-1);
|
|
|
|
Status = NtQuerySystemInformation(SystemPerformanceInformation,
|
|
(PVOID)&SystemInfoDone,
|
|
sizeof(SYSTEM_PERFORMANCE_INFORMATION),
|
|
NULL);
|
|
|
|
if (!bOneLine) {
|
|
printf("\nContextSwitches - %d\nFirst level fills = %d\nSecond level fills = %d\n",
|
|
SystemInfoDone.ContextSwitches - ContextSwitches,
|
|
SystemInfoDone.FirstLevelTbFills - FirstLevelFills,
|
|
SystemInfoDone.SecondLevelTbFills - SecondLevelFills);
|
|
}
|
|
|
|
if ( OtherProcess ) {
|
|
Status = NtQueryInformationProcess(
|
|
OtherProcess,
|
|
ProcessTimes,
|
|
&ServerDone,
|
|
sizeof(Times),
|
|
NULL
|
|
);
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
ExitProcess((DWORD)Status);
|
|
}
|
|
}
|
|
|
|
if ( ProcessHandle ) {
|
|
Status = NtQueryInformationProcess(
|
|
ProcessHandle,
|
|
ProcessTimes,
|
|
&ProcessDone,
|
|
sizeof(Times),
|
|
NULL
|
|
);
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
ExitProcess((DWORD)Status);
|
|
}
|
|
}
|
|
else {
|
|
|
|
Status = NtQueryInformationProcess(
|
|
ProcessInformation.hProcess,
|
|
ProcessTimes,
|
|
&Times,
|
|
sizeof(Times),
|
|
NULL
|
|
);
|
|
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
ExitProcess((DWORD)Status);
|
|
}
|
|
}
|
|
|
|
if ( bFull ) {
|
|
if ( OtherProcess ) {
|
|
Status = NtQueryInformationProcess(
|
|
OtherProcess,
|
|
ProcessVmCounters,
|
|
&ServerVmInfoDone,
|
|
sizeof(VM_COUNTERS),
|
|
NULL
|
|
);
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
ExitProcess((DWORD)Status);
|
|
}
|
|
}
|
|
|
|
if ( ProcessHandle ) {
|
|
Status = NtQueryInformationProcess(
|
|
ProcessHandle,
|
|
ProcessVmCounters,
|
|
&ProcessVmInfoDone,
|
|
sizeof(VM_COUNTERS),
|
|
NULL
|
|
);
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
ExitProcess((DWORD)Status);
|
|
}
|
|
}
|
|
else {
|
|
Status = NtQueryInformationProcess(
|
|
ProcessInformation.hProcess,
|
|
ProcessVmCounters,
|
|
&ProcessVmInfoDone,
|
|
sizeof(VM_COUNTERS),
|
|
NULL
|
|
);
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
ExitProcess((DWORD)Status);
|
|
}
|
|
}
|
|
#ifdef i386
|
|
Status = NtQuerySystemInformation(
|
|
SystemVdmInstemulInformation,
|
|
&VdmInfoDone,
|
|
sizeof(VdmInfoStart),
|
|
NULL
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
printf("Failed to query vdm information\n");
|
|
ExitProcess((DWORD)Status);
|
|
}
|
|
#endif
|
|
|
|
Status = NtQuerySystemInformation(SystemProcessorPerformanceInformation,
|
|
(PVOID)&ProcessorInfoDone,
|
|
sizeof (SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * MAX_PROCESSOR,
|
|
NULL);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
printf("Failed to query preocessor performance information\n");
|
|
ExitProcess((DWORD)Status);
|
|
}
|
|
|
|
}
|
|
|
|
if ( bSyscall ) {
|
|
Status = NtQuerySystemInformation(SystemCallCountInformation,
|
|
(PVOID)SystemCallBufferDone,
|
|
BUFFER_SIZE * sizeof(ULONG),
|
|
NULL);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
printf("Failed to query system call performance information: %x\n", Status);
|
|
bSyscall = FALSE;
|
|
}
|
|
}
|
|
|
|
RunTime.QuadPart = Times.ExitTime.QuadPart - Times.CreateTime.QuadPart;
|
|
IdleTime.QuadPart = SystemInfoDone.IdleProcessTime.QuadPart -
|
|
SystemInfoStart.IdleProcessTime.QuadPart;
|
|
RtlTimeToTimeFields ( (PLARGE_INTEGER)&IdleTime, &Itime);
|
|
if ( ProcessHandle ) {
|
|
RunTime.QuadPart = ProcessDone.UserTime.QuadPart -
|
|
ProcessStart.UserTime.QuadPart;
|
|
|
|
RtlTimeToTimeFields ( (PLARGE_INTEGER)&RunTime, &Utime);
|
|
RunTime.QuadPart = ProcessDone.KernelTime.QuadPart -
|
|
ProcessStart.KernelTime.QuadPart;
|
|
|
|
RtlTimeToTimeFields ( (PLARGE_INTEGER)&RunTime, &Ktime);
|
|
|
|
if (bOneLine) {
|
|
printf("%3ld:%02ld:%02ld.%03ld %3ld:%02ld:%02ld.%03ld %3ld:%02ld:%02ld.%03ld",
|
|
Utime.Hour,
|
|
Utime.Minute,
|
|
Utime.Second,
|
|
Utime.Milliseconds,
|
|
Ktime.Hour,
|
|
Ktime.Minute,
|
|
Ktime.Second,
|
|
Ktime.Milliseconds,
|
|
Itime.Hour,
|
|
Itime.Minute,
|
|
Itime.Second,
|
|
Itime.Milliseconds
|
|
);
|
|
}
|
|
else {
|
|
printf("ProcessTimes ");
|
|
|
|
printf("UTime( %3ld:%02ld:%02ld.%03ld ) ",
|
|
Utime.Hour,
|
|
Utime.Minute,
|
|
Utime.Second,
|
|
Utime.Milliseconds
|
|
);
|
|
printf("KTime( %3ld:%02ld:%02ld.%03ld ) ",
|
|
Ktime.Hour,
|
|
Ktime.Minute,
|
|
Ktime.Second,
|
|
Ktime.Milliseconds
|
|
);
|
|
printf("ITime( %3ld:%02ld:%02ld.%03ld )\n",
|
|
Itime.Hour,
|
|
Itime.Minute,
|
|
Itime.Second,
|
|
Itime.Milliseconds
|
|
);
|
|
}
|
|
}
|
|
else {
|
|
RtlTimeToTimeFields((PLARGE_INTEGER) &RunTime, &Etime);
|
|
RtlTimeToTimeFields(&Times.UserTime, &Utime);
|
|
RtlTimeToTimeFields(&Times.KernelTime, &Ktime);
|
|
|
|
if (bOneLine) {
|
|
printf("%3ld:%02ld:%02ld.%03ld %3ld:%02ld:%02ld.%03ld %3ld:%02ld:%02ld.%03ld %3ld:%02ld:%02ld.%03ld",
|
|
Etime.Hour,
|
|
Etime.Minute,
|
|
Etime.Second,
|
|
Etime.Milliseconds,
|
|
Utime.Hour,
|
|
Utime.Minute,
|
|
Utime.Second,
|
|
Utime.Milliseconds,
|
|
Ktime.Hour,
|
|
Ktime.Minute,
|
|
Ktime.Second,
|
|
Ktime.Milliseconds,
|
|
Itime.Hour,
|
|
Itime.Minute,
|
|
Itime.Second,
|
|
Itime.Milliseconds
|
|
);
|
|
}
|
|
else {
|
|
printf("\nETime( %3ld:%02ld:%02ld.%03ld ) ",
|
|
Etime.Hour,
|
|
Etime.Minute,
|
|
Etime.Second,
|
|
Etime.Milliseconds
|
|
);
|
|
printf("UTime( %3ld:%02ld:%02ld.%03ld ) ",
|
|
Utime.Hour,
|
|
Utime.Minute,
|
|
Utime.Second,
|
|
Utime.Milliseconds
|
|
);
|
|
printf("KTime( %3ld:%02ld:%02ld.%03ld )\n",
|
|
Ktime.Hour,
|
|
Ktime.Minute,
|
|
Ktime.Second,
|
|
Ktime.Milliseconds
|
|
);
|
|
printf("ITime( %3ld:%02ld:%02ld.%03ld )\n",
|
|
Itime.Hour,
|
|
Itime.Minute,
|
|
Itime.Second,
|
|
Itime.Milliseconds
|
|
);
|
|
}
|
|
}
|
|
|
|
if ( OtherProcess ) {
|
|
RunTime.QuadPart = ServerDone.UserTime.QuadPart -
|
|
ServerStart.UserTime.QuadPart;
|
|
|
|
RtlTimeToTimeFields ( (PLARGE_INTEGER)&RunTime, &Utime);
|
|
RunTime.QuadPart = ServerDone.KernelTime.QuadPart -
|
|
ServerStart.KernelTime.QuadPart;
|
|
|
|
RtlTimeToTimeFields ( (PLARGE_INTEGER)&RunTime, &Ktime);
|
|
printf("ServerTimes ");
|
|
|
|
|
|
if (bOneLine) {
|
|
printf("%3ld:%02ld:%02ld.%03ld %3ld:%02ld:%02ld.%03ld %3ld:%02ld:%02ld.%03ld",
|
|
Utime.Hour,
|
|
Utime.Minute,
|
|
Utime.Second,
|
|
Utime.Milliseconds,
|
|
Ktime.Hour,
|
|
Ktime.Minute,
|
|
Ktime.Second,
|
|
Ktime.Milliseconds,
|
|
Itime.Hour,
|
|
Itime.Minute,
|
|
Itime.Second,
|
|
Itime.Milliseconds
|
|
);
|
|
}
|
|
else {
|
|
printf("UTime( %3ld:%02ld:%02ld.%03ld ) ",
|
|
Utime.Hour,
|
|
Utime.Minute,
|
|
Utime.Second,
|
|
Utime.Milliseconds
|
|
);
|
|
printf("KTime( %3ld:%02ld:%02ld.%03ld )\n",
|
|
Ktime.Hour,
|
|
Ktime.Minute,
|
|
Ktime.Second,
|
|
Ktime.Milliseconds
|
|
);
|
|
printf("ITime( %3ld:%02ld:%02ld.%03ld )\n",
|
|
Itime.Hour,
|
|
Itime.Minute,
|
|
Itime.Second,
|
|
Itime.Milliseconds
|
|
);
|
|
}
|
|
}
|
|
|
|
if ( bFull ) {
|
|
ULONG InterruptCount;
|
|
ULONG PreviousInterruptCount;
|
|
#ifdef i386
|
|
ULONG EmulationTotal;
|
|
#endif
|
|
|
|
PreviousInterruptCount = 0;
|
|
for (i=0; i < (ULONG)BasicInfo.NumberOfProcessors; i++) {
|
|
PreviousInterruptCount += ProcessorInfoStart[i].InterruptCount;
|
|
}
|
|
|
|
InterruptCount = 0;
|
|
for (i=0; i < (ULONG)BasicInfo.NumberOfProcessors; i++) {
|
|
InterruptCount += ProcessorInfoDone[i].InterruptCount;
|
|
}
|
|
|
|
if (bOneLine) {
|
|
printf(" %ld",ProcessVmInfoDone.PageFaultCount - ProcessVmInfoStart.PageFaultCount);
|
|
if (OtherProcess) {
|
|
printf(" %ld",ServerVmInfoDone.PageFaultCount - ServerVmInfoStart.PageFaultCount);
|
|
}
|
|
printf(" %ld", InterruptCount - PreviousInterruptCount);
|
|
printf(" %ld", SystemInfoDone.ContextSwitches - SystemInfoStart.ContextSwitches);
|
|
printf(" %ld", SystemInfoDone.SystemCalls - SystemInfoStart.SystemCalls);
|
|
}
|
|
else {
|
|
printf("\n");
|
|
printf("Process PageFaultCount %ld\n",ProcessVmInfoDone.PageFaultCount - ProcessVmInfoStart.PageFaultCount);
|
|
if (OtherProcess) {
|
|
printf("Server PageFaultCount %ld\n",ServerVmInfoDone.PageFaultCount - ServerVmInfoStart.PageFaultCount);
|
|
}
|
|
printf("Total Interrupts %ld\n", InterruptCount - PreviousInterruptCount);
|
|
printf("Total Context Switches %ld\n", SystemInfoDone.ContextSwitches - SystemInfoStart.ContextSwitches);
|
|
printf("Total System Calls %ld\n", SystemInfoDone.SystemCalls - SystemInfoStart.SystemCalls);
|
|
}
|
|
|
|
if (ProcessHandle) {
|
|
#ifdef i386
|
|
printf("\n");
|
|
printf("Total OpcodeHLT %ld\n", vdelta(OpcodeHLT ));
|
|
printf("Total OpcodeCLI %ld\n", vdelta(OpcodeCLI ));
|
|
printf("Total OpcodeSTI %ld\n", vdelta(OpcodeSTI ));
|
|
printf("Total BopCount %ld\n", vdelta(BopCount ));
|
|
printf("Total SegmentNotPresent %ld\n", vdelta(SegmentNotPresent ));
|
|
printf("Total OpcodePUSHF %ld\n", vdelta(OpcodePUSHF ));
|
|
printf("Total OpcodePOPF %ld\n", vdelta(OpcodePOPF ));
|
|
printf("Total VdmOpcode0F %ld\n", vdelta(VdmOpcode0F ));
|
|
printf("Total OpcodeINSB %ld\n", vdelta(OpcodeINSB ));
|
|
printf("Total OpcodeINSW %ld\n", vdelta(OpcodeINSW ));
|
|
printf("Total OpcodeOUTSB %ld\n", vdelta(OpcodeOUTSB ));
|
|
printf("Total OpcodeOUTSW %ld\n", vdelta(OpcodeOUTSW ));
|
|
printf("Total OpcodeINTnn %ld\n", vdelta(OpcodeINTnn ));
|
|
printf("Total OpcodeINTO %ld\n", vdelta(OpcodeINTO ));
|
|
printf("Total OpcodeIRET %ld\n", vdelta(OpcodeIRET ));
|
|
printf("Total OpcodeINBimm %ld\n", vdelta(OpcodeINBimm ));
|
|
printf("Total OpcodeINWimm %ld\n", vdelta(OpcodeINWimm ));
|
|
printf("Total OpcodeOUTBimm %ld\n", vdelta(OpcodeOUTBimm ));
|
|
printf("Total OpcodeOUTWimm %ld\n", vdelta(OpcodeOUTWimm ));
|
|
printf("Total OpcodeINB %ld\n", vdelta(OpcodeINB ));
|
|
printf("Total OpcodeINW %ld\n", vdelta(OpcodeINW ));
|
|
printf("Total OpcodeOUTB %ld\n", vdelta(OpcodeOUTB ));
|
|
printf("Total OpcodeOUTW %ld\n", vdelta(OpcodeOUTW ));
|
|
|
|
EmulationTotal = vdelta(OpcodeHLT )+
|
|
vdelta(OpcodeCLI )+
|
|
vdelta(OpcodeSTI )+
|
|
vdelta(BopCount )+
|
|
vdelta(SegmentNotPresent )+
|
|
vdelta(OpcodePUSHF )+
|
|
vdelta(OpcodePOPF )+
|
|
vdelta(VdmOpcode0F )+
|
|
vdelta(OpcodeINSB )+
|
|
vdelta(OpcodeINSW )+
|
|
vdelta(OpcodeOUTSB )+
|
|
vdelta(OpcodeOUTSW )+
|
|
vdelta(OpcodeINTnn )+
|
|
vdelta(OpcodeINTO )+
|
|
vdelta(OpcodeIRET )+
|
|
vdelta(OpcodeINBimm )+
|
|
vdelta(OpcodeINWimm )+
|
|
vdelta(OpcodeOUTBimm )+
|
|
vdelta(OpcodeOUTWimm )+
|
|
vdelta(OpcodeINB )+
|
|
vdelta(OpcodeINW )+
|
|
vdelta(OpcodeOUTB )+
|
|
vdelta(OpcodeOUTW )
|
|
;
|
|
|
|
if (bOneLine) {
|
|
printf(" %ld %ld", EmulationTotal, EmulationTotal*515);
|
|
}
|
|
else {
|
|
printf("\n");
|
|
printf("Total Emulation %ld * 515clocks = %ld cycles\n", EmulationTotal, EmulationTotal*515);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if (bSyscall) {
|
|
for (i = 0; i < NumberOfCounts; i += 1) {
|
|
CallData[i] = SystemCallTableDone[i] - SystemCallTableStart[i];
|
|
}
|
|
|
|
SortUlongData(NumberOfCounts, Index, CallData);
|
|
|
|
for (i = 0; i < NumberOfCounts; i += 1) {
|
|
if (CallData[Index[i]] == 0) {
|
|
break;
|
|
}
|
|
printf("%8ld calls to %s\n", CallData[Index[i]], CallTable[Index[i]]);
|
|
}
|
|
}
|
|
|
|
if (bOneLine) {
|
|
printf("\n");
|
|
}
|
|
} else {
|
|
printf("\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|