<Filename>BaseLibInternals.h</Filename>
<Filename>String.c</Filename>
<Filename>LinkedList.c</Filename>
- <Filename>Synchronization.c</Filename>
<Filename>Cpu.c</Filename>
<Filename>CpuDeadLoop.c</Filename>
<Filename>BitField.c</Filename>
<Filename>SwapBytes32.c</Filename>
<Filename>SwapBytes64.c</Filename>
<Filename>SwitchStack.c</Filename>
- <Filename>CheckSum.c</Filename>
+ <Filename>CheckSum.c</Filename>
+ <Filename ToolChainFamily="GCC">SynchronizationGcc.c</Filename>
+ <Filename ToolChainFamily="MSFT">SynchronizationMsc.c</Filename>
<Filename SupArchList="IA32">x86DisablePaging32.c</Filename>
<Filename SupArchList="IA32">x86DisablePaging64.c</Filename>
<Filename SupArchList="IA32">x86EnablePaging32.c</Filename>
+++ /dev/null
-/** @file\r
- Implementation of synchronization functions.\r
-\r
- Copyright (c) 2006, 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
-\r
- Module Name: Synchronization.c\r
-\r
-**/\r
-\r
-#include "BaseLibInternals.h"\r
-\r
-//\r
-// SPIN_LOCK_RELEASED & SPIN_LOCK_ACQUIRED should belong to type "SPIN_LOCK".\r
-// Here we use type-case "UINTN" to avoid "volatile" modifier on const integers.\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
- optimal spin lock performance.\r
-\r
- This function retrieves the spin lock alignment requirements for optimal\r
- performance on a given CPU architecture. The spin lock alignment must be a\r
- power of two and is returned by this function. If there are no alignment\r
- requirements, then 1 must be returned. The spin lock synchronization\r
- functions must function correctly if the spin lock size and alignment values\r
- returned by this function are not used at all. These values are hints to the\r
- consumers of the spin lock synchronization functions to obtain optimal spin\r
- lock performance.\r
-\r
- @return The architecture specific spin lock alignment.\r
-\r
-**/\r
-UINTN\r
-EFIAPI\r
-GetSpinLockProperties (\r
- VOID\r
- )\r
-{\r
- // @bug May use a PCD entry to determine this alignment.\r
- return 32;\r
-}\r
-\r
-/**\r
- Initializes a spin lock to the released state and returns the spin lock.\r
-\r
- This function initializes the spin lock specified by SpinLock to the released\r
- state, and returns SpinLock. Optimal performance can be achieved by calling\r
- GetSpinLockProperties() to determine the size and alignment requirements for\r
- SpinLock.\r
-\r
- If SpinLock is NULL, then ASSERT().\r
-\r
- @param SpinLock A pointer to the spin lock to initialize to the released\r
- state.\r
-\r
- @return SpinLock\r
-\r
-**/\r
-SPIN_LOCK *\r
-EFIAPI\r
-InitializeSpinLock (\r
- OUT SPIN_LOCK *SpinLock\r
- )\r
-{\r
- ASSERT (SpinLock != NULL);\r
- *SpinLock = SPIN_LOCK_RELEASED;\r
- return SpinLock;\r
-}\r
-\r
-/**\r
- Waits until a spin lock can be placed in the acquired state.\r
-\r
- This function checks the state of the spin lock specified by SpinLock. If\r
- SpinLock is in the released state, then this function places SpinLock in the\r
- acquired state and returns SpinLock. Otherwise, this function waits\r
- indefinitely for the spin lock to be released, and then places it in the\r
- acquired state and returns SpinLock. All state transitions of SpinLock must\r
- be performed using MP safe mechanisms.\r
-\r
- If SpinLock is NULL, then ASSERT().\r
- If SpinLock was not initialized with InitializeSpinLock(), then ASSERT().\r
- If PcdSpinLockTimeout is not zero, and SpinLock is can not be acquired in\r
- PcdSpinLockTimeout microseconds, then ASSERT().\r
-\r
- @param SpinLock A pointer to the spin lock to place in the acquired state.\r
-\r
- @return SpinLock\r
-\r
-**/\r
-SPIN_LOCK *\r
-EFIAPI\r
-AcquireSpinLock (\r
- IN OUT SPIN_LOCK *SpinLock\r
- )\r
-{\r
- UINT64 Tick;\r
- UINT64 Start, End;\r
- UINT64 Timeout;\r
-\r
- Tick = 0;\r
- Start = 0;\r
- End = 0;\r
- if (PcdGet32 (PcdSpinLockTimeout) > 0) {\r
- Tick = GetPerformanceCounter ();\r
- Timeout = DivU64x32 (\r
- MultU64x32 (\r
- GetPerformanceCounterProperties (&Start, &End),\r
- PcdGet32 (PcdSpinLockTimeout)\r
- ),\r
- 1000000\r
- );\r
- if (Start < End) {\r
- Tick += Timeout;\r
- } else {\r
- Tick -= Timeout;\r
- }\r
- }\r
-\r
- while (!AcquireSpinLockOrFail (SpinLock)) {\r
- CpuPause ();\r
- ASSERT ((Start < End) ^ (Tick <= GetPerformanceCounter ()));\r
- }\r
- return SpinLock;\r
-}\r
-\r
-/**\r
- Attempts to place a spin lock in the acquired state.\r
-\r
- This function checks the state of the spin lock specified by SpinLock. If\r
- SpinLock is in the released state, then this function places SpinLock in the\r
- acquired state and returns TRUE. Otherwise, FALSE is returned. All state\r
- transitions of SpinLock must be performed using MP safe mechanisms.\r
-\r
- If SpinLock is NULL, then ASSERT().\r
- If SpinLock was not initialized with InitializeSpinLock(), then ASSERT().\r
-\r
- @param SpinLock A pointer to the spin lock to place in the acquired state.\r
-\r
- @retval TRUE SpinLock was placed in the acquired state.\r
- @retval FALSE SpinLock could not be acquired.\r
-\r
-**/\r
-BOOLEAN\r
-EFIAPI\r
-AcquireSpinLockOrFail (\r
- IN OUT SPIN_LOCK *SpinLock\r
- )\r
-{\r
- SPIN_LOCK LockValue;\r
-\r
- ASSERT (SpinLock != NULL);\r
-\r
- LockValue = *SpinLock;\r
- ASSERT (LockValue == SPIN_LOCK_ACQUIRED || LockValue == SPIN_LOCK_RELEASED);\r
-\r
- return (BOOLEAN)(\r
- InterlockedCompareExchangePointer (\r
- (VOID**)SpinLock,\r
- (VOID*)SPIN_LOCK_RELEASED,\r
- (VOID*)SPIN_LOCK_ACQUIRED\r
- ) == (VOID*)SPIN_LOCK_RELEASED\r
- );\r
-}\r
-\r
-/**\r
- Releases a spin lock.\r
-\r
- This function places the spin lock specified by SpinLock in the release state\r
- and returns SpinLock.\r
-\r
- If SpinLock is NULL, then ASSERT().\r
- If SpinLock was not initialized with InitializeSpinLock(), then ASSERT().\r
-\r
- @param SpinLock A pointer to the spin lock to release.\r
-\r
- @return SpinLock\r
-\r
-**/\r
-SPIN_LOCK *\r
-EFIAPI\r
-ReleaseSpinLock (\r
- IN OUT SPIN_LOCK *SpinLock\r
- )\r
-{\r
- SPIN_LOCK LockValue;\r
-\r
- ASSERT (SpinLock != NULL);\r
-\r
- LockValue = *SpinLock;\r
- ASSERT (LockValue == SPIN_LOCK_ACQUIRED || LockValue == SPIN_LOCK_RELEASED);\r
-\r
- *SpinLock = SPIN_LOCK_RELEASED;\r
- return SpinLock;\r
-}\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
- If Value is NULL, then ASSERT().\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
-InterlockedIncrement (\r
- IN UINT32 *Value\r
- )\r
-{\r
- ASSERT (Value != NULL);\r
- return InternalSyncIncrement (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 decremented 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
- If Value is NULL, then ASSERT().\r
-\r
- @param Value A pointer to the 32-bit value to decrement.\r
-\r
- @return The decremented value.\r
-\r
-**/\r
-UINT32\r
-EFIAPI\r
-InterlockedDecrement (\r
- IN UINT32 *Value\r
- )\r
-{\r
- ASSERT (Value != NULL);\r
- return InternalSyncDecrement (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
- If Value is NULL, then ASSERT().\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
-InterlockedCompareExchange32 (\r
- IN OUT UINT32 *Value,\r
- IN UINT32 CompareValue,\r
- IN UINT32 ExchangeValue\r
- )\r
-{\r
- ASSERT (Value != NULL);\r
- return InternalSyncCompareExchange32 (Value, CompareValue, 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
- If Value is NULL, then ASSERT().\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
-\r
-**/\r
-UINT64\r
-EFIAPI\r
-InterlockedCompareExchange64 (\r
- IN OUT UINT64 *Value,\r
- IN UINT64 CompareValue,\r
- IN UINT64 ExchangeValue\r
- )\r
-{\r
- ASSERT (Value != NULL);\r
- return InternalSyncCompareExchange64 (Value, CompareValue, ExchangeValue);\r
-}\r
-\r
-/**\r
- Performs an atomic compare exchange operation on a pointer value.\r
-\r
- Performs an atomic compare exchange operation on the pointer value specified\r
- 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\r
- CompareValue, then Value is returned. The compare exchange operation must be\r
- performed using MP safe mechanisms.\r
-\r
- If Value is NULL, then ASSERT().\r
-\r
- @param Value A pointer to the pointer value for the compare exchange\r
- operation.\r
- @param CompareValue Pointer value used in compare operation.\r
- @param ExchangeValue Pointer value used in exchange operation.\r
-\r
-**/\r
-VOID *\r
-EFIAPI\r
-InterlockedCompareExchangePointer (\r
- IN OUT VOID **Value,\r
- IN VOID *CompareValue,\r
- IN VOID *ExchangeValue\r
- )\r
-{\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
- (UINT32)(UINTN)CompareValue,\r
- (UINT32)(UINTN)ExchangeValue\r
- );\r
- case sizeof (UINT64):\r
- return (VOID*)(UINTN)InterlockedCompareExchange64 (\r
- (UINT64*)Value,\r
- (UINT64)(UINTN)CompareValue,\r
- (UINT64)(UINTN)ExchangeValue\r
- );\r
- default:\r
- ASSERT (FALSE);\r
- return NULL;\r
- }\r
-}\r
--- /dev/null
+/** @file\r
+ Implementation of synchronization functions.\r
+\r
+ Copyright (c) 2006 - 2007, 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
+\r
+ Module Name: SynchronizationGcc.c\r
+\r
+**/\r
+\r
+#include "BaseLibInternals.h"\r
+\r
+//\r
+// GCC inline assembly for Read Write Barrier \r
+//\r
+#define _ReadWriteBarrier() do { asm volatile ("": : : "memory"); } while(0)\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
+ optimal spin lock performance.\r
+\r
+ This function retrieves the spin lock alignment requirements for optimal\r
+ performance on a given CPU architecture. The spin lock alignment must be a\r
+ power of two and is returned by this function. If there are no alignment\r
+ requirements, then 1 must be returned. The spin lock synchronization\r
+ functions must function correctly if the spin lock size and alignment values\r
+ returned by this function are not used at all. These values are hints to the\r
+ consumers of the spin lock synchronization functions to obtain optimal spin\r
+ lock performance.\r
+\r
+ @return The architecture specific spin lock alignment.\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+GetSpinLockProperties (\r
+ VOID\r
+ )\r
+{\r
+ // @bug May use a PCD entry to determine this alignment.\r
+ return 32;\r
+}\r
+\r
+/**\r
+ Initializes a spin lock to the released state and returns the spin lock.\r
+\r
+ This function initializes the spin lock specified by SpinLock to the released\r
+ state, and returns SpinLock. Optimal performance can be achieved by calling\r
+ GetSpinLockProperties() to determine the size and alignment requirements for\r
+ SpinLock.\r
+\r
+ If SpinLock is NULL, then ASSERT().\r
+\r
+ @param SpinLock A pointer to the spin lock to initialize to the released\r
+ state.\r
+\r
+ @return SpinLock\r
+\r
+**/\r
+SPIN_LOCK *\r
+EFIAPI\r
+InitializeSpinLock (\r
+ OUT SPIN_LOCK *SpinLock\r
+ )\r
+{\r
+ ASSERT (SpinLock != NULL);\r
+\r
+ _ReadWriteBarrier();\r
+ *SpinLock = SPIN_LOCK_RELEASED;\r
+ _ReadWriteBarrier();\r
+\r
+ return SpinLock;\r
+}\r
+\r
+/**\r
+ Waits until a spin lock can be placed in the acquired state.\r
+\r
+ This function checks the state of the spin lock specified by SpinLock. If\r
+ SpinLock is in the released state, then this function places SpinLock in the\r
+ acquired state and returns SpinLock. Otherwise, this function waits\r
+ indefinitely for the spin lock to be released, and then places it in the\r
+ acquired state and returns SpinLock. All state transitions of SpinLock must\r
+ be performed using MP safe mechanisms.\r
+\r
+ If SpinLock is NULL, then ASSERT().\r
+ If SpinLock was not initialized with InitializeSpinLock(), then ASSERT().\r
+ If PcdSpinLockTimeout is not zero, and SpinLock is can not be acquired in\r
+ PcdSpinLockTimeout microseconds, then ASSERT().\r
+\r
+ @param SpinLock A pointer to the spin lock to place in the acquired state.\r
+\r
+ @return SpinLock\r
+\r
+**/\r
+SPIN_LOCK *\r
+EFIAPI\r
+AcquireSpinLock (\r
+ IN OUT SPIN_LOCK *SpinLock\r
+ )\r
+{\r
+ UINT64 Tick;\r
+ UINT64 Start, End;\r
+ UINT64 Timeout;\r
+\r
+ Tick = 0;\r
+ Start = 0;\r
+ End = 0;\r
+ if (PcdGet32 (PcdSpinLockTimeout) > 0) {\r
+ Tick = GetPerformanceCounter ();\r
+ Timeout = DivU64x32 (\r
+ MultU64x32 (\r
+ GetPerformanceCounterProperties (&Start, &End),\r
+ PcdGet32 (PcdSpinLockTimeout)\r
+ ),\r
+ 1000000\r
+ );\r
+ if (Start < End) {\r
+ Tick += Timeout;\r
+ } else {\r
+ Tick -= Timeout;\r
+ }\r
+ }\r
+\r
+ while (!AcquireSpinLockOrFail (SpinLock)) {\r
+ CpuPause ();\r
+ ASSERT ((Start < End) ^ (Tick <= GetPerformanceCounter ()));\r
+ }\r
+ return SpinLock;\r
+}\r
+\r
+/**\r
+ Attempts to place a spin lock in the acquired state.\r
+\r
+ This function checks the state of the spin lock specified by SpinLock. If\r
+ SpinLock is in the released state, then this function places SpinLock in the\r
+ acquired state and returns TRUE. Otherwise, FALSE is returned. All state\r
+ transitions of SpinLock must be performed using MP safe mechanisms.\r
+\r
+ If SpinLock is NULL, then ASSERT().\r
+ If SpinLock was not initialized with InitializeSpinLock(), then ASSERT().\r
+\r
+ @param SpinLock A pointer to the spin lock to place in the acquired state.\r
+\r
+ @retval TRUE SpinLock was placed in the acquired state.\r
+ @retval FALSE SpinLock could not be acquired.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+AcquireSpinLockOrFail (\r
+ IN OUT SPIN_LOCK *SpinLock\r
+ )\r
+{\r
+ VOID *Result;\r
+ \r
+ ASSERT (SpinLock != NULL);\r
+ ASSERT (*SpinLock == SPIN_LOCK_ACQUIRED || *SpinLock == SPIN_LOCK_RELEASED);\r
+\r
+ _ReadWriteBarrier ();\r
+ Result = InterlockedCompareExchangePointer (\r
+ (VOID**)SpinLock,\r
+ (VOID*)SPIN_LOCK_RELEASED,\r
+ (VOID*)SPIN_LOCK_ACQUIRED\r
+ );\r
+\r
+ _ReadWriteBarrier ();\r
+ return (BOOLEAN) (Result == (VOID*) SPIN_LOCK_RELEASED);\r
+}\r
+\r
+/**\r
+ Releases a spin lock.\r
+\r
+ This function places the spin lock specified by SpinLock in the release state\r
+ and returns SpinLock.\r
+\r
+ If SpinLock is NULL, then ASSERT().\r
+ If SpinLock was not initialized with InitializeSpinLock(), then ASSERT().\r
+\r
+ @param SpinLock A pointer to the spin lock to release.\r
+\r
+ @return SpinLock\r
+\r
+**/\r
+SPIN_LOCK *\r
+EFIAPI\r
+ReleaseSpinLock (\r
+ IN OUT SPIN_LOCK *SpinLock\r
+ )\r
+{\r
+ ASSERT (SpinLock != NULL);\r
+ ASSERT (*SpinLock == SPIN_LOCK_ACQUIRED || *SpinLock == SPIN_LOCK_RELEASED);\r
+\r
+ _ReadWriteBarrier ();\r
+ *SpinLock = SPIN_LOCK_RELEASED;\r
+ _ReadWriteBarrier ();\r
+\r
+ return SpinLock;\r
+}\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
+ If Value is NULL, then ASSERT().\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
+InterlockedIncrement (\r
+ IN UINT32 *Value\r
+ )\r
+{\r
+ ASSERT (Value != NULL);\r
+ return InternalSyncIncrement (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 decremented 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
+ If Value is NULL, then ASSERT().\r
+\r
+ @param Value A pointer to the 32-bit value to decrement.\r
+\r
+ @return The decremented value.\r
+\r
+**/\r
+UINT32\r
+EFIAPI\r
+InterlockedDecrement (\r
+ IN UINT32 *Value\r
+ )\r
+{\r
+ ASSERT (Value != NULL);\r
+ return InternalSyncDecrement (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
+ If Value is NULL, then ASSERT().\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
+InterlockedCompareExchange32 (\r
+ IN OUT UINT32 *Value,\r
+ IN UINT32 CompareValue,\r
+ IN UINT32 ExchangeValue\r
+ )\r
+{\r
+ ASSERT (Value != NULL);\r
+ return InternalSyncCompareExchange32 (Value, CompareValue, 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
+ If Value is NULL, then ASSERT().\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
+\r
+**/\r
+UINT64\r
+EFIAPI\r
+InterlockedCompareExchange64 (\r
+ IN OUT UINT64 *Value,\r
+ IN UINT64 CompareValue,\r
+ IN UINT64 ExchangeValue\r
+ )\r
+{\r
+ ASSERT (Value != NULL);\r
+ return InternalSyncCompareExchange64 (Value, CompareValue, ExchangeValue);\r
+}\r
+\r
+/**\r
+ Performs an atomic compare exchange operation on a pointer value.\r
+\r
+ Performs an atomic compare exchange operation on the pointer value specified\r
+ 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\r
+ CompareValue, then Value is returned. The compare exchange operation must be\r
+ performed using MP safe mechanisms.\r
+\r
+ If Value is NULL, then ASSERT().\r
+\r
+ @param Value A pointer to the pointer value for the compare exchange\r
+ operation.\r
+ @param CompareValue Pointer value used in compare operation.\r
+ @param ExchangeValue Pointer value used in exchange operation.\r
+\r
+**/\r
+VOID *\r
+EFIAPI\r
+InterlockedCompareExchangePointer (\r
+ IN OUT VOID **Value,\r
+ IN VOID *CompareValue,\r
+ IN VOID *ExchangeValue\r
+ )\r
+{\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
+ (UINT32)(UINTN)CompareValue,\r
+ (UINT32)(UINTN)ExchangeValue\r
+ );\r
+ case sizeof (UINT64):\r
+ return (VOID*)(UINTN)InterlockedCompareExchange64 (\r
+ (UINT64*)Value,\r
+ (UINT64)(UINTN)CompareValue,\r
+ (UINT64)(UINTN)ExchangeValue\r
+ );\r
+ default:\r
+ ASSERT (FALSE);\r
+ return NULL;\r
+ }\r
+}\r
--- /dev/null
+/** @file\r
+ Implementation of synchronization functions.\r
+\r
+ Copyright (c) 2006 - 2007, 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
+\r
+ Module Name: SynchronizationMsc.c\r
+\r
+**/\r
+\r
+#include "BaseLibInternals.h"\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
+\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
+ optimal spin lock performance.\r
+\r
+ This function retrieves the spin lock alignment requirements for optimal\r
+ performance on a given CPU architecture. The spin lock alignment must be a\r
+ power of two and is returned by this function. If there are no alignment\r
+ requirements, then 1 must be returned. The spin lock synchronization\r
+ functions must function correctly if the spin lock size and alignment values\r
+ returned by this function are not used at all. These values are hints to the\r
+ consumers of the spin lock synchronization functions to obtain optimal spin\r
+ lock performance.\r
+\r
+ @return The architecture specific spin lock alignment.\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+GetSpinLockProperties (\r
+ VOID\r
+ )\r
+{\r
+ // @bug May use a PCD entry to determine this alignment.\r
+ return 32;\r
+}\r
+\r
+/**\r
+ Initializes a spin lock to the released state and returns the spin lock.\r
+\r
+ This function initializes the spin lock specified by SpinLock to the released\r
+ state, and returns SpinLock. Optimal performance can be achieved by calling\r
+ GetSpinLockProperties() to determine the size and alignment requirements for\r
+ SpinLock.\r
+\r
+ If SpinLock is NULL, then ASSERT().\r
+\r
+ @param SpinLock A pointer to the spin lock to initialize to the released\r
+ state.\r
+\r
+ @return SpinLock\r
+\r
+**/\r
+SPIN_LOCK *\r
+EFIAPI\r
+InitializeSpinLock (\r
+ OUT SPIN_LOCK *SpinLock\r
+ )\r
+{\r
+ ASSERT (SpinLock != NULL);\r
+\r
+ _ReadWriteBarrier();\r
+ *SpinLock = SPIN_LOCK_RELEASED;\r
+ _ReadWriteBarrier();\r
+\r
+ return SpinLock;\r
+}\r
+\r
+/**\r
+ Waits until a spin lock can be placed in the acquired state.\r
+\r
+ This function checks the state of the spin lock specified by SpinLock. If\r
+ SpinLock is in the released state, then this function places SpinLock in the\r
+ acquired state and returns SpinLock. Otherwise, this function waits\r
+ indefinitely for the spin lock to be released, and then places it in the\r
+ acquired state and returns SpinLock. All state transitions of SpinLock must\r
+ be performed using MP safe mechanisms.\r
+\r
+ If SpinLock is NULL, then ASSERT().\r
+ If SpinLock was not initialized with InitializeSpinLock(), then ASSERT().\r
+ If PcdSpinLockTimeout is not zero, and SpinLock is can not be acquired in\r
+ PcdSpinLockTimeout microseconds, then ASSERT().\r
+\r
+ @param SpinLock A pointer to the spin lock to place in the acquired state.\r
+\r
+ @return SpinLock\r
+\r
+**/\r
+SPIN_LOCK *\r
+EFIAPI\r
+AcquireSpinLock (\r
+ IN OUT SPIN_LOCK *SpinLock\r
+ )\r
+{\r
+ UINT64 Tick;\r
+ UINT64 Start, End;\r
+ UINT64 Timeout;\r
+\r
+ Tick = 0;\r
+ Start = 0;\r
+ End = 0;\r
+ if (PcdGet32 (PcdSpinLockTimeout) > 0) {\r
+ Tick = GetPerformanceCounter ();\r
+ Timeout = DivU64x32 (\r
+ MultU64x32 (\r
+ GetPerformanceCounterProperties (&Start, &End),\r
+ PcdGet32 (PcdSpinLockTimeout)\r
+ ),\r
+ 1000000\r
+ );\r
+ if (Start < End) {\r
+ Tick += Timeout;\r
+ } else {\r
+ Tick -= Timeout;\r
+ }\r
+ }\r
+\r
+ while (!AcquireSpinLockOrFail (SpinLock)) {\r
+ CpuPause ();\r
+ ASSERT ((Start < End) ^ (Tick <= GetPerformanceCounter ()));\r
+ }\r
+ return SpinLock;\r
+}\r
+\r
+/**\r
+ Attempts to place a spin lock in the acquired state.\r
+\r
+ This function checks the state of the spin lock specified by SpinLock. If\r
+ SpinLock is in the released state, then this function places SpinLock in the\r
+ acquired state and returns TRUE. Otherwise, FALSE is returned. All state\r
+ transitions of SpinLock must be performed using MP safe mechanisms.\r
+\r
+ If SpinLock is NULL, then ASSERT().\r
+ If SpinLock was not initialized with InitializeSpinLock(), then ASSERT().\r
+\r
+ @param SpinLock A pointer to the spin lock to place in the acquired state.\r
+\r
+ @retval TRUE SpinLock was placed in the acquired state.\r
+ @retval FALSE SpinLock could not be acquired.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+AcquireSpinLockOrFail (\r
+ IN OUT SPIN_LOCK *SpinLock\r
+ )\r
+{\r
+ VOID *Result;\r
+ \r
+ ASSERT (SpinLock != NULL);\r
+ ASSERT (*SpinLock == SPIN_LOCK_ACQUIRED || *SpinLock == SPIN_LOCK_RELEASED);\r
+\r
+ _ReadWriteBarrier ();\r
+ Result = InterlockedCompareExchangePointer (\r
+ (VOID**)SpinLock,\r
+ (VOID*)SPIN_LOCK_RELEASED,\r
+ (VOID*)SPIN_LOCK_ACQUIRED\r
+ );\r
+\r
+ _ReadWriteBarrier ();\r
+ return (BOOLEAN) (Result == (VOID*) SPIN_LOCK_RELEASED);\r
+}\r
+\r
+/**\r
+ Releases a spin lock.\r
+\r
+ This function places the spin lock specified by SpinLock in the release state\r
+ and returns SpinLock.\r
+\r
+ If SpinLock is NULL, then ASSERT().\r
+ If SpinLock was not initialized with InitializeSpinLock(), then ASSERT().\r
+\r
+ @param SpinLock A pointer to the spin lock to release.\r
+\r
+ @return SpinLock\r
+\r
+**/\r
+SPIN_LOCK *\r
+EFIAPI\r
+ReleaseSpinLock (\r
+ IN OUT SPIN_LOCK *SpinLock\r
+ )\r
+{\r
+ ASSERT (SpinLock != NULL);\r
+ ASSERT (*SpinLock == SPIN_LOCK_ACQUIRED || *SpinLock == SPIN_LOCK_RELEASED);\r
+\r
+ _ReadWriteBarrier ();\r
+ *SpinLock = SPIN_LOCK_RELEASED;\r
+ _ReadWriteBarrier ();\r
+\r
+ return SpinLock;\r
+}\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
+ If Value is NULL, then ASSERT().\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
+InterlockedIncrement (\r
+ IN UINT32 *Value\r
+ )\r
+{\r
+ ASSERT (Value != NULL);\r
+ return InternalSyncIncrement (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 decremented 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
+ If Value is NULL, then ASSERT().\r
+\r
+ @param Value A pointer to the 32-bit value to decrement.\r
+\r
+ @return The decremented value.\r
+\r
+**/\r
+UINT32\r
+EFIAPI\r
+InterlockedDecrement (\r
+ IN UINT32 *Value\r
+ )\r
+{\r
+ ASSERT (Value != NULL);\r
+ return InternalSyncDecrement (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
+ If Value is NULL, then ASSERT().\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
+InterlockedCompareExchange32 (\r
+ IN OUT UINT32 *Value,\r
+ IN UINT32 CompareValue,\r
+ IN UINT32 ExchangeValue\r
+ )\r
+{\r
+ ASSERT (Value != NULL);\r
+ return InternalSyncCompareExchange32 (Value, CompareValue, 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
+ If Value is NULL, then ASSERT().\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
+\r
+**/\r
+UINT64\r
+EFIAPI\r
+InterlockedCompareExchange64 (\r
+ IN OUT UINT64 *Value,\r
+ IN UINT64 CompareValue,\r
+ IN UINT64 ExchangeValue\r
+ )\r
+{\r
+ ASSERT (Value != NULL);\r
+ return InternalSyncCompareExchange64 (Value, CompareValue, ExchangeValue);\r
+}\r
+\r
+/**\r
+ Performs an atomic compare exchange operation on a pointer value.\r
+\r
+ Performs an atomic compare exchange operation on the pointer value specified\r
+ 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\r
+ CompareValue, then Value is returned. The compare exchange operation must be\r
+ performed using MP safe mechanisms.\r
+\r
+ If Value is NULL, then ASSERT().\r
+\r
+ @param Value A pointer to the pointer value for the compare exchange\r
+ operation.\r
+ @param CompareValue Pointer value used in compare operation.\r
+ @param ExchangeValue Pointer value used in exchange operation.\r
+\r
+**/\r
+VOID *\r
+EFIAPI\r
+InterlockedCompareExchangePointer (\r
+ IN OUT VOID **Value,\r
+ IN VOID *CompareValue,\r
+ IN VOID *ExchangeValue\r
+ )\r
+{\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
+ (UINT32)(UINTN)CompareValue,\r
+ (UINT32)(UINTN)ExchangeValue\r
+ );\r
+ case sizeof (UINT64):\r
+ return (VOID*)(UINTN)InterlockedCompareExchange64 (\r
+ (UINT64*)Value,\r
+ (UINT64)(UINTN)CompareValue,\r
+ (UINT64)(UINTN)ExchangeValue\r
+ );\r
+ default:\r
+ ASSERT (FALSE);\r
+ return NULL;\r
+ }\r
+}\r