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 15:41:37 +0000	[thread overview]
Message-ID: <E92EE9817A31E24EB0585FDF735412F5A7D8086D@ORSMSX113.amr.corp.intel.com> (raw)
In-Reply-To: <8cba2a58-1333-7733-031d-0883dbd844c6@redhat.com>

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.

Mike

> -----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;
> > +}

  reply	other threads:[~2017-08-16 15:39 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 [this message]
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

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=E92EE9817A31E24EB0585FDF735412F5A7D8086D@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