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

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:lersek@redhat.com]
> Sent: Wednesday, August 16, 2017 11:24 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?
> 
> 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:31 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
2017-08-16 18:33         ` Kinney, Michael D [this message]

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=E92EE9817A31E24EB0585FDF735412F5A7D80A2A@ORSMSX113.amr.corp.intel.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