]> git.proxmox.com Git - mirror_edk2.git/blame - PerformancePkg/Dp_App/DpTrace.c
Libraries and utilities for instrumenting regions of code and measuring their perform...
[mirror_edk2.git] / PerformancePkg / Dp_App / DpTrace.c
CommitLineData
c06ad33e 1/** @file\r
2 * Trace reporting for the Dp utility.\r
3 *\r
4 * Copyright (c) 2009-2010, Intel Corporation. All rights reserved.<BR>\r
5 * This program and the accompanying materials\r
6 * are licensed and made available under the terms and conditions of the BSD License\r
7 * which accompanies this distribution. The full text of the license may be found at\r
8 * http://opensource.org/licenses/bsd-license.php\r
9 *\r
10 * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12**/\r
13\r
14#include <Library/BaseLib.h>\r
15#include <Library/BaseMemoryLib.h>\r
16#include <Library/MemoryAllocationLib.h>\r
17#include <Library/DebugLib.h>\r
18#include <Library/UefiBootServicesTableLib.h>\r
19#include <Library/TimerLib.h>\r
20#include <Library/PeCoffGetEntryPointLib.h>\r
21#include <Library/PerformanceLib.h>\r
22#include <Library/PrintLib.h>\r
23#include <Library/HiiLib.h>\r
24#include <Library/PcdLib.h>\r
25\r
26#include <Guid/Performance.h>\r
27\r
28#include "Dp.h"\r
29#include "Literals.h"\r
30#include "DpInternal.h"\r
31\r
32/** Collect verbose statistics about the logged performance measurements.\r
33 *\r
34 * General Summary information for all Trace measurements is gathered and\r
35 * stored within the SummaryData structure. This information is both\r
36 * used internally by subsequent reporting functions, and displayed\r
37 * at the end of verbose reports.\r
38 *\r
39 * @pre The SummaryData and CumData structures must be initialized\r
40 * prior to calling this function.\r
41 *\r
42 * @post The SummaryData and CumData structures contain statistics for the\r
43 * current performance logs.\r
44**/\r
45VOID\r
46GatherStatistics(\r
47 VOID\r
48)\r
49{\r
50 MEASUREMENT_RECORD Measurement;\r
51 UINT64 Duration;\r
52 UINTN LogEntryKey;\r
53 UINTN TIndex;\r
54\r
55 LogEntryKey = 0;\r
56 while ((LogEntryKey = GetPerformanceMeasurement (\r
57 LogEntryKey,\r
58 &Measurement.Handle,\r
59 &Measurement.Token,\r
60 &Measurement.Module,\r
61 &Measurement.StartTimeStamp,\r
62 &Measurement.EndTimeStamp)) != 0)\r
63 {\r
64 ++SummaryData.NumTrace; // Count the number of TRACE Measurement records\r
65 if (Measurement.EndTimeStamp == 0) {\r
66 ++SummaryData.NumIncomplete; // Count the incomplete records\r
67 continue;\r
68 }\r
69\r
70 if (Measurement.Handle != NULL) {\r
71 ++SummaryData.NumHandles; // Count the number of measurements with non-NULL handles\r
72 }\r
73\r
74 if (IsPhase( &Measurement)) {\r
75 ++SummaryData.NumSummary; // Count the number of major phases\r
76 }\r
77 else { // !IsPhase(...\r
78 if(Measurement.Handle == NULL) {\r
79 ++SummaryData.NumGlobal;\r
80 }\r
81 }\r
82\r
83 if (AsciiStrnCmp (Measurement.Token, ALit_PEIM, PERF_TOKEN_LENGTH) == 0) {\r
84 ++SummaryData.NumPEIMs; // Count PEIM measurements\r
85 }\r
86\r
87 Duration = GetDuration (&Measurement);\r
88 TIndex = GetCumulativeItem (&Measurement);\r
89 if (TIndex >= 0) {\r
90 CumData[TIndex].Duration += Duration;\r
91 CumData[TIndex].Count++;\r
92 if ( Duration < CumData[TIndex].MinDur ) {\r
93 CumData[TIndex].MinDur = Duration;\r
94 }\r
95 if ( Duration > CumData[TIndex].MaxDur ) {\r
96 CumData[TIndex].MaxDur = Duration;\r
97 }\r
98 }\r
99 }\r
100}\r
101\r
102/** Gather and print ALL Trace Records.\r
103 *\r
104 * Displays all "interesting" Trace measurements in order.<BR>\r
105 * The number of records displayed is controlled by:\r
106 * - records with a duration less than mInterestThreshold microseconds are not displayed.\r
107 * - No more than Limit records are displayed. A Limit of zero will not limit the output.\r
108 * - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not\r
109 * displayed.\r
110 *\r
111 * @pre The mInterestThreshold global variable is set to the shortest duration to be printed.\r
112 * The mGaugeString and mUnicodeToken global arrays are used for temporary string storage.\r
113 * They must not be in use by a calling function.\r
114 *\r
115 * @param[in] Limit The number of records to print. Zero is ALL.\r
116 * @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display.\r
117 *\r
118**/\r
119VOID\r
120DumpAllTrace(\r
121 IN UINTN Limit,\r
122 IN BOOLEAN ExcludeFlag\r
123 )\r
124{\r
125 MEASUREMENT_RECORD Measurement;\r
126 UINT64 ElapsedTime;\r
127 UINT64 Duration;\r
128 const CHAR16 *IncFlag;\r
129 UINTN LogEntryKey;\r
130 UINTN Count;\r
131 UINTN Index;\r
132 UINTN TIndex;\r
133\r
134 EFI_HANDLE *HandleBuffer;\r
135 UINTN Size;\r
136 EFI_HANDLE TempHandle;\r
137 EFI_STATUS Status;\r
138\r
139 IncFlag = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_ALL), NULL);\r
140 PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),\r
141 (IncFlag == NULL) ? ALit_UNKNOWN: IncFlag);\r
142\r
143 // Get Handle information\r
144 //\r
145 Size = 0;\r
146 HandleBuffer = NULL;\r
147 Status = gBS->LocateHandle (AllHandles, NULL, NULL, &Size, &TempHandle);\r
148 if (Status == EFI_BUFFER_TOO_SMALL) {\r
149 HandleBuffer = AllocatePool (Size);\r
150 ASSERT (HandleBuffer != NULL);\r
151 Status = gBS->LocateHandle (AllHandles, NULL, NULL, &Size, HandleBuffer);\r
152 }\r
153 if (EFI_ERROR (Status)) {\r
154 PrintToken (STRING_TOKEN (STR_DP_HANDLES_ERROR), Status);\r
155 }\r
156 else {\r
157 // We have successfully populated the HandleBuffer\r
158 // Display ALL Measurement Records\r
159 // Up to Limit lines displayed\r
160 // Display only records with Elapsed times >= mInterestThreshold\r
161 // Display driver names in Module field for records with Handles.\r
162 //\r
163 PrintToken (STRING_TOKEN (STR_DP_ALL_HEADR) );\r
164 PrintToken (STRING_TOKEN (STR_DP_DASHES) );\r
165\r
166 LogEntryKey = 0;\r
167 Count = 0;\r
168 Index = 0;\r
169 while ( WITHIN_LIMIT(Count, Limit) &&\r
170 ((LogEntryKey = GetPerformanceMeasurement (\r
171 LogEntryKey,\r
172 &Measurement.Handle,\r
173 &Measurement.Token,\r
174 &Measurement.Module,\r
175 &Measurement.StartTimeStamp,\r
176 &Measurement.EndTimeStamp)) != 0)\r
177 )\r
178 {\r
179 ++Index; // Count every record. First record is 1.\r
180 ElapsedTime = 0;\r
181 if (Measurement.EndTimeStamp != 0) {\r
182 Duration = GetDuration (&Measurement);\r
183 ElapsedTime = DurationInMicroSeconds ( Duration );\r
184 IncFlag = STR_DP_COMPLETE;\r
185 }\r
186 else {\r
187 IncFlag = STR_DP_INCOMPLETE; // Mark incomplete records\r
188 }\r
189 if ((ElapsedTime < mInterestThreshold) ||\r
190 ((ExcludeFlag) && (GetCumulativeItem(&Measurement) >= 0))\r
191 ) { // Ignore "uninteresting" or excluded records\r
192 continue;\r
193 }\r
194 if (Measurement.EndTimeStamp == 0) {\r
195 ElapsedTime = Measurement.StartTimeStamp;\r
196 }\r
197 ++Count; // Count the number of records printed\r
198\r
199 // If Handle is non-zero, see if we can determine a name for the driver\r
200 AsciiStrToUnicodeStr (Measurement.Module, mGaugeString); // Use Module by default\r
201 AsciiStrToUnicodeStr (Measurement.Token, mUnicodeToken);\r
202 if (Measurement.Handle != NULL) {\r
203 // See if the Handle is in the HandleBuffer\r
204 for (TIndex = 0; TIndex < (Size / sizeof(HandleBuffer[0])); TIndex++) {\r
205 if (Measurement.Handle == HandleBuffer[TIndex]) {\r
206 GetNameFromHandle (HandleBuffer[TIndex]);\r
207 break;\r
208 }\r
209 }\r
210 }\r
211 // Ensure that the argument strings are not too long.\r
212 mGaugeString[31] = 0;\r
213 mUnicodeToken[18] = 0;\r
214\r
215 PrintToken( STRING_TOKEN (STR_DP_ALL_STATS),\r
216 Index, // 1 based, Which measurement record is being printed\r
217 IncFlag,\r
218 Measurement.Handle,\r
219 mGaugeString,\r
220 mUnicodeToken,\r
221 ElapsedTime\r
222 );\r
223 }\r
224 }\r
225 FreePool (HandleBuffer);\r
226}\r
227\r
228/** Gather and print Raw Trace Records.\r
229 *\r
230 * All Trace measurements with a duration greater than or equal to\r
231 * mInterestThreshold are printed without interpretation.\r
232 *\r
233 * The number of records displayed is controlled by:\r
234 * - records with a duration less than mInterestThreshold microseconds are not displayed.\r
235 * - No more than Limit records are displayed. A Limit of zero will not limit the output.\r
236 * - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not\r
237 * displayed.\r
238 *\r
239 * @pre The mInterestThreshold global variable is set to the shortest duration to be printed.\r
240 *\r
241 * @param[in] Limit The number of records to print. Zero is ALL.\r
242 * @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display.\r
243 *\r
244**/\r
245VOID\r
246DumpRawTrace(\r
247 IN UINTN Limit,\r
248 IN BOOLEAN ExcludeFlag\r
249 )\r
250{\r
251 MEASUREMENT_RECORD Measurement;\r
252 UINT64 ElapsedTime;\r
253 UINT64 Duration;\r
254 UINTN LogEntryKey;\r
255 UINTN Count;\r
256 UINTN Index;\r
257\r
258 EFI_STRING StringPtr;\r
259\r
260 StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_RAWTRACE), NULL);\r
261 PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),\r
262 (StringPtr == NULL) ? ALit_UNKNOWN: StringPtr);\r
263\r
264 PrintToken (STRING_TOKEN (STR_DP_RAW_HEADR) );\r
265 PrintToken (STRING_TOKEN (STR_DP_RAW_DASHES) );\r
266\r
267 LogEntryKey = 0;\r
268 Count = 0;\r
269 Index = 0;\r
270 while ( WITHIN_LIMIT(Count, Limit) &&\r
271 ((LogEntryKey = GetPerformanceMeasurement (\r
272 LogEntryKey,\r
273 &Measurement.Handle,\r
274 &Measurement.Token,\r
275 &Measurement.Module,\r
276 &Measurement.StartTimeStamp,\r
277 &Measurement.EndTimeStamp)) != 0)\r
278 )\r
279 {\r
280 ++Index; // Count every record. First record is 1.\r
281 ElapsedTime = 0;\r
282 if (Measurement.EndTimeStamp != 0) {\r
283 Duration = GetDuration (&Measurement);\r
284 ElapsedTime = DurationInMicroSeconds ( Duration );\r
285 }\r
286 if ((ElapsedTime < mInterestThreshold) ||\r
287 ((ExcludeFlag) && (GetCumulativeItem(&Measurement) >= 0))\r
288 ) { // Ignore "uninteresting" or Excluded records\r
289 continue;\r
290 }\r
291 ++Count; // Count the number of records printed\r
292 PrintToken (STRING_TOKEN (STR_DP_RAW_VARS),\r
293 Index, // 1 based, Which measurement record is being printed\r
294 Measurement.Handle,\r
295 Measurement.StartTimeStamp,\r
296 Measurement.EndTimeStamp,\r
297 Measurement.Token,\r
298 Measurement.Module\r
299 );\r
300 }\r
301}\r
302\r
303/** Gather and print Major Phase metrics.\r
304 *\r
305 * @param[in] Ticker The timer value for the END of Shell phase\r
306 *\r
307**/\r
308VOID\r
309ProcessPhases(\r
310 UINT64 Ticker\r
311 )\r
312{\r
313 MEASUREMENT_RECORD Measurement;\r
314 UINT64 BdsTimeoutValue = 0;\r
315 UINT64 SecTime = 0;\r
316 UINT64 PeiTime = 0;\r
317 UINT64 DxeTime = 0;\r
318 UINT64 BdsTime = 0;\r
319 UINT64 ShellTime = 0;\r
320 UINT64 ElapsedTime;\r
321 UINT64 Duration;\r
322 UINT64 Total;\r
323 EFI_STRING StringPtr;\r
324 UINTN LogEntryKey;\r
325\r
326 //\r
327 // Get Execution Phase Statistics\r
328 //\r
329 StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_PHASES), NULL);\r
330 PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),\r
331 (StringPtr == NULL) ? ALit_UNKNOWN: StringPtr);\r
332\r
333 LogEntryKey = 0;\r
334 while ((LogEntryKey = GetPerformanceMeasurement (\r
335 LogEntryKey,\r
336 &Measurement.Handle,\r
337 &Measurement.Token,\r
338 &Measurement.Module,\r
339 &Measurement.StartTimeStamp,\r
340 &Measurement.EndTimeStamp)) != 0)\r
341 {\r
342 if (AsciiStrnCmp (Measurement.Token, ALit_SHELL, PERF_TOKEN_LENGTH) == 0) {\r
343 Measurement.EndTimeStamp = Ticker;\r
344 }\r
345 if (Measurement.EndTimeStamp == 0) { // Skip "incomplete" records\r
346 continue;\r
347 }\r
348 Duration = GetDuration (&Measurement);\r
349 if ( Measurement.Handle != NULL\r
350 && (AsciiStrnCmp (Measurement.Token, ALit_BdsTO, PERF_TOKEN_LENGTH) == 0)\r
351 )\r
352 {\r
353 BdsTimeoutValue = Duration;\r
354 } else if (AsciiStrnCmp (Measurement.Token, ALit_SEC, PERF_TOKEN_LENGTH) == 0) {\r
355 SecTime = Duration;\r
356 } else if (AsciiStrnCmp (Measurement.Token, ALit_PEI, PERF_TOKEN_LENGTH) == 0) {\r
357 PeiTime = Duration;\r
358 } else if (AsciiStrnCmp (Measurement.Token, ALit_DXE, PERF_TOKEN_LENGTH) == 0) {\r
359 DxeTime = Duration;\r
360 } else if (AsciiStrnCmp (Measurement.Token, ALit_BDS, PERF_TOKEN_LENGTH) == 0) {\r
361 BdsTime = Duration;\r
362 } else if (AsciiStrnCmp (Measurement.Token, ALit_SHELL, PERF_TOKEN_LENGTH) == 0) {\r
363 ShellTime = Duration;\r
364 }\r
365 }\r
366\r
367 Total = 0;\r
368\r
369 // print SEC phase duration time\r
370 //\r
371 if (SecTime > 0) {\r
372 ElapsedTime = DurationInMicroSeconds ( SecTime ); // Calculate elapsed time in microseconds\r
373 Total += DivU64x32 (ElapsedTime, 1000); // Accumulate time in milliseconds\r
374 PrintToken (STRING_TOKEN (STR_DP_SEC_PHASE), ElapsedTime);\r
375 }\r
376\r
377 // print PEI phase duration time\r
378 //\r
379 if (PeiTime > 0) {\r
380 ElapsedTime = DivU64x32 (\r
381 PeiTime,\r
382 (UINT32)TimerInfo.Frequency\r
383 );\r
384 Total += ElapsedTime;\r
385 PrintToken (STRING_TOKEN (STR_DP_PHASE_DURATION), ALit_PEI, ElapsedTime);\r
386 }\r
387\r
388 // print DXE phase duration time\r
389 //\r
390 if (DxeTime > 0) {\r
391 ElapsedTime = DivU64x32 (\r
392 DxeTime,\r
393 (UINT32)TimerInfo.Frequency\r
394 );\r
395 Total += ElapsedTime;\r
396 PrintToken (STRING_TOKEN (STR_DP_PHASE_DURATION), ALit_DXE, ElapsedTime);\r
397 }\r
398\r
399 // print BDS phase duration time\r
400 //\r
401 if (BdsTime > 0) {\r
402 ElapsedTime = DivU64x32 (\r
403 BdsTime,\r
404 (UINT32)TimerInfo.Frequency\r
405 );\r
406 Total += ElapsedTime;\r
407 PrintToken (STRING_TOKEN (STR_DP_PHASE_DURATION), ALit_BDS, ElapsedTime);\r
408 }\r
409\r
410 if (BdsTimeoutValue > 0) {\r
411 ElapsedTime = DivU64x32 (\r
412 BdsTimeoutValue,\r
413 (UINT32)TimerInfo.Frequency\r
414 );\r
415 PrintToken (STRING_TOKEN (STR_DP_PHASE_BDSTO), ALit_BdsTO, ElapsedTime);\r
416 }\r
417\r
418 // print SHELL phase duration time\r
419 //\r
420 if (ShellTime > 0) {\r
421 ElapsedTime = DivU64x32 (\r
422 ShellTime,\r
423 (UINT32)TimerInfo.Frequency\r
424 );\r
425 Total += ElapsedTime;\r
426 PrintToken (STRING_TOKEN (STR_DP_PHASE_DURATION), ALit_SHELL, ElapsedTime);\r
427 }\r
428\r
429 PrintToken (STRING_TOKEN (STR_DP_TOTAL_DURATION), Total);\r
430}\r
431\r
432/** Gather and print Handle data.\r
433 *\r
434 * @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display.\r
435 *\r
436 * @return Status from a call to gBS->LocateHandle().\r
437**/\r
438EFI_STATUS\r
439ProcessHandles(\r
440 IN BOOLEAN ExcludeFlag\r
441 )\r
442{\r
443 MEASUREMENT_RECORD Measurement;\r
444 UINT64 ElapsedTime;\r
445 UINT64 Duration;\r
446 EFI_HANDLE *HandleBuffer;\r
447 EFI_STRING StringPtr;\r
448 UINTN Index;\r
449 UINTN LogEntryKey;\r
450 UINTN Count;\r
451 UINTN Size;\r
452 EFI_HANDLE TempHandle;\r
453 EFI_STATUS Status;\r
454\r
455 StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_DRIVERS), NULL);\r
456 PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),\r
457 (StringPtr == NULL) ? ALit_UNKNOWN: StringPtr);\r
458\r
459 Size = 0;\r
460 HandleBuffer = NULL;\r
461 Status = gBS->LocateHandle (AllHandles, NULL, NULL, &Size, &TempHandle);\r
462 if (Status == EFI_BUFFER_TOO_SMALL) {\r
463 HandleBuffer = AllocatePool (Size);\r
464 ASSERT (HandleBuffer != NULL);\r
465 Status = gBS->LocateHandle (AllHandles, NULL, NULL, &Size, HandleBuffer);\r
466 }\r
467 if (EFI_ERROR (Status)) {\r
468 PrintToken (STRING_TOKEN (STR_DP_HANDLES_ERROR), Status);\r
469 }\r
470 else {\r
471#if DP_DEBUG == 2\r
472 Print (L"There are %,d Handles defined.\n", (Size / sizeof(HandleBuffer[0])));\r
473#endif\r
474\r
475 PrintToken (STRING_TOKEN (STR_DP_HANDLE_GUID) );\r
476 PrintToken (STRING_TOKEN (STR_DP_DASHES) );\r
477\r
478 LogEntryKey = 0;\r
479 Count = 0;\r
480 while ((LogEntryKey = GetPerformanceMeasurement (\r
481 LogEntryKey,\r
482 &Measurement.Handle,\r
483 &Measurement.Token,\r
484 &Measurement.Module,\r
485 &Measurement.StartTimeStamp,\r
486 &Measurement.EndTimeStamp)) != 0)\r
487 {\r
488 Count++;\r
489 Duration = GetDuration (&Measurement);\r
490 ElapsedTime = DurationInMicroSeconds ( Duration );\r
491 if ((ElapsedTime < mInterestThreshold) ||\r
492 (Measurement.EndTimeStamp == 0) ||\r
493 (Measurement.Handle == NULL) ||\r
494 ((ExcludeFlag) && (GetCumulativeItem(&Measurement) >= 0))\r
495 ) { // Ignore "uninteresting" or excluded records\r
496 continue;\r
497 }\r
498 mGaugeString[0] = 0; // Empty driver name by default\r
499 AsciiStrToUnicodeStr (Measurement.Token, mUnicodeToken);\r
500 // See if the Handle is in the HandleBuffer\r
501 for (Index = 0; Index < (Size / sizeof(HandleBuffer[0])); Index++) {\r
502 if (Measurement.Handle == HandleBuffer[Index]) {\r
503 GetNameFromHandle (HandleBuffer[Index]); // Name is put into mGaugeString\r
504 break;\r
505 }\r
506 }\r
507 // Ensure that the argument strings are not too long.\r
508 mGaugeString[31] = 0;\r
509 mUnicodeToken[18] = 0;\r
510 if (mGaugeString[0] != 0) {\r
511 // Display the record if it has a valid handle.\r
512 PrintToken (\r
513 STRING_TOKEN (STR_DP_HANDLE_VARS),\r
514 Count, // 1 based, Which measurement record is being printed\r
515 Index + 1, // 1 based, Which handle is being printed\r
516 mGaugeString,\r
517 mUnicodeToken,\r
518 ElapsedTime\r
519 );\r
520 }\r
521 }\r
522 }\r
523 FreePool (HandleBuffer);\r
524 return Status;\r
525}\r
526\r
527/** Gather and print PEIM data.\r
528 *\r
529 * Only prints complete PEIM records\r
530 *\r
531**/\r
532VOID\r
533ProcessPeims(\r
534 VOID\r
535)\r
536{\r
537 MEASUREMENT_RECORD Measurement;\r
538 UINT64 Duration;\r
539 UINT64 ElapsedTime;\r
540 EFI_STRING StringPtr;\r
541 UINTN LogEntryKey;\r
542 UINTN TIndex;\r
543\r
544\r
545 StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_PEIMS), NULL);\r
546 PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),\r
547 (StringPtr == NULL) ? ALit_UNKNOWN: StringPtr);\r
548\r
549 PrintToken (STRING_TOKEN (STR_DP_PEIM_SECTION));\r
550 PrintToken (STRING_TOKEN (STR_DP_DASHES));\r
551 TIndex = 0;\r
552 LogEntryKey = 0;\r
553 while ((LogEntryKey = GetPerformanceMeasurement (\r
554 LogEntryKey,\r
555 &Measurement.Handle,\r
556 &Measurement.Token,\r
557 &Measurement.Module,\r
558 &Measurement.StartTimeStamp,\r
559 &Measurement.EndTimeStamp)) != 0)\r
560 {\r
561 TIndex++;\r
562 if ((Measurement.EndTimeStamp == 0) ||\r
563 (AsciiStrnCmp (Measurement.Token, ALit_PEIM, PERF_TOKEN_LENGTH) != 0)\r
564 ) {\r
565 continue;\r
566 }\r
567\r
568 Duration = GetDuration (&Measurement);\r
569 ElapsedTime = DurationInMicroSeconds ( Duration ); // Calculate elapsed time in microseconds\r
570 if (ElapsedTime >= mInterestThreshold) {\r
571 GetNameFromHandle (Measurement.Handle); // Name placed in mGaugeString\r
572 PrintToken (STRING_TOKEN (STR_DP_PEIM_STAT2),\r
573 TIndex, // 1 based, Which measurement record is being printed\r
574 Measurement.Handle,\r
575 mGaugeString,\r
576 ElapsedTime\r
577 );\r
578 }\r
579 }\r
580}\r
581\r
582/** Gather and print global data.\r
583 *\r
584 * Strips out incomplete or "Execution Phase" records\r
585 * Only prints records where Handle is NULL\r
586 * Increment TIndex for every record, even skipped ones, so that we have an\r
587 * indication of every measurement record taken.\r
588 *\r
589 *\r
590**/\r
591VOID\r
592ProcessGlobal(\r
593 VOID\r
594)\r
595{\r
596 MEASUREMENT_RECORD Measurement;\r
597 UINT64 Duration;\r
598 UINT64 ElapsedTime;\r
599 EFI_STRING StringPtr;\r
600 UINTN LogEntryKey;\r
601 UINTN Index; // Index, or number, of the measurement record being processed\r
602\r
603 StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_GENERAL), NULL);\r
604 PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),\r
605 (StringPtr == NULL) ? ALit_UNKNOWN: StringPtr);\r
606\r
607 PrintToken (STRING_TOKEN (STR_DP_GLOBAL_SECTION));\r
608 PrintToken (STRING_TOKEN (STR_DP_DASHES));\r
609\r
610 Index = 1;\r
611 LogEntryKey = 0;\r
612\r
613 while ((LogEntryKey = GetPerformanceMeasurement (\r
614 LogEntryKey,\r
615 &Measurement.Handle,\r
616 &Measurement.Token,\r
617 &Measurement.Module,\r
618 &Measurement.StartTimeStamp,\r
619 &Measurement.EndTimeStamp)) != 0)\r
620 {\r
621 AsciiStrToUnicodeStr (Measurement.Module, mGaugeString);\r
622 AsciiStrToUnicodeStr (Measurement.Token, mUnicodeToken);\r
623 if ( ! ( IsPhase( &Measurement) ||\r
624 (Measurement.Handle != NULL) ||\r
625 (Measurement.EndTimeStamp == 0)\r
626 ))\r
627 {\r
628 Duration = GetDuration (&Measurement);\r
629 ElapsedTime = DurationInMicroSeconds ( Duration );\r
630 if (ElapsedTime >= mInterestThreshold) {\r
631 PrintToken (\r
632 STRING_TOKEN (STR_DP_FOUR_VARS_2),\r
633 Index,\r
634 mGaugeString,\r
635 mUnicodeToken,\r
636 ElapsedTime\r
637 );\r
638 }\r
639 }\r
640 Index++;\r
641 }\r
642}\r
643\r
644/** Gather and print cumulative data.\r
645 *\r
646 * Traverse the measurement records and:<BR>\r
647 * For each record with a Token listed in the CumData array:<BR>\r
648 * - Update the instance count and the total, minimum, and maximum durations.\r
649 * Finally, print the gathered cumulative statistics.\r
650 *\r
651**/\r
652VOID\r
653ProcessCumulative(\r
654 VOID\r
655)\r
656{\r
657 UINT64 avgval; // the computed average duration\r
658 EFI_STRING StringPtr;\r
659 UINTN TIndex;\r
660\r
661\r
662 StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_CUMULATIVE), NULL);\r
663 PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),\r
664 (StringPtr == NULL) ? ALit_UNKNOWN: StringPtr);\r
665\r
666 PrintToken (STRING_TOKEN (STR_DP_CUMULATIVE_SECT_1));\r
667 PrintToken (STRING_TOKEN (STR_DP_CUMULATIVE_SECT_2));\r
668 PrintToken (STRING_TOKEN (STR_DP_DASHES));\r
669\r
670 for ( TIndex = 0; TIndex < NumCum; ++TIndex) {\r
671 avgval = DivU64x32 (CumData[TIndex].Duration, CumData[TIndex].Count);\r
672 PrintToken (STRING_TOKEN (STR_DP_CUMULATIVE_STATS),\r
673 CumData[TIndex].Name,\r
674 CumData[TIndex].Count,\r
675 DurationInMicroSeconds(CumData[TIndex].Duration),\r
676 DurationInMicroSeconds(avgval),\r
677 DurationInMicroSeconds(CumData[TIndex].MinDur),\r
678 DurationInMicroSeconds(CumData[TIndex].MaxDur)\r
679 );\r
680 }\r
681}\r