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: SynchronizationMsc.c\r
-\r
**/\r
\r
+\r
+\r
+\r
#include "BaseLibInternals.h"\r
\r
-//\r
-// Microsoft Visual Studio 7.1 Function Prototypes for read write barrier Intrinsics\r
-//\r
+/**\r
+ Microsoft Visual Studio 7.1 Function Prototypes for read write barrier Intrinsics.\r
+**/\r
void _ReadWriteBarrier (void);\r
#pragma intrinsic(_ReadWriteBarrier)\r
\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 in released 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 aquiring 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
- VOID *Result;\r
+ SPIN_LOCK LockValue;\r
+ VOID *Result;\r
\r
ASSERT (SpinLock != NULL);\r
- ASSERT (*SpinLock == SPIN_LOCK_ACQUIRED || *SpinLock == SPIN_LOCK_RELEASED);\r
+\r
+ LockValue = *SpinLock;\r
+ ASSERT (LockValue == SPIN_LOCK_ACQUIRED || LockValue == SPIN_LOCK_RELEASED);\r
\r
_ReadWriteBarrier ();\r
Result = InterlockedCompareExchangePointer (\r
\r
@param SpinLock A pointer to the spin lock to release.\r
\r
- @return SpinLock\r
+ @return SpinLock releasing lock.\r
\r
**/\r
SPIN_LOCK *\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 (LockValue == SPIN_LOCK_ACQUIRED || LockValue == SPIN_LOCK_RELEASED);\r
\r
_ReadWriteBarrier ();\r
*SpinLock = SPIN_LOCK_RELEASED;\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