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.

354 lines
8.6 KiB

  1. /*++
  2. Copyright (c) 1991 - 2002 Microsoft Corporation
  3. Module Name:
  4. ## ## ##### ### ## ###### ## ## #### ##### #####
  5. ## ## ## ### ## ## ## ## ## # ## ## ## ##
  6. ## ## ## ## ## ## ## ## ## ## ## ## ## ##
  7. ####### ##### ## ## ## ## ####### ## ## ## ## ##
  8. ## ## ## ####### ## ## ## ## ## ##### #####
  9. ## ## ## ## ## ## ## ## ## ## ## # ## ##
  10. ## ## ##### ## ## ##### ## ## ## ## #### ## ##
  11. Abstract:
  12. This module implements the system health monitoring
  13. functions for the watchdog driver.
  14. Author:
  15. Wesley Witt (wesw) 23-Jan-2002
  16. Environment:
  17. Kernel mode only.
  18. Notes:
  19. --*/
  20. #include "internal.h"
  21. NTSTATUS
  22. WdInitializeSystemHealth(
  23. PSYSTEM_HEALTH_DATA Health
  24. )
  25. /*++
  26. Routine Description:
  27. This function is called to initialize the system
  28. health monitoring functions in the watchdog driver.
  29. Arguments:
  30. Health - Pointer to a health data structure that is used
  31. for input and output of data to the health monitoring.
  32. Return Value:
  33. If we successfully create a device object, STATUS_SUCCESS is
  34. returned. Otherwise, return the appropriate error code.
  35. Notes:
  36. --*/
  37. {
  38. NTSTATUS Status = STATUS_SUCCESS;
  39. SYSTEM_BASIC_INFORMATION si;
  40. RtlZeroMemory( Health, sizeof(SYSTEM_HEALTH_DATA) );
  41. Status = ZwQuerySystemInformation(
  42. SystemBasicInformation,
  43. &si,
  44. sizeof(SYSTEM_BASIC_INFORMATION),
  45. NULL
  46. );
  47. if (!NT_SUCCESS(Status)) {
  48. return Status;
  49. }
  50. Health->CpuCount = si.NumberOfProcessors;
  51. Health->ProcInfoSize = sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * Health->CpuCount;
  52. Health->ProcInfoPrev = (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) ExAllocatePool( NonPagedPool, Health->ProcInfoSize );
  53. if (Health->ProcInfoPrev == NULL) {
  54. return STATUS_NO_MEMORY;
  55. }
  56. Health->ProcInfo = (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) ExAllocatePool( NonPagedPool, Health->ProcInfoSize );
  57. if (Health->ProcInfo == NULL) {
  58. return STATUS_NO_MEMORY;
  59. }
  60. RtlZeroMemory( Health->ProcInfo, Health->ProcInfoSize );
  61. RtlZeroMemory( Health->ProcInfoPrev, Health->ProcInfoSize );
  62. Health->HealthyCpuRatio = 10;
  63. return STATUS_SUCCESS;
  64. }
  65. LONG
  66. GetPercentage(
  67. LARGE_INTEGER part,
  68. LARGE_INTEGER total
  69. )
  70. /*++
  71. Routine Description:
  72. This function computes a percentage number.
  73. Arguments:
  74. Health - Pointer to a health data structure that is used
  75. for input and output of data to the health monitoring.
  76. Return Value:
  77. If we successfully create a device object, STATUS_SUCCESS is
  78. returned. Otherwise, return the appropriate error code.
  79. Notes:
  80. --*/
  81. {
  82. if (total.HighPart == 0 && total.LowPart == 0) {
  83. return 100;
  84. }
  85. ULONG ul;
  86. LARGE_INTEGER t1, t2, t3;
  87. if (total.HighPart == 0) {
  88. t1 = RtlEnlargedIntegerMultiply(part.LowPart, 100);
  89. t2 = RtlExtendedLargeIntegerDivide(t1, total.LowPart, &ul);
  90. } else {
  91. t1 = RtlExtendedLargeIntegerDivide(total, 100, &ul);
  92. t2 = RtlLargeIntegerDivide(part, t1, &t3);
  93. }
  94. return t2.LowPart;
  95. }
  96. NTSTATUS
  97. WdCollectContextSwitchData(
  98. PSYSTEM_HEALTH_DATA Health
  99. )
  100. /*++
  101. Routine Description:
  102. This function collects context switch data and
  103. computes an accumulation for use in determining
  104. system health.
  105. Arguments:
  106. Health - Pointer to a health data structure that is used
  107. for input and output of data to the health monitoring.
  108. Return Value:
  109. If we successfully create a device object, STATUS_SUCCESS is
  110. returned. Otherwise, return the appropriate error code.
  111. Notes:
  112. --*/
  113. {
  114. NTSTATUS Status = STATUS_SUCCESS;
  115. SYSTEM_CONTEXT_SWITCH_INFORMATION ContextSwitch;
  116. LARGE_INTEGER TickCountCurrent;
  117. LONGLONG TickCountElapsed = 0;
  118. Status = ZwQuerySystemInformation(
  119. SystemContextSwitchInformation,
  120. &ContextSwitch,
  121. sizeof(SYSTEM_CONTEXT_SWITCH_INFORMATION),
  122. NULL
  123. );
  124. if (!NT_SUCCESS(Status)) {
  125. return Status;
  126. }
  127. KeQueryTickCount( &TickCountCurrent );
  128. TickCountElapsed = TickCountCurrent.QuadPart - Health->TickCountPrevious;
  129. if (TickCountElapsed){
  130. if ((ContextSwitch.ContextSwitches > Health->ContextSwitchesPrevious) &&
  131. (TickCountCurrent.QuadPart > Health->TickCountPrevious))
  132. {
  133. Health->ContextSwitchRate = (LONG)(((ContextSwitch.ContextSwitches - Health->ContextSwitchesPrevious) * 1000) / TickCountElapsed);
  134. Health->ContextSwitchRate = Health->ContextSwitchRate / Health->CpuCount;
  135. }
  136. Health->ContextSwitchesPrevious = ContextSwitch.ContextSwitches;
  137. Health->TickCountPrevious = TickCountCurrent.QuadPart;
  138. }
  139. return STATUS_SUCCESS;
  140. }
  141. NTSTATUS
  142. WdCollectCpuData(
  143. PSYSTEM_HEALTH_DATA Health
  144. )
  145. /*++
  146. Routine Description:
  147. This function collects CPU data and
  148. computes an accumulation for use in determining
  149. system health.
  150. Arguments:
  151. Health - Pointer to a health data structure that is used
  152. for input and output of data to the health monitoring.
  153. Return Value:
  154. If we successfully create a device object, STATUS_SUCCESS is
  155. returned. Otherwise, return the appropriate error code.
  156. Notes:
  157. --*/
  158. {
  159. NTSTATUS Status = STATUS_SUCCESS;
  160. ULONG i;
  161. LARGE_INTEGER cpuIdleTime = {0};
  162. LARGE_INTEGER cpuUserTime = {0};
  163. LARGE_INTEGER cpuKernelTime = {0};
  164. LARGE_INTEGER cpuBusyTime = {0};
  165. LARGE_INTEGER cpuTotalTime = {0};
  166. LARGE_INTEGER sumBusyTime = {0};
  167. LARGE_INTEGER sumTotalTime = {0};
  168. Status = ZwQuerySystemInformation(
  169. SystemProcessorPerformanceInformation,
  170. Health->ProcInfo,
  171. Health->ProcInfoSize,
  172. NULL
  173. );
  174. if (!NT_SUCCESS(Status)) {
  175. return Status;
  176. }
  177. for (i=0; i<Health->CpuCount; i++) {
  178. cpuIdleTime = RtlLargeIntegerSubtract( Health->ProcInfo[i].IdleTime, Health->ProcInfoPrev[i].IdleTime );
  179. cpuUserTime = RtlLargeIntegerSubtract( Health->ProcInfo[i].UserTime, Health->ProcInfoPrev[i].UserTime );
  180. cpuKernelTime = RtlLargeIntegerSubtract( Health->ProcInfo[i].KernelTime, Health->ProcInfoPrev[i].KernelTime );
  181. cpuTotalTime = RtlLargeIntegerAdd( cpuUserTime, cpuKernelTime );
  182. cpuBusyTime = RtlLargeIntegerSubtract( cpuTotalTime, cpuIdleTime );
  183. sumBusyTime = RtlLargeIntegerAdd( sumBusyTime, cpuBusyTime );
  184. sumTotalTime = RtlLargeIntegerAdd( sumTotalTime, cpuTotalTime );
  185. }
  186. Health->CPUTime = GetPercentage(sumBusyTime, sumTotalTime);
  187. RtlCopyMemory( Health->ProcInfoPrev, Health->ProcInfo, Health->ProcInfoSize );
  188. return STATUS_SUCCESS;
  189. }
  190. BOOLEAN
  191. WdCheckSystemHealth(
  192. PSYSTEM_HEALTH_DATA Health
  193. )
  194. /*++
  195. Routine Description:
  196. This function determines if the system is in a healthy
  197. state.
  198. Arguments:
  199. Health - Pointer to a health data structure that is used
  200. for input and output of data to the health monitoring.
  201. Return Value:
  202. If we successfully create a device object, STATUS_SUCCESS is
  203. returned. Otherwise, return the appropriate error code.
  204. Notes:
  205. --*/
  206. {
  207. NTSTATUS Status;
  208. BOOLEAN rVal = FALSE;
  209. //
  210. // return TRUE always because we have not yet decided
  211. // how the system health is really supposed to be
  212. // computed.
  213. //
  214. return TRUE;
  215. __try {
  216. Status = WdCollectContextSwitchData( Health );
  217. if (!NT_SUCCESS(Status)) {
  218. DebugPrint(( 0xffffffff, "WdCollectContextSwitchData failed [0x%08x]\n", Status ));
  219. __leave;
  220. }
  221. Status = WdCollectCpuData( Health );
  222. if (!NT_SUCCESS(Status)) {
  223. DebugPrint(( 0xffffffff, "WdCollectCpuData failed [0x%08x]\n", Status ));
  224. __leave;
  225. }
  226. if (Health->CPUTime) {
  227. Health->ContextCpuRatio = Health->ContextSwitchRate / Health->CPUTime;
  228. if (Health->ContextCpuRatio < Health->HealthyCpuRatio) {
  229. __leave;
  230. }
  231. rVal = TRUE;
  232. }
  233. } __finally {
  234. }
  235. DebugPrint(( 0xffffffff, "context-switch=[%d] cpu=[%d] ratio=[%d%s\n",
  236. Health->ContextSwitchRate,
  237. Health->CPUTime,
  238. Health->ContextCpuRatio,
  239. rVal == TRUE ? "*]" : "]"
  240. ));
  241. return rVal;
  242. }