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 EACBA21E1452C for ; Wed, 16 Aug 2017 11:21:40 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id BCD84C04D954; Wed, 16 Aug 2017 18:24:06 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com BCD84C04D954 Authentication-Results: ext-mx08.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx08.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 8E64062499; Wed, 16 Aug 2017 18:24:05 +0000 (UTC) To: "Kinney, Michael D" , "Gao, Liming" Cc: edk2-devel-01 References: <8cba2a58-1333-7733-031d-0883dbd844c6@redhat.com> <3e1428f1-0880-17a1-5aed-f73aa2212735@redhat.com> From: Laszlo Ersek Message-ID: <1fb4df7c-0b65-b912-5ea4-2c105c8d866f@redhat.com> Date: Wed, 16 Aug 2017 20:24:04 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.2.1 MIME-Version: 1.0 In-Reply-To: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Wed, 16 Aug 2017 18:24:06 +0000 (UTC) Subject: Re: 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 18:21:41 -0000 Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 7bit 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 ; Gao, Liming >> >> Cc: edk2-devel-01 >> 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 ; Gao, >> Liming >>>> >>>> Cc: edk2-devel-01 >>>> 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 >>>>> 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/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 >>>>> + >>>>> +/** >>>>> + 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; >>>>> +} >> >> _______________________________________________ >> edk2-devel mailing list >> edk2-devel@lists.01.org >> https://lists.01.org/mailman/listinfo/edk2-devel