]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdePkg/Library/BaseLib/Synchronization.c
Use #include "XXX.h" for module internal header files.
[mirror_edk2.git] / MdePkg / Library / BaseLib / Synchronization.c
index cf001ce4d155ebd66d832eef9ec520db6503faaa..1a95026a794483984c3074cfd7436199de1a801e 100644 (file)
   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
 \r
-  Module Name:  Synchronization.c\r
-\r
-**/\r
-\r
-#define SPIN_LOCK_RELEASED          ((SPIN_LOCK)1)\r
-#define SPIN_LOCK_ACQUIRED          ((SPIN_LOCK)2)\r
-\r
-/**\r
-  Performs an atomic increment of an 32-bit unsigned integer.\r
-\r
-  Performs an atomic increment of the 32-bit unsigned integer specified by\r
-  Value and returns the incremented value. The increment operation must be\r
-  performed using MP safe mechanisms. The state of the return value is not\r
-  guaranteed to be MP safe.\r
-\r
-  @param  Value A pointer to the 32-bit value to increment.\r
-\r
-  @return The incremented value.\r
-\r
-**/\r
-UINT32\r
-EFIAPI\r
-InternalSyncIncrement (\r
-  IN      volatile UINT32           *Value\r
-  );\r
-\r
-/**\r
-  Performs an atomic decrement of an 32-bit unsigned integer.\r
-\r
-  Performs an atomic decrement of the 32-bit unsigned integer specified by\r
-  Value and returns the decrement value. The decrement operation must be\r
-  performed using MP safe mechanisms. The state of the return value is not\r
-  guaranteed to be MP safe.\r
-\r
-  @param  Value A pointer to the 32-bit value to decrement.\r
-\r
-  @return The decrement value.\r
-\r
-**/\r
-UINT32\r
-EFIAPI\r
-InternalSyncDecrement (\r
-  IN      volatile UINT32           *Value\r
-  );\r
-\r
-/**\r
-  Performs an atomic compare exchange operation on a 32-bit unsigned integer.\r
-\r
-  Performs an atomic compare exchange operation on the 32-bit unsigned integer\r
-  specified by Value.  If Value is equal to CompareValue, then Value is set to \r
-  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,\r
-  then Value is returned.  The compare exchange operation must be performed using \r
-  MP safe mechanisms.\r
-\r
-  @param  Value         A pointer to the 32-bit value for the compare exchange\r
-                        operation.\r
-  @param  CompareValue  32-bit value used in compare operation.\r
-  @param  ExchangeValue 32-bit value used in exchange operation.\r
-\r
-  @return The original *Value before exchange.\r
-\r
 **/\r
-UINT32\r
-EFIAPI\r
-InternalSyncCompareExchange32 (\r
-  IN      volatile UINT32           *Value,\r
-  IN      UINT32                    CompareValue,\r
-  IN      UINT32                    ExchangeValue\r
-  );\r
-\r
-/**\r
-  Performs an atomic compare exchange operation on a 64-bit unsigned integer.\r
-\r
-  Performs an atomic compare exchange operation on the 64-bit unsigned integer specified \r
-  by Value.  If Value is equal to CompareValue, then Value is set to ExchangeValue and \r
-  CompareValue is returned.  If Value is not equal to CompareValue, then Value is returned. \r
-  The compare exchange operation must be performed using MP safe mechanisms.\r
-\r
-  @param  Value         A pointer to the 64-bit value for the compare exchange\r
-                        operation.\r
-  @param  CompareValue  64-bit value used in compare operation.\r
-  @param  ExchangeValue 64-bit value used in exchange operation.\r
 \r
-  @return The original *Value before exchange.\r
+#include "BaseLibInternals.h"\r
 \r
-**/\r
-UINT64\r
-EFIAPI\r
-InternalSyncCompareExchange64 (\r
-  IN      volatile UINT64           *Value,\r
-  IN      UINT64                    CompareValue,\r
-  IN      UINT64                    ExchangeValue\r
-  );\r
+#define SPIN_LOCK_RELEASED          ((UINTN) 1)\r
+#define SPIN_LOCK_ACQUIRED          ((UINTN) 2)\r
 \r
 /**\r
   Retrieves the architecture specific spin lock alignment requirements for\r
@@ -126,7 +39,6 @@ GetSpinLockProperties (
   VOID\r
   )\r
 {\r
-  // @bug May use a PCD entry to determine this alignment.\r
   return 32;\r
 }\r
 \r
@@ -143,7 +55,7 @@ GetSpinLockProperties (
   @param  SpinLock  A pointer to the spin lock to initialize to the released\r
                     state.\r
 \r
-  @return SpinLock\r
+  @return SpinLock initialized in release state.\r
 \r
 **/\r
 SPIN_LOCK *\r
@@ -174,7 +86,7 @@ InitializeSpinLock (
 \r
   @param  SpinLock  A pointer to the spin lock to place in the acquired state.\r
 \r
-  @return SpinLock\r
+  @return SpinLock aquired lock.\r
 \r
 **/\r
 SPIN_LOCK *\r
@@ -183,15 +95,32 @@ AcquireSpinLock (
   IN OUT  SPIN_LOCK                 *SpinLock\r
   )\r
 {\r
-  UINT64                            Tick;\r
-  UINT64                            Start, End;\r
-  UINT64                            Timeout;\r
+  UINT64  Current;\r
+  UINT64  Previous;\r
+  UINT64  Total;\r
+  UINT64  Start;\r
+  UINT64  End;\r
+  UINT64  Timeout;\r
+  INT64   Cycle;\r
+  INT64   Delta;\r
 \r
-  Tick = 0;\r
-  Start = 0;\r
-  End = 0;\r
   if (PcdGet32 (PcdSpinLockTimeout) > 0) {\r
-    Tick = GetPerformanceCounter ();\r
+    //\r
+    // Get the current timer value\r
+    //\r
+    Current = GetPerformanceCounter();\r
+\r
+    //\r
+    // Initialize local variables\r
+    //\r
+    Start = 0;\r
+    End   = 0;\r
+    Total = 0;\r
+\r
+    //\r
+    // Retrieve the performance counter properties and compute the number of performance\r
+    // counter ticks required to reach the timeout\r
+    //\r
     Timeout = DivU64x32 (\r
                 MultU64x32 (\r
                   GetPerformanceCounterProperties (&Start, &End),\r
@@ -199,16 +128,30 @@ AcquireSpinLock (
                   ),\r
                 1000000\r
                 );\r
-    if (Start < End) {\r
-      Tick += Timeout;\r
-    } else {\r
-      Tick -= Timeout;\r
+    Cycle = End - Start;\r
+    if (Cycle < 0) {\r
+      Cycle = -Cycle;\r
+    }\r
+    Cycle++;\r
+\r
+    while (!AcquireSpinLockOrFail (SpinLock)) {\r
+      CpuPause ();\r
+      Previous = Current;\r
+      Current  = GetPerformanceCounter();\r
+      Delta = (INT64) (Current - Previous);\r
+      if (Start > End) {\r
+        Delta = -Delta;\r
+      }\r
+      if (Delta < 0) {\r
+        Delta += Cycle;\r
+      }\r
+      Total += Delta;\r
+      ASSERT (Total < Timeout);\r
+    }\r
+  } else {\r
+    while (!AcquireSpinLockOrFail (SpinLock)) {\r
+      CpuPause ();\r
     }\r
-  }\r
-\r
-  while (!AcquireSpinLockOrFail (SpinLock)) {\r
-    CpuPause ();\r
-    ASSERT ((Start < End) ^ (Tick <= GetPerformanceCounter ()));\r
   }\r
   return SpinLock;\r
 }\r
@@ -236,8 +179,13 @@ AcquireSpinLockOrFail (
   IN OUT  SPIN_LOCK                 *SpinLock\r
   )\r
 {\r
+  SPIN_LOCK    LockValue;\r
+\r
   ASSERT (SpinLock != NULL);\r
-  ASSERT (*SpinLock == SPIN_LOCK_ACQUIRED || *SpinLock == SPIN_LOCK_RELEASED);\r
+\r
+  LockValue = *SpinLock;\r
+  ASSERT (SPIN_LOCK_ACQUIRED == LockValue || SPIN_LOCK_RELEASED == LockValue);\r
+\r
   return (BOOLEAN)(\r
            InterlockedCompareExchangePointer (\r
              (VOID**)SpinLock,\r
@@ -267,8 +215,13 @@ ReleaseSpinLock (
   IN OUT  SPIN_LOCK                 *SpinLock\r
   )\r
 {\r
+  SPIN_LOCK    LockValue;\r
+\r
   ASSERT (SpinLock != NULL);\r
-  ASSERT (*SpinLock == SPIN_LOCK_ACQUIRED || *SpinLock == SPIN_LOCK_RELEASED);\r
+\r
+  LockValue = *SpinLock;\r
+  ASSERT (SPIN_LOCK_ACQUIRED == LockValue || SPIN_LOCK_RELEASED == LockValue);\r
+\r
   *SpinLock = SPIN_LOCK_RELEASED;\r
   return SpinLock;\r
 }\r
@@ -399,6 +352,8 @@ InterlockedCompareExchange64 (
                         operation.\r
   @param  CompareValue  Pointer value used in compare operation.\r
   @param  ExchangeValue Pointer value used in exchange operation.\r
+  \r
+  @return The original *Value before exchange.\r
 \r
 **/\r
 VOID *\r
@@ -409,7 +364,11 @@ InterlockedCompareExchangePointer (
   IN      VOID                      *ExchangeValue\r
   )\r
 {\r
-  switch (sizeof (*Value)) {\r
+  UINT8  SizeOfValue;\r
+\r
+  SizeOfValue = sizeof (*Value);\r
+\r
+  switch (SizeOfValue) {\r
     case sizeof (UINT32):\r
       return (VOID*)(UINTN)InterlockedCompareExchange32 (\r
                              (UINT32*)Value,\r