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
VOID\r
)\r
{\r
- // @bug May use a PCD entry to determine this alignment.\r
return 32;\r
}\r
\r
@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
\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
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
),\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
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
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
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
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