Windows NT 4.0 source code leak
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.

417 lines
7.0 KiB

4 years ago
  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. napdump.c
  5. Module Description:
  6. Dump Nt Api Profiling data.
  7. This is a perverted derivative of teh apfdump.* utility.
  8. Environment:
  9. Windows command line.
  10. Author:
  11. Russ Blake (russbl) 25-Apr-1991
  12. Revision History:
  13. --*/
  14. #include <excpt.h>
  15. #include <nt.h>
  16. #include <ntrtl.h>
  17. #include <nturtl.h>
  18. #undef NULL
  19. #include <stdio.h>
  20. #include <string.h>
  21. #include <direct.h>
  22. #include <sys\types.h>
  23. #include <sys\stat.h>
  24. #include <io.h>
  25. #include <conio.h>
  26. #include <errno.h>
  27. #include <process.h>
  28. #include <ctype.h>
  29. #include <windows.h>
  30. #include <tools.h>
  31. #define MICROSEC_FACTOR 1000000
  32. #define MAX_TIME 0x7fffffffL
  33. //
  34. // Dump switches and defaults
  35. //
  36. BOOLEAN Dump = TRUE; // if not dumping,
  37. // then clearing
  38. CHAR DumpFileName[256] = "ntdll.nap"; // default name
  39. CHAR OutputRecord[132];
  40. CHAR *rgstrUsage[] = {
  41. "Usage: napdump [ {/c | filename } ]",
  42. " Default - data dumped to file named ntdll.nap",
  43. " /c - clear data already collected",
  44. " filename - dump data to filename",
  45. 0};
  46. FILE *DumpFile;
  47. ULONG ApiCount;
  48. NAPDATA *ApiProfilingData;
  49. PCHAR *ApiNames;
  50. PLARGE_INTEGER CounterFreq;
  51. /*++
  52. Usage takes a variable number of strings, terminated by zero,
  53. e.g. Usage ("first ", "second ", 0);
  54. --*/
  55. void
  56. Usage (
  57. CHAR *p,
  58. ...
  59. )
  60. {
  61. CHAR **rgstr;
  62. rgstr = &p;
  63. if (*rgstr) {
  64. fprintf (stderr, "TC: ");
  65. while (*rgstr)
  66. fprintf(stderr, "%s", *rgstr++);
  67. fprintf(stderr, "\n");
  68. }
  69. rgstr = rgstrUsage;
  70. while (*rgstr)
  71. fprintf(stderr, "%s\n", *rgstr++);
  72. exit (1);
  73. }
  74. /*++
  75. ExtractTime()
  76. Extract a time from a large integer, converting it to microseconds
  77. --*/
  78. VOID
  79. ExtractTime (
  80. PLARGE_INTEGER RealTime,
  81. LARGE_INTEGER Time,
  82. LONG Overhead,
  83. ULONG Count
  84. )
  85. {
  86. LARGE_INTEGER ElapsedTime;
  87. LARGE_INTEGER OverheadTime;
  88. ElapsedTime = RtlExtendedIntegerMultiply (Time, MICROSEC_FACTOR);
  89. ElapsedTime = RtlExtendedLargeIntegerDivide (ElapsedTime,
  90. CounterFreq->LowPart,
  91. NULL);
  92. OverheadTime.HighPart = 0;
  93. OverheadTime.LowPart = Count * Overhead;
  94. *RealTime = RtlLargeIntegerSubtract(ElapsedTime, OverheadTime);
  95. }
  96. /*++
  97. AdjustTime
  98. This routine is called to convert long times to smaller times
  99. expressed as multiples of 1024 (= 1K).
  100. --*/
  101. VOID
  102. AdjustTime (
  103. PLARGE_INTEGER Time,
  104. PCHAR Kchar
  105. )
  106. {
  107. if (Time->HighPart != 0) {
  108. if (Time->HighPart>>10 > 0) {
  109. fprintf(DumpFile,
  110. "*** Unexpected timer overflow: %ld \t %lu ***\n",
  111. Time->HighPart,
  112. Time->LowPart);
  113. Time->HighPart = 0;
  114. Time->LowPart = 0;
  115. *Kchar = '?';
  116. } else if (Time->HighPart>>10 < 0) {
  117. fprintf(DumpFile,
  118. "*** Unexpected timer underflow: %ld \t %lu ***\n",
  119. Time->HighPart,
  120. Time->LowPart);
  121. Time->HighPart = 0;
  122. Time->LowPart = 0;
  123. *Kchar = '?';
  124. } else {
  125. Time->LowPart = ((ULONG)(Time->HighPart))<<22 +
  126. Time->LowPart>>10;
  127. *Kchar = 'K';
  128. }
  129. } else {
  130. *Kchar = ' ';
  131. }
  132. }
  133. /*++
  134. Main Routine
  135. --*/
  136. VOID
  137. main (c, v)
  138. int c;
  139. CHAR *v[];
  140. {
  141. ULONG Api;
  142. CHAR *p;
  143. LONG Overhead;
  144. struct {
  145. LONG TotalTime;
  146. LONG FirstTime;
  147. LONG MaxTime;
  148. LONG MinTime;
  149. } ProfData;
  150. LARGE_INTEGER OverheadTime;
  151. LARGE_INTEGER TotalTime;
  152. LARGE_INTEGER PerCallTime;
  153. LARGE_INTEGER FirstTime;
  154. LARGE_INTEGER MaxTime;
  155. LARGE_INTEGER MinTime;
  156. CHAR TotalSuffix;
  157. CHAR PerCallSuffix;
  158. CHAR FirstSuffix;
  159. CHAR MaxSuffix;
  160. CHAR MinSuffix;
  161. SHIFT(c,v);
  162. while (c && fSwitChr (*v[0])) {
  163. p = v[0];
  164. SHIFT(c,v);
  165. while (*++p) {
  166. switch (*p) {
  167. case 'c':
  168. Dump = FALSE;
  169. break;
  170. case '?':
  171. case 'h':
  172. case 'H':
  173. Usage(0);
  174. break;
  175. default:
  176. Usage("Invalid switch - ", p, 0);
  177. }
  178. }
  179. }
  180. if (c > 1) {
  181. Usage("Too many parameters - ", p, 0);
  182. }
  183. if (c == 1) {
  184. strcpy(DumpFileName, v[0]);
  185. }
  186. if (!Dump) {
  187. NapPause();
  188. NapClearData();
  189. NapResume();
  190. }
  191. else {
  192. //
  193. // Stop recording
  194. //
  195. NapPause();
  196. DumpFile = fopen(DumpFileName, "w");
  197. if (!DumpFile) {
  198. Usage("Unable to open output file %s\n", DumpFileName);
  199. }
  200. NapGetApiCount(&ApiCount);
  201. ApiProfilingData = (NAPDATA *) malloc((ApiCount+1) * sizeof(NAPDATA));
  202. NapRetrieveData(ApiProfilingData, &ApiNames, &CounterFreq);
  203. ExtractTime(&OverheadTime, ApiProfilingData[0].MinTime, 0, 0);
  204. //
  205. // Now dump the data; start with the header info
  206. //
  207. fprintf(DumpFile,
  208. "%s: Api profile of nt service routines.\n",
  209. DumpFileName);
  210. fprintf(DumpFile, "All times are in microseconds.\n");
  211. fprintf(DumpFile,
  212. "All times (except Calibration) corrected "
  213. "by %lu microseconds/call.\n",
  214. OverheadTime.LowPart);
  215. fprintf(DumpFile,
  216. "(Note: First Time not included in Max or Min Times)\n\n\n");
  217. fprintf(DumpFile,
  218. "%-32s\t%10s\t%10s\t%10s\t%10s\t%10s\t%10s\t\n\n",
  219. "API Name",
  220. "Num Calls",
  221. "Total Time",
  222. "Time/Call",
  223. "First Time",
  224. "Max Time",
  225. "Min Time");
  226. //
  227. // Dump the data for each api that got used
  228. //
  229. //
  230. // The Calibration Counters (Api = 0) should not be adjusted for
  231. // overhead.
  232. // Note: this is repaired for all api at the end of the for loop.
  233. //
  234. Overhead = 0;
  235. for (Api = 0; Api <= ApiCount; Api++) {
  236. if (ApiProfilingData[Api].Calls >= 1) {
  237. ExtractTime(&TotalTime,
  238. ApiProfilingData[Api].TotalTime,
  239. Overhead,
  240. ApiProfilingData[Api].Calls);
  241. ExtractTime(&FirstTime,
  242. ApiProfilingData[Api].FirstTime,
  243. Overhead, 1);
  244. AdjustTime(&TotalTime,&TotalSuffix);
  245. PerCallTime.HighPart = 0;
  246. PerCallTime.LowPart = TotalTime.LowPart /
  247. ApiProfilingData[Api].Calls;
  248. PerCallSuffix = TotalSuffix;
  249. AdjustTime(&FirstTime,&FirstSuffix);
  250. if (ApiProfilingData[Api].Calls > 1) {
  251. ExtractTime(&MaxTime,
  252. ApiProfilingData[Api].MaxTime,
  253. Overhead, 1);
  254. ExtractTime(&MinTime,
  255. ApiProfilingData[Api].MinTime,
  256. Overhead, 1);
  257. AdjustTime(&MaxTime,&MaxSuffix);
  258. AdjustTime(&MinTime,&MinSuffix);
  259. fprintf(DumpFile,
  260. "%-32s\t%10lu\t%10lu%1c\t%10lu%1c\t%10lu%1c"
  261. "\t%10lu%1c\t%10lu%1c\n",
  262. ApiNames[Api],
  263. ApiProfilingData[Api].Calls,
  264. TotalTime.LowPart,
  265. TotalSuffix,
  266. PerCallTime.LowPart,
  267. PerCallSuffix,
  268. FirstTime.LowPart,
  269. FirstSuffix,
  270. MaxTime.LowPart,
  271. MaxSuffix,
  272. MinTime.LowPart,
  273. MinSuffix);
  274. }
  275. else if (ApiProfilingData[Api].Calls == 1) {
  276. fprintf(DumpFile,
  277. "%-32s\t%10lu\t%10lu%1c\t%10lu%1c\t%10lu%1c"
  278. "\t%10s\t%10s\n",
  279. ApiNames[Api],
  280. ApiProfilingData[Api].Calls,
  281. TotalTime.LowPart,
  282. TotalSuffix,
  283. PerCallTime.LowPart,
  284. PerCallSuffix,
  285. FirstTime.LowPart,
  286. FirstSuffix,
  287. "n/a",
  288. "n/a");
  289. }
  290. }
  291. Overhead = OverheadTime.LowPart;
  292. }
  293. //
  294. // Start collecting data again
  295. //
  296. free(ApiProfilingData);
  297. NapResume();
  298. fclose(DumpFile);
  299. }
  300. }