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.

509 lines
10 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. DriverHandle = NULL;
  80. return 0;
  81. }
  82. InitPossibleEventList();
  83. return(NumberOfProcessors);
  84. }
  85. BOOL
  86. CalcPerf(
  87. PDISPLAY_ITEM pPerf1
  88. )
  89. /*++
  90. Routine Description:
  91. calculate and return %cpu time and time periods
  92. Arguments:
  93. None
  94. Return Value:
  95. Revision History:
  96. 10-21-91 Initial code
  97. --*/
  98. {
  99. ULONG i;
  100. ULONG TotalDataPoint;
  101. ULONG OldGlobalMax;
  102. PDISPLAY_ITEM pPerf;
  103. //
  104. // get system performance info
  105. //
  106. OldGlobalMax = GlobalMax;
  107. GlobalMax = 0;
  108. UpdateInternalStats();
  109. for (pPerf = pPerf1; pPerf; pPerf = pPerf->Next) {
  110. TotalDataPoint = 0;
  111. pPerf->SnapData (pPerf);
  112. if (pPerf->AutoTotal) {
  113. //
  114. // Automatically calc system total by summing each processor
  115. //
  116. switch (pPerf->DisplayMode) {
  117. case DISPLAY_MODE_TOTAL:
  118. case DISPLAY_MODE_BREAKDOWN:
  119. default:
  120. for (i=0; i < NumberOfProcessors; i++) {
  121. TotalDataPoint += pPerf->CurrentDataPoint[i + 1];
  122. UpdatePerfInfo1 (
  123. pPerf->DataList[i + 1],
  124. pPerf->CurrentDataPoint[i + 1]
  125. );
  126. }
  127. pPerf->ChangeScale = UpdatePerfInfo (
  128. pPerf->DataList[0],
  129. TotalDataPoint,
  130. &pPerf->Max
  131. );
  132. break;
  133. case DISPLAY_MODE_PER_PROCESSOR:
  134. for (i=0; i < NumberOfProcessors; i++) {
  135. TotalDataPoint += pPerf->CurrentDataPoint[i + 1];
  136. pPerf->ChangeScale = UpdatePerfInfo (
  137. pPerf->DataList[i + 1],
  138. pPerf->CurrentDataPoint[i + 1],
  139. &pPerf->Max
  140. );
  141. }
  142. UpdatePerfInfo1 (pPerf->DataList[0], TotalDataPoint);
  143. break;
  144. }
  145. } else {
  146. for (i=0; i < NumberOfProcessors+1; i++) {
  147. pPerf->ChangeScale = UpdatePerfInfo (
  148. pPerf->DataList[i],
  149. pPerf->CurrentDataPoint[i],
  150. &pPerf->Max
  151. );
  152. }
  153. }
  154. }
  155. if (UseGlobalMax && OldGlobalMax != GlobalMax) {
  156. for (pPerf = pPerf1; pPerf; pPerf = pPerf->Next) {
  157. pPerf->ChangeScale = TRUE;
  158. }
  159. }
  160. return(TRUE);
  161. }
  162. VOID
  163. UpdateInternalStats(VOID)
  164. {
  165. IO_STATUS_BLOCK IOSB;
  166. if (! DriverHandle) {
  167. return;
  168. }
  169. NtDeviceIoControlFile(
  170. DriverHandle,
  171. (HANDLE) NULL, // event
  172. (PIO_APC_ROUTINE) NULL,
  173. (PVOID) NULL,
  174. &IOSB,
  175. PSTAT_READ_STATS,
  176. Buffer, // input buffer
  177. INFSIZE,
  178. NULL, // output buffer
  179. 0
  180. );
  181. }
  182. VOID
  183. SetCounterEvents (PVOID Events, ULONG length)
  184. {
  185. IO_STATUS_BLOCK IOSB;
  186. if (! DriverHandle) {
  187. return;
  188. }
  189. NtDeviceIoControlFile(
  190. DriverHandle,
  191. (HANDLE) NULL, // event
  192. (PIO_APC_ROUTINE) NULL,
  193. (PVOID) NULL,
  194. &IOSB,
  195. PSTAT_SET_CESR,
  196. Events, // input buffer
  197. length,
  198. NULL, // output buffer
  199. 0
  200. );
  201. }
  202. VOID
  203. SnapNull (
  204. IN OUT PDISPLAY_ITEM pPerf
  205. )
  206. {
  207. ULONG i;
  208. for (i=0; i < NumberOfProcessors; i++) {
  209. pPerf->CurrentDataPoint[i + 1] = 0;
  210. }
  211. }
  212. VOID
  213. SnapInterrupts (
  214. IN OUT PDISPLAY_ITEM pPerf
  215. )
  216. {
  217. SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION ProcessorInfo[MAX_PROCESSORS];
  218. ULONG i, l;
  219. NtQuerySystemInformation(
  220. SystemProcessorPerformanceInformation,
  221. ProcessorInfo,
  222. sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * MAX_PROCESSORS,
  223. NULL
  224. );
  225. for (i=0; i < NumberOfProcessors; i++) {
  226. l = ProcessorInfo[i].InterruptCount - pPerf->LastAccumulator[i+1];
  227. pPerf->LastAccumulator[i+1] = ProcessorInfo[i].InterruptCount;
  228. pPerf->CurrentDataPoint[i+1] = l / DELAY_SECONDS;
  229. }
  230. }
  231. VOID
  232. SnapPrivateInfo (
  233. IN OUT PDISPLAY_ITEM pPerf
  234. )
  235. {
  236. ULONG i, j, l, len;
  237. PULONG PrivateStat;
  238. len = *((PULONG) Buffer);
  239. PrivateStat = (PULONG) ((PUCHAR) Buffer + sizeof(ULONG) + pPerf->SnapParam1);
  240. // accumlating data, take delta
  241. for (i=0; i < NumberOfProcessors; i++) {
  242. if (pPerf->Mega) {
  243. PULONGLONG li = (PULONGLONG) PrivateStat;
  244. *li = *li >> 10;
  245. }
  246. j = *PrivateStat / DELAY_SECONDS;
  247. l = j - pPerf->LastAccumulator[i+1];
  248. pPerf->LastAccumulator[i+1] = j;
  249. if (l > 0) {
  250. pPerf->CurrentDataPoint[i+1] = l;
  251. } else {
  252. // item wrapped
  253. pPerf->CurrentDataPoint[i+1] = 0 - l;
  254. }
  255. PrivateStat = (PULONG)((PUCHAR)PrivateStat + len);
  256. }
  257. }
  258. BOOL
  259. UpdatePerfInfo(
  260. PULONG DataPointer,
  261. ULONG NewDataValue,
  262. PULONG OldMaxValue
  263. )
  264. /*++
  265. Routine Description:
  266. Shift array of DATA_LIST_LENGTH USORTS and add the new value to the
  267. start of list
  268. Arguments:
  269. DataPointer - Pointer to the start of a DATA_LIST_LENGTH array
  270. NewDataValue - Data element to be added
  271. OldMaxValue - Scale value
  272. Return Value:
  273. TRUE is MaxValue must be increased or decreased
  274. Revision History:
  275. 10-21-91 Initial code
  276. --*/
  277. {
  278. ULONG Index;
  279. ULONG ScanMax;
  280. //
  281. // Shift DataArray while keeping track of the max value
  282. //
  283. //
  284. // Set temp max to 100 to init a minimum maximum
  285. //
  286. ScanMax = 100;
  287. for (Index=DATA_LIST_LENGTH-1;Index>=1;Index--) {
  288. DataPointer[Index] = DataPointer[Index-1];
  289. if (DataPointer[Index] > ScanMax) {
  290. ScanMax = DataPointer[Index];
  291. }
  292. }
  293. //
  294. // add and check first value
  295. //
  296. DataPointer[0] = NewDataValue;
  297. if (NewDataValue > ScanMax) {
  298. ScanMax = NewDataValue;
  299. }
  300. //
  301. // If Max values changed then undate the new max
  302. // value and return TRUE.
  303. //
  304. if (ScanMax > GlobalMax) {
  305. GlobalMax = ScanMax;
  306. }
  307. if (ScanMax != *OldMaxValue) {
  308. if (ScanMax < *OldMaxValue &&
  309. *OldMaxValue - ScanMax <= *OldMaxValue / 10) {
  310. //
  311. // New ScanMax is smaller, but only by a tiny amount
  312. //
  313. return (FALSE);
  314. }
  315. *OldMaxValue = ScanMax;
  316. return(TRUE);
  317. }
  318. return(FALSE);
  319. }
  320. VOID
  321. UpdatePerfInfo1(
  322. PULONG DataPointer,
  323. ULONG NewDataValue
  324. )
  325. /*++
  326. Routine Description:
  327. Shift array of DATA_LIST_LENGTH USORTS and add the new value to the
  328. start of list
  329. Arguments:
  330. DataPointer - Pointer to the start of a DATA_LIST_LENGTH array
  331. NewDataValue - Data element to be added
  332. OldMaxValue - Scale value
  333. Return Value:
  334. TRUE is MaxValue must be increased or decreased
  335. Revision History:
  336. 10-21-91 Initial code
  337. --*/
  338. {
  339. ULONG Index;
  340. ULONG ScanMax;
  341. //
  342. // Shift DataArray while keeping track of the max value
  343. //
  344. //
  345. // Set temp max to 100 to init a minimum maximum
  346. //
  347. ScanMax = 100;
  348. for (Index=DATA_LIST_LENGTH-1;Index>=1;Index--) {
  349. DataPointer[Index] = DataPointer[Index-1];
  350. }
  351. //
  352. // add and check first value
  353. //
  354. DataPointer[0] = NewDataValue;
  355. return ;
  356. }
  357.