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.

1058 lines
30 KiB

  1. #ifndef KERNRATE_H_INCLUDED
  2. #define KERNRATE_H_INCLUDED
  3. /*++
  4. Copyright (c) 1989-2002 Microsoft Corporation
  5. --*/
  6. //
  7. // set the debug environment
  8. //
  9. #if DBG // NTBE environment
  10. #if NDEBUG
  11. #undef NDEBUG // <assert.h>: assert() is defined
  12. #endif // NDEBUG
  13. #define _DEBUG // <crtdbg.h>: _ASSERT(), _ASSERTE() are defined.
  14. #define DEBUG 1 // our internal file debug flag
  15. #elif _DEBUG // VC++ environment
  16. #ifndef NEBUG
  17. #define NDEBUG
  18. #endif // !NDEBUG
  19. #define DEBUG 1 // our internal file debug flag
  20. #endif
  21. //
  22. // Include System Header files
  23. //
  24. #include <nt.h>
  25. #include <ntrtl.h>
  26. #include <nturtl.h>
  27. #include <windows.h>
  28. #include <dbghelp.h> //The debugger team recommends using dbghelp.h rather than imagehlp.h
  29. #include <assert.h>
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <search.h>
  33. #include <string.h>
  34. #include <memory.h>
  35. #include <ctype.h>
  36. //MC
  37. #include <wchar.h>
  38. //MC
  39. #include <..\pperf\pstat.h>
  40. #include ".\kernrate.rc"
  41. //
  42. // Constant Definitions
  43. //
  44. #define DEFAULT_ZOOM_BUCKET_SIZE 16 //Minimum is 4 bytes
  45. #define DEFAULT_LOG2_ZOOM_BUCKET 4
  46. #define MINIMUM_ZOOM_BUCKET_SIZE 4
  47. #define DEFAULT_SOURCE_CHANGE_INTERVAL 1000 //ms
  48. #define KRATE_DEFAULT_TIMESOURCE_RATE 25000 //Events/Hit
  49. #define DEFAULT_SLEEP_INTERVAL 0
  50. #define MAX_SYMNAME_SIZE 1024
  51. #define USER_SYMPATH_LENGTH 512 //specified on the command line
  52. #define TOTAL_SYMPATH_LENGTH 1024
  53. #define SYM_VALUES_BUF_SIZE 160
  54. #define SYM_KERNEL_HANDLE (HANDLE)-1
  55. #define SYSTEM_PROCESS_NAME "System"
  56. #define TITLE_SIZE 64
  57. #define PROCESS_NAME_SIZE 36 //without extension
  58. #define EXT_SIZE 4 //.exe
  59. #define PROCESS_SIZE (PROCESS_NAME_SIZE+EXT_SIZE+1)
  60. #define DEFAULT_MAX_TASKS 256
  61. #define MAX_PROC_SAME_NAME 8
  62. #define INITIAL_STEP 2 //Symbol enumeration default address stepping
  63. #define JIT_MAX_INITIAL_STEP 16 //Managed Code symbol enumeration maximum step size (bytes)
  64. #define LOCK_CONTENTION_MIN_COUNT 1000
  65. #define MIN_HITS_TO_DISPLAY 1
  66. #define SECONDS_TO_DELAY_PROFILE 0
  67. #define SECONDS_TO_WAIT_CREATED_PROC 2
  68. #define UINT64_MAXDWORD ((unsigned __int64)0xffffffff)
  69. #define DEFAULT_TOKEN_MAX_LENGTH 12 // strlen("dcacheacces")
  70. #define DEFAULT_DESCRIPTION_MAX_LENGTH 25 // strlen("Load Linked Instructions")
  71. #define MAX_DIGITS_IN_INPUT_STRING 9 // Max. allowed digits considered valid input for a number on the command line
  72. #if defined(_IA64_)|| defined(_AMD64_)
  73. #define MAX_SIMULTANEOUS_SOURCES 4
  74. #else
  75. #define MAX_SIMULTANEOUS_SOURCES 1
  76. #endif
  77. #if defined(DISASM_AVAILABLE)
  78. #undefine(DISASM_AVAILABLE)
  79. #endif
  80. //MC
  81. #define MANAGED_CODE_MAINLIB "mscoree.dll" // Presence of which indicates need to handle Managed Code
  82. #define MANAGED_CODE_SYMHLPLIB "ip2md.dll" // Symbol translation helper library for Managed Code
  83. //MC
  84. //
  85. // Macros
  86. //
  87. #define WIN2K_OS (gOSInfo.dwMajorVersion == 5 && gOSInfo.dwMinorVersion == 0)
  88. #define FPRINTF (void)fprintf
  89. #define RATE_DATA_FIXED_SIZE (5*sizeof(ULONGLONG))
  90. #define RATE_DATA_VAR_SIZE ((sizeof(ULONGLONG *)+sizeof(HANDLE *)+sizeof(ULONG *)+sizeof(PULONG *))*gProfileProcessors)
  91. #define BUCKETS_NEEDED(length) ( length%gZoomBucket == 0? (length/gZoomBucket):(1+length/gZoomBucket) )
  92. #define MODULE_SIZE (sizeof(MODULE)+(RATE_DATA_FIXED_SIZE + RATE_DATA_VAR_SIZE)*gSourceMaximum)
  93. #define IsValidHandle( _Hdl ) ( ( (_Hdl) != (HANDLE)0 ) && ( (_Hdl) != INVALID_HANDLE_VALUE ) )
  94. #define VerbosePrint( _x_ ) vVerbosePrint _x_
  95. #define ModuleFileName( _Module ) \
  96. ( (_Module)->module_FileName ? (_Module)->module_FileName : (_Module)->module_Name )
  97. #define ModuleFullName( _Module ) \
  98. ( (_Module)->module_FullName ? (_Module)->module_FullName : ModuleFileName( _Module ) )
  99. //
  100. // On Itanium it turns out that you may request a rate of let's say 800 but actually get 799...
  101. // The check for an exact match in this case will fail and the logic will force the default rate
  102. // The following allows a tollerance of 25 percent to be considered as a match
  103. //
  104. #define PERCENT_DIFF(a,b) ( a > b? (100*(a-b))/b : (100*(b-a))/b )
  105. #define RATES_MATCH(a,b) ( PERCENT_DIFF(a,b) <= 25 )
  106. //
  107. // Struct and Enum Type Definitions and Related Globals
  108. //
  109. typedef enum _KERNRATE_NAMESPACE {
  110. cMAPANDLOAD_READONLY = TRUE,
  111. cDONOT_ALLOCATE_DESTINATION_STRING = FALSE,
  112. } eKERNRATE_NAMESPACE;
  113. typedef enum _ACTION_TYPE {
  114. START = 0,
  115. STOP = 1,
  116. OUTPUT = 2,
  117. DEFAULT= 3
  118. } ACTION_TYPE;
  119. //
  120. // Verbose Output Related
  121. //
  122. typedef enum _VERBOSE_ENUM {
  123. VERBOSE_NONE = 0, //
  124. VERBOSE_IMAGEHLP = 0x1, //
  125. VERBOSE_PROFILING = 0x2, //
  126. VERBOSE_INTERNALS = 0x4, //
  127. VERBOSE_MODULES = 0x8, //
  128. VERBOSE_DEFAULT = VERBOSE_IMAGEHLP,
  129. VERBOSE_MAX = VERBOSE_IMAGEHLP | VERBOSE_PROFILING | VERBOSE_INTERNALS | VERBOSE_MODULES
  130. } VERBOSE_ENUM;
  131. typedef struct _VERBOSE_DEFINITION {
  132. VERBOSE_ENUM VerboseEnum;
  133. const char * const VerboseString;
  134. } VERBOSE_DEFINITION, *PVERBOSE_DEFINITION;
  135. //
  136. // Profile Source Related
  137. //
  138. typedef struct _SOURCE {
  139. PCHAR Name; // pstat EVENTID.Description
  140. KPROFILE_SOURCE ProfileSource;
  141. PCHAR ShortName; // pstat EVENTID.ShortName
  142. ULONG DesiredInterval; // system default interval
  143. ULONG Interval; // user set interval (not guaranteed)
  144. BOOL bProfileStarted;
  145. } SOURCE, *PSOURCE;
  146. typedef struct _RATE_DATA {
  147. ULONGLONG StartTime;
  148. ULONGLONG TotalTime;
  149. ULONGLONG Rate; // Events/Second
  150. ULONGLONG GrandTotalCount;
  151. ULONGLONG DoubtfulCounts;
  152. ULONGLONG *TotalCount;
  153. HANDLE *ProfileHandle;
  154. ULONG *CurrentCount;
  155. PULONG *ProfileBuffer;
  156. } RATE_DATA, *PRATE_DATA;
  157. //
  158. // Module related definitions
  159. //
  160. typedef enum _MODULE_NAMESPACE {
  161. cMODULE_NAME_STRLEN = 132, // maximum module name, including '\0'
  162. } eMODULE_NAMESPACE;
  163. typedef struct _MODULE {
  164. struct _MODULE *Next;
  165. HANDLE hProcess;
  166. ULONG64 Base;
  167. ULONG Length;
  168. BOOL bZoom;
  169. union {
  170. BOOL bProfileStarted;
  171. BOOL bHasHits;
  172. } mu;
  173. CHAR module_Name[cMODULE_NAME_STRLEN]; // filename w/o its extension
  174. PCHAR module_FileName; // filename with its extension
  175. PCHAR module_FullName; // full pathname
  176. RATE_DATA Rate[];
  177. } MODULE, *PMODULE;
  178. typedef struct _RATE_SUMMARY {
  179. ULONGLONG TotalCount;
  180. PMODULE *Modules;
  181. ULONG ModuleCount;
  182. } RATE_SUMMARY, *PRATE_SUMMARY;
  183. //
  184. // Process related definitions
  185. //
  186. typedef struct _PROC_PERF_INFO {
  187. ULONG NumberOfThreads;
  188. LARGE_INTEGER UserTime;
  189. LARGE_INTEGER KernelTime;
  190. LARGE_INTEGER ReadOperationCount;
  191. LARGE_INTEGER WriteOperationCount;
  192. LARGE_INTEGER OtherOperationCount;
  193. LARGE_INTEGER ReadTransferCount;
  194. LARGE_INTEGER WriteTransferCount;
  195. LARGE_INTEGER OtherTransferCount;
  196. SIZE_T VirtualSize;
  197. ULONG HandleCount;
  198. ULONG PageFaultCount;
  199. SIZE_T WorkingSetSize;
  200. SIZE_T QuotaPagedPoolUsage;
  201. SIZE_T QuotaNonPagedPoolUsage;
  202. SIZE_T PagefileUsage;
  203. SIZE_T PeakPagefileUsage;
  204. SIZE_T PrivatePageCount;
  205. // If ever needed the following can be added
  206. // SIZE_T PeakVirtualSize;
  207. // SIZE_T PeakWorkingSetSize;
  208. // SIZE_T QuotaPeakPagedPoolUsage;
  209. // SIZE_T QuotaPeakNonPagedPoolUsage;
  210. } PROC_PERF_INFO, *PPROC_PERF_INFO;
  211. typedef struct _PROC_TO_MONITOR {
  212. struct _PROC_TO_MONITOR *Next;
  213. HANDLE ProcessHandle;
  214. LONGLONG Pid;
  215. ULONG Index;
  216. PCHAR ProcessName;
  217. ULONG ModuleCount;
  218. ULONG ZoomCount;
  219. PMODULE ModuleList;
  220. PMODULE ZoomList;
  221. PSOURCE Source;
  222. PROC_PERF_INFO ProcPerfInfoStart;
  223. PSYSTEM_THREAD_INFORMATION pProcThreadInfoStart;
  224. PRTL_DEBUG_INFORMATION pProcDebugInfoStart;
  225. PRTL_DEBUG_INFORMATION pProcDebugInfoStop;
  226. //MC
  227. DWORD *JITHeapLocationsStart;
  228. DWORD *JITHeapLocationsStop;
  229. //MC
  230. } PROC_TO_MONITOR, *PPROC_TO_MONITOR;
  231. //
  232. // These processor level enums should be defined in public headers.
  233. // ntexapi.h - NtQuerySystemInformation( SystemProcessorInformation).
  234. //
  235. // For Now Define them locally.
  236. //
  237. typedef enum _PROCESSOR_FAMILY {
  238. IA64_FAMILY_MERCED = 0x7,
  239. IA64_FAMILY_ITANIUM = IA64_FAMILY_MERCED,
  240. IA64_FAMILY_MCKINLEY = 0x1f
  241. } PROCESSOR_FAMILY;
  242. #if defined(_IA64_)
  243. #if 0
  244. #define IA64ProcessorLevel2ProcessorFamily( (_ProcessorLevel >> 8) & 0xff )
  245. #else
  246. //
  247. // BUGBUG - Thierry - 02/20/2002
  248. // Fix until SYSTEM_PROCESSOR_INFORMATION is fixed in the OS.
  249. //
  250. #ifndef CV_IA64_CPUID3
  251. #define CV_IA64_CPUID3 3331
  252. #endif
  253. __inline USHORT
  254. IA64ProcessorLevel2ProcessorFamily(
  255. USHORT ProcessorLevel
  256. )
  257. {
  258. return( (USHORT)((__getReg(CV_IA64_CPUID3) >> 24) & 0xff));
  259. }
  260. #endif
  261. #endif // _IA64_
  262. //
  263. // The Following is Defined in pstat.h but not for Win2K
  264. // The definition below allows for single source management for Win2K and above
  265. //
  266. #ifndef PSTAT_QUERY_EVENTS_INFO
  267. #define PSTAT_QUERY_EVENTS_INFO CTL_CODE (FILE_DEVICE_UNKNOWN, 5, METHOD_NEITHER, FILE_ANY_ACCESS)
  268. typedef struct _EVENTS_INFO {
  269. ULONG Events;
  270. ULONG TokenMaxLength;
  271. ULONG DescriptionMaxLength;
  272. ULONG OfficialTokenMaxLength;
  273. ULONG OfficialDescriptionMaxLength;
  274. } EVENTS_INFO, *PEVENTS_INFO;
  275. #endif
  276. #ifndef RTL_QUERY_PROCESS_NONINVASIVE
  277. #define RTL_QUERY_PROCESS_NONINVASIVE 0x80000000
  278. #endif
  279. //
  280. //
  281. //
  282. typedef struct _TASK_LIST {
  283. LONGLONG ProcessId;
  284. CHAR ProcessName[PROCESS_SIZE];
  285. PSYSTEM_THREAD_INFORMATION pProcessThreadInfo;
  286. PROC_PERF_INFO ProcessPerfInfo;
  287. } TASK_LIST, *PTASK_LIST;
  288. typedef struct _TASK_LIST_ENUM {
  289. PTASK_LIST tlist;
  290. ULONG numtasks;
  291. } TASK_LIST_ENUM, *PTASK_LIST_ENUM;
  292. typedef struct _uint64div {
  293. unsigned __int64 quot;
  294. unsigned __int64 rem;
  295. } uint64div_t;
  296. typedef struct _int64div {
  297. __int64 quot;
  298. __int64 rem;
  299. } int64div_t;
  300. typedef struct _InputCount {
  301. UCHAR InputOption;
  302. SHORT Allowed;
  303. SHORT ActualCount;
  304. } InputCount;
  305. //
  306. // Globals
  307. //
  308. //
  309. static CHAR gUserSymbolPath[USER_SYMPATH_LENGTH];
  310. static CHAR gSymbolPath[TOTAL_SYMPATH_LENGTH];
  311. static DWORD gSymOptions;
  312. PIMAGEHLP_SYMBOL64 gSymbol;
  313. BOOL bSymPathInitialized = FALSE;
  314. //
  315. static PMODULE gCurrentModule = (PMODULE)0;
  316. PMODULE gCallbackCurrent;
  317. ULONG gZoomCount;
  318. //
  319. PSYSTEM_BASIC_INFORMATION gSysBasicInfo;
  320. LONG gProfileProcessors; //Actual being profiled
  321. KAFFINITY gAffinityMask = 0; //Processor Afinity Mask for selected processor profiling
  322. ULONG gMaxSimultaneousSources; //Maximum allowed number of sources that can be turned on simultaneously
  323. CHAR gSystemProcessName[] = SYSTEM_PROCESS_NAME;
  324. OSVERSIONINFO gOSInfo;
  325. HANDLE ghDoneEvent;
  326. BOOL gProfilingDone = FALSE;
  327. //
  328. ULONG gNumProcToMonitor = 0; //Total Number of Processes To Monitor
  329. ULONG gKernelModuleCount = 0;
  330. PPROC_TO_MONITOR gProcessList = NULL;
  331. PPROC_TO_MONITOR gpProcDummy;
  332. PPROC_TO_MONITOR gpSysProc = NULL;
  333. PMODULE gCommonZoomList = NULL; //List of Zoom Modules Common to More Than One Process such as ntdll
  334. //
  335. long double gldElapsedSeconds;
  336. ULONG gTotalElapsedSeconds; // Sum On All Processors
  337. LARGE_INTEGER gTotalElapsedTime64;
  338. LARGE_INTEGER gTotal2ElapsedTime64;
  339. //
  340. ULONG gZoomBucket = DEFAULT_ZOOM_BUCKET_SIZE;
  341. ULONG gLog2ZoomBucket = DEFAULT_LOG2_ZOOM_BUCKET;
  342. ULONG gSourceMaximum = 0;
  343. ULONG gStaticCount = 0;
  344. ULONG gTotalActiveSources = 0;
  345. PSOURCE gStaticSource = NULL;
  346. //
  347. ULONG gNumTasksStart;
  348. ULONG gNumTasksStop;
  349. PTASK_LIST gTlistStart;
  350. double gTotalIdleTime = 0;
  351. //MC
  352. BOOL bMCHelperLoaded = FALSE; //Is Managed Code Helper Library Loaded
  353. BOOL bMCJitRangesExist = FALSE; //Were any JIT ranges found
  354. BOOL bImageHlpSymbolFound = FALSE; //SymEnumerateSymbols64 found at least one symbol
  355. HANDLE ghMCLib = NULL; //Handle to MC helper IP2MC.DLL
  356. WCHAR* gwszSymbol;
  357. //MC
  358. //
  359. // Print format for event strings
  360. //
  361. ULONG gTokenMaxLen = DEFAULT_TOKEN_MAX_LENGTH;
  362. ULONG gDescriptionMaxLen = DEFAULT_DESCRIPTION_MAX_LENGTH;
  363. //
  364. //Verbose Output related
  365. //
  366. VERBOSE_DEFINITION VerboseDefinition[] = {
  367. { VERBOSE_NONE, "None" },
  368. { VERBOSE_IMAGEHLP, "Displays ImageHlp Operations" },
  369. { VERBOSE_PROFILING, "Displays Profiling Operations and Per Bucket Information Including Symbol Verification" },
  370. { VERBOSE_INTERNALS, "Displays Internals Operations" },
  371. { VERBOSE_MODULES, "Displays Modules Operations" },
  372. { VERBOSE_NONE, NULL }
  373. };
  374. ULONG gVerbose = VERBOSE_NONE;
  375. BOOL bRoundingVerboseOutput = FALSE;
  376. //
  377. // User command-line input related
  378. //
  379. typedef enum _INPUT_ERROR_TYPE {
  380. INPUT_GOOD = 1,
  381. UNKNOWN_OPTION,
  382. BOGUS_ENTRY,
  383. MISSING_PARAMETER,
  384. MISSING_NUMBER,
  385. MISSING_REQUIRED_NUMBER,
  386. MISSING_STRING,
  387. MISSING_REQUIRED_STRING,
  388. INVALID_NUMBER
  389. } INPUT_ERROR_TYPE;
  390. typedef enum _INPUT_ORDER {
  391. ORDER_ANY,
  392. ORDER_STRING_FIRST,
  393. ORDER_NUMBER_FIRST
  394. } INPUT_ORDER;
  395. typedef enum _INPUT_OPTIONAL {
  396. OPTIONAL_ANY,
  397. OPTIONAL_STRING,
  398. OPTIONAL_NUMBER,
  399. OPTIONAL_NONE,
  400. } INPUT_OPTIONAL;
  401. BOOL bCombinedProfile = FALSE; // Do Both Kernel and User Process(es)
  402. LONG gChangeInterval = DEFAULT_SOURCE_CHANGE_INTERVAL;
  403. BOOL bWaitForUserInput = FALSE; // Wait for the user to press a key before starting the profile
  404. BOOL bWaitCreatedProcToSettle = FALSE; // Indication that one or more processes were created via the -o option
  405. BOOL bCreatedProcWaitForUserInput = FALSE; // Wait for the user to press a key to indicate a created process has settled (gone idle)
  406. LONG gSecondsToDelayProfile = SECONDS_TO_DELAY_PROFILE; // Wait for N seconds before starting the profile
  407. LONG gSecondsToWaitCreatedProc = SECONDS_TO_WAIT_CREATED_PROC; // Wait for N seconds for a created process to settle (go idle)
  408. LONG gSleepInterval = DEFAULT_SLEEP_INTERVAL; //Used to set the profile period
  409. BOOL bRawData = FALSE;
  410. BOOL bRawDisasm = FALSE;
  411. BOOL bProfileByProcessor = FALSE;
  412. BOOL bGetInterestingData = FALSE; // Get Interesting statistics (turns on several sources, depends on hits, not guaratied)
  413. BOOL bOldSampling = FALSE; // Use new sampling scheme (start all sources and let them run simultaneously)
  414. BOOL bIncludeGeneralInfo = TRUE; // Include system-wide and process-specific information (such as context switches, memory usage, etc.)
  415. BOOL bDisplayTaskSummary = FALSE;
  416. ULONG gMaxTasks = DEFAULT_MAX_TASKS; //Max Number of tasks accomodated in Kernrate's Task List
  417. BOOL bIncludeSystemLocksInfo = FALSE; // Get System lock contention info
  418. BOOL bIncludeUserProcLocksInfo= FALSE; // Get User process lock contention info
  419. ULONG gLockContentionMinCount = LOCK_CONTENTION_MIN_COUNT; // Default minimum count of lock contention for output processing
  420. ULONG gMinHitsToDisplay = MIN_HITS_TO_DISPLAY;
  421. BOOL bProcessDataHighPriority = FALSE; // User may opt to finish processing the collected data at high priority
  422. // This is useful on a very busy system if the momentary overhead is not an issue
  423. BOOL bSystemThreadsInfo = FALSE; // System-Process (kernel mode) threads
  424. BOOL bIncludeThreadsInfo = FALSE; // Get thread info (it will then be gathered for all running tasks)
  425. HANDLE ghInput = NULL, ghOutput = NULL, ghError = NULL;
  426. //
  427. // Most Static Sources desired intervals are computed to give approximately
  428. // one interrupt per millisecond and be a nice even power of 2
  429. //
  430. enum _STATIC_SOURCE_TYPE {
  431. SOURCE_TIME = 0,
  432. };
  433. // The following are defined in several headers,
  434. // were supported on ALPHA, but they currently have no x86 KE/HAL support except for Time and AlignFixup
  435. // Merced.c and Mckinley.c define the supported static sources on IA64 Merced/McKinley systems
  436. // Amd64.c defines the supported static sources on Amd64 systems
  437. SOURCE StaticSources[] = {
  438. {"Time", ProfileTime, "time" , 1000, KRATE_DEFAULT_TIMESOURCE_RATE},
  439. {"Alignment Fixup", ProfileAlignmentFixup, "alignfixup" , 1,0},
  440. {"Total Issues", ProfileTotalIssues, "totalissues", 131072,0},
  441. {"Pipeline Dry", ProfilePipelineDry, "pipelinedry", 131072,0},
  442. {"Load Instructions", ProfileLoadInstructions, "loadinst" , 65536,0},
  443. {"Pipeline Frozen", ProfilePipelineFrozen, "pilelinefrz", 131072,0},
  444. {"Branch Instructions", ProfileBranchInstructions, "branchinst" , 65536,0},
  445. {"Total Nonissues", ProfileTotalNonissues, "totalnoniss", 131072,0},
  446. {"Dcache Misses", ProfileDcacheMisses, "dcachemiss" , 16384,0},
  447. {"Icache Misses", ProfileIcacheMisses, "icachemiss" , 16384,0},
  448. {"Cache Misses", ProfileCacheMisses, "cachemiss" , 16384,0},
  449. {"Branch Mispredictions", ProfileBranchMispredictions, "branchpred" , 16384,0},
  450. {"Store Instructions", ProfileStoreInstructions, "storeinst" , 65536,0},
  451. {"Floating Point Instr", ProfileFpInstructions, "fpinst" , 65536,0},
  452. {"Integer Instructions", ProfileIntegerInstructions, "intinst" , 65536,0},
  453. {"Dual Issues", Profile2Issue, "2issue" , 65536,0},
  454. {"Triple Issues", Profile3Issue, "3issue" , 16384,0},
  455. {"Quad Issues", Profile4Issue, "4issue" , 16384,0},
  456. {"Special Instructions", ProfileSpecialInstructions, "specinst" , 16384,0},
  457. {"Cycles", ProfileTotalCycles, "totalcycles", 655360,0},
  458. {"Icache Issues", ProfileIcacheIssues, "icacheissue", 65536,0},
  459. {"Dcache Accesses", ProfileDcacheAccesses, "dcacheacces", 65536,0},
  460. {"MB Stall Cycles", ProfileMemoryBarrierCycles, "membarcycle", 32767,0},
  461. {"Load Linked Instructions", ProfileLoadLinkedIssues, "loadlinkiss", 16384,0},
  462. {NULL, ProfileMaximum, "", 0, 0}
  463. };
  464. #if defined(_IA64_)
  465. #include "merced.c"
  466. #include "mckinley.c"
  467. #endif // _IA64_
  468. #if defined(_AMD64_)
  469. #include "amd64.c"
  470. #endif // _AMD64_
  471. //
  472. // "Interesting Data" constituents
  473. //
  474. KPROFILE_SOURCE IData[] = {
  475. #if defined(_IA64_)
  476. ProfileTotalIssues, //This source must always be first in the array
  477. ProfileLoadInstructions,
  478. ProfileStoreInstructions,
  479. ProfileBranchInstructions,
  480. ProfileFpInstructions,
  481. ProfileIntegerInstructions,
  482. ProfileCacheMisses,
  483. ProfileIcacheMisses,
  484. ProfileDcacheMisses,
  485. ProfileBranchMispredictions,
  486. ProfileTotalCycles
  487. #elif defined(_AMD64_)
  488. ProfileTotalIssues,
  489. ProfileBranchInstructions,
  490. ProfileFpInstructions,
  491. ProfileIcacheMisses,
  492. ProfileDcacheMisses,
  493. ProfileBranchMispredictions
  494. #else
  495. ProfileTotalIssues
  496. #endif
  497. };
  498. PULONG gulActiveSources;
  499. //
  500. // For checking command line input options for unallowed duplicates
  501. // (0=no such option, -1=unlimited, -2 don't care)
  502. //
  503. InputCount InputOption[] = {
  504. { 'A', 1, 0 },
  505. { 'B', 1, 0 },
  506. { 'C', 1, 0 },
  507. { 'D',-2, 0 },
  508. { 'E',-2, 0 },
  509. { 'F',-2, 0 },
  510. { 'G', 1, 0 },
  511. { 'H',-2, 0 },
  512. { 'I',-1, 0 },
  513. { 'J', 1, 0 },
  514. { 'K', 1, 0 },
  515. { 'L', 1, 0 },
  516. { 'M', 1, 0 },
  517. { 'N',-1, 0 },
  518. { 'O',-1, 0 },
  519. { 'P',-1, 0 },
  520. { 'Q', 0, 0 },
  521. { 'R',-2, 0 },
  522. { 'S', 1, 0 },
  523. { 'T', 1, 0 },
  524. { 'U',-2, 0 },
  525. { 'V',-1, 0 },
  526. { 'W', 2, 0 },
  527. { 'X', 1, 0 },
  528. { 'Y', 0, 0 },
  529. { 'Z',-1, 0 }
  530. };
  531. InputCount wCount = {'W', 1, 0};
  532. InputCount wpCount = {'W', 1, 0};
  533. //
  534. // Function prototypes
  535. //
  536. VOID
  537. CleanZoomModuleList(
  538. PPROC_TO_MONITOR Proc
  539. );
  540. VOID
  541. CreateDoneEvent(
  542. VOID
  543. );
  544. //MC
  545. BOOL
  546. CreateJITZoomModuleCallback(
  547. IN PWCHAR wszSymName,
  548. IN LPSTR szSymName,
  549. IN ULONG64 Address,
  550. IN ULONG Size,
  551. IN PVOID Cxt
  552. );
  553. //MC
  554. PMODULE
  555. CreateNewModule(
  556. IN PPROC_TO_MONITOR ProcToMonitor,
  557. IN PCHAR ModuleName,
  558. IN PCHAR ModuleFullName,
  559. IN ULONG64 ImageBase,
  560. IN ULONG ImageSize
  561. );
  562. VOID
  563. CreateProfiles(
  564. IN PMODULE Root,
  565. IN PPROC_TO_MONITOR ProcToMonitor
  566. );
  567. VOID
  568. CreateZoomedModuleList(
  569. IN PMODULE ZoomModule,
  570. IN ULONG RoundDown,
  571. IN PPROC_TO_MONITOR pProc
  572. );
  573. BOOL
  574. CreateZoomModuleCallback(
  575. IN LPSTR szSymName,
  576. IN ULONG64 Address,
  577. IN ULONG Size,
  578. IN PVOID Cxt
  579. );
  580. VOID
  581. DisplayRunningTasksSummary (
  582. PTASK_LIST pTaskStart,
  583. PTASK_LIST pTaskStop
  584. );
  585. VOID
  586. DisplaySystemWideInformation(
  587. PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION SystemInfoBegin,
  588. PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION SystemInfoEnd
  589. );
  590. VOID
  591. DisplayTotalAndRate (
  592. LONGLONG StartCount,
  593. LONGLONG StopCount,
  594. long double RateAgainst,
  595. PCHAR CounterName,
  596. PCHAR RateAgainstUnits
  597. );
  598. BOOL
  599. EnumerateSymbolsByBuckets(
  600. IN HANDLE SymHandle,
  601. IN PMODULE Current,
  602. IN PSYM_ENUMSYMBOLS_CALLBACK64 EnumSymbolsCallback,
  603. IN PVOID pProc
  604. );
  605. VOID
  606. ExecuteProfiles(
  607. BOOL bMode
  608. );
  609. VOID
  610. ExitWithMissingEntryMessage(
  611. PCHAR CurrentOption,
  612. PCHAR Remark,
  613. BOOL bUsage
  614. );
  615. VOID
  616. ExitWithUnknownOptionMessage(
  617. PCHAR CurrentOption
  618. );
  619. PMODULE
  620. FindModuleForAddress64(
  621. PPROC_TO_MONITOR ProcToMonitor,
  622. DWORD64 Address
  623. );
  624. VOID
  625. GetConfiguration(
  626. int argc,
  627. char *argv[]
  628. );
  629. PMODULE
  630. GetKernelModuleInformation(
  631. VOID
  632. );
  633. VOID
  634. GetProcessLocksInformation (
  635. PPROC_TO_MONITOR ProcToMonitor,
  636. ULONG Flags,
  637. ACTION_TYPE Action
  638. );
  639. PMODULE
  640. GetProcessModuleInformation(
  641. IN PPROC_TO_MONITOR ProcToMonitor
  642. );
  643. VOID
  644. GetProfileSystemInfo(
  645. ACTION_TYPE Action
  646. );
  647. PSYSTEM_BASIC_INFORMATION
  648. GetSystemBasicInformation(
  649. VOID
  650. );
  651. VOID
  652. GetSystemLocksInformation (
  653. ACTION_TYPE Action
  654. );
  655. DWORD
  656. GetTaskList(
  657. PTASK_LIST pTask,
  658. ULONG NumTasks
  659. );
  660. ULONG
  661. HandleRedirections(
  662. IN PCHAR cmdLine,
  663. IN ULONG nCharsStart,
  664. OUT HANDLE *hInput,
  665. OUT HANDLE *hOutput,
  666. OUT HANDLE *hError
  667. );
  668. BOOL
  669. HitsFound(
  670. IN PPROC_TO_MONITOR pProc,
  671. IN ULONG BucketIndex
  672. );
  673. VOID
  674. InitAllProcessesModulesInfo(
  675. VOID
  676. );
  677. BOOL
  678. InitializeAsDebugger(VOID);
  679. BOOL
  680. InitializeKernelProfile(VOID);
  681. VOID
  682. InitializeKernrate(
  683. int argc,
  684. char *argv[]
  685. );
  686. PPROC_TO_MONITOR
  687. InitializeProcToMonitor(
  688. LONGLONG Pid
  689. );
  690. ULONG
  691. InitializeProfileSourceInfo (
  692. PPROC_TO_MONITOR ProcToMonitor
  693. );
  694. VOID
  695. InitSymbolPath(
  696. HANDLE SymHandle
  697. );
  698. VOID
  699. InvalidEntryMessage(
  700. PCHAR CurrentOption,
  701. PCHAR CurrentValue,
  702. PCHAR Remark,
  703. BOOL bUsage,
  704. BOOL bExit
  705. );
  706. INPUT_ERROR_TYPE
  707. IsInputValid(int argc,
  708. int OptionIndex,
  709. PCHAR *Option,
  710. PCHAR AllowedTrailLetters,
  711. PLONG AssociatedNumber,
  712. PCHAR AssociatedString,
  713. ULONG MaxStringLength,
  714. INPUT_ORDER Order,
  715. INPUT_OPTIONAL Optional
  716. );
  717. BOOL
  718. IsStringANumber(
  719. IN PCHAR String
  720. );
  721. ULONG
  722. NextSource(
  723. IN ULONG CurrentSource,
  724. IN PMODULE ModuleList,
  725. IN PPROC_TO_MONITOR ProcToMonitor
  726. );
  727. VOID
  728. OutputInterestingData(
  729. IN FILE *Out,
  730. IN RATE_DATA Data[]
  731. );
  732. VOID
  733. OutputLine(
  734. IN FILE *Out,
  735. IN ULONG ProfileSourceIndex,
  736. IN PMODULE Module,
  737. IN PRATE_SUMMARY RateSummary,
  738. IN PPROC_TO_MONITOR ProcToMonitor
  739. );
  740. VOID
  741. OutputLineFromAddress64(
  742. HANDLE hProc,
  743. DWORD64 qwAddr,
  744. PIMAGEHLP_LINE64 pLine
  745. );
  746. VOID
  747. OutputLocksInformation(
  748. PRTL_PROCESS_LOCKS pLockInfoStart,
  749. PRTL_PROCESS_LOCKS pLockInfoStop,
  750. PPROC_TO_MONITOR Proc
  751. );
  752. VOID
  753. OutputModuleList(
  754. IN FILE *Out,
  755. IN PMODULE ModuleList,
  756. IN ULONG NumberModules,
  757. IN PPROC_TO_MONITOR ProcToMonitor,
  758. IN PMODULE Parent
  759. );
  760. VOID
  761. OutputPercentValue (
  762. LONGLONG StartCount,
  763. LONGLONG StopCount,
  764. LARGE_INTEGER Base,
  765. PCHAR CounterName
  766. );
  767. VOID
  768. OutputProcessPerfInfo (
  769. PTASK_LIST pTask,
  770. ULONG NumTasks,
  771. PPROC_TO_MONITOR ProcToMonitor
  772. );
  773. VOID
  774. OutputRawDataForZoomModule(
  775. IN FILE *Out,
  776. IN PPROC_TO_MONITOR ProcToMonitor,
  777. IN PMODULE Current
  778. );
  779. VOID
  780. OutputResults(
  781. IN FILE *Out,
  782. IN PPROC_TO_MONITOR ProcToMonitor
  783. );
  784. VOID
  785. OutputStartStopValues (
  786. SIZE_T StartCount,
  787. SIZE_T StopCount,
  788. PCHAR CounterName
  789. );
  790. VOID
  791. OutputThreadInfo (
  792. PTASK_LIST pTask,
  793. DWORD TaskNumber,
  794. PPROC_TO_MONITOR ProcToMonitor
  795. );
  796. BOOL
  797. PrivEnumerateSymbols(
  798. IN HANDLE SymHandle,
  799. IN PMODULE Current,
  800. IN PSYM_ENUMSYMBOLS_CALLBACK64 EnumSymbolsCallback,
  801. IN PVOID pProc,
  802. IN DWORD64 BaseOptional,
  803. IN ULONG SizeOptional
  804. );
  805. VOID
  806. SetProfileSourcesRates(
  807. PPROC_TO_MONITOR ProcToMonitor
  808. );
  809. VOID
  810. StartSource(
  811. IN ULONG ProfileSource,
  812. IN PMODULE ModuleList,
  813. IN PPROC_TO_MONITOR ProcToMonitor
  814. );
  815. VOID
  816. StopSource(
  817. IN ULONG ProfileSourceIndex,
  818. IN PMODULE ModuleList,
  819. IN PPROC_TO_MONITOR ProcToMonitor
  820. );
  821. BOOL
  822. TkEnumerateSymbols(
  823. IN HANDLE SymHandle,
  824. IN PMODULE Current,
  825. IN PSYM_ENUMSYMBOLS_CALLBACK64 EnumSymbolsCallback,
  826. IN PVOID pProc
  827. );
  828. VOID
  829. UpdateProcessStartInfo(
  830. PPROC_TO_MONITOR ProcToMonitor,
  831. PTASK_LIST TaskListEntry,
  832. BOOL bIncludeProcessThreadsInfo
  833. );
  834. VOID
  835. vVerbosePrint(
  836. ULONG Level,
  837. PCCHAR Msg,
  838. ...
  839. );
  840. //MC
  841. //
  842. // Note: CLR currently does not support 64 bit.
  843. //
  844. // AttachToProcess is not reentrant, even for different PIDs!
  845. // only call once and pair with DetachFromProcess.
  846. extern void AttachToProcess(DWORD dwPid);
  847. extern void DetachFromProcess();
  848. // 0 is error
  849. // 1 is normal JIT
  850. // 2 is ngen (prejitted module)
  851. // wszResult contains class/method (string) of given IP address
  852. // Note: The space is allocated by the routine itself!
  853. extern int IP2MD(DWORD_PTR test,WCHAR** wszResult);
  854. // return value is array of DWORDs, stored in pairs, null terminated.
  855. // first dword is start address, second dword is length.
  856. extern DWORD* GetJitRange();
  857. typedef void (*PFN1)(DWORD);
  858. PFN1 pfnAttachToProcess;
  859. typedef void (*PFN2)(VOID);
  860. PFN2 pfnDetachFromProcess;
  861. typedef int (*PFN3)(DWORD_PTR, WCHAR**);
  862. PFN3 pfnIP2MD;
  863. typedef DWORD* (*PFN4)(VOID);
  864. PFN4 pfnGetJitRange;
  865. BOOL
  866. InitializeManagedCodeSupport(
  867. PPROC_TO_MONITOR ProcToMonitor
  868. );
  869. BOOL
  870. JITEnumerateSymbols(
  871. IN PMODULE Current,
  872. IN PVOID pProc,
  873. IN DWORD64 BaseOptional,
  874. IN ULONG SizeOptional
  875. );
  876. VOID
  877. OutputJITRangeComparison(
  878. PPROC_TO_MONITOR ProcToMonitor
  879. );
  880. //MC
  881. PCHAR WaitReason [] = {
  882. {"Executive"},
  883. {"FreePage"},
  884. {"PageIn"},
  885. {"PoolAllocation"},
  886. {"DelayExecution"},
  887. {"Suspended"},
  888. {"UserRequest"},
  889. {"WrExecutive"},
  890. {"WrFreePage"},
  891. {"WrPageIn"},
  892. {"WrPoolAllocation"},
  893. {"WrDelayExecution"},
  894. {"WrSuspended"},
  895. {"WrUserRequest"},
  896. {"WrEventPair"},
  897. {"WrQueue"},
  898. {"WrLpcReceive"},
  899. {"WrLpcReply"},
  900. {"WrVirtualMemory"},
  901. {"WrPageOut"},
  902. {"WrRendezvous"},
  903. {"Spare2"},
  904. {"Spare3"},
  905. {"Spare4"},
  906. {"Spare5"},
  907. {"Spare6"},
  908. {"WrKernel"},
  909. {"WrResource"},
  910. {"WrPushLock"},
  911. {"WrMutex"},
  912. {"WrQuantumEnd"},
  913. {"WrDispatchInt"},
  914. {"WrPreempted"},
  915. {"WrYieldExecution"},
  916. {"MaximumWaitReason"}
  917. };
  918. PCHAR ThreadState[] = {
  919. {"Initialized"},
  920. {"Ready"},
  921. {"Running"},
  922. {"Standby"},
  923. {"Terminated"},
  924. {"Waiting"},
  925. {"Transition"},
  926. {"DeferredReady"}
  927. };
  928. #endif /* !KERNRATE_H_INCLUDED */