Leaked source code of windows server 2003
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.

528 lines
13 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, ULONG, 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. // Make sure local buffers are NULL terminated
  73. //
  74. s1[sizeof(s1) - 1] = 0;
  75. s2[sizeof(s2) - 1] = 0;
  76. //
  77. // Initialize supported event list
  78. //
  79. InitPossibleEventList();
  80. if (!Counters) {
  81. printf ("No events to monitor\n");
  82. exit (1);
  83. }
  84. //
  85. // Check args
  86. //
  87. if (argc < 2) {
  88. printf (Usage);
  89. for (i=0; Counters[i].ShortName; i++) {
  90. printf (" %-20s\t%s\n", Counters[i].ShortName, Counters[i].PerfName);
  91. }
  92. exit (1);
  93. }
  94. pos = 1;
  95. Fail = FALSE;
  96. Delay = 0;
  97. DumpAll = FALSE;
  98. ProcessorBreakout = FALSE;
  99. ProcessorTotal = FALSE;
  100. while (pos < argc && argv[pos][0] == '-') {
  101. switch (argv[pos][1]) {
  102. case 't':
  103. ProcessorTotal = TRUE;
  104. break;
  105. case 'p':
  106. ProcessorBreakout = TRUE;
  107. break;
  108. default:
  109. printf ("pdump: unkown switch '%c'\n", argv[pos][1]);
  110. Fail = TRUE;
  111. break;
  112. }
  113. pos += 1;
  114. }
  115. if (pos < argc) {
  116. Delay = atoi (argv[pos]) * 1000;
  117. pos += 1;
  118. }
  119. if (Fail /* || Delay == 0 */) {
  120. printf (Usage);
  121. exit (1);
  122. }
  123. //
  124. // Raise to highest priority
  125. //
  126. if (!SetPriorityClass(GetCurrentProcess(),REALTIME_PRIORITY_CLASS)) {
  127. printf("Failed to raise to realtime priority\n");
  128. }
  129. SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
  130. //
  131. // Loop for every pentium count desired
  132. //
  133. if (pos >= argc) {
  134. pos = 0;
  135. DumpAll = TRUE;
  136. }
  137. printf (" %-30s %17s %17s\n", "", "Cycles", "Count");
  138. for (; ;) {
  139. //
  140. // Set MAX_EVENTS
  141. //
  142. CounterSet = FALSE;
  143. i = 0;
  144. while (i < MAX_EVENTS) {
  145. cnttype = -1;
  146. if (DumpAll) {
  147. //
  148. // Dump all - get next counter
  149. //
  150. if (Counters[pos].ShortName) {
  151. cnttype = pos;
  152. pos++;
  153. }
  154. } else {
  155. //
  156. // process command line args
  157. //
  158. if (pos < argc) {
  159. cnttype = FindShortName (argv[pos]);
  160. if (cnttype == -1) {
  161. printf ("Counter '%s' not found\n", argv[pos]);
  162. pos++;
  163. continue;
  164. }
  165. pos++;
  166. }
  167. }
  168. CounterSet |= SetCounter (cnttype, i);
  169. i++;
  170. }
  171. if (!CounterSet) {
  172. // done
  173. exit (1);
  174. }
  175. //
  176. // Call driver and perform the setting
  177. //
  178. SetCounterEncodings ();
  179. if ( Delay == 0 ) {
  180. printf( "Counters set\n" );
  181. // done
  182. exit(1);
  183. }
  184. //
  185. // Snap begining & ending counts
  186. //
  187. Sleep (50); // slight settle
  188. GetInternalStats (BufferStart); // snap current values
  189. Sleep (Delay); // sleep desired time
  190. GetInternalStats (BufferEnd); // snap ending values
  191. //
  192. // Calculate each counter and print it
  193. //
  194. for (i=0; i < MAX_EVENTS; i++) {
  195. if (!CounterEvent[i].Active) {
  196. continue;
  197. }
  198. len = *((PULONG) BufferStart);
  199. if (ProcessorBreakout) {
  200. //
  201. // Print stat for each processor
  202. //
  203. ProcStart = (pPSTATS) ((PUCHAR) BufferStart + sizeof(ULONG));
  204. ProcEnd = (pPSTATS) ((PUCHAR) BufferEnd + sizeof(ULONG));
  205. for (j=0; j < NumberOfProcessors; j++) {
  206. ETime = ProcEnd->TSC - ProcStart->TSC;
  207. ECount = ProcEnd->Counters[i] - ProcStart->Counters[i];
  208. ProcStart = (pPSTATS) (((PUCHAR) ProcStart) + len);
  209. ProcEnd = (pPSTATS) (((PUCHAR) ProcEnd) + len);
  210. LI2Str (s1, sizeof(s1) - 1, ETime);
  211. LI2Str (s2, sizeof(s2) - 1, ECount);
  212. printf (" P%d %-30s %s %s\n",
  213. j,
  214. Counters[CounterEvent[i].AppReserved].PerfName,
  215. s1, s2
  216. );
  217. }
  218. }
  219. if (!ProcessorBreakout || ProcessorTotal) {
  220. //
  221. // Sum processor's and print it
  222. //
  223. ProcStart = (pPSTATS) ((PUCHAR) BufferStart + sizeof(ULONG));
  224. ProcEnd = (pPSTATS) ((PUCHAR) BufferEnd + sizeof(ULONG));
  225. ETime = 0;
  226. ECount = 0;
  227. for (j=0; j < NumberOfProcessors; j++) {
  228. ETime = ETime + ProcEnd->TSC;
  229. ETime = ETime - ProcStart->TSC;
  230. ECount = ECount + ProcEnd->Counters[i];
  231. ECount = ECount - ProcStart->Counters[i];
  232. ProcStart = (pPSTATS) (((PUCHAR) ProcStart) + len);
  233. ProcEnd = (pPSTATS) (((PUCHAR) ProcEnd) + len);
  234. }
  235. LI2Str (s1, sizeof(s1) - 1, ETime);
  236. LI2Str (s2, sizeof(s2) - 1, ECount);
  237. printf (" %-30s %s %s\n",
  238. Counters[CounterEvent[i].AppReserved].PerfName,
  239. s1, s2
  240. );
  241. }
  242. }
  243. }
  244. return 0;
  245. }
  246. BOOLEAN
  247. InitDriver ()
  248. {
  249. UNICODE_STRING DriverName;
  250. NTSTATUS status;
  251. OBJECT_ATTRIBUTES ObjA;
  252. IO_STATUS_BLOCK IOSB;
  253. SYSTEM_BASIC_INFORMATION BasicInfo;
  254. PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION PPerfInfo;
  255. int i;
  256. //
  257. // Init Nt performance interface
  258. //
  259. NtQuerySystemInformation(
  260. SystemBasicInformation,
  261. &BasicInfo,
  262. sizeof(BasicInfo),
  263. NULL
  264. );
  265. NumberOfProcessors = BasicInfo.NumberOfProcessors;
  266. if (NumberOfProcessors > MAX_PROCESSORS) {
  267. return FALSE;
  268. }
  269. //
  270. // Open PStat driver
  271. //
  272. RtlInitUnicodeString(&DriverName, L"\\Device\\PStat");
  273. InitializeObjectAttributes(
  274. &ObjA,
  275. &DriverName,
  276. OBJ_CASE_INSENSITIVE,
  277. 0,
  278. 0 );
  279. status = NtOpenFile (
  280. &DriverHandle, // return handle
  281. SYNCHRONIZE | FILE_READ_DATA, // desired access
  282. &ObjA, // Object
  283. &IOSB, // io status block
  284. FILE_SHARE_READ | FILE_SHARE_WRITE, // share access
  285. FILE_SYNCHRONOUS_IO_ALERT // open options
  286. );
  287. return NT_SUCCESS(status) ? TRUE : FALSE;
  288. return TRUE;
  289. }
  290. VOID
  291. InitPossibleEventList()
  292. {
  293. UCHAR buffer[400];
  294. ULONG i, Count;
  295. NTSTATUS status;
  296. PEVENTID Event;
  297. IO_STATUS_BLOCK IOSB;
  298. //
  299. // Initialize possible counters
  300. //
  301. // determine how many events there are
  302. Event = (PEVENTID) buffer;
  303. Count = 0;
  304. do {
  305. *((PULONG) buffer) = Count;
  306. Count += 1;
  307. status = NtDeviceIoControlFile(
  308. DriverHandle,
  309. (HANDLE) NULL, // event
  310. (PIO_APC_ROUTINE) NULL,
  311. (PVOID) NULL,
  312. &IOSB,
  313. PSTAT_QUERY_EVENTS,
  314. buffer, // input buffer
  315. sizeof (buffer),
  316. NULL, // output buffer
  317. 0
  318. );
  319. } while (NT_SUCCESS(status));
  320. Counters = malloc(sizeof(*Counters) * Count);
  321. if (Counters == NULL) {
  322. printf ("Memory allocation failure initializing event list\n");
  323. exit(1);
  324. }
  325. Count -= 1;
  326. for (i=0; i < Count; i++) {
  327. *((PULONG) buffer) = i;
  328. NtDeviceIoControlFile(
  329. DriverHandle,
  330. (HANDLE) NULL, // event
  331. (PIO_APC_ROUTINE) NULL,
  332. (PVOID) NULL,
  333. &IOSB,
  334. PSTAT_QUERY_EVENTS,
  335. buffer, // input buffer
  336. sizeof (buffer),
  337. NULL, // output buffer
  338. 0
  339. );
  340. Counters[i].EventId = Event->EventId;
  341. Counters[i].ShortName = _strdup (Event->Buffer);
  342. Counters[i].PerfName = _strdup (Event->Buffer + Event->DescriptionOffset);
  343. }
  344. Counters[i].EventId = 0;
  345. Counters[i].ShortName = NULL;
  346. Counters[i].PerfName = NULL;
  347. }
  348. VOID LI2Str (PSZ s, ULONG Size, ULONGLONG li)
  349. {
  350. //
  351. // BogdanA - 02/22/2002: added another parameter (the size of s) so we
  352. // do not overflow s. s is guaranteed to be NULL terminated, so
  353. // we will not worry about it.
  354. //
  355. if (li > 0xFFFFFFFF) {
  356. _snprintf (s, Size, "%08x:%08x", (ULONG) (li >> 32), (ULONG) li);
  357. } else {
  358. _snprintf (s, Size, " %08x", (ULONG) li);
  359. }
  360. }
  361. LONG FindShortName (PSZ name)
  362. {
  363. LONG i;
  364. for (i=0; Counters[i].ShortName; i++) {
  365. if (strcmp (Counters[i].ShortName, name) == 0) {
  366. return i;
  367. }
  368. }
  369. return -1;
  370. }
  371. VOID GetInternalStats (PVOID Buffer)
  372. {
  373. IO_STATUS_BLOCK IOSB;
  374. NtDeviceIoControlFile(
  375. DriverHandle,
  376. (HANDLE) NULL, // event
  377. (PIO_APC_ROUTINE) NULL,
  378. (PVOID) NULL,
  379. &IOSB,
  380. PSTAT_READ_STATS,
  381. Buffer, // input buffer
  382. INFSIZE,
  383. NULL, // output buffer
  384. 0
  385. );
  386. }
  387. VOID SetCounterEncodings (VOID)
  388. {
  389. IO_STATUS_BLOCK IOSB;
  390. NtDeviceIoControlFile(
  391. DriverHandle,
  392. (HANDLE) NULL, // event
  393. (PIO_APC_ROUTINE) NULL,
  394. (PVOID) NULL,
  395. &IOSB,
  396. PSTAT_SET_CESR,
  397. CounterEvent, // input buffer
  398. sizeof (CounterEvent),
  399. NULL, // output buffer
  400. 0
  401. );
  402. }
  403. BOOLEAN SetCounter (LONG CounterId, ULONG counter)
  404. {
  405. if (CounterId == -1) {
  406. CounterEvent[counter].Active = FALSE;
  407. return FALSE;
  408. }
  409. CounterEvent[counter].EventId = Counters[CounterId].EventId;
  410. CounterEvent[counter].AppReserved = (ULONG) CounterId;
  411. CounterEvent[counter].Active = TRUE;
  412. CounterEvent[counter].UserMode = TRUE;
  413. CounterEvent[counter].KernelMode = TRUE;
  414. return TRUE;
  415. }