Laszlo, I can help with the usage review and API proposals for this new lib class.
I agree that the caching of GetPerformanceCounterProperties() can be handled in the TimerLib instances. We just need to make sure existing and new instances actually do this as needed. Mike > -----Original Message----- > From: Laszlo Ersek [mailto:[email protected]] > Sent: Wednesday, August 16, 2017 11:24 AM > To: Kinney, Michael D <[email protected]>; Gao, Liming > <[email protected]> > Cc: edk2-devel-01 <[email protected]> > Subject: Re: [edk2] TimerTickDiffLib for MdePkg? > > Mike, > > On 08/16/17 20:01, Kinney, Michael D wrote: > > Hi Laszlo, > > > > I agree with the complexity of handling the combinations. > > > > A single implementation of a new lib class that provides > > helper functions on top of TimerLib class would be valuable. > > > > There is another code pattern we may also want to review to > see > > if adding more helper functions would also have value. > Modules > > that have APIs or loops with a timeout need to know when the > > timeout has been reached with good accuracy and low overhead. > > A couple of examples are: > > > > MdePkg\Library\BaseSynchronizationLib\Synchronization.c: 94 > > AcquireSpinLock() > > > > UefiCpuPkg\Library\MpInitLib\MpLib.c: 1052 > > CheckTimeout() > > > > We can search the repos for calls to > GetPerformanceCounterProperties() > > to find the types of helper functions that might be valuable. > > This sounds very valuable, but a bit larger bite than I expected > :) > > > There are a couple of approaches on timeouts. One is to wait > > until the tick difference reaches the timeout. This works if > > the timeout does not exceed the number of ticks that the > > TimerLib counter rolls over. The second approach is to > accumulate > > the number of ticks that have elapsed within the loop to > support > > timeouts that are longer that the TimerLibs rollover count. > > > > We may also want to consider multiple INF files for this > library. > > Calling GetPerformanceCounterProperties() is extra overhead. > If > > we are executing from RAM and can use global variables, then > we can > > call GetPerformanceCounterProperties() once and cache the > results in > > global variables. > > I thought of this. However, I figured the TimerLib instances > themselves > would make the same distinction (for example, we make a similar > distinction in OvmfPkg, with "BaseRomAcpiTimerLib.inf", > "BaseAcpiTimerLib.inf", and "DxeAcpiTimerLib.inf"). > > Once a TimerLib instance -- e.g. for DXE and later -- caches the > data > needed by GetPerformanceCounterProperties(), any caching layered > on top > becomes a waste. > > So my idea was to let the TimerLib instance cache whatever it > can, > internally to GetPerformanceCounterProperties(). This would be > justified > anyway, considering the current callers of > GetPerformanceCounterProperties(). > > > We only need to call GetPerformanceCounterProperties() > > if the code is XIP from NV storage. An example of this > technique is > > in the implementation of > InternalGetPerformanceCounterFrequency() > > in PcAtChipsetPkg\Library\AcpiTimerLib. There is a Base and > Dxe > > version of this TimerLib. The Dxe one only does the work to > > determine the frequency of the timer once and saves it in a > global > > variable. > > Right. My argument is, if the StartValue and EndValue output > parameters > of GetPerformanceCounterProperties() are not constants, but > require > hardware access and/or some calculation, then a DXE TimerLib > instance > can cache those values as well, not just the frequency. > > So calling GetPerformanceCounterProperties() every time would > add > basically no overhead (while caching the results of > GetPerformanceCounterProperties() could easily lead to duplicate > caching > -- internal and external). > > Thanks, > Laszlo > > > > > Best regards, > > > > Mike > > > >> -----Original Message----- > >> From: edk2-devel [mailto:[email protected]] On > >> Behalf Of Laszlo Ersek > >> Sent: Wednesday, August 16, 2017 9:09 AM > >> To: Kinney, Michael D <[email protected]>; Gao, > Liming > >> <[email protected]> > >> Cc: edk2-devel-01 <[email protected]> > >> Subject: Re: [edk2] TimerTickDiffLib for MdePkg? > >> > >> On 08/16/17 17:41, Kinney, Michael D wrote: > >>> Laszlo, > >>> > >>> The TimerLib already has the following API. > >>> > >>> /** > >>> Converts elapsed ticks of performance counter to time in > >> nanoseconds. > >>> > >>> This function converts the elapsed ticks of running > >> performance counter to > >>> time value in unit of nanoseconds. > >>> > >>> @param Ticks The number of elapsed ticks of running > >> performance counter. > >>> > >>> @return The elapsed time in nanoseconds. > >>> > >>> **/ > >>> UINT64 > >>> EFIAPI > >>> GetTimeInNanoSecond ( > >>> IN UINT64 Ticks > >>> ); > >>> > >>> I think a couple macros on top of this API could provide the > >> microsecond > >>> and millisecond units. > >> > >> I'm aware of GetTimeInNanoSecond(), and I agree that some > macros > >> on top > >> would be sufficient for providing usec and msec wrappers. > >> > >> However, such wrappers are not the main point of this > library. > >> > >> The main difficulty with using GetTimeInNanoSecond() is that > the > >> caller > >> has to calculate the "Ticks" parameter. In theory, this is a > >> simple > >> difference, such as: > >> > >> // > >> // fetch the start tick > >> // > >> PerformanceCounterStart = GetPerformanceCounter (); > >> // > >> // do some work, then fetch the stop tick > >> // > >> PerformanceCounterStop = GetPerformanceCounter (); > >> // > >> // calculate tick difference > >> // > >> Ticks = PerformanceCounterStop - PerformanceCounterStart; > >> // > >> // get elapsed time > >> // > >> NanoSeconds = GetTimeInNanoSecond (Ticks); > >> > >> However, the Ticks parameter cannot be calculated as naively > as > >> written > >> above, for two reasons: > >> > >> - The performance counter can wrap around while doing the > work. > >> - The performance counter can be counting down as time > >> progresses. > >> > >> Therefore the simple subtraction for Ticks has to be replaced > >> every time > >> with an elaborate four-branched check; for every variation of > >> > >> { counts up, counts down } x { wrapped around, did not wrap > >> around } > >> > >> Additionally, in order to determine the counting direction, > and > >> the > >> boundaries that have to be considered in case of wrap-around, > >> GetPerformanceCounterProperties() must be called first. > >> > >> Extracting this logic is the main point of the library -- > please > >> see the > >> GetTickDifference() function. The rest is just convenience > >> fluff. > >> > >> Thanks > >> Laszlo > >> > >>>> -----Original Message----- > >>>> From: Laszlo Ersek [mailto:[email protected]] > >>>> Sent: Wednesday, August 16, 2017 4:46 AM > >>>> To: Kinney, Michael D <[email protected]>; Gao, > >> Liming > >>>> <[email protected]> > >>>> Cc: edk2-devel-01 <[email protected]> > >>>> Subject: TimerTickDiffLib for MdePkg? > >>>> > >>>> Hi, > >>>> > >>>> edk2 code frequently needs to calculate a time difference > (in > >>>> nano-, > >>>> micro-, or milliseconds) between two timer tick values > >> retrieved > >>>> with > >>>> TimerLib's GetPerformanceCounter() call. For performance > >>>> measurements, > >>>> PERF_START() and friends can be used, but in many contexts > >> the > >>>> time > >>>> difference is needed for lower-level reasons. > >>>> > >>>> Such users can be enumerated by grepping for > >>>> GetPerformanceCounterProperties() call sites that pass in > >> non- > >>>> NULL > >>>> parameters -- this is needed for interpreting wrap-arounds > in > >>>> tick > >>>> values (direction and boundaries). I'm seeing a whole lot > of > >>>> such call > >>>> sites. (And some call sites don't handle both directions of > >>>> counting.) > >>>> > >>>> I've written a very small library for centralizing this. > >> While > >>>> I'm not > >>>> suggesting that existent code be rebased (although I'm also > >> not > >>>> advising > >>>> against it), I think this library would be convenient for > new > >>>> code. > >>>> > >>>> I don't think TimerLib should be extended with the new > >>>> (suggested) APIs. > >>>> There's a huge number of TimerLib instances (21 in my > count), > >>>> and > >>>> replicating the implementation of the new APIs -- which are > >>>> totally > >>>> platform independent -- would defeat the whole exercise > >> (which > >>>> is to > >>>> prevent code duplication). > >>>> > >>>> The library is currently for OvmfPkg only (in my local > tree). > >>>> I'm > >>>> pasting the patch below. If there is interest, I could > rework > >> it > >>>> for > >>>> MdePkg. > >>>> > >>>> Thanks > >>>> Laszlo > >>>> > >>>>> commit f1963c7b1705c7e46ce369802d8c15f943a114d6 > >>>>> Author: Laszlo Ersek <[email protected]> > >>>>> Date: Tue Aug 8 22:46:47 2017 +0200 > >>>>> > >>>>> OvmfPkg: add TimerTickDiffLib > >>>>> > >>>>> Contributed-under: TianoCore Contribution Agreement > 1.1 > >>>>> Signed-off-by: Laszlo Ersek <[email protected]> > >>>>> > >>>>> diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec > >>>>> index 6a4c15c7917a..53a0a34d326d 100644 > >>>>> --- a/OvmfPkg/OvmfPkg.dec > >>>>> +++ b/OvmfPkg/OvmfPkg.dec > >>>>> @@ -60,6 +60,10 @@ [LibraryClasses] > >>>>> # > >>>>> HexDumpLib|Include/Library/HexDumpLib.h > >>>>> > >>>>> + ## @libraryclass Timer tick difference functions, to > be > >>>> used with TimerLib. > >>>>> + # > >>>>> + TimerTickDiffLib|Include/Library/TimerTickDiffLib.h > >>>>> + > >>>>> [Guids] > >>>>> gUefiOvmfPkgTokenSpaceGuid = {0x93bb96af, > >> 0xb9f2, > >>>> 0x4eb8, {0x94, 0x62, 0xe0, 0xba, 0x74, 0x56, 0x42, 0x36}} > >>>>> gEfiXenInfoGuid = {0xd3b46f3b, > >> 0xd441, > >>>> 0x1244, {0x9a, 0x12, 0x0, 0x12, 0x27, 0x3f, 0xc1, 0x4d}} > >>>>> diff --git a/OvmfPkg/OvmfPkgIa32.dsc > >> b/OvmfPkg/OvmfPkgIa32.dsc > >>>>> index 5b0461ff46b1..17f1db43f57d 100644 > >>>>> --- a/OvmfPkg/OvmfPkgIa32.dsc > >>>>> +++ b/OvmfPkg/OvmfPkgIa32.dsc > >>>>> @@ -97,6 +97,7 @@ [SkuIds] > >>>>> # > >>>>> > >>>> > >> > ################################################################ > >>>> ################ > >>>>> [LibraryClasses] > >>>>> + > >>>> > >> > TimerTickDiffLib|OvmfPkg/Library/TimerTickDiffLib/TimerTickDiffL > >>>> ib.inf > >>>>> HexDumpLib|OvmfPkg/Library/HexDumpLib/HexDumpLib.inf > >>>>> PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf > >>>>> > >> TimerLib|OvmfPkg/Library/AcpiTimerLib/BaseAcpiTimerLib.inf > >>>>> diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc > >>>> b/OvmfPkg/OvmfPkgIa32X64.dsc > >>>>> index 0ce3cbd3ebd0..924e17824760 100644 > >>>>> --- a/OvmfPkg/OvmfPkgIa32X64.dsc > >>>>> +++ b/OvmfPkg/OvmfPkgIa32X64.dsc > >>>>> @@ -102,6 +102,7 @@ [SkuIds] > >>>>> # > >>>>> > >>>> > >> > ################################################################ > >>>> ################ > >>>>> [LibraryClasses] > >>>>> + > >>>> > >> > TimerTickDiffLib|OvmfPkg/Library/TimerTickDiffLib/TimerTickDiffL > >>>> ib.inf > >>>>> HexDumpLib|OvmfPkg/Library/HexDumpLib/HexDumpLib.inf > >>>>> PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf > >>>>> > >> TimerLib|OvmfPkg/Library/AcpiTimerLib/BaseAcpiTimerLib.inf > >>>>> diff --git a/OvmfPkg/OvmfPkgX64.dsc > b/OvmfPkg/OvmfPkgX64.dsc > >>>>> index e7bdf8711b0f..d22384a26768 100644 > >>>>> --- a/OvmfPkg/OvmfPkgX64.dsc > >>>>> +++ b/OvmfPkg/OvmfPkgX64.dsc > >>>>> @@ -102,6 +102,7 @@ [SkuIds] > >>>>> # > >>>>> > >>>> > >> > ################################################################ > >>>> ################ > >>>>> [LibraryClasses] > >>>>> + > >>>> > >> > TimerTickDiffLib|OvmfPkg/Library/TimerTickDiffLib/TimerTickDiffL > >>>> ib.inf > >>>>> HexDumpLib|OvmfPkg/Library/HexDumpLib/HexDumpLib.inf > >>>>> PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf > >>>>> > >> TimerLib|OvmfPkg/Library/AcpiTimerLib/BaseAcpiTimerLib.inf > >>>>> diff --git > >>>> a/OvmfPkg/Library/TimerTickDiffLib/TimerTickDiffLib.inf > >>>> b/OvmfPkg/Library/TimerTickDiffLib/TimerTickDiffLib.inf > >>>>> new file mode 100644 > >>>>> index 000000000000..4d464565eb2f > >>>>> --- /dev/null > >>>>> +++ > b/OvmfPkg/Library/TimerTickDiffLib/TimerTickDiffLib.inf > >>>>> @@ -0,0 +1,31 @@ > >>>>> +## @file > >>>>> +# Timer tick difference functions, to be used with > >> TimerLib. > >>>>> +# > >>>>> +# Copyright (C) 2017, Red Hat, Inc. > >>>>> +# > >>>>> +# This program and the accompanying materials are > licensed > >>>> and made available > >>>>> +# under the terms and conditions of the BSD License which > >>>> accompanies this > >>>>> +# distribution. The full text of the license may be found > >> at > >>>>> +# http://opensource.org/licenses/bsd-license.php > >>>>> +# > >>>>> +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN > >> "AS > >>>> IS" BASIS, WITHOUT > >>>>> +# WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER > EXPRESS > >>>> OR IMPLIED. > >>>>> +## > >>>>> + > >>>>> +[Defines] > >>>>> + INF_VERSION = 1.26 > >>>>> + BASE_NAME = TimerTickDiffLib > >>>>> + FILE_GUID = F1998AED-934F-4C96- > AEFB- > >>>> 29C39FA62434 > >>>>> + MODULE_TYPE = BASE > >>>>> + VERSION_STRING = 1.0 > >>>>> + LIBRARY_CLASS = TimerTickDiffLib > >>>>> + > >>>>> +[Sources] > >>>>> + TimerTickDiffLib.c > >>>>> + > >>>>> +[Packages] > >>>>> + MdePkg/MdePkg.dec > >>>>> + > >>>>> +[LibraryClasses] > >>>>> + BaseLib > >>>>> + TimerLib > >>>>> diff --git a/OvmfPkg/Include/Library/TimerTickDiffLib.h > >>>> b/OvmfPkg/Include/Library/TimerTickDiffLib.h > >>>>> new file mode 100644 > >>>>> index 000000000000..40052e11b6ed > >>>>> --- /dev/null > >>>>> +++ b/OvmfPkg/Include/Library/TimerTickDiffLib.h > >>>>> @@ -0,0 +1,109 @@ > >>>>> +/** @file > >>>>> + Timer tick difference functions, to be used with > >> TimerLib. > >>>>> + > >>>>> + Copyright (C) 2017, Red Hat, Inc. > >>>>> + > >>>>> + This program and the accompanying materials are > licensed > >>>> and made available > >>>>> + under the terms and conditions of the BSD License which > >>>> accompanies this > >>>>> + distribution. The full text of the license may be found > >> at > >>>>> + http://opensource.org/licenses/bsd-license.php > >>>>> + > >>>>> + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN > >> "AS > >>>> IS" BASIS, WITHOUT > >>>>> + WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER > EXPRESS > >>>> OR IMPLIED. > >>>>> +**/ > >>>>> + > >>>>> +#ifndef __TIMER_TICK_DIFF_LIB_H__ > >>>>> +#define __TIMER_TICK_DIFF_LIB_H__ > >>>>> + > >>>>> +#include <Base.h> > >>>>> + > >>>>> +/** > >>>>> + From two values retrieved with TimerLib's > >>>> GetPerformanceCounter(), calculate > >>>>> + the number of ticks elapsed between them, such that the > >>>> difference can be > >>>>> + passed to TimerLib's GetTimeInNanoSecond(). > >>>>> + > >>>>> + The function cannot handle multiple wrap-arounds of the > >>>> performance counter. > >>>>> + > >>>>> + @param[in] PerfCounterStart The value returned by > >>>> GetPerformanceCounter(), > >>>>> + called earlier in wall > clock > >>>> time. > >>>>> + > >>>>> + @param[in] PerfCounterStop The value returned by > >>>> GetPerformanceCounter(), > >>>>> + called later in wall clock > >>>> time. > >>>>> + > >>>>> + @retval The number of ticks corresponding to the > >>>> conceptual difference > >>>>> + (PerfCounterStop-PerfCounterStart). > >>>>> +**/ > >>>>> +UINT64 > >>>>> +EFIAPI > >>>>> +GetTickDifference ( > >>>>> + IN UINT64 PerfCounterStart, > >>>>> + IN UINT64 PerfCounterStop > >>>>> + ); > >>>>> + > >>>>> +/** > >>>>> + From two values retrieved with TimerLib's > >>>> GetPerformanceCounter(), calculate > >>>>> + the number of nanoseconds elapsed between them. > >>>>> + > >>>>> + The function cannot handle multiple wrap-arounds of the > >>>> performance counter. > >>>>> + > >>>>> + @param[in] PerfCounterStart The value returned by > >>>> GetPerformanceCounter(), > >>>>> + called earlier in wall > clock > >>>> time. > >>>>> + > >>>>> + @param[in] PerfCounterStop The value returned by > >>>> GetPerformanceCounter(), > >>>>> + called later in wall clock > >>>> time. > >>>>> + > >>>>> + @retval The number of nanoseconds corresponding to the > >>>> conceptual difference > >>>>> + (PerfCounterStop-PerfCounterStart). > >>>>> +**/ > >>>>> +UINT64 > >>>>> +EFIAPI > >>>>> +GetNanoSecondDifference ( > >>>>> + IN UINT64 PerfCounterStart, > >>>>> + IN UINT64 PerfCounterStop > >>>>> + ); > >>>>> + > >>>>> +/** > >>>>> + From two values retrieved with TimerLib's > >>>> GetPerformanceCounter(), calculate > >>>>> + the number of microseconds elapsed between them. > >>>>> + > >>>>> + The function cannot handle multiple wrap-arounds of the > >>>> performance counter. > >>>>> + > >>>>> + @param[in] PerfCounterStart The value returned by > >>>> GetPerformanceCounter(), > >>>>> + called earlier in wall > clock > >>>> time. > >>>>> + > >>>>> + @param[in] PerfCounterStop The value returned by > >>>> GetPerformanceCounter(), > >>>>> + called later in wall clock > >>>> time. > >>>>> + > >>>>> + @retval The number of microseconds corresponding to > the > >>>> conceptual > >>>>> + difference (PerfCounterStop-PerfCounterStart). > >>>>> +**/ > >>>>> +UINT64 > >>>>> +EFIAPI > >>>>> +GetMicroSecondDifference ( > >>>>> + IN UINT64 PerfCounterStart, > >>>>> + IN UINT64 PerfCounterStop > >>>>> + ); > >>>>> + > >>>>> +/** > >>>>> + From two values retrieved with TimerLib's > >>>> GetPerformanceCounter(), calculate > >>>>> + the number of milliseconds elapsed between them. > >>>>> + > >>>>> + The function cannot handle multiple wrap-arounds of the > >>>> performance counter. > >>>>> + > >>>>> + @param[in] PerfCounterStart The value returned by > >>>> GetPerformanceCounter(), > >>>>> + called earlier in wall > clock > >>>> time. > >>>>> + > >>>>> + @param[in] PerfCounterStop The value returned by > >>>> GetPerformanceCounter(), > >>>>> + called later in wall clock > >>>> time. > >>>>> + > >>>>> + @retval The number of milliseconds corresponding to > the > >>>> conceptual > >>>>> + difference (PerfCounterStop-PerfCounterStart). > >>>>> +**/ > >>>>> +UINT64 > >>>>> +EFIAPI > >>>>> +GetMilliSecondDifference ( > >>>>> + IN UINT64 PerfCounterStart, > >>>>> + IN UINT64 PerfCounterStop > >>>>> + ); > >>>>> + > >>>>> +#endif > >>>>> diff --git > >>>> a/OvmfPkg/Library/TimerTickDiffLib/TimerTickDiffLib.c > >>>> b/OvmfPkg/Library/TimerTickDiffLib/TimerTickDiffLib.c > >>>>> new file mode 100644 > >>>>> index 000000000000..03ecae8200aa > >>>>> --- /dev/null > >>>>> +++ b/OvmfPkg/Library/TimerTickDiffLib/TimerTickDiffLib.c > >>>>> @@ -0,0 +1,178 @@ > >>>>> +/** @file > >>>>> + Timer tick difference functions, to be used with > >> TimerLib. > >>>>> + > >>>>> + Copyright (C) 2017, Red Hat, Inc. > >>>>> + > >>>>> + This program and the accompanying materials are > licensed > >>>> and made available > >>>>> + under the terms and conditions of the BSD License which > >>>> accompanies this > >>>>> + distribution. The full text of the license may be found > >> at > >>>>> + http://opensource.org/licenses/bsd-license.php > >>>>> + > >>>>> + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN > >> "AS > >>>> IS" BASIS, WITHOUT > >>>>> + WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER > EXPRESS > >>>> OR IMPLIED. > >>>>> +**/ > >>>>> + > >>>>> +#include <Library/BaseLib.h> > >>>>> +#include <Library/TimerLib.h> > >>>>> + > >>>>> +/** > >>>>> + From two values retrieved with TimerLib's > >>>> GetPerformanceCounter(), calculate > >>>>> + the number of ticks elapsed between them, such that the > >>>> difference can be > >>>>> + passed to TimerLib's GetTimeInNanoSecond(). > >>>>> + > >>>>> + The function cannot handle multiple wrap-arounds of the > >>>> performance counter. > >>>>> + > >>>>> + @param[in] PerfCounterStart The value returned by > >>>> GetPerformanceCounter(), > >>>>> + called earlier in wall > clock > >>>> time. > >>>>> + > >>>>> + @param[in] PerfCounterStop The value returned by > >>>> GetPerformanceCounter(), > >>>>> + called later in wall clock > >>>> time. > >>>>> + > >>>>> + @retval The number of ticks corresponding to the > >>>> conceptual difference > >>>>> + (PerfCounterStop-PerfCounterStart). > >>>>> +**/ > >>>>> +UINT64 > >>>>> +EFIAPI > >>>>> +GetTickDifference ( > >>>>> + IN UINT64 PerfCounterStart, > >>>>> + IN UINT64 PerfCounterStop > >>>>> + ) > >>>>> +{ > >>>>> + UINT64 StartValue; > >>>>> + UINT64 EndValue; > >>>>> + UINT64 TickDifference; > >>>>> + > >>>>> + GetPerformanceCounterProperties (&StartValue, > &EndValue); > >>>>> + > >>>>> + if (StartValue < EndValue) { > >>>>> + // > >>>>> + // The performance counter counts up. > >>>>> + // > >>>>> + if (PerfCounterStart < PerfCounterStop) { > >>>>> + // > >>>>> + // The counter didn't wrap around. > >>>>> + // > >>>>> + TickDifference = PerfCounterStop - > PerfCounterStart; > >>>>> + } else { > >>>>> + // > >>>>> + // The counter wrapped around. > >>>>> + // > >>>>> + TickDifference = (EndValue - PerfCounterStart) + > >>>>> + (PerfCounterStop - StartValue); > >>>>> + } > >>>>> + } else { > >>>>> + // > >>>>> + // The performance counter counts down. > >>>>> + // > >>>>> + if (PerfCounterStart < PerfCounterStop) { > >>>>> + // > >>>>> + // The counter wrapped around. > >>>>> + // > >>>>> + TickDifference = (PerfCounterStart - EndValue) + > >>>>> + (StartValue - PerfCounterStop); > >>>>> + } else { > >>>>> + // > >>>>> + // The counter didn't wrap around. > >>>>> + // > >>>>> + TickDifference = PerfCounterStart - > PerfCounterStop; > >>>>> + } > >>>>> + } > >>>>> + > >>>>> + return TickDifference; > >>>>> +} > >>>>> + > >>>>> +/** > >>>>> + From two values retrieved with TimerLib's > >>>> GetPerformanceCounter(), calculate > >>>>> + the number of nanoseconds elapsed between them. > >>>>> + > >>>>> + The function cannot handle multiple wrap-arounds of the > >>>> performance counter. > >>>>> + > >>>>> + @param[in] PerfCounterStart The value returned by > >>>> GetPerformanceCounter(), > >>>>> + called earlier in wall > clock > >>>> time. > >>>>> + > >>>>> + @param[in] PerfCounterStop The value returned by > >>>> GetPerformanceCounter(), > >>>>> + called later in wall clock > >>>> time. > >>>>> + > >>>>> + @retval The number of nanoseconds corresponding to the > >>>> conceptual difference > >>>>> + (PerfCounterStop-PerfCounterStart). > >>>>> +**/ > >>>>> +UINT64 > >>>>> +EFIAPI > >>>>> +GetNanoSecondDifference ( > >>>>> + IN UINT64 PerfCounterStart, > >>>>> + IN UINT64 PerfCounterStop > >>>>> + ) > >>>>> +{ > >>>>> + UINT64 TickDifference; > >>>>> + UINT64 NanoSecondDifference; > >>>>> + > >>>>> + TickDifference = GetTickDifference (PerfCounterStart, > >>>> PerfCounterStop); > >>>>> + NanoSecondDifference = GetTimeInNanoSecond > >>>> (TickDifference); > >>>>> + return NanoSecondDifference; > >>>>> +} > >>>>> + > >>>>> +/** > >>>>> + From two values retrieved with TimerLib's > >>>> GetPerformanceCounter(), calculate > >>>>> + the number of microseconds elapsed between them. > >>>>> + > >>>>> + The function cannot handle multiple wrap-arounds of the > >>>> performance counter. > >>>>> + > >>>>> + @param[in] PerfCounterStart The value returned by > >>>> GetPerformanceCounter(), > >>>>> + called earlier in wall > clock > >>>> time. > >>>>> + > >>>>> + @param[in] PerfCounterStop The value returned by > >>>> GetPerformanceCounter(), > >>>>> + called later in wall clock > >>>> time. > >>>>> + > >>>>> + @retval The number of microseconds corresponding to > the > >>>> conceptual > >>>>> + difference (PerfCounterStop-PerfCounterStart). > >>>>> +**/ > >>>>> +UINT64 > >>>>> +EFIAPI > >>>>> +GetMicroSecondDifference ( > >>>>> + IN UINT64 PerfCounterStart, > >>>>> + IN UINT64 PerfCounterStop > >>>>> + ) > >>>>> +{ > >>>>> + UINT64 NanoSecondDifference; > >>>>> + UINT64 MicroSecondDifference; > >>>>> + > >>>>> + NanoSecondDifference = GetNanoSecondDifference ( > >>>>> + PerfCounterStart, > >>>>> + PerfCounterStop > >>>>> + ); > >>>>> + MicroSecondDifference = DivU64x32 > (NanoSecondDifference, > >>>> 1000); > >>>>> + return MicroSecondDifference; > >>>>> +} > >>>>> + > >>>>> +/** > >>>>> + From two values retrieved with TimerLib's > >>>> GetPerformanceCounter(), calculate > >>>>> + the number of milliseconds elapsed between them. > >>>>> + > >>>>> + The function cannot handle multiple wrap-arounds of the > >>>> performance counter. > >>>>> + > >>>>> + @param[in] PerfCounterStart The value returned by > >>>> GetPerformanceCounter(), > >>>>> + called earlier in wall > clock > >>>> time. > >>>>> + > >>>>> + @param[in] PerfCounterStop The value returned by > >>>> GetPerformanceCounter(), > >>>>> + called later in wall clock > >>>> time. > >>>>> + > >>>>> + @retval The number of milliseconds corresponding to > the > >>>> conceptual > >>>>> + difference (PerfCounterStop-PerfCounterStart). > >>>>> +**/ > >>>>> +UINT64 > >>>>> +EFIAPI > >>>>> +GetMilliSecondDifference ( > >>>>> + IN UINT64 PerfCounterStart, > >>>>> + IN UINT64 PerfCounterStop > >>>>> + ) > >>>>> +{ > >>>>> + UINT64 NanoSecondDifference; > >>>>> + UINT64 MilliSecondDifference; > >>>>> + > >>>>> + NanoSecondDifference = GetNanoSecondDifference ( > >>>>> + PerfCounterStart, > >>>>> + PerfCounterStop > >>>>> + ); > >>>>> + MilliSecondDifference = DivU64x32 > (NanoSecondDifference, > >>>> 1000 * 1000); > >>>>> + return MilliSecondDifference; > >>>>> +} > >> > >> _______________________________________________ > >> edk2-devel mailing list > >> [email protected] > >> https://lists.01.org/mailman/listinfo/edk2-devel _______________________________________________ edk2-devel mailing list [email protected] https://lists.01.org/mailman/listinfo/edk2-devel

