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.

500 lines
9.7 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. CalcPerf.c
  5. Abstract:
  6. calculate perfoemance statistics
  7. Author:
  8. Environment:
  9. Win32
  10. Revision History:
  11. 10-20-91 Initial version
  12. --*/
  13. #include <nt.h>
  14. #include <ntrtl.h>
  15. #include <nturtl.h>
  16. #include <windows.h>
  17. #include <assert.h>
  18. #include "calcperf.h"
  19. #include "..\pstat.h"
  20. //SYSTEM_PERFORMANCE_INFORMATION PerfInfo;
  21. //SYSTEM_PERFORMANCE_INFORMATION PreviousPerfInfo;
  22. #define INFSIZE 60000
  23. HANDLE DriverHandle;
  24. ULONG NumberOfProcessors;
  25. ULONG Buffer[INFSIZE/4];
  26. extern ULONG UseGlobalMax, GlobalMax;
  27. ULONG
  28. InitPerfInfo()
  29. /*++
  30. Routine Description:
  31. Initialize data for perf measurements
  32. Arguments:
  33. None
  34. Return Value:
  35. Number of system processors (0 if error)
  36. Revision History:
  37. 10-21-91 Initial code
  38. --*/
  39. {
  40. UNICODE_STRING DriverName;
  41. NTSTATUS status;
  42. OBJECT_ATTRIBUTES ObjA;
  43. IO_STATUS_BLOCK IOSB;
  44. SYSTEM_BASIC_INFORMATION BasicInfo;
  45. PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION PPerfInfo;
  46. int i;
  47. //
  48. // Init Nt performance interface
  49. //
  50. NtQuerySystemInformation(
  51. SystemBasicInformation,
  52. &BasicInfo,
  53. sizeof(BasicInfo),
  54. NULL
  55. );
  56. NumberOfProcessors = BasicInfo.NumberOfProcessors;
  57. if (NumberOfProcessors > MAX_PROCESSORS) {
  58. return(0);
  59. }
  60. //
  61. // Open P5Stat driver
  62. //
  63. RtlInitUnicodeString(&DriverName, L"\\Device\\PStat");
  64. InitializeObjectAttributes(
  65. &ObjA,
  66. &DriverName,
  67. OBJ_CASE_INSENSITIVE,
  68. 0,
  69. 0 );
  70. status = NtOpenFile (
  71. &DriverHandle, // return handle
  72. SYNCHRONIZE | FILE_READ_DATA, // desired access
  73. &ObjA, // Object
  74. &IOSB, // io status block
  75. FILE_SHARE_READ | FILE_SHARE_WRITE, // share access
  76. FILE_SYNCHRONOUS_IO_ALERT // open options
  77. );
  78. if (!NT_SUCCESS(status)) {
  79. return 0;
  80. }
  81. InitPossibleEventList();
  82. return(NumberOfProcessors);
  83. }
  84. BOOL
  85. CalcPerf(
  86. PDISPLAY_ITEM pPerf1
  87. )
  88. /*++
  89. Routine Description:
  90. calculate and return %cpu time and time periods
  91. Arguments:
  92. None
  93. Return Value:
  94. Revision History:
  95. 10-21-91 Initial code
  96. --*/
  97. {
  98. ULONG i;
  99. ULONG TotalDataPoint;
  100. ULONG OldGlobalMax;
  101. PDISPLAY_ITEM pPerf;
  102. //
  103. // get system performance info
  104. //
  105. OldGlobalMax = GlobalMax;
  106. GlobalMax = 0;
  107. UpdateInternalStats();
  108. for (pPerf = pPerf1; pPerf; pPerf = pPerf->Next) {
  109. TotalDataPoint = 0;
  110. pPerf->SnapData (pPerf);
  111. if (pPerf->AutoTotal) {
  112. //
  113. // Automatically calc system total by summing each processor
  114. //
  115. switch (pPerf->DisplayMode) {
  116. case DISPLAY_MODE_TOTAL:
  117. case DISPLAY_MODE_BREAKDOWN:
  118. default:
  119. for (i=0; i < NumberOfProcessors; i++) {
  120. TotalDataPoint += pPerf->CurrentDataPoint[i + 1];
  121. UpdatePerfInfo1 (
  122. pPerf->DataList[i + 1],
  123. pPerf->CurrentDataPoint[i + 1]
  124. );
  125. }
  126. pPerf->ChangeScale = UpdatePerfInfo (
  127. pPerf->DataList[0],
  128. TotalDataPoint,
  129. &pPerf->Max
  130. );
  131. break;
  132. case DISPLAY_MODE_PER_PROCESSOR:
  133. for (i=0; i < NumberOfProcessors; i++) {
  134. TotalDataPoint += pPerf->CurrentDataPoint[i + 1];
  135. pPerf->ChangeScale = UpdatePerfInfo (
  136. pPerf->DataList[i + 1],
  137. pPerf->CurrentDataPoint[i + 1],
  138. &pPerf->Max
  139. );
  140. }
  141. UpdatePerfInfo1 (pPerf->DataList[0], TotalDataPoint);
  142. break;
  143. }
  144. } else {
  145. for (i=0; i < NumberOfProcessors+1; i++) {
  146. pPerf->ChangeScale = UpdatePerfInfo (
  147. pPerf->DataList[i],
  148. pPerf->CurrentDataPoint[i],
  149. &pPerf->Max
  150. );
  151. }
  152. }
  153. }
  154. if (UseGlobalMax && OldGlobalMax != GlobalMax) {
  155. for (pPerf = pPerf1; pPerf; pPerf = pPerf->Next) {
  156. pPerf->ChangeScale = TRUE;
  157. }
  158. }
  159. return(TRUE);
  160. }
  161. VOID
  162. UpdateInternalStats(VOID)
  163. {
  164. IO_STATUS_BLOCK IOSB;
  165. NtDeviceIoControlFile(
  166. DriverHandle,
  167. (HANDLE) NULL, // event
  168. (PIO_APC_ROUTINE) NULL,
  169. (PVOID) NULL,
  170. &IOSB,
  171. PSTAT_READ_STATS,
  172. Buffer, // input buffer
  173. INFSIZE,
  174. NULL, // output buffer
  175. 0
  176. );
  177. }
  178. VOID
  179. SetCounterEvents (PVOID Events, ULONG length)
  180. {
  181. IO_STATUS_BLOCK IOSB;
  182. NtDeviceIoControlFile(
  183. DriverHandle,
  184. (HANDLE) NULL, // event
  185. (PIO_APC_ROUTINE) NULL,
  186. (PVOID) NULL,
  187. &IOSB,
  188. PSTAT_SET_CESR,
  189. Events, // input buffer
  190. length,
  191. NULL, // output buffer
  192. 0
  193. );
  194. }
  195. VOID
  196. SnapNull (
  197. IN OUT PDISPLAY_ITEM pPerf
  198. )
  199. {
  200. ULONG i;
  201. for (i=0; i < NumberOfProcessors; i++) {
  202. pPerf->CurrentDataPoint[i + 1] = 0;
  203. }
  204. }
  205. VOID
  206. SnapInterrupts (
  207. IN OUT PDISPLAY_ITEM pPerf
  208. )
  209. {
  210. SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION ProcessorInfo[MAX_PROCESSORS];
  211. ULONG i, l;
  212. NtQuerySystemInformation(
  213. SystemProcessorPerformanceInformation,
  214. ProcessorInfo,
  215. sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * MAX_PROCESSORS,
  216. NULL
  217. );
  218. for (i=0; i < NumberOfProcessors; i++) {
  219. l = ProcessorInfo[i].InterruptCount - pPerf->LastAccumulator[i+1];
  220. pPerf->LastAccumulator[i+1] = ProcessorInfo[i].InterruptCount;
  221. pPerf->CurrentDataPoint[i+1] = l / DELAY_SECONDS;
  222. }
  223. }
  224. VOID
  225. SnapPrivateInfo (
  226. IN OUT PDISPLAY_ITEM pPerf
  227. )
  228. {
  229. ULONG i, j, l, len;
  230. PULONG PrivateStat;
  231. len = *((PULONG) Buffer);
  232. PrivateStat = (PULONG) ((PUCHAR) Buffer + sizeof(ULONG) + pPerf->SnapParam1);
  233. // accumlating data, take delta
  234. for (i=0; i < NumberOfProcessors; i++) {
  235. if (pPerf->Mega) {
  236. PULONGLONG li = (PULONGLONG) PrivateStat;
  237. *li = *li >> 10;
  238. }
  239. j = *PrivateStat / DELAY_SECONDS;
  240. l = j - pPerf->LastAccumulator[i+1];
  241. pPerf->LastAccumulator[i+1] = j;
  242. if (l > 0) {
  243. pPerf->CurrentDataPoint[i+1] = l;
  244. } else {
  245. // item wrapped
  246. pPerf->CurrentDataPoint[i+1] = 0 - l;
  247. }
  248. PrivateStat = (PULONG)((PUCHAR)PrivateStat + len);
  249. }
  250. }
  251. BOOL
  252. UpdatePerfInfo(
  253. PULONG DataPointer,
  254. ULONG NewDataValue,
  255. PULONG OldMaxValue
  256. )
  257. /*++
  258. Routine Description:
  259. Shift array of DATA_LIST_LENGTH USORTS and add the new value to the
  260. start of list
  261. Arguments:
  262. DataPointer - Pointer to the start of a DATA_LIST_LENGTH array
  263. NewDataValue - Data element to be added
  264. OldMaxValue - Scale value
  265. Return Value:
  266. TRUE is MaxValue must be increased or decreased
  267. Revision History:
  268. 10-21-91 Initial code
  269. --*/
  270. {
  271. ULONG Index;
  272. ULONG ScanMax;
  273. //
  274. // Shift DataArray while keeping track of the max value
  275. //
  276. //
  277. // Set temp max to 100 to init a minimum maximum
  278. //
  279. ScanMax = 100;
  280. for (Index=DATA_LIST_LENGTH-1;Index>=1;Index--) {
  281. DataPointer[Index] = DataPointer[Index-1];
  282. if (DataPointer[Index] > ScanMax) {
  283. ScanMax = DataPointer[Index];
  284. }
  285. }
  286. //
  287. // add and check first value
  288. //
  289. DataPointer[0] = NewDataValue;
  290. if (NewDataValue > ScanMax) {
  291. ScanMax = NewDataValue;
  292. }
  293. //
  294. // If Max values changed then undate the new max
  295. // value and return TRUE.
  296. //
  297. if (ScanMax > GlobalMax) {
  298. GlobalMax = ScanMax;
  299. }
  300. if (ScanMax != *OldMaxValue) {
  301. if (ScanMax < *OldMaxValue &&
  302. *OldMaxValue - ScanMax <= *OldMaxValue / 10) {
  303. //
  304. // New ScanMax is smaller, but only by a tiny amount
  305. //
  306. return (FALSE);
  307. }
  308. *OldMaxValue = ScanMax;
  309. return(TRUE);
  310. }
  311. return(FALSE);
  312. }
  313. VOID
  314. UpdatePerfInfo1(
  315. PULONG DataPointer,
  316. ULONG NewDataValue
  317. )
  318. /*++
  319. Routine Description:
  320. Shift array of DATA_LIST_LENGTH USORTS and add the new value to the
  321. start of list
  322. Arguments:
  323. DataPointer - Pointer to the start of a DATA_LIST_LENGTH array
  324. NewDataValue - Data element to be added
  325. OldMaxValue - Scale value
  326. Return Value:
  327. TRUE is MaxValue must be increased or decreased
  328. Revision History:
  329. 10-21-91 Initial code
  330. --*/
  331. {
  332. ULONG Index;
  333. ULONG ScanMax;
  334. //
  335. // Shift DataArray while keeping track of the max value
  336. //
  337. //
  338. // Set temp max to 100 to init a minimum maximum
  339. //
  340. ScanMax = 100;
  341. for (Index=DATA_LIST_LENGTH-1;Index>=1;Index--) {
  342. DataPointer[Index] = DataPointer[Index-1];
  343. }
  344. //
  345. // add and check first value
  346. //
  347. DataPointer[0] = NewDataValue;
  348. return ;
  349. }
  350.