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