Source code of Windows XP (NT5)
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.

838 lines
28 KiB

  1. #include <assert.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <memory.h>
  5. #include <nt.h>
  6. #include <ntrtl.h>
  7. #include <nturtl.h>
  8. #include <windows.h>
  9. #include <..\ztools\inc\tools.h>
  10. #define NUMBER_SERVICE_TABLES 2
  11. #define BUFFER_SIZE 1024
  12. VOID
  13. SortUlongData (
  14. IN ULONG Count,
  15. IN ULONG Index[],
  16. IN ULONG Data[]
  17. );
  18. extern UCHAR *CallTable[];
  19. ULONG SystemCallBufferStart[BUFFER_SIZE];
  20. ULONG SystemCallBufferDone[BUFFER_SIZE];
  21. ULONG Index[BUFFER_SIZE];
  22. ULONG CallData[BUFFER_SIZE];
  23. #define MAX_PROCESSOR 16
  24. SYSTEM_BASIC_INFORMATION BasicInfo;
  25. SYSTEM_PERFORMANCE_INFORMATION SystemInfoStart;
  26. SYSTEM_PERFORMANCE_INFORMATION SystemInfoDone;
  27. SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION ProcessorInfoStart[MAX_PROCESSOR];
  28. SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION ProcessorInfoDone[MAX_PROCESSOR];
  29. #define vdelta(FLD) (VdmInfoDone.FLD - VdmInfoStart.FLD)
  30. #ifdef i386
  31. SYSTEM_VDM_INSTEMUL_INFO VdmInfoStart;
  32. SYSTEM_VDM_INSTEMUL_INFO VdmInfoDone;
  33. #endif
  34. HANDLE
  35. GetServerProcessHandle( VOID )
  36. {
  37. HANDLE Process;
  38. OBJECT_ATTRIBUTES Obja;
  39. UNICODE_STRING Unicode;
  40. NTSTATUS Status;
  41. RtlInitUnicodeString(&Unicode, L"\\WindowsSS");
  42. InitializeObjectAttributes(
  43. &Obja,
  44. &Unicode,
  45. 0,
  46. NULL,
  47. NULL
  48. );
  49. Status = NtOpenProcess(
  50. &Process,
  51. PROCESS_ALL_ACCESS,
  52. &Obja,
  53. NULL
  54. );
  55. if ( !NT_SUCCESS(Status) ) {
  56. printf("OpenProcess Failed %lx\n",Status);
  57. Process = NULL;
  58. }
  59. return Process;
  60. }
  61. BOOL WINAPI
  62. CtrlcHandler(
  63. ULONG CtrlType
  64. )
  65. {
  66. //
  67. // Ignore control C interrupts. Let child process deal with them
  68. // if it wants. If it doesn't then it will terminate and we will
  69. // get control and terminate ourselves
  70. //
  71. return TRUE;
  72. }
  73. int
  74. __cdecl main(
  75. int argc,
  76. char *argv[],
  77. char *envp[]
  78. )
  79. {
  80. LPSTR s;
  81. BOOL bFull;
  82. BOOL bOneLine;
  83. BOOL bSyscall;
  84. STARTUPINFO StartupInfo;
  85. PROCESS_INFORMATION ProcessInformation;
  86. BOOL b;
  87. VM_COUNTERS ServerVmInfoStart, ServerVmInfoDone, ProcessVmInfoStart, ProcessVmInfoDone;
  88. KERNEL_USER_TIMES Times, ServerStart, ServerDone, ProcessStart, ProcessDone;
  89. NTSTATUS Status;
  90. TIME_FIELDS Etime,Utime,Ktime,Itime;
  91. LARGE_INTEGER RunTime;
  92. LARGE_INTEGER IdleTime;
  93. HANDLE OtherProcess;
  94. ULONG i;
  95. CHAR ch;
  96. ULONG ProcessId;
  97. HANDLE ProcessHandle;
  98. ULONG Temp;
  99. ULONG ContextSwitches;
  100. ULONG FirstLevelFills;
  101. ULONG SecondLevelFills;
  102. PSYSTEM_CALL_COUNT_INFORMATION SystemCallInfoStart;
  103. PSYSTEM_CALL_COUNT_INFORMATION SystemCallInfoDone;
  104. PULONG SystemCallTableStart;
  105. PULONG SystemCallTableDone;
  106. ULONG NumberOfCounts;
  107. PULONG p;
  108. BOOL bShowHelpMsg = FALSE;
  109. argv;
  110. envp;
  111. ConvertAppToOem( argc, argv );
  112. OtherProcess = NULL;
  113. ProcessHandle = NULL;
  114. if ( (argc < 2) ) {
  115. bShowHelpMsg = TRUE;
  116. }
  117. SetConsoleCtrlHandler( CtrlcHandler, TRUE );
  118. ProcessId = 0;
  119. s = GetCommandLine();
  120. if( s != NULL ) {
  121. CharToOem( s, s );
  122. }
  123. bFull = FALSE;
  124. bOneLine = FALSE;
  125. bSyscall = FALSE;
  126. //
  127. // skip blanks
  128. //
  129. while(*s>' ')s++;
  130. //
  131. // get to next token
  132. //
  133. while(*s<=' ')s++;
  134. while (( *s == '-' ) || ( *s == '/' )) {
  135. s++;
  136. while (*s > ' ') {
  137. switch (*s) {
  138. case '1' :
  139. bOneLine = TRUE;
  140. break;
  141. case 'c' :
  142. case 'C' :
  143. bSyscall = TRUE;
  144. break;
  145. case 'f' :
  146. case 'F' :
  147. bFull = TRUE;
  148. break;
  149. case 's' :
  150. case 'S' :
  151. OtherProcess = GetServerProcessHandle();
  152. break;
  153. case 'P':
  154. case 'p':
  155. // pid takes decimal argument
  156. s++;
  157. do
  158. ch = *s++;
  159. while (ch == ' ' || ch == '\t');
  160. while (ch >= '0' && ch <= '9') {
  161. Temp = ProcessId * 10 + ch - '0';
  162. if (Temp < ProcessId) {
  163. printf("pid number overflow\n");
  164. ExitProcess(1);
  165. }
  166. ProcessId = Temp;
  167. ch = *s++;
  168. }
  169. if (!ProcessId) {
  170. printf("bad pid '%ld'\n", ProcessId);
  171. ExitProcess(1);
  172. }
  173. s--;
  174. if ( *s == ' ' ) s--;
  175. break;
  176. case 'h':
  177. case 'H':
  178. case '?':
  179. bShowHelpMsg = TRUE;
  180. break;
  181. default :
  182. break;
  183. }
  184. s++;
  185. }
  186. //
  187. // get to next token
  188. //
  189. while(*s<=' ')s++;
  190. }
  191. // see if this is just a request for command line help.
  192. if ( bShowHelpMsg ) {
  193. puts("\n"
  194. "Usage: ntimer [-1 -f -s] name-of-image [parameters]...\n"
  195. "\n"
  196. " Displays the Elapsed, Kernel, User and Idle time of the\n"
  197. " image specified in the command line\n"
  198. "\n"
  199. " -1 displays output on one line\n"
  200. " -f displays the process page faults, total\n"
  201. " system interrupts, context switches and system\n"
  202. " calls\n"
  203. " -s indicates the name of the image is that of a\n"
  204. " server process. Press Ctrl-C to get the times.");
  205. ExitProcess(1);
  206. }
  207. if ( ProcessId ) {
  208. ProcessHandle = OpenProcess(PROCESS_ALL_ACCESS,FALSE,ProcessId);
  209. }
  210. memset(&StartupInfo,0,sizeof(StartupInfo));
  211. StartupInfo.cb = sizeof(StartupInfo);
  212. if (bOneLine) {
  213. bSyscall = FALSE;
  214. }
  215. if (bSyscall) {
  216. Status = NtQuerySystemInformation(SystemCallCountInformation,
  217. (PVOID)SystemCallBufferStart,
  218. BUFFER_SIZE * sizeof(ULONG),
  219. NULL);
  220. bSyscall = FALSE;
  221. if (!NT_SUCCESS(Status)) {
  222. printf("Failed to query system call performance information: %x\n", Status);
  223. } else {
  224. SystemCallInfoStart = (PVOID)SystemCallBufferStart;
  225. SystemCallInfoDone = (PVOID)SystemCallBufferDone;
  226. //
  227. // Make sure that the number of tables reported by the kernel matches
  228. // our list.
  229. //
  230. if (SystemCallInfoStart->NumberOfTables != NUMBER_SERVICE_TABLES) {
  231. printf("System call table count (%d) doesn't match NTIMER's count (%d)\n",
  232. SystemCallInfoStart->NumberOfTables, NUMBER_SERVICE_TABLES);
  233. } else {
  234. //
  235. // Make sure call count information is available for base services.
  236. //
  237. p = (PULONG)(SystemCallInfoStart + 1);
  238. SystemCallTableStart = (PULONG)(SystemCallInfoStart + 1) + NUMBER_SERVICE_TABLES;
  239. SystemCallTableDone = (PULONG)(SystemCallInfoDone + 1) + NUMBER_SERVICE_TABLES;
  240. if (p[0] == 0) {
  241. printf("No system call count information available for base services\n");
  242. } else {
  243. //
  244. // If there is a hole in the count information (i.e., one set of services
  245. // doesn't have counting enabled, but a subsequent one does, then our
  246. // indexes will be off, and we'll display the wrong service names.
  247. //
  248. i = 2;
  249. for ( ; i < NUMBER_SERVICE_TABLES; i++ ) {
  250. if ((p[i] != 0) && (p[i-1] == 0)) {
  251. printf("One or more call count tables empty. NTIMER can't report\n");
  252. break;
  253. }
  254. }
  255. if ( i >= NUMBER_SERVICE_TABLES ) {
  256. bSyscall = TRUE;
  257. NumberOfCounts = SystemCallInfoStart->Length
  258. - sizeof(SYSTEM_CALL_COUNT_INFORMATION)
  259. - NUMBER_SERVICE_TABLES * sizeof(ULONG);
  260. }
  261. }
  262. }
  263. }
  264. }
  265. if ( OtherProcess ) {
  266. Status = NtQueryInformationProcess(
  267. OtherProcess,
  268. ProcessTimes,
  269. &ServerStart,
  270. sizeof(Times),
  271. NULL
  272. );
  273. if ( !NT_SUCCESS(Status) ) {
  274. ExitProcess((DWORD)Status);
  275. }
  276. }
  277. if ( ProcessHandle ) {
  278. Status = NtQueryInformationProcess(
  279. ProcessHandle,
  280. ProcessTimes,
  281. &ProcessStart,
  282. sizeof(Times),
  283. NULL
  284. );
  285. if ( !NT_SUCCESS(Status) ) {
  286. ExitProcess((DWORD)Status);
  287. }
  288. }
  289. if ( bFull ) {
  290. if ( OtherProcess ) {
  291. Status = NtQueryInformationProcess(
  292. OtherProcess,
  293. ProcessVmCounters,
  294. &ServerVmInfoStart,
  295. sizeof(VM_COUNTERS),
  296. NULL
  297. );
  298. if ( !NT_SUCCESS(Status) ) {
  299. ExitProcess((DWORD)Status);
  300. }
  301. }
  302. if ( ProcessHandle ) {
  303. Status = NtQueryInformationProcess(
  304. ProcessHandle,
  305. ProcessVmCounters,
  306. &ProcessVmInfoStart,
  307. sizeof(VM_COUNTERS),
  308. NULL
  309. );
  310. if ( !NT_SUCCESS(Status) ) {
  311. ExitProcess((DWORD)Status);
  312. }
  313. }
  314. else {
  315. ZeroMemory(&ProcessVmInfoStart,sizeof(VM_COUNTERS));
  316. }
  317. #ifdef i386
  318. Status = NtQuerySystemInformation(
  319. SystemVdmInstemulInformation,
  320. &VdmInfoStart,
  321. sizeof(VdmInfoStart),
  322. NULL
  323. );
  324. if (!NT_SUCCESS(Status)) {
  325. printf("Failed to query vdm information\n");
  326. ExitProcess((DWORD)Status);
  327. }
  328. #endif
  329. Status = NtQuerySystemInformation(
  330. SystemBasicInformation,
  331. &BasicInfo,
  332. sizeof(BasicInfo),
  333. NULL
  334. );
  335. if (!NT_SUCCESS(Status)) {
  336. printf("Failed to query basic information\n");
  337. ExitProcess((DWORD)Status);
  338. }
  339. Status = NtQuerySystemInformation(SystemProcessorPerformanceInformation,
  340. (PVOID)&ProcessorInfoStart,
  341. sizeof (SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * MAX_PROCESSOR,
  342. NULL);
  343. if (!NT_SUCCESS(Status)) {
  344. printf("Failed to query preocessor performance information\n");
  345. ExitProcess((DWORD)Status);
  346. }
  347. }
  348. Status = NtQuerySystemInformation(SystemPerformanceInformation,
  349. (PVOID)&SystemInfoStart,
  350. sizeof(SYSTEM_PERFORMANCE_INFORMATION),
  351. NULL);
  352. ContextSwitches = SystemInfoStart.ContextSwitches;
  353. FirstLevelFills = SystemInfoStart.FirstLevelTbFills;
  354. SecondLevelFills = SystemInfoStart.SecondLevelTbFills;
  355. b = CreateProcess(
  356. NULL,
  357. s,
  358. NULL,
  359. NULL,
  360. TRUE,
  361. 0,
  362. NULL,
  363. NULL,
  364. &StartupInfo,
  365. &ProcessInformation
  366. );
  367. if ( !b ) {
  368. printf("CreateProcess(%s) failed %lx\n",s,GetLastError());
  369. ExitProcess(GetLastError());
  370. }
  371. WaitForSingleObject(ProcessInformation.hProcess,(DWORD)-1);
  372. Status = NtQuerySystemInformation(SystemPerformanceInformation,
  373. (PVOID)&SystemInfoDone,
  374. sizeof(SYSTEM_PERFORMANCE_INFORMATION),
  375. NULL);
  376. if (!bOneLine) {
  377. printf("\nContextSwitches - %d\nFirst level fills = %d\nSecond level fills = %d\n",
  378. SystemInfoDone.ContextSwitches - ContextSwitches,
  379. SystemInfoDone.FirstLevelTbFills - FirstLevelFills,
  380. SystemInfoDone.SecondLevelTbFills - SecondLevelFills);
  381. }
  382. if ( OtherProcess ) {
  383. Status = NtQueryInformationProcess(
  384. OtherProcess,
  385. ProcessTimes,
  386. &ServerDone,
  387. sizeof(Times),
  388. NULL
  389. );
  390. if ( !NT_SUCCESS(Status) ) {
  391. ExitProcess((DWORD)Status);
  392. }
  393. }
  394. if ( ProcessHandle ) {
  395. Status = NtQueryInformationProcess(
  396. ProcessHandle,
  397. ProcessTimes,
  398. &ProcessDone,
  399. sizeof(Times),
  400. NULL
  401. );
  402. if ( !NT_SUCCESS(Status) ) {
  403. ExitProcess((DWORD)Status);
  404. }
  405. }
  406. else {
  407. Status = NtQueryInformationProcess(
  408. ProcessInformation.hProcess,
  409. ProcessTimes,
  410. &Times,
  411. sizeof(Times),
  412. NULL
  413. );
  414. if ( !NT_SUCCESS(Status) ) {
  415. ExitProcess((DWORD)Status);
  416. }
  417. }
  418. if ( bFull ) {
  419. if ( OtherProcess ) {
  420. Status = NtQueryInformationProcess(
  421. OtherProcess,
  422. ProcessVmCounters,
  423. &ServerVmInfoDone,
  424. sizeof(VM_COUNTERS),
  425. NULL
  426. );
  427. if ( !NT_SUCCESS(Status) ) {
  428. ExitProcess((DWORD)Status);
  429. }
  430. }
  431. if ( ProcessHandle ) {
  432. Status = NtQueryInformationProcess(
  433. ProcessHandle,
  434. ProcessVmCounters,
  435. &ProcessVmInfoDone,
  436. sizeof(VM_COUNTERS),
  437. NULL
  438. );
  439. if ( !NT_SUCCESS(Status) ) {
  440. ExitProcess((DWORD)Status);
  441. }
  442. }
  443. else {
  444. Status = NtQueryInformationProcess(
  445. ProcessInformation.hProcess,
  446. ProcessVmCounters,
  447. &ProcessVmInfoDone,
  448. sizeof(VM_COUNTERS),
  449. NULL
  450. );
  451. if ( !NT_SUCCESS(Status) ) {
  452. ExitProcess((DWORD)Status);
  453. }
  454. }
  455. #ifdef i386
  456. Status = NtQuerySystemInformation(
  457. SystemVdmInstemulInformation,
  458. &VdmInfoDone,
  459. sizeof(VdmInfoStart),
  460. NULL
  461. );
  462. if (!NT_SUCCESS(Status)) {
  463. printf("Failed to query vdm information\n");
  464. ExitProcess((DWORD)Status);
  465. }
  466. #endif
  467. Status = NtQuerySystemInformation(SystemProcessorPerformanceInformation,
  468. (PVOID)&ProcessorInfoDone,
  469. sizeof (SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * MAX_PROCESSOR,
  470. NULL);
  471. if (!NT_SUCCESS(Status)) {
  472. printf("Failed to query preocessor performance information\n");
  473. ExitProcess((DWORD)Status);
  474. }
  475. }
  476. if ( bSyscall ) {
  477. Status = NtQuerySystemInformation(SystemCallCountInformation,
  478. (PVOID)SystemCallBufferDone,
  479. BUFFER_SIZE * sizeof(ULONG),
  480. NULL);
  481. if (!NT_SUCCESS(Status)) {
  482. printf("Failed to query system call performance information: %x\n", Status);
  483. bSyscall = FALSE;
  484. }
  485. }
  486. RunTime.QuadPart = Times.ExitTime.QuadPart - Times.CreateTime.QuadPart;
  487. IdleTime.QuadPart = SystemInfoDone.IdleProcessTime.QuadPart -
  488. SystemInfoStart.IdleProcessTime.QuadPart;
  489. RtlTimeToTimeFields ( (PLARGE_INTEGER)&IdleTime, &Itime);
  490. if ( ProcessHandle ) {
  491. RunTime.QuadPart = ProcessDone.UserTime.QuadPart -
  492. ProcessStart.UserTime.QuadPart;
  493. RtlTimeToTimeFields ( (PLARGE_INTEGER)&RunTime, &Utime);
  494. RunTime.QuadPart = ProcessDone.KernelTime.QuadPart -
  495. ProcessStart.KernelTime.QuadPart;
  496. RtlTimeToTimeFields ( (PLARGE_INTEGER)&RunTime, &Ktime);
  497. if (bOneLine) {
  498. printf("%3ld:%02ld:%02ld.%03ld %3ld:%02ld:%02ld.%03ld %3ld:%02ld:%02ld.%03ld",
  499. Utime.Hour,
  500. Utime.Minute,
  501. Utime.Second,
  502. Utime.Milliseconds,
  503. Ktime.Hour,
  504. Ktime.Minute,
  505. Ktime.Second,
  506. Ktime.Milliseconds,
  507. Itime.Hour,
  508. Itime.Minute,
  509. Itime.Second,
  510. Itime.Milliseconds
  511. );
  512. }
  513. else {
  514. printf("ProcessTimes ");
  515. printf("UTime( %3ld:%02ld:%02ld.%03ld ) ",
  516. Utime.Hour,
  517. Utime.Minute,
  518. Utime.Second,
  519. Utime.Milliseconds
  520. );
  521. printf("KTime( %3ld:%02ld:%02ld.%03ld ) ",
  522. Ktime.Hour,
  523. Ktime.Minute,
  524. Ktime.Second,
  525. Ktime.Milliseconds
  526. );
  527. printf("ITime( %3ld:%02ld:%02ld.%03ld )\n",
  528. Itime.Hour,
  529. Itime.Minute,
  530. Itime.Second,
  531. Itime.Milliseconds
  532. );
  533. }
  534. }
  535. else {
  536. RtlTimeToTimeFields((PLARGE_INTEGER) &RunTime, &Etime);
  537. RtlTimeToTimeFields(&Times.UserTime, &Utime);
  538. RtlTimeToTimeFields(&Times.KernelTime, &Ktime);
  539. if (bOneLine) {
  540. printf("%3ld:%02ld:%02ld.%03ld %3ld:%02ld:%02ld.%03ld %3ld:%02ld:%02ld.%03ld %3ld:%02ld:%02ld.%03ld",
  541. Etime.Hour,
  542. Etime.Minute,
  543. Etime.Second,
  544. Etime.Milliseconds,
  545. Utime.Hour,
  546. Utime.Minute,
  547. Utime.Second,
  548. Utime.Milliseconds,
  549. Ktime.Hour,
  550. Ktime.Minute,
  551. Ktime.Second,
  552. Ktime.Milliseconds,
  553. Itime.Hour,
  554. Itime.Minute,
  555. Itime.Second,
  556. Itime.Milliseconds
  557. );
  558. }
  559. else {
  560. printf("\nETime( %3ld:%02ld:%02ld.%03ld ) ",
  561. Etime.Hour,
  562. Etime.Minute,
  563. Etime.Second,
  564. Etime.Milliseconds
  565. );
  566. printf("UTime( %3ld:%02ld:%02ld.%03ld ) ",
  567. Utime.Hour,
  568. Utime.Minute,
  569. Utime.Second,
  570. Utime.Milliseconds
  571. );
  572. printf("KTime( %3ld:%02ld:%02ld.%03ld )\n",
  573. Ktime.Hour,
  574. Ktime.Minute,
  575. Ktime.Second,
  576. Ktime.Milliseconds
  577. );
  578. printf("ITime( %3ld:%02ld:%02ld.%03ld )\n",
  579. Itime.Hour,
  580. Itime.Minute,
  581. Itime.Second,
  582. Itime.Milliseconds
  583. );
  584. }
  585. }
  586. if ( OtherProcess ) {
  587. RunTime.QuadPart = ServerDone.UserTime.QuadPart -
  588. ServerStart.UserTime.QuadPart;
  589. RtlTimeToTimeFields ( (PLARGE_INTEGER)&RunTime, &Utime);
  590. RunTime.QuadPart = ServerDone.KernelTime.QuadPart -
  591. ServerStart.KernelTime.QuadPart;
  592. RtlTimeToTimeFields ( (PLARGE_INTEGER)&RunTime, &Ktime);
  593. printf("ServerTimes ");
  594. if (bOneLine) {
  595. printf("%3ld:%02ld:%02ld.%03ld %3ld:%02ld:%02ld.%03ld %3ld:%02ld:%02ld.%03ld",
  596. Utime.Hour,
  597. Utime.Minute,
  598. Utime.Second,
  599. Utime.Milliseconds,
  600. Ktime.Hour,
  601. Ktime.Minute,
  602. Ktime.Second,
  603. Ktime.Milliseconds,
  604. Itime.Hour,
  605. Itime.Minute,
  606. Itime.Second,
  607. Itime.Milliseconds
  608. );
  609. }
  610. else {
  611. printf("UTime( %3ld:%02ld:%02ld.%03ld ) ",
  612. Utime.Hour,
  613. Utime.Minute,
  614. Utime.Second,
  615. Utime.Milliseconds
  616. );
  617. printf("KTime( %3ld:%02ld:%02ld.%03ld )\n",
  618. Ktime.Hour,
  619. Ktime.Minute,
  620. Ktime.Second,
  621. Ktime.Milliseconds
  622. );
  623. printf("ITime( %3ld:%02ld:%02ld.%03ld )\n",
  624. Itime.Hour,
  625. Itime.Minute,
  626. Itime.Second,
  627. Itime.Milliseconds
  628. );
  629. }
  630. }
  631. if ( bFull ) {
  632. ULONG InterruptCount;
  633. ULONG PreviousInterruptCount;
  634. #ifdef i386
  635. ULONG EmulationTotal;
  636. #endif
  637. PreviousInterruptCount = 0;
  638. for (i=0; i < (ULONG)BasicInfo.NumberOfProcessors; i++) {
  639. PreviousInterruptCount += ProcessorInfoStart[i].InterruptCount;
  640. }
  641. InterruptCount = 0;
  642. for (i=0; i < (ULONG)BasicInfo.NumberOfProcessors; i++) {
  643. InterruptCount += ProcessorInfoDone[i].InterruptCount;
  644. }
  645. if (bOneLine) {
  646. printf(" %ld",ProcessVmInfoDone.PageFaultCount - ProcessVmInfoStart.PageFaultCount);
  647. if (OtherProcess) {
  648. printf(" %ld",ServerVmInfoDone.PageFaultCount - ServerVmInfoStart.PageFaultCount);
  649. }
  650. printf(" %ld", InterruptCount - PreviousInterruptCount);
  651. printf(" %ld", SystemInfoDone.ContextSwitches - SystemInfoStart.ContextSwitches);
  652. printf(" %ld", SystemInfoDone.SystemCalls - SystemInfoStart.SystemCalls);
  653. }
  654. else {
  655. printf("\n");
  656. printf("Process PageFaultCount %ld\n",ProcessVmInfoDone.PageFaultCount - ProcessVmInfoStart.PageFaultCount);
  657. if (OtherProcess) {
  658. printf("Server PageFaultCount %ld\n",ServerVmInfoDone.PageFaultCount - ServerVmInfoStart.PageFaultCount);
  659. }
  660. printf("Total Interrupts %ld\n", InterruptCount - PreviousInterruptCount);
  661. printf("Total Context Switches %ld\n", SystemInfoDone.ContextSwitches - SystemInfoStart.ContextSwitches);
  662. printf("Total System Calls %ld\n", SystemInfoDone.SystemCalls - SystemInfoStart.SystemCalls);
  663. }
  664. if (ProcessHandle) {
  665. #ifdef i386
  666. printf("\n");
  667. printf("Total OpcodeHLT %ld\n", vdelta(OpcodeHLT ));
  668. printf("Total OpcodeCLI %ld\n", vdelta(OpcodeCLI ));
  669. printf("Total OpcodeSTI %ld\n", vdelta(OpcodeSTI ));
  670. printf("Total BopCount %ld\n", vdelta(BopCount ));
  671. printf("Total SegmentNotPresent %ld\n", vdelta(SegmentNotPresent ));
  672. printf("Total OpcodePUSHF %ld\n", vdelta(OpcodePUSHF ));
  673. printf("Total OpcodePOPF %ld\n", vdelta(OpcodePOPF ));
  674. printf("Total VdmOpcode0F %ld\n", vdelta(VdmOpcode0F ));
  675. printf("Total OpcodeINSB %ld\n", vdelta(OpcodeINSB ));
  676. printf("Total OpcodeINSW %ld\n", vdelta(OpcodeINSW ));
  677. printf("Total OpcodeOUTSB %ld\n", vdelta(OpcodeOUTSB ));
  678. printf("Total OpcodeOUTSW %ld\n", vdelta(OpcodeOUTSW ));
  679. printf("Total OpcodeINTnn %ld\n", vdelta(OpcodeINTnn ));
  680. printf("Total OpcodeINTO %ld\n", vdelta(OpcodeINTO ));
  681. printf("Total OpcodeIRET %ld\n", vdelta(OpcodeIRET ));
  682. printf("Total OpcodeINBimm %ld\n", vdelta(OpcodeINBimm ));
  683. printf("Total OpcodeINWimm %ld\n", vdelta(OpcodeINWimm ));
  684. printf("Total OpcodeOUTBimm %ld\n", vdelta(OpcodeOUTBimm ));
  685. printf("Total OpcodeOUTWimm %ld\n", vdelta(OpcodeOUTWimm ));
  686. printf("Total OpcodeINB %ld\n", vdelta(OpcodeINB ));
  687. printf("Total OpcodeINW %ld\n", vdelta(OpcodeINW ));
  688. printf("Total OpcodeOUTB %ld\n", vdelta(OpcodeOUTB ));
  689. printf("Total OpcodeOUTW %ld\n", vdelta(OpcodeOUTW ));
  690. EmulationTotal = vdelta(OpcodeHLT )+
  691. vdelta(OpcodeCLI )+
  692. vdelta(OpcodeSTI )+
  693. vdelta(BopCount )+
  694. vdelta(SegmentNotPresent )+
  695. vdelta(OpcodePUSHF )+
  696. vdelta(OpcodePOPF )+
  697. vdelta(VdmOpcode0F )+
  698. vdelta(OpcodeINSB )+
  699. vdelta(OpcodeINSW )+
  700. vdelta(OpcodeOUTSB )+
  701. vdelta(OpcodeOUTSW )+
  702. vdelta(OpcodeINTnn )+
  703. vdelta(OpcodeINTO )+
  704. vdelta(OpcodeIRET )+
  705. vdelta(OpcodeINBimm )+
  706. vdelta(OpcodeINWimm )+
  707. vdelta(OpcodeOUTBimm )+
  708. vdelta(OpcodeOUTWimm )+
  709. vdelta(OpcodeINB )+
  710. vdelta(OpcodeINW )+
  711. vdelta(OpcodeOUTB )+
  712. vdelta(OpcodeOUTW )
  713. ;
  714. if (bOneLine) {
  715. printf(" %ld %ld", EmulationTotal, EmulationTotal*515);
  716. }
  717. else {
  718. printf("\n");
  719. printf("Total Emulation %ld * 515clocks = %ld cycles\n", EmulationTotal, EmulationTotal*515);
  720. }
  721. #endif
  722. }
  723. if (bSyscall) {
  724. for (i = 0; i < NumberOfCounts; i += 1) {
  725. CallData[i] = SystemCallTableDone[i] - SystemCallTableStart[i];
  726. }
  727. SortUlongData(NumberOfCounts, Index, CallData);
  728. for (i = 0; i < NumberOfCounts; i += 1) {
  729. if (CallData[Index[i]] == 0) {
  730. break;
  731. }
  732. printf("%8ld calls to %s\n", CallData[Index[i]], CallTable[Index[i]]);
  733. }
  734. }
  735. if (bOneLine) {
  736. printf("\n");
  737. }
  738. } else {
  739. printf("\n");
  740. }
  741. return 0;
  742. }