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.

516 lines
12 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. Wperf.c
  5. Abstract:
  6. Win32 application to display performance statictics.
  7. Author:
  8. Ken Reneris
  9. Environment:
  10. console
  11. --*/
  12. //
  13. // set variable to define global variables
  14. //
  15. #include <nt.h>
  16. #include <ntrtl.h>
  17. #include <nturtl.h>
  18. #include <windows.h>
  19. #include <errno.h>
  20. #include <malloc.h>
  21. #include <stdlib.h>
  22. #include <stdio.h>
  23. #include "..\pstat.h"
  24. //
  25. // global handles
  26. //
  27. extern UCHAR Buffer[];
  28. #define INFSIZE 1024
  29. UCHAR Usage[] = "pdump: [-p] [-t] second-delay [counter] [counter]...\n";
  30. UCHAR NumberOfProcessors;
  31. HANDLE DriverHandle;
  32. ULONG BufferStart [INFSIZE/4];
  33. ULONG BufferEnd [INFSIZE/4];
  34. //
  35. // Selected Display Mode (read from wp2.ini), default set here.
  36. //
  37. struct {
  38. ULONG EventId;
  39. PUCHAR ShortName;
  40. PUCHAR PerfName;
  41. } *Counters;
  42. SETEVENT CounterEvent[MAX_EVENTS];
  43. //
  44. // Protos..
  45. //
  46. VOID GetInternalStats (PVOID Buffer);
  47. VOID SetCounterEncodings (VOID);
  48. LONG FindShortName (PSZ);
  49. VOID LI2Str (PSZ, ULONGLONG);
  50. BOOLEAN SetCounter (LONG CounterID, ULONG counter);
  51. BOOLEAN InitDriver ();
  52. VOID InitPossibleEventList();
  53. int
  54. __cdecl
  55. main(USHORT argc, CHAR **argv)
  56. {
  57. ULONG i, j, len, pos, Delay;
  58. LONG cnttype;
  59. BOOLEAN CounterSet;
  60. pPSTATS ProcStart, ProcEnd;
  61. ULONGLONG ETime, ECount;
  62. UCHAR s1[40], s2[40];
  63. BOOLEAN Fail, DumpAll, ProcessorBreakout, ProcessorTotal;
  64. //
  65. // Locate pentium perf driver
  66. //
  67. if (!InitDriver ()) {
  68. printf ("pstat.sys is not installed\n");
  69. exit (1);
  70. }
  71. //
  72. // Initialize supported event list
  73. //
  74. InitPossibleEventList();
  75. if (!Counters) {
  76. printf ("No events to monitor\n");
  77. exit (1);
  78. }
  79. //
  80. // Check args
  81. //
  82. if (argc < 2) {
  83. printf (Usage);
  84. for (i=0; Counters[i].ShortName; i++) {
  85. printf (" %-20s\t%s\n", Counters[i].ShortName, Counters[i].PerfName);
  86. }
  87. exit (1);
  88. }
  89. pos = 1;
  90. Fail = FALSE;
  91. Delay = 0;
  92. DumpAll = FALSE;
  93. ProcessorBreakout = FALSE;
  94. ProcessorTotal = FALSE;
  95. while (pos < argc && argv[pos][0] == '-') {
  96. switch (argv[pos][1]) {
  97. case 't':
  98. ProcessorTotal = TRUE;
  99. break;
  100. case 'p':
  101. ProcessorBreakout = TRUE;
  102. break;
  103. default:
  104. printf ("pdump: unkown switch '%c'\n", argv[pos][1]);
  105. Fail = TRUE;
  106. break;
  107. }
  108. pos += 1;
  109. }
  110. if (pos < argc) {
  111. Delay = atoi (argv[pos]) * 1000;
  112. pos += 1;
  113. }
  114. if (Fail /* || Delay == 0 */) {
  115. printf (Usage);
  116. exit (1);
  117. }
  118. //
  119. // Raise to highest priority
  120. //
  121. if (!SetPriorityClass(GetCurrentProcess(),REALTIME_PRIORITY_CLASS)) {
  122. printf("Failed to raise to realtime priority\n");
  123. }
  124. SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
  125. //
  126. // Loop for every pentium count desired
  127. //
  128. if (pos >= argc) {
  129. pos = 0;
  130. DumpAll = TRUE;
  131. }
  132. printf (" %-30s %17s %17s\n", "", "Cycles", "Count");
  133. for (; ;) {
  134. //
  135. // Set MAX_EVENTS
  136. //
  137. CounterSet = FALSE;
  138. i = 0;
  139. while (i < MAX_EVENTS) {
  140. cnttype = -1;
  141. if (DumpAll) {
  142. //
  143. // Dump all - get next counter
  144. //
  145. if (Counters[pos].ShortName) {
  146. cnttype = pos;
  147. pos++;
  148. }
  149. } else {
  150. //
  151. // process command line args
  152. //
  153. if (pos < argc) {
  154. cnttype = FindShortName (argv[pos]);
  155. if (cnttype == -1) {
  156. printf ("Counter '%s' not found\n", argv[pos]);
  157. pos++;
  158. continue;
  159. }
  160. pos++;
  161. }
  162. }
  163. CounterSet |= SetCounter (cnttype, i);
  164. i++;
  165. }
  166. if (!CounterSet) {
  167. // done
  168. exit (1);
  169. }
  170. //
  171. // Call driver and perform the setting
  172. //
  173. SetCounterEncodings ();
  174. if ( Delay == 0 ) {
  175. printf( "Counters set\n" );
  176. // done
  177. exit(1);
  178. }
  179. //
  180. // Snap begining & ending counts
  181. //
  182. Sleep (50); // slight settle
  183. GetInternalStats (BufferStart); // snap current values
  184. Sleep (Delay); // sleep desired time
  185. GetInternalStats (BufferEnd); // snap ending values
  186. //
  187. // Calculate each counter and print it
  188. //
  189. for (i=0; i < MAX_EVENTS; i++) {
  190. if (!CounterEvent[i].Active) {
  191. continue;
  192. }
  193. len = *((PULONG) BufferStart);
  194. if (ProcessorBreakout) {
  195. //
  196. // Print stat for each processor
  197. //
  198. ProcStart = (pPSTATS) ((PUCHAR) BufferStart + sizeof(ULONG));
  199. ProcEnd = (pPSTATS) ((PUCHAR) BufferEnd + sizeof(ULONG));
  200. for (j=0; j < NumberOfProcessors; j++) {
  201. ETime = ProcEnd->TSC - ProcStart->TSC;
  202. ECount = ProcEnd->Counters[i] - ProcStart->Counters[i];
  203. ProcStart = (pPSTATS) (((PUCHAR) ProcStart) + len);
  204. ProcEnd = (pPSTATS) (((PUCHAR) ProcEnd) + len);
  205. LI2Str (s1, ETime);
  206. LI2Str (s2, ECount);
  207. printf (" P%d %-30s %s %s\n",
  208. j,
  209. Counters[CounterEvent[i].AppReserved].PerfName,
  210. s1, s2
  211. );
  212. }
  213. }
  214. if (!ProcessorBreakout || ProcessorTotal) {
  215. //
  216. // Sum processor's and print it
  217. //
  218. ProcStart = (pPSTATS) ((PUCHAR) BufferStart + sizeof(ULONG));
  219. ProcEnd = (pPSTATS) ((PUCHAR) BufferEnd + sizeof(ULONG));
  220. ETime = 0;
  221. ECount = 0;
  222. for (j=0; j < NumberOfProcessors; j++) {
  223. ETime = ETime + ProcEnd->TSC;
  224. ETime = ETime - ProcStart->TSC;
  225. ECount = ECount + ProcEnd->Counters[i];
  226. ECount = ECount - ProcStart->Counters[i];
  227. ProcStart = (pPSTATS) (((PUCHAR) ProcStart) + len);
  228. ProcEnd = (pPSTATS) (((PUCHAR) ProcEnd) + len);
  229. }
  230. LI2Str (s1, ETime);
  231. LI2Str (s2, ECount);
  232. printf (" %-30s %s %s\n",
  233. Counters[CounterEvent[i].AppReserved].PerfName,
  234. s1, s2
  235. );
  236. }
  237. }
  238. }
  239. return 0;
  240. }
  241. BOOLEAN
  242. InitDriver ()
  243. {
  244. UNICODE_STRING DriverName;
  245. NTSTATUS status;
  246. OBJECT_ATTRIBUTES ObjA;
  247. IO_STATUS_BLOCK IOSB;
  248. SYSTEM_BASIC_INFORMATION BasicInfo;
  249. PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION PPerfInfo;
  250. int i;
  251. //
  252. // Init Nt performance interface
  253. //
  254. NtQuerySystemInformation(
  255. SystemBasicInformation,
  256. &BasicInfo,
  257. sizeof(BasicInfo),
  258. NULL
  259. );
  260. NumberOfProcessors = BasicInfo.NumberOfProcessors;
  261. if (NumberOfProcessors > MAX_PROCESSORS) {
  262. return FALSE;
  263. }
  264. //
  265. // Open PStat driver
  266. //
  267. RtlInitUnicodeString(&DriverName, L"\\Device\\PStat");
  268. InitializeObjectAttributes(
  269. &ObjA,
  270. &DriverName,
  271. OBJ_CASE_INSENSITIVE,
  272. 0,
  273. 0 );
  274. status = NtOpenFile (
  275. &DriverHandle, // return handle
  276. SYNCHRONIZE | FILE_READ_DATA, // desired access
  277. &ObjA, // Object
  278. &IOSB, // io status block
  279. FILE_SHARE_READ | FILE_SHARE_WRITE, // share access
  280. FILE_SYNCHRONOUS_IO_ALERT // open options
  281. );
  282. return NT_SUCCESS(status) ? TRUE : FALSE;
  283. return TRUE;
  284. }
  285. VOID
  286. InitPossibleEventList()
  287. {
  288. UCHAR buffer[400];
  289. ULONG i, Count;
  290. NTSTATUS status;
  291. PEVENTID Event;
  292. IO_STATUS_BLOCK IOSB;
  293. //
  294. // Initialize possible counters
  295. //
  296. // determine how many events there are
  297. Event = (PEVENTID) buffer;
  298. Count = 0;
  299. do {
  300. *((PULONG) buffer) = Count;
  301. Count += 1;
  302. status = NtDeviceIoControlFile(
  303. DriverHandle,
  304. (HANDLE) NULL, // event
  305. (PIO_APC_ROUTINE) NULL,
  306. (PVOID) NULL,
  307. &IOSB,
  308. PSTAT_QUERY_EVENTS,
  309. buffer, // input buffer
  310. sizeof (buffer),
  311. NULL, // output buffer
  312. 0
  313. );
  314. } while (NT_SUCCESS(status));
  315. Counters = malloc(sizeof(*Counters) * Count);
  316. if (Counters == NULL) {
  317. printf ("Memory allocation failure initializing event list\n");
  318. exit(1);
  319. }
  320. Count -= 1;
  321. for (i=0; i < Count; i++) {
  322. *((PULONG) buffer) = i;
  323. NtDeviceIoControlFile(
  324. DriverHandle,
  325. (HANDLE) NULL, // event
  326. (PIO_APC_ROUTINE) NULL,
  327. (PVOID) NULL,
  328. &IOSB,
  329. PSTAT_QUERY_EVENTS,
  330. buffer, // input buffer
  331. sizeof (buffer),
  332. NULL, // output buffer
  333. 0
  334. );
  335. Counters[i].EventId = Event->EventId;
  336. Counters[i].ShortName = _strdup (Event->Buffer);
  337. Counters[i].PerfName = _strdup (Event->Buffer + Event->DescriptionOffset);
  338. }
  339. Counters[i].EventId = 0;
  340. Counters[i].ShortName = NULL;
  341. Counters[i].PerfName = NULL;
  342. }
  343. VOID LI2Str (PSZ s, ULONGLONG li)
  344. {
  345. if (li > 0xFFFFFFFF) {
  346. sprintf (s, "%08x:%08x", (ULONG) (li >> 32), (ULONG) li);
  347. } else {
  348. sprintf (s, " %08x", (ULONG) li);
  349. }
  350. }
  351. LONG FindShortName (PSZ name)
  352. {
  353. LONG i;
  354. for (i=0; Counters[i].ShortName; i++) {
  355. if (strcmp (Counters[i].ShortName, name) == 0) {
  356. return i;
  357. }
  358. }
  359. return -1;
  360. }
  361. VOID GetInternalStats (PVOID Buffer)
  362. {
  363. IO_STATUS_BLOCK IOSB;
  364. NtDeviceIoControlFile(
  365. DriverHandle,
  366. (HANDLE) NULL, // event
  367. (PIO_APC_ROUTINE) NULL,
  368. (PVOID) NULL,
  369. &IOSB,
  370. PSTAT_READ_STATS,
  371. Buffer, // input buffer
  372. INFSIZE,
  373. NULL, // output buffer
  374. 0
  375. );
  376. }
  377. VOID SetCounterEncodings (VOID)
  378. {
  379. IO_STATUS_BLOCK IOSB;
  380. NtDeviceIoControlFile(
  381. DriverHandle,
  382. (HANDLE) NULL, // event
  383. (PIO_APC_ROUTINE) NULL,
  384. (PVOID) NULL,
  385. &IOSB,
  386. PSTAT_SET_CESR,
  387. CounterEvent, // input buffer
  388. sizeof (CounterEvent),
  389. NULL, // output buffer
  390. 0
  391. );
  392. }
  393. BOOLEAN SetCounter (LONG CounterId, ULONG counter)
  394. {
  395. if (CounterId == -1) {
  396. CounterEvent[counter].Active = FALSE;
  397. return FALSE;
  398. }
  399. CounterEvent[counter].EventId = Counters[CounterId].EventId;
  400. CounterEvent[counter].AppReserved = (ULONG) CounterId;
  401. CounterEvent[counter].Active = TRUE;
  402. CounterEvent[counter].UserMode = TRUE;
  403. CounterEvent[counter].KernelMode = TRUE;
  404. return TRUE;
  405. }