From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id D68EA21E14547 for ; Wed, 16 Aug 2017 04:43:13 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 3DFBE66220; Wed, 16 Aug 2017 11:45:39 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 3DFBE66220 Authentication-Results: ext-mx04.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx04.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=lersek@redhat.com Received: from lacos-laptop-7.usersys.redhat.com (ovpn-116-59.phx2.redhat.com [10.3.116.59]) by smtp.corp.redhat.com (Postfix) with ESMTP id 97AFC60627; Wed, 16 Aug 2017 11:45:37 +0000 (UTC) To: Michael Kinney , "Gao, Liming" Cc: edk2-devel-01 From: Laszlo Ersek Message-ID: <8cba2a58-1333-7733-031d-0883dbd844c6@redhat.com> Date: Wed, 16 Aug 2017 13:45:36 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.2.1 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Wed, 16 Aug 2017 11:45:39 +0000 (UTC) Subject: TimerTickDiffLib for MdePkg? X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 16 Aug 2017 11:43:14 -0000 Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 7bit 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 > Date: Tue Aug 8 22:46:47 2017 +0200 > > OvmfPkg: add TimerTickDiffLib > > Contributed-under: TianoCore Contribution Agreement 1.1 > Signed-off-by: Laszlo Ersek > > 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/TimerTickDiffLib.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/TimerTickDiffLib.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/TimerTickDiffLib.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 > + > +/** > + 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 > +#include > + > +/** > + 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; > +}