public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: Laszlo Ersek <lersek@redhat.com>
To: "Kinney, Michael D" <michael.d.kinney@intel.com>,
	"Gao, Liming" <liming.gao@intel.com>
Cc: edk2-devel-01 <edk2-devel@lists.01.org>
Subject: Re: TimerTickDiffLib for MdePkg?
Date: Wed, 16 Aug 2017 20:24:04 +0200	[thread overview]
Message-ID: <1fb4df7c-0b65-b912-5ea4-2c105c8d866f@redhat.com> (raw)
In-Reply-To: <E92EE9817A31E24EB0585FDF735412F5A7D809C2@ORSMSX113.amr.corp.intel.com>

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:edk2-devel-bounces@lists.01.org] On
>> Behalf Of Laszlo Ersek
>> Sent: Wednesday, August 16, 2017 9:09 AM
>> To: Kinney, Michael D <michael.d.kinney@intel.com>; Gao, Liming
>> <liming.gao@intel.com>
>> Cc: edk2-devel-01 <edk2-devel@lists.01.org>
>> 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:lersek@redhat.com]
>>>> Sent: Wednesday, August 16, 2017 4:46 AM
>>>> To: Kinney, Michael D <michael.d.kinney@intel.com>; Gao,
>> Liming
>>>> <liming.gao@intel.com>
>>>> Cc: edk2-devel-01 <edk2-devel@lists.01.org>
>>>> 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 <lersek@redhat.com>
>>>>> Date:   Tue Aug 8 22:46:47 2017 +0200
>>>>>
>>>>>     OvmfPkg: add TimerTickDiffLib
>>>>>
>>>>>     Contributed-under: TianoCore Contribution Agreement 1.1
>>>>>     Signed-off-by: Laszlo Ersek <lersek@redhat.com>
>>>>>
>>>>> 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
>> edk2-devel@lists.01.org
>> https://lists.01.org/mailman/listinfo/edk2-devel



  reply	other threads:[~2017-08-16 18:21 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-08-16 11:45 TimerTickDiffLib for MdePkg? Laszlo Ersek
2017-08-16 15:41 ` Kinney, Michael D
2017-08-16 16:08   ` Laszlo Ersek
2017-08-16 18:01     ` Kinney, Michael D
2017-08-16 18:24       ` Laszlo Ersek [this message]
2017-08-16 18:33         ` Kinney, Michael D

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1fb4df7c-0b65-b912-5ea4-2c105c8d866f@redhat.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox