13eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang/*++
23eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
32c7e5c2febd407ed1849c06da50734dd6f751956hhtianCopyright (c) 2004 - 2006, Intel Corporation. All rights reserved.<BR>
42c7e5c2febd407ed1849c06da50734dd6f751956hhtianThis program and the accompanying materials
53eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangare licensed and made available under the terms and conditions of the BSD License
63eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangwhich accompanies this distribution.  The full text of the license may be found at
73eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwanghttp://opensource.org/licenses/bsd-license.php
83eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
93eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
103eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
113eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
123eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
133eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangModule Name:
143eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
153eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Synchronization.c
163eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
173eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangAbstract:
183eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
193eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Implementation of synchronization functions.
203eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
213eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang--*/
223eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
23c7f33ca42470dc87bc41a8583f427883123d67a1qwang#include "BaseLibInternals.h"
243eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
25c7f33ca42470dc87bc41a8583f427883123d67a1qwang#define SPIN_LOCK_RELEASED          ((UINTN) 1)
26c7f33ca42470dc87bc41a8583f427883123d67a1qwang#define SPIN_LOCK_ACQUIRED          ((UINTN) 2)
273eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
283eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang/**
293eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Retrieves the architecture specific spin lock alignment requirements for
303eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  optimal spin lock performance.
313eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
323eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  This function retrieves the spin lock alignment requirements for optimal
333eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  performance on a given CPU architecture. The spin lock alignment must be a
343eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  power of two and is returned by this function. If there are no alignment
353eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  requirements, then 1 must be returned. The spin lock synchronization
363eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  functions must function correctly if the spin lock size and alignment values
373eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  returned by this function are not used at all. These values are hints to the
383eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  consumers of the spin lock synchronization functions to obtain optimal spin
393eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  lock performance.
403eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
413eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  @return The architecture specific spin lock alignment.
423eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
433eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang**/
443eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangUINTN
453eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangEFIAPI
463eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangGetSpinLockProperties (
473eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  VOID
483eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  )
493eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang{
503eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  // @bug May use a PCD entry to determine this alignment.
513eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  return 32;
523eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang}
533eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
543eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang/**
553eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Initializes a spin lock to the released state and returns the spin lock.
563eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
573eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  This function initializes the spin lock specified by SpinLock to the released
583eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  state, and returns SpinLock. Optimal performance can be achieved by calling
593eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  GetSpinLockProperties() to determine the size and alignment requirements for
603eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  SpinLock.
613eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
623eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  If SpinLock is NULL, then ASSERT().
633eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
643eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  @param  SpinLock  A pointer to the spin lock to initialize to the released
653eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang                    state.
663eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
673eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  @return SpinLock
683eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
693eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang**/
703eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangSPIN_LOCK *
713eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangEFIAPI
723eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangInitializeSpinLock (
733eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  OUT     SPIN_LOCK                 *SpinLock
743eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  )
753eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang{
763eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  ASSERT (SpinLock != NULL);
773eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  *SpinLock = SPIN_LOCK_RELEASED;
783eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  return SpinLock;
793eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang}
803eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
813eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang/**
823eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Waits until a spin lock can be placed in the acquired state.
833eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
843eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  This function checks the state of the spin lock specified by SpinLock. If
853eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  SpinLock is in the released state, then this function places SpinLock in the
863eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  acquired state and returns SpinLock. Otherwise, this function waits
873eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  indefinitely for the spin lock to be released, and then places it in the
883eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  acquired state and returns SpinLock. All state transitions of SpinLock must
893eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  be performed using MP safe mechanisms.
903eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
913eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  If SpinLock is NULL, then ASSERT().
923eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  If SpinLock was not initialized with InitializeSpinLock(), then ASSERT().
933eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  If PcdSpinLockTimeout is not zero, and SpinLock is can not be acquired in
943eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  PcdSpinLockTimeout microseconds, then ASSERT().
953eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
963eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  @param  SpinLock  A pointer to the spin lock to place in the acquired state.
973eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
983eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  @return SpinLock
993eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1003eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang**/
1013eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangSPIN_LOCK *
1023eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangEFIAPI
1033eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangAcquireSpinLock (
1043eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  IN OUT  SPIN_LOCK                 *SpinLock
1053eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  )
1063eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang{
1073eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  UINT64                            Tick;
1083eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  UINT64                            Start, End;
1093eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  UINT64                            Timeout;
1103eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1113eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Tick = 0;
1123eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Start = 0;
1133eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  End = 0;
1143eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  if (PcdGet32 (PcdSpinLockTimeout) > 0) {
1153eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Tick = GetPerformanceCounter ();
1163eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Timeout = DivU64x32 (
1173eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang                MultU64x32 (
1183eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang                  GetPerformanceCounterProperties (&Start, &End),
1193eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang                  PcdGet32 (PcdSpinLockTimeout)
1203eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang                  ),
1213eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang                1000000
1223eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang                );
1233eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    if (Start < End) {
1243eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      Tick += Timeout;
1253eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    } else {
1263eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      Tick -= Timeout;
1273eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    }
1283eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
1293eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1303eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  while (!AcquireSpinLockOrFail (SpinLock)) {
1313eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    CpuPause ();
1323eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    ASSERT ((Start < End) ^ (Tick <= GetPerformanceCounter ()));
1333eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
1343eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  return SpinLock;
1353eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang}
1363eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1373eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang/**
1383eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Attempts to place a spin lock in the acquired state.
1393eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1403eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  This function checks the state of the spin lock specified by SpinLock. If
1413eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  SpinLock is in the released state, then this function places SpinLock in the
1423eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  acquired state and returns TRUE. Otherwise, FALSE is returned. All state
1433eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  transitions of SpinLock must be performed using MP safe mechanisms.
1443eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1453eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  If SpinLock is NULL, then ASSERT().
1463eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  If SpinLock was not initialized with InitializeSpinLock(), then ASSERT().
1473eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1483eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  @param  SpinLock  A pointer to the spin lock to place in the acquired state.
1493eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1503eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  @retval TRUE  SpinLock was placed in the acquired state.
1513eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  @retval FALSE SpinLock could not be acquired.
1523eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1533eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang**/
1543eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangBOOLEAN
1553eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangEFIAPI
1563eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangAcquireSpinLockOrFail (
1573eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  IN OUT  SPIN_LOCK                 *SpinLock
1583eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  )
1593eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang{
160c7f33ca42470dc87bc41a8583f427883123d67a1qwang  SPIN_LOCK    LockValue;
1613eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1623eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  ASSERT (SpinLock != NULL);
1633eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1643eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  LockValue = *SpinLock;
1653eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  ASSERT (LockValue == SPIN_LOCK_ACQUIRED || LockValue == SPIN_LOCK_RELEASED);
1663eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1673eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  return (BOOLEAN)(
1683eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang           InterlockedCompareExchangePointer (
1693eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang             (VOID**)SpinLock,
1703eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang             (VOID*)SPIN_LOCK_RELEASED,
1713eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang             (VOID*)SPIN_LOCK_ACQUIRED
1723eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang             ) == (VOID*)SPIN_LOCK_RELEASED
1733eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang           );
1743eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang}
1753eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1763eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang/**
1773eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Releases a spin lock.
1783eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1793eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  This function places the spin lock specified by SpinLock in the release state
1803eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  and returns SpinLock.
1813eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1823eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  If SpinLock is NULL, then ASSERT().
1833eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  If SpinLock was not initialized with InitializeSpinLock(), then ASSERT().
1843eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1853eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  @param  SpinLock  A pointer to the spin lock to release.
1863eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1873eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  @return SpinLock
1883eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1893eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang**/
1903eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangSPIN_LOCK *
1913eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangEFIAPI
1923eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangReleaseSpinLock (
1933eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  IN OUT  SPIN_LOCK                 *SpinLock
1943eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  )
1953eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang{
196c7f33ca42470dc87bc41a8583f427883123d67a1qwang  SPIN_LOCK    LockValue;
1973eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1983eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  ASSERT (SpinLock != NULL);
1993eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2003eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  LockValue = *SpinLock;
2013eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  ASSERT (LockValue == SPIN_LOCK_ACQUIRED || LockValue == SPIN_LOCK_RELEASED);
2023eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2033eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  *SpinLock = SPIN_LOCK_RELEASED;
2043eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  return SpinLock;
2053eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang}
2063eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2073eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang/**
2083eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Performs an atomic increment of an 32-bit unsigned integer.
2093eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2103eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Performs an atomic increment of the 32-bit unsigned integer specified by
2113eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Value and returns the incremented value. The increment operation must be
2123eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  performed using MP safe mechanisms. The state of the return value is not
2133eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  guaranteed to be MP safe.
2143eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2153eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  If Value is NULL, then ASSERT().
2163eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2173eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  @param  Value A pointer to the 32-bit value to increment.
2183eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2193eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  @return The incremented value.
2203eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2213eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang**/
2223eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangUINT32
2233eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangEFIAPI
2243eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangInterlockedIncrement (
2253eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  IN      UINT32                    *Value
2263eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  )
2273eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang{
2283eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  ASSERT (Value != NULL);
2293eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  return InternalSyncIncrement (Value);
2303eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang}
2313eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2323eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang/**
2333eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Performs an atomic decrement of an 32-bit unsigned integer.
2343eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2353eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Performs an atomic decrement of the 32-bit unsigned integer specified by
2363eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Value and returns the decremented value. The decrement operation must be
2373eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  performed using MP safe mechanisms. The state of the return value is not
2383eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  guaranteed to be MP safe.
2393eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2403eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  If Value is NULL, then ASSERT().
2413eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2423eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  @param  Value A pointer to the 32-bit value to decrement.
2433eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2443eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  @return The decremented value.
2453eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2463eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang**/
2473eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangUINT32
2483eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangEFIAPI
2493eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangInterlockedDecrement (
2503eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  IN      UINT32                    *Value
2513eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  )
2523eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang{
2533eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  ASSERT (Value != NULL);
2543eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  return InternalSyncDecrement (Value);
2553eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang}
2563eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2573eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang/**
2583eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Performs an atomic compare exchange operation on a 32-bit unsigned integer.
2593eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2603eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Performs an atomic compare exchange operation on the 32-bit unsigned integer
2613eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  specified by Value.  If Value is equal to CompareValue, then Value is set to
2623eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
2633eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  then Value is returned.  The compare exchange operation must be performed using
2643eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  MP safe mechanisms.
2653eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2663eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  If Value is NULL, then ASSERT().
2673eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2683eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  @param  Value         A pointer to the 32-bit value for the compare exchange
2693eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang                        operation.
2703eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  @param  CompareValue  32-bit value used in compare operation.
2713eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  @param  ExchangeValue 32-bit value used in exchange operation.
2723eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2733eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  @return The original *Value before exchange.
2743eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2753eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang**/
2763eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangUINT32
2773eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangEFIAPI
2783eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangInterlockedCompareExchange32 (
2793eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  IN OUT  UINT32                    *Value,
2803eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  IN      UINT32                    CompareValue,
2813eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  IN      UINT32                    ExchangeValue
2823eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  )
2833eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang{
2843eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  ASSERT (Value != NULL);
2853eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  return InternalSyncCompareExchange32 (Value, CompareValue, ExchangeValue);
2863eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang}
2873eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2883eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang/**
2893eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Performs an atomic compare exchange operation on a 64-bit unsigned integer.
2903eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2913eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Performs an atomic compare exchange operation on the 64-bit unsigned integer specified
2923eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  by Value.  If Value is equal to CompareValue, then Value is set to ExchangeValue and
2933eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  CompareValue is returned.  If Value is not equal to CompareValue, then Value is returned.
2943eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  The compare exchange operation must be performed using MP safe mechanisms.
2953eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2963eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  If Value is NULL, then ASSERT().
2973eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2983eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  @param  Value         A pointer to the 64-bit value for the compare exchange
2993eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang                        operation.
3003eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  @param  CompareValue  64-bit value used in compare operation.
3013eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  @param  ExchangeValue 64-bit value used in exchange operation.
3023eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
3033eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  @return The original *Value before exchange.
3043eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
3053eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang**/
3063eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangUINT64
3073eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangEFIAPI
3083eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangInterlockedCompareExchange64 (
3093eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  IN OUT  UINT64                    *Value,
3103eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  IN      UINT64                    CompareValue,
3113eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  IN      UINT64                    ExchangeValue
3123eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  )
3133eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang{
3143eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  ASSERT (Value != NULL);
3153eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  return InternalSyncCompareExchange64 (Value, CompareValue, ExchangeValue);
3163eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang}
3173eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
3183eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang/**
3193eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Performs an atomic compare exchange operation on a pointer value.
3203eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
3213eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Performs an atomic compare exchange operation on the pointer value specified
3223eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  by Value. If Value is equal to CompareValue, then Value is set to
3233eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  ExchangeValue and CompareValue is returned. If Value is not equal to
3243eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  CompareValue, then Value is returned. The compare exchange operation must be
3253eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  performed using MP safe mechanisms.
3263eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
3273eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  If Value is NULL, then ASSERT().
3283eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
3293eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  @param  Value         A pointer to the pointer value for the compare exchange
3303eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang                        operation.
3313eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  @param  CompareValue  Pointer value used in compare operation.
3323eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  @param  ExchangeValue Pointer value used in exchange operation.
3333eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
3343eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang**/
3353eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangVOID *
3363eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangEFIAPI
3373eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangInterlockedCompareExchangePointer (
3383eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  IN OUT  VOID                      **Value,
3393eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  IN      VOID                      *CompareValue,
3403eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  IN      VOID                      *ExchangeValue
3413eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  )
3423eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang{
3433eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  UINT8  SizeOfValue;
3443eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
3453eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  SizeOfValue = sizeof (*Value);
3463eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
3473eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  switch (SizeOfValue) {
3483eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    case sizeof (UINT32):
3493eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      return (VOID*)(UINTN)InterlockedCompareExchange32 (
3503eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang                             (UINT32*)Value,
3513eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang                             (UINT32)(UINTN)CompareValue,
3523eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang                             (UINT32)(UINTN)ExchangeValue
3533eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang                             );
3543eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    case sizeof (UINT64):
3553eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      return (VOID*)(UINTN)InterlockedCompareExchange64 (
3563eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang                             (UINT64*)Value,
3573eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang                             (UINT64)(UINTN)CompareValue,
3583eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang                             (UINT64)(UINTN)ExchangeValue
3593eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang                             );
3603eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    default:
3613eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      ASSERT (FALSE);
3623eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      return NULL;
3633eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
3643eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang}
365