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.

289 lines
7.3 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. ntsdexts.c
  5. Abstract:
  6. This function contains the default ntsd debugger extensions
  7. Author:
  8. Revision History:
  9. --*/
  10. #include "ntsdextp.h"
  11. //
  12. // Lists threads sorted by CPU time consumed, in order to
  13. // track runaway threads
  14. //
  15. typedef struct _INTERESTING_THREAD_INFO {
  16. ULONG_PTR ThreadId ;
  17. ULONG_PTR Flags ;
  18. LARGE_INTEGER UserTime ;
  19. LARGE_INTEGER KernelTime ;
  20. LARGE_INTEGER ElapsedTime ;
  21. } INTERESTING_THREAD_INFO, * PINTERESTING_THREAD_INFO ;
  22. #define ITI_USER_DONE 0x00000001
  23. #define ITI_KERNEL_DONE 0x00000002
  24. #define ITI_ELAPSED_DONE 0x00000004
  25. DECLARE_API( runaway )
  26. {
  27. PROCESS_BASIC_INFORMATION ProcessInfo ;
  28. PSYSTEM_PROCESS_INFORMATION SystemInfo ;
  29. PSYSTEM_PROCESS_INFORMATION Walk ;
  30. PSYSTEM_THREAD_INFORMATION ThreadInfo ;
  31. PINTERESTING_THREAD_INFO Threads ;
  32. NTSTATUS Status ;
  33. ULONG Flags = 1 ;
  34. ULONG i, j, Found ;
  35. LARGE_INTEGER Now ;
  36. LARGE_INTEGER Compare ;
  37. TIME_FIELDS Time ;
  38. INIT_API();
  39. if (sscanf( args, "%x", &Flags ) == 0) {
  40. goto Exit;
  41. }
  42. Status = NtQueryInformationProcess(
  43. g_hCurrentProcess,
  44. ProcessBasicInformation,
  45. &ProcessInfo,
  46. sizeof( ProcessInfo ),
  47. NULL );
  48. if ( !NT_SUCCESS( Status ) )
  49. {
  50. dprintf( "could not get process information, %d\n",
  51. RtlNtStatusToDosError( Status ) );
  52. goto Exit;
  53. }
  54. SystemInfo = RtlAllocateHeap(
  55. RtlProcessHeap(),
  56. 0,
  57. 1024 * sizeof( SYSTEM_PROCESS_INFORMATION ) );
  58. if ( !SystemInfo )
  59. {
  60. dprintf( "not enough memory\n" );
  61. goto Exit;
  62. }
  63. Status = NtQuerySystemInformation(
  64. SystemProcessInformation,
  65. SystemInfo,
  66. 1024 * sizeof( SYSTEM_PROCESS_INFORMATION ),
  67. NULL );
  68. if ( !NT_SUCCESS( Status ) )
  69. {
  70. dprintf( "unable to get system information\n" );
  71. RtlFreeHeap(
  72. RtlProcessHeap(),
  73. 0,
  74. SystemInfo );
  75. goto Exit;
  76. }
  77. //
  78. // First, find the process:
  79. //
  80. Walk = SystemInfo ;
  81. while ( HandleToUlong( Walk->UniqueProcessId ) != ProcessInfo.UniqueProcessId )
  82. {
  83. if ( Walk->NextEntryOffset == 0 )
  84. {
  85. Walk = NULL ;
  86. break;
  87. }
  88. Walk = (PSYSTEM_PROCESS_INFORMATION) ((PUCHAR) Walk + Walk->NextEntryOffset );
  89. }
  90. if ( !Walk )
  91. {
  92. dprintf( "unable to find process\n" );
  93. RtlFreeHeap( RtlProcessHeap(), 0, SystemInfo );
  94. goto Exit;
  95. }
  96. //
  97. // Now, walk the threads
  98. //
  99. ThreadInfo = (PSYSTEM_THREAD_INFORMATION) (Walk + 1);
  100. Threads = RtlAllocateHeap(
  101. RtlProcessHeap(),
  102. 0,
  103. sizeof( INTERESTING_THREAD_INFO ) * Walk->NumberOfThreads );
  104. if ( !Threads )
  105. {
  106. dprintf( "not enough memory\n" );
  107. RtlFreeHeap(
  108. RtlProcessHeap(),
  109. 0,
  110. SystemInfo );
  111. goto Exit;
  112. }
  113. GetSystemTimeAsFileTime( (LPFILETIME) &Now );
  114. for ( i = 0 ; i < Walk->NumberOfThreads ; i++ )
  115. {
  116. Threads[ i ].Flags = 0 ;
  117. Threads[ i ].ThreadId = HandleToUlong( ThreadInfo[ i ].ClientId.UniqueThread );
  118. Threads[ i ].ElapsedTime.QuadPart = Now.QuadPart - ThreadInfo[ i ].CreateTime.QuadPart ;
  119. Threads[ i ].KernelTime = ThreadInfo[ i ].KernelTime ;
  120. Threads[ i ].UserTime = ThreadInfo[ i ].UserTime ;
  121. }
  122. //
  123. // Scan through the list of threads (in an ugly, bubble-ish sort
  124. // of way), and display the threads in order of time, once per time
  125. // field, by way of the flags:
  126. //
  127. if ( Flags & ITI_USER_DONE )
  128. {
  129. j = Walk->NumberOfThreads ;
  130. Found = 0 ;
  131. dprintf( " User Mode Time\n" );
  132. dprintf( " Thread Time\n" );
  133. while ( j-- )
  134. {
  135. Compare.QuadPart = 0 ;
  136. for ( i = 0 ; i < Walk->NumberOfThreads ; i++ )
  137. {
  138. if ( ( ( Threads[ i ].Flags & ITI_USER_DONE ) == 0 ) &&
  139. ( Threads[ i ].UserTime.QuadPart >= Compare.QuadPart ) )
  140. {
  141. Compare.QuadPart = Threads[ i ].UserTime.QuadPart ;
  142. Found = i ;
  143. }
  144. }
  145. Threads[ Found ].Flags |= ITI_USER_DONE ;
  146. RtlTimeToElapsedTimeFields( &Compare, &Time );
  147. dprintf( " %-3x %3ld:%02ld:%02ld.%04ld\n",
  148. Threads[ Found ].ThreadId,
  149. Time.Hour,
  150. Time.Minute,
  151. Time.Second,
  152. Time.Milliseconds );
  153. }
  154. }
  155. if ( Flags & ITI_KERNEL_DONE )
  156. {
  157. j = Walk->NumberOfThreads ;
  158. Found = 0 ;
  159. dprintf( " Kernel Mode Time\n" );
  160. dprintf( " Thread Time\n" );
  161. while ( j-- )
  162. {
  163. Compare.QuadPart = 0 ;
  164. for ( i = 0 ; i < Walk->NumberOfThreads ; i++ )
  165. {
  166. if ( ( ( Threads[ i ].Flags & ITI_KERNEL_DONE ) == 0 ) &&
  167. ( Threads[ i ].KernelTime.QuadPart >= Compare.QuadPart ) )
  168. {
  169. Compare.QuadPart = Threads[ i ].KernelTime.QuadPart ;
  170. Found = i ;
  171. }
  172. }
  173. Threads[ Found ].Flags |= ITI_KERNEL_DONE ;
  174. RtlTimeToElapsedTimeFields( &Compare, &Time );
  175. dprintf( " %-3x %3ld:%02ld:%02ld.%04ld\n",
  176. Threads[ Found ].ThreadId,
  177. Time.Hour,
  178. Time.Minute,
  179. Time.Second,
  180. Time.Milliseconds );
  181. }
  182. }
  183. if ( Flags & ITI_ELAPSED_DONE )
  184. {
  185. j = Walk->NumberOfThreads ;
  186. Found = 0 ;
  187. dprintf( " Elapsed Time\n" );
  188. dprintf( " Thread Time\n" );
  189. while ( j-- )
  190. {
  191. Compare.QuadPart = 0 ;
  192. for ( i = 0 ; i < Walk->NumberOfThreads ; i++ )
  193. {
  194. if ( ( ( Threads[ i ].Flags & ITI_ELAPSED_DONE ) == 0 ) &&
  195. ( Threads[ i ].ElapsedTime.QuadPart >= Compare.QuadPart ) )
  196. {
  197. Compare.QuadPart = Threads[ i ].ElapsedTime.QuadPart ;
  198. Found = i ;
  199. }
  200. }
  201. Threads[ Found ].Flags |= ITI_ELAPSED_DONE ;
  202. RtlTimeToElapsedTimeFields( &Compare, &Time );
  203. dprintf( " %-3x %3ld:%02ld:%02ld.%04ld\n",
  204. Threads[ Found ].ThreadId,
  205. Time.Hour,
  206. Time.Minute,
  207. Time.Second,
  208. Time.Milliseconds );
  209. }
  210. }
  211. if ( SystemInfo )
  212. {
  213. RtlFreeHeap( RtlProcessHeap(), 0, SystemInfo );
  214. }
  215. Exit:
  216. EXIT_API();
  217. }