]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/Dxe/Misc/Stall.c
MdeModulePkg: Apply uncrustify changes
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Misc / Stall.c
index 175e1f5c35251b0cd9b6207aec89b657915db809..35e045d41a6cbe46dfff5a5bee0191595dc0c093 100644 (file)
@@ -1,14 +1,8 @@
 /** @file\r
   UEFI Miscellaneous boot Services Stall service implementation\r
 \r
-Copyright (c) 2006 - 2008, Intel Corporation. <BR>\r
-All rights reserved. This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution.  The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -18,7 +12,27 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 #include "DxeMain.h"\r
 \r
+/**\r
+  Internal worker function to call the Metronome Architectural Protocol for\r
+  the number of ticks specified by the UINT64 Counter value.  WaitForTick()\r
+  service of the Metronome Architectural Protocol uses a UINT32 for the number\r
+  of ticks to wait, so this function loops when Counter is larger than 0xffffffff.\r
+\r
+  @param  Counter           Number of ticks to wait.\r
 \r
+**/\r
+VOID\r
+CoreInternalWaitForTick (\r
+  IN UINT64  Counter\r
+  )\r
+{\r
+  while (RShiftU64 (Counter, 32) > 0) {\r
+    gMetronome->WaitForTick (gMetronome, 0xffffffff);\r
+    Counter -= 0xffffffff;\r
+  }\r
+\r
+  gMetronome->WaitForTick (gMetronome, (UINT32)Counter);\r
+}\r
 \r
 /**\r
   Introduces a fine-grained stall.\r
@@ -33,36 +47,63 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 EFI_STATUS\r
 EFIAPI\r
 CoreStall (\r
-  IN UINTN            Microseconds\r
+  IN UINTN  Microseconds\r
   )\r
 {\r
-  UINT32  Counter;\r
+  UINT64  Counter;\r
   UINT32  Remainder;\r
+  UINTN   Index;\r
 \r
   if (gMetronome == NULL) {\r
     return EFI_NOT_AVAILABLE_YET;\r
   }\r
 \r
   //\r
-  // Calculate the number of ticks by dividing the number of microseconds by\r
-  // the TickPeriod.\r
-  // Calculation is based on 100ns unit.\r
-  //\r
-  Counter = (UINT32) DivU64x32Remainder (\r
-                       Microseconds * 10,\r
-                       gMetronome->TickPeriod,\r
-                       &Remainder\r
-                       );\r
-\r
-  //\r
-  // Call WaitForTick for Counter + 1 ticks to try to guarantee Counter tick\r
-  // periods, thus attempting to ensure Microseconds of stall time.\r
+  // Counter = Microseconds * 10 / gMetronome->TickPeriod\r
+  // 0x1999999999999999 = (2^64 - 1) / 10\r
   //\r
-  if (Remainder != 0) {\r
-    Counter++;\r
+  if ((UINT64)Microseconds > 0x1999999999999999ULL) {\r
+    //\r
+    // Microseconds is too large to multiple by 10 first.  Perform the divide\r
+    // operation first and loop 10 times to avoid 64-bit math overflow.\r
+    //\r
+    Counter = DivU64x32Remainder (\r
+                Microseconds,\r
+                gMetronome->TickPeriod,\r
+                &Remainder\r
+                );\r
+    for (Index = 0; Index < 10; Index++) {\r
+      CoreInternalWaitForTick (Counter);\r
+    }\r
+\r
+    if (Remainder != 0) {\r
+      //\r
+      // If Remainder was not zero, then normally, Counter would be rounded\r
+      // up by 1 tick.  In this case, since a loop for 10 counts was used\r
+      // to emulate the multiply by 10 operation, Counter needs to be rounded\r
+      // up by 10 counts.\r
+      //\r
+      CoreInternalWaitForTick (10);\r
+    }\r
+  } else {\r
+    //\r
+    // Calculate the number of ticks by dividing the number of microseconds by\r
+    // the TickPeriod.  Calculation is based on 100ns unit.\r
+    //\r
+    Counter = DivU64x32Remainder (\r
+                MultU64x32 (Microseconds, 10),\r
+                gMetronome->TickPeriod,\r
+                &Remainder\r
+                );\r
+    if (Remainder != 0) {\r
+      //\r
+      // If Remainder is not zero, then round Counter up by one tick.\r
+      //\r
+      Counter++;\r
+    }\r
+\r
+    CoreInternalWaitForTick (Counter);\r
   }\r
 \r
-  gMetronome->WaitForTick (gMetronome, Counter);\r
-\r
   return EFI_SUCCESS;\r
 }\r