diff mbox

[edk2,v4,14/29] MdePkg/BaseSynchronizationLib: implement 16-bit compare-exchange

Message ID 1423739961-5945-15-git-send-email-ard.biesheuvel@linaro.org
State New
Headers show

Commit Message

Ard Biesheuvel Feb. 12, 2015, 11:19 a.m. UTC
This implements the function InterlockedCompareExchange16 () for all
architectures, using architecture and toolchain specific intrinsics
or primitive assembler instructions.

Contributed-under: TianoCore Contribution Agreement 1.0
Reviewed-by: Olivier Martin <olivier.martin@arm.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 MdePkg/Include/Library/SynchronizationLib.h                                 | 26 ++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S             | 44 ++++++++++++++++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S                 | 44 ++++++++++++++++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm               | 44 ++++++++++++++++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf            |  5 +++++
 MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h     | 26 ++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c                 | 31 +++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c                      | 42 ++++++++++++++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c   | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s    | 30 ++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/Synchronization.c                     | 31 +++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c                  | 31 +++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c                  | 31 +++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c                       | 44 ++++++++++++++++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm  | 42 ++++++++++++++++++++++++++++++++++++++++++
 MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c    | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 17 files changed, 622 insertions(+)

Comments

Ard Biesheuvel Feb. 18, 2015, 8:37 a.m. UTC | #1
On 17 February 2015 at 18:40, Jordan Justen <jordan.l.justen@intel.com> wrote:
> Ard,
>
> For the subject, I think
> MdePkg/BaseSynchronizationLib: Add InterlockedCompareExchange16
> would be better.
>

OK

> Acked-by: Jordan Justen <jordan.l.justen@intel.com>
>

Thanks

> Thanks for working to move this to a common location.
>

No problem

> Mike,
>
> I think Anthony tested the IA32 and X64 implementations with Xen. For
> IPF, I don't think it has been tested.
>

As mentioned in the other thread, Anthony seems to be incommunicado,
and some other of the Xen guys have replied that Xen on OVMF/x86 is
broken for other reasons so they cannot positively confirm that
everything still works, even though the x86 changes other than the
PCI/xenbus split are primarily refactoring of existing code.

As far as IPF is concerned: I don't think Xen or Ovmf can be built for
IPF anyway, but I think a build test and visual inspection of the .S
file should be sufficient here?

Thanks,
Ard.


> On 2015-02-12 03:19:06, Ard Biesheuvel wrote:
>> This implements the function InterlockedCompareExchange16 () for all
>> architectures, using architecture and toolchain specific intrinsics
>> or primitive assembler instructions.
>>
>> Contributed-under: TianoCore Contribution Agreement 1.0
>> Reviewed-by: Olivier Martin <olivier.martin@arm.com>
>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>> ---
>>  MdePkg/Include/Library/SynchronizationLib.h                                 | 26 ++++++++++++++++++++++++++
>>  MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S             | 44 ++++++++++++++++++++++++++++++++++++++++++++
>>  MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S                 | 44 ++++++++++++++++++++++++++++++++++++++++++++
>>  MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm               | 44 ++++++++++++++++++++++++++++++++++++++++++++
>>  MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf            |  5 +++++
>>  MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h     | 26 ++++++++++++++++++++++++++
>>  MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c                 | 31 +++++++++++++++++++++++++++++++
>>  MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c                      | 42 ++++++++++++++++++++++++++++++++++++++++++
>>  MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm | 46 ++++++++++++++++++++++++++++++++++++++++++++++
>>  MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c   | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
>>  MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s    | 30 ++++++++++++++++++++++++++++++
>>  MdePkg/Library/BaseSynchronizationLib/Synchronization.c                     | 31 +++++++++++++++++++++++++++++++
>>  MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c                  | 31 +++++++++++++++++++++++++++++++
>>  MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c                  | 31 +++++++++++++++++++++++++++++++
>>  MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c                       | 44 ++++++++++++++++++++++++++++++++++++++++++++
>>  MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm  | 42 ++++++++++++++++++++++++++++++++++++++++++
>>  MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c    | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  17 files changed, 622 insertions(+)
>>
>> diff --git a/MdePkg/Include/Library/SynchronizationLib.h b/MdePkg/Include/Library/SynchronizationLib.h
>> index f97569739914..7b97683ca0af 100644
>> --- a/MdePkg/Include/Library/SynchronizationLib.h
>> +++ b/MdePkg/Include/Library/SynchronizationLib.h
>> @@ -184,6 +184,32 @@ InterlockedDecrement (
>>
>>
>>  /**
>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>> +
>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>> +  then Value is returned.  The compare exchange operation must be performed using
>> +  MP safe mechanisms.
>> +
>> +  If Value is NULL, then ASSERT().
>> +
>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>> +                        operation.
>> +  @param  CompareValue  16-bit value used in compare operation.
>> +  @param  ExchangeValue 16-bit value used in exchange operation.
>> +
>> +  @return The original *Value before exchange.
>> +**/
>> +UINT16
>> +EFIAPI
>> +InterlockedCompareExchange16 (
>> +  IN OUT  UINT16                    *Value,
>> +  IN      UINT16                    CompareValue,
>> +  IN      UINT16                    ExchangeValue
>> +  );
>> +
>> +/**
>>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>>
>>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
>> diff --git a/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S b/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S
>> index 601b00495f26..ecb87fc12755 100644
>> --- a/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S
>> +++ b/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S
>> @@ -16,12 +16,56 @@
>>  .text
>>  .align 3
>>
>> +GCC_ASM_EXPORT(InternalSyncCompareExchange16)
>>  GCC_ASM_EXPORT(InternalSyncCompareExchange32)
>>  GCC_ASM_EXPORT(InternalSyncCompareExchange64)
>>  GCC_ASM_EXPORT(InternalSyncIncrement)
>>  GCC_ASM_EXPORT(InternalSyncDecrement)
>>
>>  /**
>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>> +
>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>> +  then Value is returned.  The compare exchange operation must be performed using
>> +  MP safe mechanisms.
>> +
>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>> +                        operation.
>> +  @param  CompareValue  16-bit value used in compare operation.
>> +  @param  ExchangeValue 16-bit value used in exchange operation.
>> +
>> +  @return The original *Value before exchange.
>> +
>> +**/
>> +//UINT16
>> +//EFIAPI
>> +//InternalSyncCompareExchange16 (
>> +//  IN      volatile UINT16           *Value,
>> +//  IN      UINT16                    CompareValue,
>> +//  IN      UINT16                    ExchangeValue
>> +//  )
>> +ASM_PFX(InternalSyncCompareExchange16):
>> +  uxth    w1, w1
>> +  uxth    w2, w2
>> +  dmb     sy
>> +
>> +InternalSyncCompareExchange16Again:
>> +  ldxrh   w3, [x0]
>> +  cmp     w3, w1
>> +  bne     InternalSyncCompareExchange16Fail
>> +
>> +InternalSyncCompareExchange16Exchange:
>> +  stxrh   w4, w2, [x0]
>> +  cbnz    w4, InternalSyncCompareExchange16Again
>> +
>> +InternalSyncCompareExchange16Fail:
>> +  dmb     sy
>> +  mov     w0, w3
>> +  ret
>> +
>> +/**
>>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>>
>>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
>> diff --git a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S
>> index 0128f8f016bd..d699eb40d2a2 100644
>> --- a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S
>> +++ b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S
>> @@ -1,6 +1,7 @@
>>  //  Implementation of synchronization functions for ARM architecture
>>  //
>>  //  Copyright (c) 2012-2015, ARM Limited. All rights reserved.
>> +//  Copyright (c) 2015, Linaro Limited. All rights reserved.
>>  //
>>  //  This program and the accompanying materials
>>  //  are licensed and made available under the terms and conditions of the BSD License
>> @@ -15,12 +16,55 @@
>>  .text
>>  .align 3
>>
>> +GCC_ASM_EXPORT(InternalSyncCompareExchange16)
>>  GCC_ASM_EXPORT(InternalSyncCompareExchange32)
>>  GCC_ASM_EXPORT(InternalSyncCompareExchange64)
>>  GCC_ASM_EXPORT(InternalSyncIncrement)
>>  GCC_ASM_EXPORT(InternalSyncDecrement)
>>
>>  /**
>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>> +
>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>> +  then Value is returned.  The compare exchange operation must be performed using
>> +  MP safe mechanisms.
>> +
>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>> +                        operation.
>> +  @param  CompareValue  16-bit value used in compare operation.
>> +  @param  ExchangeValue 16-bit value used in exchange operation.
>> +
>> +  @return The original *Value before exchange.
>> +
>> +**/
>> +//UINT16
>> +//EFIAPI
>> +//InternalSyncCompareExchange16 (
>> +//  IN      volatile UINT16           *Value,
>> +//  IN      UINT16                    CompareValue,
>> +//  IN      UINT16                    ExchangeValue
>> +//  )
>> +ASM_PFX(InternalSyncCompareExchange16):
>> +  dmb
>> +
>> +InternalSyncCompareExchange16Again:
>> +  ldrexh  r3, [r0]
>> +  cmp     r3, r1
>> +  bne     InternalSyncCompareExchange16Fail
>> +
>> +InternalSyncCompareExchange16Exchange:
>> +  strexh  ip, r2, [r0]
>> +  cmp     ip, #0
>> +  bne     InternalSyncCompareExchange16Again
>> +
>> +InternalSyncCompareExchange16Fail:
>> +  dmb
>> +  mov     r0, r3
>> +  bx      lr
>> +
>> +/**
>>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>>
>>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
>> diff --git a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm
>> index f9f80737774a..dbc599114093 100644
>> --- a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm
>> +++ b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm
>> @@ -1,6 +1,7 @@
>>  //  Implementation of synchronization functions for ARM architecture
>>  //
>>  //  Copyright (c) 2012-2015, ARM Limited. All rights reserved.
>> +//  Copyright (c) 2015, Linaro Limited. All rights reserved.
>>  //
>>  //  This program and the accompanying materials
>>  //  are licensed and made available under the terms and conditions of the BSD License
>> @@ -12,6 +13,7 @@
>>  //
>>  //
>>
>> +    EXPORT  InternalSyncCompareExchange16
>>      EXPORT  InternalSyncCompareExchange32
>>      EXPORT  InternalSyncCompareExchange64
>>      EXPORT  InternalSyncIncrement
>> @@ -20,6 +22,48 @@
>>      AREA   ArmSynchronization, CODE, READONLY
>>
>>  /**
>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>> +
>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>> +  then Value is returned.  The compare exchange operation must be performed using
>> +  MP safe mechanisms.
>> +
>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>> +                        operation.
>> +  @param  CompareValue  16-bit value used in compare operation.
>> +  @param  ExchangeValue 16-bit value used in exchange operation.
>> +
>> +  @return The original *Value before exchange.
>> +
>> +**/
>> +//UINT16
>> +//EFIAPI
>> +//InternalSyncCompareExchange16 (
>> +//  IN      volatile UINT16           *Value,
>> +//  IN      UINT16                    CompareValue,
>> +//  IN      UINT16                    ExchangeValue
>> +//  )
>> +InternalSyncCompareExchange16
>> +  dmb
>> +
>> +InternalSyncCompareExchange16Again
>> +  ldrexh  r3, [r0]
>> +  cmp     r3, r1
>> +  bne     InternalSyncCompareExchange16Fail
>> +
>> +InternalSyncCompareExchange16Exchange
>> +  strexh  ip, r2, [r0]
>> +  cmp     ip, #0
>> +  bne     InternalSyncCompareExchange16Again
>> +
>> +InternalSyncCompareExchange16Fail
>> +  dmb
>> +  mov     r0, r3
>> +  bx      lr
>> +
>> +/**
>>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>>
>>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
>> diff --git a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
>> index 5e3b4e6b9bf2..bd1bec3fb5e7 100755
>> --- a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
>> +++ b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
>> @@ -32,12 +32,14 @@
>>  [Sources.IA32]
>>    Ia32/InterlockedCompareExchange64.c | MSFT
>>    Ia32/InterlockedCompareExchange32.c | MSFT
>> +  Ia32/InterlockedCompareExchange16.c | MSFT
>>    Ia32/InterlockedDecrement.c | MSFT
>>    Ia32/InterlockedIncrement.c | MSFT
>>    SynchronizationMsc.c  | MSFT
>>
>>    Ia32/InterlockedCompareExchange64.asm | INTEL
>>    Ia32/InterlockedCompareExchange32.asm | INTEL
>> +  Ia32/InterlockedCompareExchange16.asm | INTEL
>>    Ia32/InterlockedDecrement.asm | INTEL
>>    Ia32/InterlockedIncrement.asm | INTEL
>>    Synchronization.c | INTEL
>> @@ -48,9 +50,11 @@
>>  [Sources.X64]
>>    X64/InterlockedCompareExchange64.c | MSFT
>>    X64/InterlockedCompareExchange32.c | MSFT
>> +  X64/InterlockedCompareExchange16.c | MSFT
>>
>>    X64/InterlockedCompareExchange64.asm | INTEL
>>    X64/InterlockedCompareExchange32.asm | INTEL
>> +  X64/InterlockedCompareExchange16.asm | INTEL
>>
>>    X64/InterlockedDecrement.c | MSFT
>>    X64/InterlockedIncrement.c | MSFT
>> @@ -67,6 +71,7 @@
>>    Ipf/Synchronization.c
>>    Ipf/InterlockedCompareExchange64.s
>>    Ipf/InterlockedCompareExchange32.s
>> +  Ipf/InterlockedCompareExchange16.s
>>
>>    Synchronization.c     | INTEL
>>    SynchronizationMsc.c  | MSFT
>> diff --git a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h
>> index e42824c75d12..76f702324156 100644
>> --- a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h
>> +++ b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h
>> @@ -63,6 +63,32 @@ InternalSyncDecrement (
>>
>>
>>  /**
>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>> +
>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>> +  then Value is returned.  The compare exchange operation must be performed using
>> +  MP safe mechanisms.
>> +
>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>> +                        operation.
>> +  @param  CompareValue  A 16-bit value used in compare operation.
>> +  @param  ExchangeValue A 16-bit value used in exchange operation.
>> +
>> +  @return The original *Value before exchange.
>> +
>> +**/
>> +UINT16
>> +EFIAPI
>> +InternalSyncCompareExchange16 (
>> +  IN      volatile UINT16           *Value,
>> +  IN      UINT16                    CompareValue,
>> +  IN      UINT16                    ExchangeValue
>> +  );
>> +
>> +
>> +/**
>>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>>
>>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
>> diff --git a/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c b/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c
>> index 9c34b9f128ed..a57860203b12 100644
>> --- a/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c
>> +++ b/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c
>> @@ -13,6 +13,37 @@
>>  **/
>>
>>  /**
>> +  Performs an atomic compare exchange operation on a 16-bit
>> +  unsigned integer.
>> +
>> +  Performs an atomic compare exchange operation on the 16-bit
>> +  unsigned integer specified by Value.  If Value is equal to
>> +  CompareValue, then Value is set to ExchangeValue and
>> +  CompareValue is returned.  If Value is not equal to
>> +  CompareValue, then Value is returned. The compare exchange
>> +  operation must be performed using MP safe mechanisms.
>> +
>> +  @param  Value         A pointer to the 16-bit value for the
>> +                        compare exchange operation.
>> +  @param  CompareValue  16-bit value used in compare operation.
>> +  @param  ExchangeValue 16-bit value used in exchange operation.
>> +
>> +  @return The original *Value before exchange.
>> +
>> +**/
>> +UINT16
>> +EFIAPI
>> +InternalSyncCompareExchange16 (
>> +  IN      volatile UINT16           *Value,
>> +  IN      UINT16                    CompareValue,
>> +  IN      UINT16                    ExchangeValue
>> +  )
>> +{
>> +  return *Value != CompareValue ? *Value :
>> +           ((*Value = ExchangeValue), CompareValue);
>> +}
>> +
>> +/**
>>    Performs an atomic compare exchange operation on a 32-bit
>>    unsigned integer.
>>
>> diff --git a/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c b/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c
>> index b5a7827fc0e8..bd81aad6c243 100644
>> --- a/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c
>> +++ b/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c
>> @@ -88,6 +88,48 @@ InternalSyncDecrement (
>>  }
>>
>>  /**
>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>> +
>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>> +  then Value is returned.  The compare exchange operation must be performed using
>> +  MP safe mechanisms.
>> +
>> +
>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>> +                        operation.
>> +  @param  CompareValue  16-bit value used in compare operation.
>> +  @param  ExchangeValue 16-bit value used in exchange operation.
>> +
>> +  @return The original *Value before exchange.
>> +
>> +**/
>> +UINT16
>> +EFIAPI
>> +InternalSyncCompareExchange16 (
>> +  IN OUT volatile  UINT16           *Value,
>> +  IN      UINT16                    CompareValue,
>> +  IN      UINT16                    ExchangeValue
>> +  )
>> +{
>> +
>> +  __asm__ __volatile__ (
>> +    "                     \n    "
>> +    "lock                 \n    "
>> +    "cmpxchgw    %1, %2   \n    "
>> +    : "=a" (CompareValue)
>> +    : "q"  (ExchangeValue),
>> +      "m"  (*Value),
>> +      "0"  (CompareValue)
>> +    : "memory",
>> +      "cc"
>> +    );
>> +
>> +  return CompareValue;
>> +}
>> +
>> +/**
>>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>>
>>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
>> diff --git a/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm
>> new file mode 100644
>> index 000000000000..f8705042661d
>> --- /dev/null
>> +++ b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm
>> @@ -0,0 +1,46 @@
>> +;------------------------------------------------------------------------------
>> +;
>> +; Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
>> +; Copyright (c) 2015, Linaro Ltd. All rights reserved.<BR>
>> +; This program and the accompanying materials
>> +; are licensed and made available under the terms and conditions of the BSD License
>> +; which accompanies this distribution.  The full text of the license may be found at
>> +; http://opensource.org/licenses/bsd-license.php.
>> +;
>> +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
>> +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
>> +;
>> +; Module Name:
>> +;
>> +;   InterlockedCompareExchange16.Asm
>> +;
>> +; Abstract:
>> +;
>> +;   InterlockedCompareExchange16 function
>> +;
>> +; Notes:
>> +;
>> +;------------------------------------------------------------------------------
>> +
>> +    .486
>> +    .model  flat,C
>> +    .code
>> +
>> +;------------------------------------------------------------------------------
>> +; UINT16
>> +; EFIAPI
>> +; InternalSyncCompareExchange16 (
>> +;   IN      UINT16                    *Value,
>> +;   IN      UINT16                    CompareValue,
>> +;   IN      UINT16                    ExchangeValue
>> +;   );
>> +;------------------------------------------------------------------------------
>> +InternalSyncCompareExchange16   PROC
>> +    mov     ecx, [esp + 4]
>> +    mov     eax, [esp + 8]
>> +    mov     edx, [esp + 12]
>> +    lock    cmpxchg [ecx], dx
>> +    ret
>> +InternalSyncCompareExchange16   ENDP
>> +
>> +    END
>> diff --git a/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c
>> new file mode 100644
>> index 000000000000..3d06dd9baa63
>> --- /dev/null
>> +++ b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c
>> @@ -0,0 +1,51 @@
>> +/** @file
>> +  InterlockedCompareExchange16 function
>> +
>> +  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
>> +  Copyright (c) 2015, Linaro Ltd. All rights reserved.<BR>
>> +  This program and the accompanying materials
>> +  are licensed and made available under the terms and conditions of the BSD License
>> +  which accompanies this distribution.  The full text of the license may be found at
>> +  http://opensource.org/licenses/bsd-license.php.
>> +
>> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
>> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
>> +
>> +**/
>> +
>> +
>> +
>> +
>> +/**
>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>> +
>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>> +  then Value is returned.  The compare exchange operation must be performed using
>> +  MP safe mechanisms.
>> +
>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>> +                        operation.
>> +  @param  CompareValue  16-bit value used in compare operation.
>> +  @param  ExchangeValue 16-bit value used in exchange operation.
>> +
>> +  @return The original *Value before exchange.
>> +
>> +**/
>> +UINT16
>> +EFIAPI
>> +InternalSyncCompareExchange16 (
>> +  IN      UINT16                    *Value,
>> +  IN      UINT16                    CompareValue,
>> +  IN      UINT16                    ExchangeValue
>> +  )
>> +{
>> +  _asm {
>> +    mov     ecx, Value
>> +    mov     eax, CompareValue
>> +    mov     edx, ExchangeValue
>> +    lock    cmpxchg [ecx], dx
>> +  }
>> +}
>> +
>> diff --git a/MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s b/MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s
>> new file mode 100644
>> index 000000000000..1e56942a98cb
>> --- /dev/null
>> +++ b/MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s
>> @@ -0,0 +1,30 @@
>> +/// @file
>> +///   Contains an implementation of InterlockedCompareExchange16 on Itanium-
>> +///   based architecture.
>> +///
>> +/// Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
>> +/// Copyright (c) 2015, Linaro Ltd. All rights reserved.<BR>
>> +/// This program and the accompanying materials
>> +/// are licensed and made available under the terms and conditions of the BSD License
>> +/// which accompanies this distribution.  The full text of the license may be found at
>> +/// http://opensource.org/licenses/bsd-license.php.
>> +///
>> +/// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
>> +/// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
>> +///
>> +/// Module Name:  InterlockedCompareExchange16.s
>> +///
>> +///
>> +
>> +.auto
>> +.text
>> +
>> +.proc   InternalSyncCompareExchange16
>> +.type   InternalSyncCompareExchange16, @function
>> +InternalSyncCompareExchange16::
>> +        zxt2                r33 = r33
>> +        mov                 ar.ccv = r33
>> +        cmpxchg2.rel        r8  = [r32], r34
>> +        mf
>> +        br.ret.sptk.many    b0
>> +.endp   InternalSyncCompareExchange16
>> diff --git a/MdePkg/Library/BaseSynchronizationLib/Synchronization.c b/MdePkg/Library/BaseSynchronizationLib/Synchronization.c
>> index 0eea40ba1622..4218a265a0ec 100644
>> --- a/MdePkg/Library/BaseSynchronizationLib/Synchronization.c
>> +++ b/MdePkg/Library/BaseSynchronizationLib/Synchronization.c
>> @@ -277,6 +277,37 @@ InterlockedDecrement (
>>  }
>>
>>  /**
>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>> +
>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>> +  then Value is returned.  The compare exchange operation must be performed using
>> +  MP safe mechanisms.
>> +
>> +  If Value is NULL, then ASSERT().
>> +
>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>> +                        operation.
>> +  @param  CompareValue  16-bit value used in compare operation.
>> +  @param  ExchangeValue 16-bit value used in exchange operation.
>> +
>> +  @return The original *Value before exchange.
>> +
>> +**/
>> +UINT16
>> +EFIAPI
>> +InterlockedCompareExchange16 (
>> +  IN OUT  UINT16                    *Value,
>> +  IN      UINT16                    CompareValue,
>> +  IN      UINT16                    ExchangeValue
>> +  )
>> +{
>> +  ASSERT (Value != NULL);
>> +  return InternalSyncCompareExchange16 (Value, CompareValue, ExchangeValue);
>> +}
>> +
>> +/**
>>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>>
>>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
>> diff --git a/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c b/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c
>> index badf73c1a6ce..587f5a771c35 100644
>> --- a/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c
>> +++ b/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c
>> @@ -293,6 +293,37 @@ InterlockedDecrement (
>>  }
>>
>>  /**
>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>> +
>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>> +  then Value is returned.  The compare exchange operation must be performed using
>> +  MP safe mechanisms.
>> +
>> +  If Value is NULL, then ASSERT().
>> +
>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>> +                        operation.
>> +  @param  CompareValue  A 16-bit value used in compare operation.
>> +  @param  ExchangeValue A 16-bit value used in exchange operation.
>> +
>> +  @return The original *Value before exchange.
>> +
>> +**/
>> +UINT16
>> +EFIAPI
>> +InterlockedCompareExchange16 (
>> +  IN OUT  UINT16                    *Value,
>> +  IN      UINT16                    CompareValue,
>> +  IN      UINT16                    ExchangeValue
>> +  )
>> +{
>> +  ASSERT (Value != NULL);
>> +  return InternalSyncCompareExchange16 (Value, CompareValue, ExchangeValue);
>> +}
>> +
>> +/**
>>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>>
>>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
>> diff --git a/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c b/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c
>> index 9b20236acfa6..ca21f5dccee5 100644
>> --- a/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c
>> +++ b/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c
>> @@ -295,6 +295,37 @@ InterlockedDecrement (
>>  }
>>
>>  /**
>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>> +
>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>> +  then Value is returned.  The compare exchange operation must be performed using
>> +  MP safe mechanisms.
>> +
>> +  If Value is NULL, then ASSERT().
>> +
>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>> +                        operation.
>> +  @param  CompareValue  A 16-bit value used in a compare operation.
>> +  @param  ExchangeValue A 16-bit value used in an exchange operation.
>> +
>> +  @return The original *Value before exchange.
>> +
>> +**/
>> +UINT16
>> +EFIAPI
>> +InterlockedCompareExchange16 (
>> +  IN OUT  UINT16                    *Value,
>> +  IN      UINT16                    CompareValue,
>> +  IN      UINT16                    ExchangeValue
>> +  )
>> +{
>> +  ASSERT (Value != NULL);
>> +  return InternalSyncCompareExchange16 (Value, CompareValue, ExchangeValue);
>> +}
>> +
>> +/**
>>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>>
>>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
>> diff --git a/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c b/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c
>> index ceb80aed94f8..6347073fee51 100644
>> --- a/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c
>> +++ b/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c
>> @@ -89,6 +89,50 @@ InternalSyncDecrement (
>>
>>
>>  /**
>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>> +
>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>> +  then Value is returned.  The compare exchange operation must be performed using
>> +  MP safe mechanisms.
>> +
>> +
>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>> +                        operation.
>> +  @param  CompareValue  16-bit value used in compare operation.
>> +  @param  ExchangeValue 16-bit value used in exchange operation.
>> +
>> +  @return The original *Value before exchange.
>> +
>> +**/
>> +UINT16
>> +EFIAPI
>> +InternalSyncCompareExchange16 (
>> +  IN OUT volatile  UINT16           *Value,
>> +  IN      UINT16                    CompareValue,
>> +  IN      UINT16                    ExchangeValue
>> +  )
>> +{
>> +
>> +
>> +  __asm__ __volatile__ (
>> +    "lock                 \n    "
>> +    "cmpxchgw    %3, %1       "
>> +    : "=a" (CompareValue),
>> +      "=m" (*Value)
>> +    : "a"  (CompareValue),
>> +      "r"  (ExchangeValue),
>> +      "m"  (*Value)
>> +    : "memory",
>> +      "cc"
>> +    );
>> +
>> +  return CompareValue;
>> +}
>> +
>> +
>> +/**
>>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>>
>>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
>> diff --git a/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm
>> new file mode 100644
>> index 000000000000..8fe2aae1a28b
>> --- /dev/null
>> +++ b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm
>> @@ -0,0 +1,42 @@
>> +;------------------------------------------------------------------------------
>> +;
>> +; Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
>> +; Copyright (c) 2015, Linaro Ltd. All rights reserved.<BR>
>> +; This program and the accompanying materials
>> +; are licensed and made available under the terms and conditions of the BSD License
>> +; which accompanies this distribution.  The full text of the license may be found at
>> +; http://opensource.org/licenses/bsd-license.php.
>> +;
>> +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
>> +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
>> +;
>> +; Module Name:
>> +;
>> +;   InterlockedCompareExchange16.Asm
>> +;
>> +; Abstract:
>> +;
>> +;   InterlockedCompareExchange16 function
>> +;
>> +; Notes:
>> +;
>> +;------------------------------------------------------------------------------
>> +
>> +    .code
>> +
>> +;------------------------------------------------------------------------------
>> +; UINT16
>> +; EFIAPI
>> +; InterlockedCompareExchange16 (
>> +;   IN      UINT16                    *Value,
>> +;   IN      UINT16                    CompareValue,
>> +;   IN      UINT16                    ExchangeValue
>> +;   );
>> +;------------------------------------------------------------------------------
>> +InternalSyncCompareExchange16   PROC
>> +    mov     eax, edx
>> +    lock    cmpxchg [rcx], r8w
>> +    ret
>> +InternalSyncCompareExchange16   ENDP
>> +
>> +    END
>> diff --git a/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c
>> new file mode 100644
>> index 000000000000..76aa6fbc0e81
>> --- /dev/null
>> +++ b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c
>> @@ -0,0 +1,54 @@
>> +/** @file
>> +  InterlockedCompareExchange16 function
>> +
>> +  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
>> +  Copyright (c) 2015, Linaro Ltd. All rights reserved.<BR>
>> +  This program and the accompanying materials
>> +  are licensed and made available under the terms and conditions of the BSD License
>> +  which accompanies this distribution.  The full text of the license may be found at
>> +  http://opensource.org/licenses/bsd-license.php.
>> +
>> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
>> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
>> +
>> +**/
>> +
>> +/**
>> +  Microsoft Visual Studio 7.1 Function Prototypes for I/O Intrinsics.
>> +**/
>> +
>> +__int16 _InterlockedCompareExchange16(
>> +   __int16 volatile * Destination,
>> +   __int16 Exchange,
>> +   __int16 Comperand
>> +);
>> +
>> +#pragma intrinsic(_InterlockedCompareExchange16)
>> +
>> +/**
>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>> +
>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer specified
>> +  by Value.  If Value is equal to CompareValue, then Value is set to ExchangeValue and
>> +  CompareValue is returned.  If Value is not equal to CompareValue, then Value is returned.
>> +  The compare exchange operation must be performed using MP safe mechanisms.
>> +
>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>> +                        operation.
>> +  @param  CompareValue  16-bit value used in compare operation.
>> +  @param  ExchangeValue 16-bit value used in exchange operation.
>> +
>> +  @return The original *Value before exchange.
>> +
>> +**/
>> +UINT16
>> +EFIAPI
>> +InternalSyncCompareExchange16 (
>> +  IN      UINT16                    *Value,
>> +  IN      UINT16                    CompareValue,
>> +  IN      UINT16                    ExchangeValue
>> +  )
>> +{
>> +  return _InterlockedCompareExchange16 (Value, ExchangeValue, CompareValue);
>> +}
>> +
>> --
>> 1.8.3.2
>>

------------------------------------------------------------------------------
Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server
from Actuate! Instantly Supercharge Your Business Reports and Dashboards
with Interactivity, Sharing, Native Excel Exports, App Integration & more
Get technology previously reserved for billion-dollar corporations, FREE
http://pubads.g.doubleclick.net/gampad/clk?id=190641631&iu=/4140/ostg.clktrk
Ard Biesheuvel Feb. 23, 2015, 8:33 p.m. UTC | #2
On 18 February 2015 at 08:37, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> On 17 February 2015 at 18:40, Jordan Justen <jordan.l.justen@intel.com> wrote:
>> Ard,
>>
>> For the subject, I think
>> MdePkg/BaseSynchronizationLib: Add InterlockedCompareExchange16
>> would be better.
>>
>
> OK
>
>> Acked-by: Jordan Justen <jordan.l.justen@intel.com>
>>
>
> Thanks
>
>> Thanks for working to move this to a common location.
>>
>
> No problem
>
>> Mike,
>>
>> I think Anthony tested the IA32 and X64 implementations with Xen. For
>> IPF, I don't think it has been tested.
>>
>
> As mentioned in the other thread, Anthony seems to be incommunicado,
> and some other of the Xen guys have replied that Xen on OVMF/x86 is
> broken for other reasons so they cannot positively confirm that
> everything still works, even though the x86 changes other than the
> PCI/xenbus split are primarily refactoring of existing code.
>
> As far as IPF is concerned: I don't think Xen or Ovmf can be built for
> IPF anyway, but I think a build test and visual inspection of the .S
> file should be sufficient here?
>

Hello Jordan, Michael,

As I mentioned in the other thread, this series is now tested on ARM
and x86, and no regressions were reported.
The only thing holding back this series is the confirmation that the
IPF build has not been broken by introducing the
InterlockedCompareExchange16() function, which i would gladly test
myself, but I really don't have access to the required build
environment.

So please, could you have a look, or perhaps appoint someone else to
handle it in your place?

Thanks,
Ard.


>> On 2015-02-12 03:19:06, Ard Biesheuvel wrote:
>>> This implements the function InterlockedCompareExchange16 () for all
>>> architectures, using architecture and toolchain specific intrinsics
>>> or primitive assembler instructions.
>>>
>>> Contributed-under: TianoCore Contribution Agreement 1.0
>>> Reviewed-by: Olivier Martin <olivier.martin@arm.com>
>>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>>> ---
>>>  MdePkg/Include/Library/SynchronizationLib.h                                 | 26 ++++++++++++++++++++++++++
>>>  MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S             | 44 ++++++++++++++++++++++++++++++++++++++++++++
>>>  MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S                 | 44 ++++++++++++++++++++++++++++++++++++++++++++
>>>  MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm               | 44 ++++++++++++++++++++++++++++++++++++++++++++
>>>  MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf            |  5 +++++
>>>  MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h     | 26 ++++++++++++++++++++++++++
>>>  MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c                 | 31 +++++++++++++++++++++++++++++++
>>>  MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c                      | 42 ++++++++++++++++++++++++++++++++++++++++++
>>>  MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm | 46 ++++++++++++++++++++++++++++++++++++++++++++++
>>>  MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c   | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
>>>  MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s    | 30 ++++++++++++++++++++++++++++++
>>>  MdePkg/Library/BaseSynchronizationLib/Synchronization.c                     | 31 +++++++++++++++++++++++++++++++
>>>  MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c                  | 31 +++++++++++++++++++++++++++++++
>>>  MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c                  | 31 +++++++++++++++++++++++++++++++
>>>  MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c                       | 44 ++++++++++++++++++++++++++++++++++++++++++++
>>>  MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm  | 42 ++++++++++++++++++++++++++++++++++++++++++
>>>  MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c    | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>>  17 files changed, 622 insertions(+)
>>>
>>> diff --git a/MdePkg/Include/Library/SynchronizationLib.h b/MdePkg/Include/Library/SynchronizationLib.h
>>> index f97569739914..7b97683ca0af 100644
>>> --- a/MdePkg/Include/Library/SynchronizationLib.h
>>> +++ b/MdePkg/Include/Library/SynchronizationLib.h
>>> @@ -184,6 +184,32 @@ InterlockedDecrement (
>>>
>>>
>>>  /**
>>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>>> +
>>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>>> +  then Value is returned.  The compare exchange operation must be performed using
>>> +  MP safe mechanisms.
>>> +
>>> +  If Value is NULL, then ASSERT().
>>> +
>>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>>> +                        operation.
>>> +  @param  CompareValue  16-bit value used in compare operation.
>>> +  @param  ExchangeValue 16-bit value used in exchange operation.
>>> +
>>> +  @return The original *Value before exchange.
>>> +**/
>>> +UINT16
>>> +EFIAPI
>>> +InterlockedCompareExchange16 (
>>> +  IN OUT  UINT16                    *Value,
>>> +  IN      UINT16                    CompareValue,
>>> +  IN      UINT16                    ExchangeValue
>>> +  );
>>> +
>>> +/**
>>>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>>>
>>>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
>>> diff --git a/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S b/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S
>>> index 601b00495f26..ecb87fc12755 100644
>>> --- a/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S
>>> +++ b/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S
>>> @@ -16,12 +16,56 @@
>>>  .text
>>>  .align 3
>>>
>>> +GCC_ASM_EXPORT(InternalSyncCompareExchange16)
>>>  GCC_ASM_EXPORT(InternalSyncCompareExchange32)
>>>  GCC_ASM_EXPORT(InternalSyncCompareExchange64)
>>>  GCC_ASM_EXPORT(InternalSyncIncrement)
>>>  GCC_ASM_EXPORT(InternalSyncDecrement)
>>>
>>>  /**
>>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>>> +
>>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>>> +  then Value is returned.  The compare exchange operation must be performed using
>>> +  MP safe mechanisms.
>>> +
>>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>>> +                        operation.
>>> +  @param  CompareValue  16-bit value used in compare operation.
>>> +  @param  ExchangeValue 16-bit value used in exchange operation.
>>> +
>>> +  @return The original *Value before exchange.
>>> +
>>> +**/
>>> +//UINT16
>>> +//EFIAPI
>>> +//InternalSyncCompareExchange16 (
>>> +//  IN      volatile UINT16           *Value,
>>> +//  IN      UINT16                    CompareValue,
>>> +//  IN      UINT16                    ExchangeValue
>>> +//  )
>>> +ASM_PFX(InternalSyncCompareExchange16):
>>> +  uxth    w1, w1
>>> +  uxth    w2, w2
>>> +  dmb     sy
>>> +
>>> +InternalSyncCompareExchange16Again:
>>> +  ldxrh   w3, [x0]
>>> +  cmp     w3, w1
>>> +  bne     InternalSyncCompareExchange16Fail
>>> +
>>> +InternalSyncCompareExchange16Exchange:
>>> +  stxrh   w4, w2, [x0]
>>> +  cbnz    w4, InternalSyncCompareExchange16Again
>>> +
>>> +InternalSyncCompareExchange16Fail:
>>> +  dmb     sy
>>> +  mov     w0, w3
>>> +  ret
>>> +
>>> +/**
>>>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>>>
>>>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
>>> diff --git a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S
>>> index 0128f8f016bd..d699eb40d2a2 100644
>>> --- a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S
>>> +++ b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S
>>> @@ -1,6 +1,7 @@
>>>  //  Implementation of synchronization functions for ARM architecture
>>>  //
>>>  //  Copyright (c) 2012-2015, ARM Limited. All rights reserved.
>>> +//  Copyright (c) 2015, Linaro Limited. All rights reserved.
>>>  //
>>>  //  This program and the accompanying materials
>>>  //  are licensed and made available under the terms and conditions of the BSD License
>>> @@ -15,12 +16,55 @@
>>>  .text
>>>  .align 3
>>>
>>> +GCC_ASM_EXPORT(InternalSyncCompareExchange16)
>>>  GCC_ASM_EXPORT(InternalSyncCompareExchange32)
>>>  GCC_ASM_EXPORT(InternalSyncCompareExchange64)
>>>  GCC_ASM_EXPORT(InternalSyncIncrement)
>>>  GCC_ASM_EXPORT(InternalSyncDecrement)
>>>
>>>  /**
>>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>>> +
>>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>>> +  then Value is returned.  The compare exchange operation must be performed using
>>> +  MP safe mechanisms.
>>> +
>>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>>> +                        operation.
>>> +  @param  CompareValue  16-bit value used in compare operation.
>>> +  @param  ExchangeValue 16-bit value used in exchange operation.
>>> +
>>> +  @return The original *Value before exchange.
>>> +
>>> +**/
>>> +//UINT16
>>> +//EFIAPI
>>> +//InternalSyncCompareExchange16 (
>>> +//  IN      volatile UINT16           *Value,
>>> +//  IN      UINT16                    CompareValue,
>>> +//  IN      UINT16                    ExchangeValue
>>> +//  )
>>> +ASM_PFX(InternalSyncCompareExchange16):
>>> +  dmb
>>> +
>>> +InternalSyncCompareExchange16Again:
>>> +  ldrexh  r3, [r0]
>>> +  cmp     r3, r1
>>> +  bne     InternalSyncCompareExchange16Fail
>>> +
>>> +InternalSyncCompareExchange16Exchange:
>>> +  strexh  ip, r2, [r0]
>>> +  cmp     ip, #0
>>> +  bne     InternalSyncCompareExchange16Again
>>> +
>>> +InternalSyncCompareExchange16Fail:
>>> +  dmb
>>> +  mov     r0, r3
>>> +  bx      lr
>>> +
>>> +/**
>>>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>>>
>>>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
>>> diff --git a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm
>>> index f9f80737774a..dbc599114093 100644
>>> --- a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm
>>> +++ b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm
>>> @@ -1,6 +1,7 @@
>>>  //  Implementation of synchronization functions for ARM architecture
>>>  //
>>>  //  Copyright (c) 2012-2015, ARM Limited. All rights reserved.
>>> +//  Copyright (c) 2015, Linaro Limited. All rights reserved.
>>>  //
>>>  //  This program and the accompanying materials
>>>  //  are licensed and made available under the terms and conditions of the BSD License
>>> @@ -12,6 +13,7 @@
>>>  //
>>>  //
>>>
>>> +    EXPORT  InternalSyncCompareExchange16
>>>      EXPORT  InternalSyncCompareExchange32
>>>      EXPORT  InternalSyncCompareExchange64
>>>      EXPORT  InternalSyncIncrement
>>> @@ -20,6 +22,48 @@
>>>      AREA   ArmSynchronization, CODE, READONLY
>>>
>>>  /**
>>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>>> +
>>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>>> +  then Value is returned.  The compare exchange operation must be performed using
>>> +  MP safe mechanisms.
>>> +
>>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>>> +                        operation.
>>> +  @param  CompareValue  16-bit value used in compare operation.
>>> +  @param  ExchangeValue 16-bit value used in exchange operation.
>>> +
>>> +  @return The original *Value before exchange.
>>> +
>>> +**/
>>> +//UINT16
>>> +//EFIAPI
>>> +//InternalSyncCompareExchange16 (
>>> +//  IN      volatile UINT16           *Value,
>>> +//  IN      UINT16                    CompareValue,
>>> +//  IN      UINT16                    ExchangeValue
>>> +//  )
>>> +InternalSyncCompareExchange16
>>> +  dmb
>>> +
>>> +InternalSyncCompareExchange16Again
>>> +  ldrexh  r3, [r0]
>>> +  cmp     r3, r1
>>> +  bne     InternalSyncCompareExchange16Fail
>>> +
>>> +InternalSyncCompareExchange16Exchange
>>> +  strexh  ip, r2, [r0]
>>> +  cmp     ip, #0
>>> +  bne     InternalSyncCompareExchange16Again
>>> +
>>> +InternalSyncCompareExchange16Fail
>>> +  dmb
>>> +  mov     r0, r3
>>> +  bx      lr
>>> +
>>> +/**
>>>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>>>
>>>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
>>> diff --git a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
>>> index 5e3b4e6b9bf2..bd1bec3fb5e7 100755
>>> --- a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
>>> +++ b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
>>> @@ -32,12 +32,14 @@
>>>  [Sources.IA32]
>>>    Ia32/InterlockedCompareExchange64.c | MSFT
>>>    Ia32/InterlockedCompareExchange32.c | MSFT
>>> +  Ia32/InterlockedCompareExchange16.c | MSFT
>>>    Ia32/InterlockedDecrement.c | MSFT
>>>    Ia32/InterlockedIncrement.c | MSFT
>>>    SynchronizationMsc.c  | MSFT
>>>
>>>    Ia32/InterlockedCompareExchange64.asm | INTEL
>>>    Ia32/InterlockedCompareExchange32.asm | INTEL
>>> +  Ia32/InterlockedCompareExchange16.asm | INTEL
>>>    Ia32/InterlockedDecrement.asm | INTEL
>>>    Ia32/InterlockedIncrement.asm | INTEL
>>>    Synchronization.c | INTEL
>>> @@ -48,9 +50,11 @@
>>>  [Sources.X64]
>>>    X64/InterlockedCompareExchange64.c | MSFT
>>>    X64/InterlockedCompareExchange32.c | MSFT
>>> +  X64/InterlockedCompareExchange16.c | MSFT
>>>
>>>    X64/InterlockedCompareExchange64.asm | INTEL
>>>    X64/InterlockedCompareExchange32.asm | INTEL
>>> +  X64/InterlockedCompareExchange16.asm | INTEL
>>>
>>>    X64/InterlockedDecrement.c | MSFT
>>>    X64/InterlockedIncrement.c | MSFT
>>> @@ -67,6 +71,7 @@
>>>    Ipf/Synchronization.c
>>>    Ipf/InterlockedCompareExchange64.s
>>>    Ipf/InterlockedCompareExchange32.s
>>> +  Ipf/InterlockedCompareExchange16.s
>>>
>>>    Synchronization.c     | INTEL
>>>    SynchronizationMsc.c  | MSFT
>>> diff --git a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h
>>> index e42824c75d12..76f702324156 100644
>>> --- a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h
>>> +++ b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h
>>> @@ -63,6 +63,32 @@ InternalSyncDecrement (
>>>
>>>
>>>  /**
>>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>>> +
>>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>>> +  then Value is returned.  The compare exchange operation must be performed using
>>> +  MP safe mechanisms.
>>> +
>>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>>> +                        operation.
>>> +  @param  CompareValue  A 16-bit value used in compare operation.
>>> +  @param  ExchangeValue A 16-bit value used in exchange operation.
>>> +
>>> +  @return The original *Value before exchange.
>>> +
>>> +**/
>>> +UINT16
>>> +EFIAPI
>>> +InternalSyncCompareExchange16 (
>>> +  IN      volatile UINT16           *Value,
>>> +  IN      UINT16                    CompareValue,
>>> +  IN      UINT16                    ExchangeValue
>>> +  );
>>> +
>>> +
>>> +/**
>>>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>>>
>>>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
>>> diff --git a/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c b/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c
>>> index 9c34b9f128ed..a57860203b12 100644
>>> --- a/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c
>>> +++ b/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c
>>> @@ -13,6 +13,37 @@
>>>  **/
>>>
>>>  /**
>>> +  Performs an atomic compare exchange operation on a 16-bit
>>> +  unsigned integer.
>>> +
>>> +  Performs an atomic compare exchange operation on the 16-bit
>>> +  unsigned integer specified by Value.  If Value is equal to
>>> +  CompareValue, then Value is set to ExchangeValue and
>>> +  CompareValue is returned.  If Value is not equal to
>>> +  CompareValue, then Value is returned. The compare exchange
>>> +  operation must be performed using MP safe mechanisms.
>>> +
>>> +  @param  Value         A pointer to the 16-bit value for the
>>> +                        compare exchange operation.
>>> +  @param  CompareValue  16-bit value used in compare operation.
>>> +  @param  ExchangeValue 16-bit value used in exchange operation.
>>> +
>>> +  @return The original *Value before exchange.
>>> +
>>> +**/
>>> +UINT16
>>> +EFIAPI
>>> +InternalSyncCompareExchange16 (
>>> +  IN      volatile UINT16           *Value,
>>> +  IN      UINT16                    CompareValue,
>>> +  IN      UINT16                    ExchangeValue
>>> +  )
>>> +{
>>> +  return *Value != CompareValue ? *Value :
>>> +           ((*Value = ExchangeValue), CompareValue);
>>> +}
>>> +
>>> +/**
>>>    Performs an atomic compare exchange operation on a 32-bit
>>>    unsigned integer.
>>>
>>> diff --git a/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c b/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c
>>> index b5a7827fc0e8..bd81aad6c243 100644
>>> --- a/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c
>>> +++ b/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c
>>> @@ -88,6 +88,48 @@ InternalSyncDecrement (
>>>  }
>>>
>>>  /**
>>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>>> +
>>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>>> +  then Value is returned.  The compare exchange operation must be performed using
>>> +  MP safe mechanisms.
>>> +
>>> +
>>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>>> +                        operation.
>>> +  @param  CompareValue  16-bit value used in compare operation.
>>> +  @param  ExchangeValue 16-bit value used in exchange operation.
>>> +
>>> +  @return The original *Value before exchange.
>>> +
>>> +**/
>>> +UINT16
>>> +EFIAPI
>>> +InternalSyncCompareExchange16 (
>>> +  IN OUT volatile  UINT16           *Value,
>>> +  IN      UINT16                    CompareValue,
>>> +  IN      UINT16                    ExchangeValue
>>> +  )
>>> +{
>>> +
>>> +  __asm__ __volatile__ (
>>> +    "                     \n    "
>>> +    "lock                 \n    "
>>> +    "cmpxchgw    %1, %2   \n    "
>>> +    : "=a" (CompareValue)
>>> +    : "q"  (ExchangeValue),
>>> +      "m"  (*Value),
>>> +      "0"  (CompareValue)
>>> +    : "memory",
>>> +      "cc"
>>> +    );
>>> +
>>> +  return CompareValue;
>>> +}
>>> +
>>> +/**
>>>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>>>
>>>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
>>> diff --git a/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm
>>> new file mode 100644
>>> index 000000000000..f8705042661d
>>> --- /dev/null
>>> +++ b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm
>>> @@ -0,0 +1,46 @@
>>> +;------------------------------------------------------------------------------
>>> +;
>>> +; Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
>>> +; Copyright (c) 2015, Linaro Ltd. All rights reserved.<BR>
>>> +; This program and the accompanying materials
>>> +; are licensed and made available under the terms and conditions of the BSD License
>>> +; which accompanies this distribution.  The full text of the license may be found at
>>> +; http://opensource.org/licenses/bsd-license.php.
>>> +;
>>> +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
>>> +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
>>> +;
>>> +; Module Name:
>>> +;
>>> +;   InterlockedCompareExchange16.Asm
>>> +;
>>> +; Abstract:
>>> +;
>>> +;   InterlockedCompareExchange16 function
>>> +;
>>> +; Notes:
>>> +;
>>> +;------------------------------------------------------------------------------
>>> +
>>> +    .486
>>> +    .model  flat,C
>>> +    .code
>>> +
>>> +;------------------------------------------------------------------------------
>>> +; UINT16
>>> +; EFIAPI
>>> +; InternalSyncCompareExchange16 (
>>> +;   IN      UINT16                    *Value,
>>> +;   IN      UINT16                    CompareValue,
>>> +;   IN      UINT16                    ExchangeValue
>>> +;   );
>>> +;------------------------------------------------------------------------------
>>> +InternalSyncCompareExchange16   PROC
>>> +    mov     ecx, [esp + 4]
>>> +    mov     eax, [esp + 8]
>>> +    mov     edx, [esp + 12]
>>> +    lock    cmpxchg [ecx], dx
>>> +    ret
>>> +InternalSyncCompareExchange16   ENDP
>>> +
>>> +    END
>>> diff --git a/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c
>>> new file mode 100644
>>> index 000000000000..3d06dd9baa63
>>> --- /dev/null
>>> +++ b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c
>>> @@ -0,0 +1,51 @@
>>> +/** @file
>>> +  InterlockedCompareExchange16 function
>>> +
>>> +  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
>>> +  Copyright (c) 2015, Linaro Ltd. All rights reserved.<BR>
>>> +  This program and the accompanying materials
>>> +  are licensed and made available under the terms and conditions of the BSD License
>>> +  which accompanies this distribution.  The full text of the license may be found at
>>> +  http://opensource.org/licenses/bsd-license.php.
>>> +
>>> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
>>> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
>>> +
>>> +**/
>>> +
>>> +
>>> +
>>> +
>>> +/**
>>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>>> +
>>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>>> +  then Value is returned.  The compare exchange operation must be performed using
>>> +  MP safe mechanisms.
>>> +
>>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>>> +                        operation.
>>> +  @param  CompareValue  16-bit value used in compare operation.
>>> +  @param  ExchangeValue 16-bit value used in exchange operation.
>>> +
>>> +  @return The original *Value before exchange.
>>> +
>>> +**/
>>> +UINT16
>>> +EFIAPI
>>> +InternalSyncCompareExchange16 (
>>> +  IN      UINT16                    *Value,
>>> +  IN      UINT16                    CompareValue,
>>> +  IN      UINT16                    ExchangeValue
>>> +  )
>>> +{
>>> +  _asm {
>>> +    mov     ecx, Value
>>> +    mov     eax, CompareValue
>>> +    mov     edx, ExchangeValue
>>> +    lock    cmpxchg [ecx], dx
>>> +  }
>>> +}
>>> +
>>> diff --git a/MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s b/MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s
>>> new file mode 100644
>>> index 000000000000..1e56942a98cb
>>> --- /dev/null
>>> +++ b/MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s
>>> @@ -0,0 +1,30 @@
>>> +/// @file
>>> +///   Contains an implementation of InterlockedCompareExchange16 on Itanium-
>>> +///   based architecture.
>>> +///
>>> +/// Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
>>> +/// Copyright (c) 2015, Linaro Ltd. All rights reserved.<BR>
>>> +/// This program and the accompanying materials
>>> +/// are licensed and made available under the terms and conditions of the BSD License
>>> +/// which accompanies this distribution.  The full text of the license may be found at
>>> +/// http://opensource.org/licenses/bsd-license.php.
>>> +///
>>> +/// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
>>> +/// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
>>> +///
>>> +/// Module Name:  InterlockedCompareExchange16.s
>>> +///
>>> +///
>>> +
>>> +.auto
>>> +.text
>>> +
>>> +.proc   InternalSyncCompareExchange16
>>> +.type   InternalSyncCompareExchange16, @function
>>> +InternalSyncCompareExchange16::
>>> +        zxt2                r33 = r33
>>> +        mov                 ar.ccv = r33
>>> +        cmpxchg2.rel        r8  = [r32], r34
>>> +        mf
>>> +        br.ret.sptk.many    b0
>>> +.endp   InternalSyncCompareExchange16
>>> diff --git a/MdePkg/Library/BaseSynchronizationLib/Synchronization.c b/MdePkg/Library/BaseSynchronizationLib/Synchronization.c
>>> index 0eea40ba1622..4218a265a0ec 100644
>>> --- a/MdePkg/Library/BaseSynchronizationLib/Synchronization.c
>>> +++ b/MdePkg/Library/BaseSynchronizationLib/Synchronization.c
>>> @@ -277,6 +277,37 @@ InterlockedDecrement (
>>>  }
>>>
>>>  /**
>>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>>> +
>>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>>> +  then Value is returned.  The compare exchange operation must be performed using
>>> +  MP safe mechanisms.
>>> +
>>> +  If Value is NULL, then ASSERT().
>>> +
>>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>>> +                        operation.
>>> +  @param  CompareValue  16-bit value used in compare operation.
>>> +  @param  ExchangeValue 16-bit value used in exchange operation.
>>> +
>>> +  @return The original *Value before exchange.
>>> +
>>> +**/
>>> +UINT16
>>> +EFIAPI
>>> +InterlockedCompareExchange16 (
>>> +  IN OUT  UINT16                    *Value,
>>> +  IN      UINT16                    CompareValue,
>>> +  IN      UINT16                    ExchangeValue
>>> +  )
>>> +{
>>> +  ASSERT (Value != NULL);
>>> +  return InternalSyncCompareExchange16 (Value, CompareValue, ExchangeValue);
>>> +}
>>> +
>>> +/**
>>>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>>>
>>>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
>>> diff --git a/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c b/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c
>>> index badf73c1a6ce..587f5a771c35 100644
>>> --- a/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c
>>> +++ b/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c
>>> @@ -293,6 +293,37 @@ InterlockedDecrement (
>>>  }
>>>
>>>  /**
>>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>>> +
>>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>>> +  then Value is returned.  The compare exchange operation must be performed using
>>> +  MP safe mechanisms.
>>> +
>>> +  If Value is NULL, then ASSERT().
>>> +
>>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>>> +                        operation.
>>> +  @param  CompareValue  A 16-bit value used in compare operation.
>>> +  @param  ExchangeValue A 16-bit value used in exchange operation.
>>> +
>>> +  @return The original *Value before exchange.
>>> +
>>> +**/
>>> +UINT16
>>> +EFIAPI
>>> +InterlockedCompareExchange16 (
>>> +  IN OUT  UINT16                    *Value,
>>> +  IN      UINT16                    CompareValue,
>>> +  IN      UINT16                    ExchangeValue
>>> +  )
>>> +{
>>> +  ASSERT (Value != NULL);
>>> +  return InternalSyncCompareExchange16 (Value, CompareValue, ExchangeValue);
>>> +}
>>> +
>>> +/**
>>>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>>>
>>>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
>>> diff --git a/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c b/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c
>>> index 9b20236acfa6..ca21f5dccee5 100644
>>> --- a/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c
>>> +++ b/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c
>>> @@ -295,6 +295,37 @@ InterlockedDecrement (
>>>  }
>>>
>>>  /**
>>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>>> +
>>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>>> +  then Value is returned.  The compare exchange operation must be performed using
>>> +  MP safe mechanisms.
>>> +
>>> +  If Value is NULL, then ASSERT().
>>> +
>>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>>> +                        operation.
>>> +  @param  CompareValue  A 16-bit value used in a compare operation.
>>> +  @param  ExchangeValue A 16-bit value used in an exchange operation.
>>> +
>>> +  @return The original *Value before exchange.
>>> +
>>> +**/
>>> +UINT16
>>> +EFIAPI
>>> +InterlockedCompareExchange16 (
>>> +  IN OUT  UINT16                    *Value,
>>> +  IN      UINT16                    CompareValue,
>>> +  IN      UINT16                    ExchangeValue
>>> +  )
>>> +{
>>> +  ASSERT (Value != NULL);
>>> +  return InternalSyncCompareExchange16 (Value, CompareValue, ExchangeValue);
>>> +}
>>> +
>>> +/**
>>>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>>>
>>>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
>>> diff --git a/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c b/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c
>>> index ceb80aed94f8..6347073fee51 100644
>>> --- a/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c
>>> +++ b/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c
>>> @@ -89,6 +89,50 @@ InternalSyncDecrement (
>>>
>>>
>>>  /**
>>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>>> +
>>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
>>> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
>>> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
>>> +  then Value is returned.  The compare exchange operation must be performed using
>>> +  MP safe mechanisms.
>>> +
>>> +
>>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>>> +                        operation.
>>> +  @param  CompareValue  16-bit value used in compare operation.
>>> +  @param  ExchangeValue 16-bit value used in exchange operation.
>>> +
>>> +  @return The original *Value before exchange.
>>> +
>>> +**/
>>> +UINT16
>>> +EFIAPI
>>> +InternalSyncCompareExchange16 (
>>> +  IN OUT volatile  UINT16           *Value,
>>> +  IN      UINT16                    CompareValue,
>>> +  IN      UINT16                    ExchangeValue
>>> +  )
>>> +{
>>> +
>>> +
>>> +  __asm__ __volatile__ (
>>> +    "lock                 \n    "
>>> +    "cmpxchgw    %3, %1       "
>>> +    : "=a" (CompareValue),
>>> +      "=m" (*Value)
>>> +    : "a"  (CompareValue),
>>> +      "r"  (ExchangeValue),
>>> +      "m"  (*Value)
>>> +    : "memory",
>>> +      "cc"
>>> +    );
>>> +
>>> +  return CompareValue;
>>> +}
>>> +
>>> +
>>> +/**
>>>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>>>
>>>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
>>> diff --git a/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm
>>> new file mode 100644
>>> index 000000000000..8fe2aae1a28b
>>> --- /dev/null
>>> +++ b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm
>>> @@ -0,0 +1,42 @@
>>> +;------------------------------------------------------------------------------
>>> +;
>>> +; Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
>>> +; Copyright (c) 2015, Linaro Ltd. All rights reserved.<BR>
>>> +; This program and the accompanying materials
>>> +; are licensed and made available under the terms and conditions of the BSD License
>>> +; which accompanies this distribution.  The full text of the license may be found at
>>> +; http://opensource.org/licenses/bsd-license.php.
>>> +;
>>> +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
>>> +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
>>> +;
>>> +; Module Name:
>>> +;
>>> +;   InterlockedCompareExchange16.Asm
>>> +;
>>> +; Abstract:
>>> +;
>>> +;   InterlockedCompareExchange16 function
>>> +;
>>> +; Notes:
>>> +;
>>> +;------------------------------------------------------------------------------
>>> +
>>> +    .code
>>> +
>>> +;------------------------------------------------------------------------------
>>> +; UINT16
>>> +; EFIAPI
>>> +; InterlockedCompareExchange16 (
>>> +;   IN      UINT16                    *Value,
>>> +;   IN      UINT16                    CompareValue,
>>> +;   IN      UINT16                    ExchangeValue
>>> +;   );
>>> +;------------------------------------------------------------------------------
>>> +InternalSyncCompareExchange16   PROC
>>> +    mov     eax, edx
>>> +    lock    cmpxchg [rcx], r8w
>>> +    ret
>>> +InternalSyncCompareExchange16   ENDP
>>> +
>>> +    END
>>> diff --git a/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c
>>> new file mode 100644
>>> index 000000000000..76aa6fbc0e81
>>> --- /dev/null
>>> +++ b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c
>>> @@ -0,0 +1,54 @@
>>> +/** @file
>>> +  InterlockedCompareExchange16 function
>>> +
>>> +  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
>>> +  Copyright (c) 2015, Linaro Ltd. All rights reserved.<BR>
>>> +  This program and the accompanying materials
>>> +  are licensed and made available under the terms and conditions of the BSD License
>>> +  which accompanies this distribution.  The full text of the license may be found at
>>> +  http://opensource.org/licenses/bsd-license.php.
>>> +
>>> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
>>> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
>>> +
>>> +**/
>>> +
>>> +/**
>>> +  Microsoft Visual Studio 7.1 Function Prototypes for I/O Intrinsics.
>>> +**/
>>> +
>>> +__int16 _InterlockedCompareExchange16(
>>> +   __int16 volatile * Destination,
>>> +   __int16 Exchange,
>>> +   __int16 Comperand
>>> +);
>>> +
>>> +#pragma intrinsic(_InterlockedCompareExchange16)
>>> +
>>> +/**
>>> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
>>> +
>>> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer specified
>>> +  by Value.  If Value is equal to CompareValue, then Value is set to ExchangeValue and
>>> +  CompareValue is returned.  If Value is not equal to CompareValue, then Value is returned.
>>> +  The compare exchange operation must be performed using MP safe mechanisms.
>>> +
>>> +  @param  Value         A pointer to the 16-bit value for the compare exchange
>>> +                        operation.
>>> +  @param  CompareValue  16-bit value used in compare operation.
>>> +  @param  ExchangeValue 16-bit value used in exchange operation.
>>> +
>>> +  @return The original *Value before exchange.
>>> +
>>> +**/
>>> +UINT16
>>> +EFIAPI
>>> +InternalSyncCompareExchange16 (
>>> +  IN      UINT16                    *Value,
>>> +  IN      UINT16                    CompareValue,
>>> +  IN      UINT16                    ExchangeValue
>>> +  )
>>> +{
>>> +  return _InterlockedCompareExchange16 (Value, ExchangeValue, CompareValue);
>>> +}
>>> +
>>> --
>>> 1.8.3.2
>>>

------------------------------------------------------------------------------
Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server
from Actuate! Instantly Supercharge Your Business Reports and Dashboards
with Interactivity, Sharing, Native Excel Exports, App Integration & more
Get technology previously reserved for billion-dollar corporations, FREE
http://pubads.g.doubleclick.net/gampad/clk?id=190641631&iu=/4140/ostg.clktrk
Ard Biesheuvel Feb. 25, 2015, 10:19 p.m. UTC | #3
On 25 February 2015 at 21:56, Kinney, Michael D
<michael.d.kinney@intel.com> wrote:
> Ard Biesheuvel,
>
> Thank you for providing the implementation of this new function for all supported CPU architectures.  The one for IPF looks correct and passes builds.

Good. Thanks for confirming that.

> However, I am seeing some build breaks and some issues with the IA32 and X64 versions.  The following changes are required to your patch to build with VS20xx compilers and for the code generated by asm/Inline asm to match code generated by VS20xx compiler intrinsics.

OK, I will update the patch with your suggested changes.

> I have not built and disassembled GCC yet, but I think GCC inline asm should generate the expected 16-bit register load operations that have been addressed here.
>

This is what I get for X64 and IA32, respectively:

Disassembly of section .text.InternalSyncCompareExchange16:

0000000000000000 <InternalSyncCompareExchange16>:
   0: 55                   push   %rbp
   1: 48 89 e5             mov    %rsp,%rbp
   4: 48 89 4d 10           mov    %rcx,0x10(%rbp)
   8: 89 d0                 mov    %edx,%eax
   a: 44 89 c2             mov    %r8d,%edx
   d: 66 89 45 18           mov    %ax,0x18(%rbp)
  11: 66 89 55 20           mov    %dx,0x20(%rbp)
  15: 4c 8b 45 10           mov    0x10(%rbp),%r8
  19: 0f b7 45 18           movzwl 0x18(%rbp),%eax
  1d: 0f b7 55 20           movzwl 0x20(%rbp),%edx
  21: 48 8b 4d 10           mov    0x10(%rbp),%rcx
  25: f0 66 41 0f b1 10     lock cmpxchg %dx,(%r8)
  2b: 66 89 45 18           mov    %ax,0x18(%rbp)
  2f: 0f b7 45 18           movzwl 0x18(%rbp),%eax
  33: 5d                   pop    %rbp
  34: c3                   retq

Disassembly of section .text.InternalSyncCompareExchange16:

00000000 <InternalSyncCompareExchange16>:
   0: 55                   push   %ebp
   1: 89 e5                 mov    %esp,%ebp
   3: 8b 45 0c             mov    0xc(%ebp),%eax
   6: 8b 55 10             mov    0x10(%ebp),%edx
   9: 8b 4d 08             mov    0x8(%ebp),%ecx
   c: f0 66 0f b1 11       lock cmpxchg %dx,(%ecx)
  11: 5d                   pop    %ebp
  12: c3                   ret

The latter looks equivalent to me, but perhaps you could confirm that
the former does the right thing?

Thanks a lot for taking the time,
Ard.



> --- Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm        Mon Jan 19 14:26:36 1970
> +++ Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm        Mon Jan 19 14:26:36 1970
> @@ -37,8 +37,8 @@
>  ;------------------------------------------------------------------------------
>  InternalSyncCompareExchange16   PROC
>      mov     ecx, [esp + 4]
> -    mov     eax, [esp + 8]
> -    mov     edx, [esp + 12]
> +    mov     ax, [esp + 8]
> +    mov     dx, [esp + 12]
>      lock    cmpxchg [ecx], dx
>      ret
>  InternalSyncCompareExchange16   ENDP
> --- Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c  Mon Jan 19 14:26:36 1970
> +++ Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c  Mon Jan 19 14:26:36 1970
> @@ -43,8 +43,8 @@
>  {
>    _asm {
>      mov     ecx, Value
> -    mov     eax, CompareValue
> -    mov     edx, ExchangeValue
> +    mov     ax, CompareValue
> +    mov     dx, ExchangeValue
>      lock    cmpxchg [ecx], dx
>    }
>  }
> --- Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm Mon Jan 19 14:26:36 1970
> +++ Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm Mon Jan 19 14:26:36 1970
> @@ -34,7 +34,7 @@
>  ;   );
>  ;------------------------------------------------------------------------------
>  InternalSyncCompareExchange16   PROC
> -    mov     eax, edx
> +    mov     ax, dx
>      lock    cmpxchg [rcx], r8w
>      ret
>  InternalSyncCompareExchange16   ENDP
>
> Best regards,
>
> Mike
>
> -----Original Message-----
> From: Ard Biesheuvel [mailto:ard.biesheuvel@linaro.org]
> Sent: Thursday, February 12, 2015 3:19 AM
> To: edk2-devel@lists.sourceforge.net; olivier.martin@arm.com; lersek@redhat.com; roy.franz@linaro.org; leif.lindholm@linaro.org; stefano.stabellini@eu.citrix.com; ian.campbell@citrix.com; anthony.perard@citrix.com; xen-devel@lists.xen.org; julien.grall@linaro.org; Justen, Jordan L; Kinney, Michael D; Tian, Feng
> Cc: Ard Biesheuvel
> Subject: [PATCH v4 14/29] MdePkg/BaseSynchronizationLib: implement 16-bit compare-exchange
>
> This implements the function InterlockedCompareExchange16 () for all
> architectures, using architecture and toolchain specific intrinsics
> or primitive assembler instructions.
>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Reviewed-by: Olivier Martin <olivier.martin@arm.com>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
>  MdePkg/Include/Library/SynchronizationLib.h                                 | 26 ++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S             | 44 ++++++++++++++++++++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S                 | 44 ++++++++++++++++++++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm               | 44 ++++++++++++++++++++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf            |  5 +++++
>  MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h     | 26 ++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c                 | 31 +++++++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c                      | 42 ++++++++++++++++++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm | 46 ++++++++++++++++++++++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c   | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s    | 30 ++++++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/Synchronization.c                     | 31 +++++++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c                  | 31 +++++++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c                  | 31 +++++++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c                       | 44 ++++++++++++++++++++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm  | 42 ++++++++++++++++++++++++++++++++++++++++++
>  MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c    | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  17 files changed, 622 insertions(+)
>
> diff --git a/MdePkg/Include/Library/SynchronizationLib.h b/MdePkg/Include/Library/SynchronizationLib.h
> index f97569739914..7b97683ca0af 100644
> --- a/MdePkg/Include/Library/SynchronizationLib.h
> +++ b/MdePkg/Include/Library/SynchronizationLib.h
> @@ -184,6 +184,32 @@ InterlockedDecrement (
>
>
>  /**
> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
> +
> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
> +  then Value is returned.  The compare exchange operation must be performed using
> +  MP safe mechanisms.
> +
> +  If Value is NULL, then ASSERT().
> +
> +  @param  Value         A pointer to the 16-bit value for the compare exchange
> +                        operation.
> +  @param  CompareValue  16-bit value used in compare operation.
> +  @param  ExchangeValue 16-bit value used in exchange operation.
> +
> +  @return The original *Value before exchange.
> +**/
> +UINT16
> +EFIAPI
> +InterlockedCompareExchange16 (
> +  IN OUT  UINT16                    *Value,
> +  IN      UINT16                    CompareValue,
> +  IN      UINT16                    ExchangeValue
> +  );
> +
> +/**
>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>
>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
> diff --git a/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S b/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S
> index 601b00495f26..ecb87fc12755 100644
> --- a/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S
> +++ b/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S
> @@ -16,12 +16,56 @@
>  .text
>  .align 3
>
> +GCC_ASM_EXPORT(InternalSyncCompareExchange16)
>  GCC_ASM_EXPORT(InternalSyncCompareExchange32)
>  GCC_ASM_EXPORT(InternalSyncCompareExchange64)
>  GCC_ASM_EXPORT(InternalSyncIncrement)
>  GCC_ASM_EXPORT(InternalSyncDecrement)
>
>  /**
> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
> +
> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
> +  then Value is returned.  The compare exchange operation must be performed using
> +  MP safe mechanisms.
> +
> +  @param  Value         A pointer to the 16-bit value for the compare exchange
> +                        operation.
> +  @param  CompareValue  16-bit value used in compare operation.
> +  @param  ExchangeValue 16-bit value used in exchange operation.
> +
> +  @return The original *Value before exchange.
> +
> +**/
> +//UINT16
> +//EFIAPI
> +//InternalSyncCompareExchange16 (
> +//  IN      volatile UINT16           *Value,
> +//  IN      UINT16                    CompareValue,
> +//  IN      UINT16                    ExchangeValue
> +//  )
> +ASM_PFX(InternalSyncCompareExchange16):
> +  uxth    w1, w1
> +  uxth    w2, w2
> +  dmb     sy
> +
> +InternalSyncCompareExchange16Again:
> +  ldxrh   w3, [x0]
> +  cmp     w3, w1
> +  bne     InternalSyncCompareExchange16Fail
> +
> +InternalSyncCompareExchange16Exchange:
> +  stxrh   w4, w2, [x0]
> +  cbnz    w4, InternalSyncCompareExchange16Again
> +
> +InternalSyncCompareExchange16Fail:
> +  dmb     sy
> +  mov     w0, w3
> +  ret
> +
> +/**
>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>
>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
> diff --git a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S
> index 0128f8f016bd..d699eb40d2a2 100644
> --- a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S
> +++ b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S
> @@ -1,6 +1,7 @@
>  //  Implementation of synchronization functions for ARM architecture
>  //
>  //  Copyright (c) 2012-2015, ARM Limited. All rights reserved.
> +//  Copyright (c) 2015, Linaro Limited. All rights reserved.
>  //
>  //  This program and the accompanying materials
>  //  are licensed and made available under the terms and conditions of the BSD License
> @@ -15,12 +16,55 @@
>  .text
>  .align 3
>
> +GCC_ASM_EXPORT(InternalSyncCompareExchange16)
>  GCC_ASM_EXPORT(InternalSyncCompareExchange32)
>  GCC_ASM_EXPORT(InternalSyncCompareExchange64)
>  GCC_ASM_EXPORT(InternalSyncIncrement)
>  GCC_ASM_EXPORT(InternalSyncDecrement)
>
>  /**
> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
> +
> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
> +  then Value is returned.  The compare exchange operation must be performed using
> +  MP safe mechanisms.
> +
> +  @param  Value         A pointer to the 16-bit value for the compare exchange
> +                        operation.
> +  @param  CompareValue  16-bit value used in compare operation.
> +  @param  ExchangeValue 16-bit value used in exchange operation.
> +
> +  @return The original *Value before exchange.
> +
> +**/
> +//UINT16
> +//EFIAPI
> +//InternalSyncCompareExchange16 (
> +//  IN      volatile UINT16           *Value,
> +//  IN      UINT16                    CompareValue,
> +//  IN      UINT16                    ExchangeValue
> +//  )
> +ASM_PFX(InternalSyncCompareExchange16):
> +  dmb
> +
> +InternalSyncCompareExchange16Again:
> +  ldrexh  r3, [r0]
> +  cmp     r3, r1
> +  bne     InternalSyncCompareExchange16Fail
> +
> +InternalSyncCompareExchange16Exchange:
> +  strexh  ip, r2, [r0]
> +  cmp     ip, #0
> +  bne     InternalSyncCompareExchange16Again
> +
> +InternalSyncCompareExchange16Fail:
> +  dmb
> +  mov     r0, r3
> +  bx      lr
> +
> +/**
>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>
>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
> diff --git a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm
> index f9f80737774a..dbc599114093 100644
> --- a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm
> +++ b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm
> @@ -1,6 +1,7 @@
>  //  Implementation of synchronization functions for ARM architecture
>  //
>  //  Copyright (c) 2012-2015, ARM Limited. All rights reserved.
> +//  Copyright (c) 2015, Linaro Limited. All rights reserved.
>  //
>  //  This program and the accompanying materials
>  //  are licensed and made available under the terms and conditions of the BSD License
> @@ -12,6 +13,7 @@
>  //
>  //
>
> +    EXPORT  InternalSyncCompareExchange16
>      EXPORT  InternalSyncCompareExchange32
>      EXPORT  InternalSyncCompareExchange64
>      EXPORT  InternalSyncIncrement
> @@ -20,6 +22,48 @@
>      AREA   ArmSynchronization, CODE, READONLY
>
>  /**
> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
> +
> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
> +  then Value is returned.  The compare exchange operation must be performed using
> +  MP safe mechanisms.
> +
> +  @param  Value         A pointer to the 16-bit value for the compare exchange
> +                        operation.
> +  @param  CompareValue  16-bit value used in compare operation.
> +  @param  ExchangeValue 16-bit value used in exchange operation.
> +
> +  @return The original *Value before exchange.
> +
> +**/
> +//UINT16
> +//EFIAPI
> +//InternalSyncCompareExchange16 (
> +//  IN      volatile UINT16           *Value,
> +//  IN      UINT16                    CompareValue,
> +//  IN      UINT16                    ExchangeValue
> +//  )
> +InternalSyncCompareExchange16
> +  dmb
> +
> +InternalSyncCompareExchange16Again
> +  ldrexh  r3, [r0]
> +  cmp     r3, r1
> +  bne     InternalSyncCompareExchange16Fail
> +
> +InternalSyncCompareExchange16Exchange
> +  strexh  ip, r2, [r0]
> +  cmp     ip, #0
> +  bne     InternalSyncCompareExchange16Again
> +
> +InternalSyncCompareExchange16Fail
> +  dmb
> +  mov     r0, r3
> +  bx      lr
> +
> +/**
>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>
>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
> diff --git a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
> index 5e3b4e6b9bf2..bd1bec3fb5e7 100755
> --- a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
> +++ b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
> @@ -32,12 +32,14 @@
>  [Sources.IA32]
>    Ia32/InterlockedCompareExchange64.c | MSFT
>    Ia32/InterlockedCompareExchange32.c | MSFT
> +  Ia32/InterlockedCompareExchange16.c | MSFT
>    Ia32/InterlockedDecrement.c | MSFT
>    Ia32/InterlockedIncrement.c | MSFT
>    SynchronizationMsc.c  | MSFT
>
>    Ia32/InterlockedCompareExchange64.asm | INTEL
>    Ia32/InterlockedCompareExchange32.asm | INTEL
> +  Ia32/InterlockedCompareExchange16.asm | INTEL
>    Ia32/InterlockedDecrement.asm | INTEL
>    Ia32/InterlockedIncrement.asm | INTEL
>    Synchronization.c | INTEL
> @@ -48,9 +50,11 @@
>  [Sources.X64]
>    X64/InterlockedCompareExchange64.c | MSFT
>    X64/InterlockedCompareExchange32.c | MSFT
> +  X64/InterlockedCompareExchange16.c | MSFT
>
>    X64/InterlockedCompareExchange64.asm | INTEL
>    X64/InterlockedCompareExchange32.asm | INTEL
> +  X64/InterlockedCompareExchange16.asm | INTEL
>
>    X64/InterlockedDecrement.c | MSFT
>    X64/InterlockedIncrement.c | MSFT
> @@ -67,6 +71,7 @@
>    Ipf/Synchronization.c
>    Ipf/InterlockedCompareExchange64.s
>    Ipf/InterlockedCompareExchange32.s
> +  Ipf/InterlockedCompareExchange16.s
>
>    Synchronization.c     | INTEL
>    SynchronizationMsc.c  | MSFT
> diff --git a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h
> index e42824c75d12..76f702324156 100644
> --- a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h
> +++ b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h
> @@ -63,6 +63,32 @@ InternalSyncDecrement (
>
>
>  /**
> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
> +
> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
> +  then Value is returned.  The compare exchange operation must be performed using
> +  MP safe mechanisms.
> +
> +  @param  Value         A pointer to the 16-bit value for the compare exchange
> +                        operation.
> +  @param  CompareValue  A 16-bit value used in compare operation.
> +  @param  ExchangeValue A 16-bit value used in exchange operation.
> +
> +  @return The original *Value before exchange.
> +
> +**/
> +UINT16
> +EFIAPI
> +InternalSyncCompareExchange16 (
> +  IN      volatile UINT16           *Value,
> +  IN      UINT16                    CompareValue,
> +  IN      UINT16                    ExchangeValue
> +  );
> +
> +
> +/**
>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>
>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
> diff --git a/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c b/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c
> index 9c34b9f128ed..a57860203b12 100644
> --- a/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c
> +++ b/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c
> @@ -13,6 +13,37 @@
>  **/
>
>  /**
> +  Performs an atomic compare exchange operation on a 16-bit
> +  unsigned integer.
> +
> +  Performs an atomic compare exchange operation on the 16-bit
> +  unsigned integer specified by Value.  If Value is equal to
> +  CompareValue, then Value is set to ExchangeValue and
> +  CompareValue is returned.  If Value is not equal to
> +  CompareValue, then Value is returned. The compare exchange
> +  operation must be performed using MP safe mechanisms.
> +
> +  @param  Value         A pointer to the 16-bit value for the
> +                        compare exchange operation.
> +  @param  CompareValue  16-bit value used in compare operation.
> +  @param  ExchangeValue 16-bit value used in exchange operation.
> +
> +  @return The original *Value before exchange.
> +
> +**/
> +UINT16
> +EFIAPI
> +InternalSyncCompareExchange16 (
> +  IN      volatile UINT16           *Value,
> +  IN      UINT16                    CompareValue,
> +  IN      UINT16                    ExchangeValue
> +  )
> +{
> +  return *Value != CompareValue ? *Value :
> +           ((*Value = ExchangeValue), CompareValue);
> +}
> +
> +/**
>    Performs an atomic compare exchange operation on a 32-bit
>    unsigned integer.
>
> diff --git a/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c b/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c
> index b5a7827fc0e8..bd81aad6c243 100644
> --- a/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c
> +++ b/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c
> @@ -88,6 +88,48 @@ InternalSyncDecrement (
>  }
>
>  /**
> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
> +
> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
> +  then Value is returned.  The compare exchange operation must be performed using
> +  MP safe mechanisms.
> +
> +
> +  @param  Value         A pointer to the 16-bit value for the compare exchange
> +                        operation.
> +  @param  CompareValue  16-bit value used in compare operation.
> +  @param  ExchangeValue 16-bit value used in exchange operation.
> +
> +  @return The original *Value before exchange.
> +
> +**/
> +UINT16
> +EFIAPI
> +InternalSyncCompareExchange16 (
> +  IN OUT volatile  UINT16           *Value,
> +  IN      UINT16                    CompareValue,
> +  IN      UINT16                    ExchangeValue
> +  )
> +{
> +
> +  __asm__ __volatile__ (
> +    "                     \n\t"
> +    "lock                 \n\t"
> +    "cmpxchgw    %1, %2   \n\t"
> +    : "=a" (CompareValue)
> +    : "q"  (ExchangeValue),
> +      "m"  (*Value),
> +      "0"  (CompareValue)
> +    : "memory",
> +      "cc"
> +    );
> +
> +  return CompareValue;
> +}
> +
> +/**
>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>
>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
> diff --git a/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm
> new file mode 100644
> index 000000000000..f8705042661d
> --- /dev/null
> +++ b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm
> @@ -0,0 +1,46 @@
> +;------------------------------------------------------------------------------
> +;
> +; Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
> +; Copyright (c) 2015, Linaro Ltd. All rights reserved.<BR>
> +; This program and the accompanying materials
> +; are licensed and made available under the terms and conditions of the BSD License
> +; which accompanies this distribution.  The full text of the license may be found at
> +; http://opensource.org/licenses/bsd-license.php.
> +;
> +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +;
> +; Module Name:
> +;
> +;   InterlockedCompareExchange16.Asm
> +;
> +; Abstract:
> +;
> +;   InterlockedCompareExchange16 function
> +;
> +; Notes:
> +;
> +;------------------------------------------------------------------------------
> +
> +    .486
> +    .model  flat,C
> +    .code
> +
> +;------------------------------------------------------------------------------
> +; UINT16
> +; EFIAPI
> +; InternalSyncCompareExchange16 (
> +;   IN      UINT16                    *Value,
> +;   IN      UINT16                    CompareValue,
> +;   IN      UINT16                    ExchangeValue
> +;   );
> +;------------------------------------------------------------------------------
> +InternalSyncCompareExchange16   PROC
> +    mov     ecx, [esp + 4]
> +    mov     eax, [esp + 8]
> +    mov     edx, [esp + 12]
> +    lock    cmpxchg [ecx], dx
> +    ret
> +InternalSyncCompareExchange16   ENDP
> +
> +    END
> diff --git a/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c
> new file mode 100644
> index 000000000000..3d06dd9baa63
> --- /dev/null
> +++ b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c
> @@ -0,0 +1,51 @@
> +/** @file
> +  InterlockedCompareExchange16 function
> +
> +  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
> +  Copyright (c) 2015, Linaro Ltd. All rights reserved.<BR>
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php.
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +
> +
> +
> +/**
> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
> +
> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
> +  then Value is returned.  The compare exchange operation must be performed using
> +  MP safe mechanisms.
> +
> +  @param  Value         A pointer to the 16-bit value for the compare exchange
> +                        operation.
> +  @param  CompareValue  16-bit value used in compare operation.
> +  @param  ExchangeValue 16-bit value used in exchange operation.
> +
> +  @return The original *Value before exchange.
> +
> +**/
> +UINT16
> +EFIAPI
> +InternalSyncCompareExchange16 (
> +  IN      UINT16                    *Value,
> +  IN      UINT16                    CompareValue,
> +  IN      UINT16                    ExchangeValue
> +  )
> +{
> +  _asm {
> +    mov     ecx, Value
> +    mov     eax, CompareValue
> +    mov     edx, ExchangeValue
> +    lock    cmpxchg [ecx], dx
> +  }
> +}
> +
> diff --git a/MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s b/MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s
> new file mode 100644
> index 000000000000..1e56942a98cb
> --- /dev/null
> +++ b/MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s
> @@ -0,0 +1,30 @@
> +/// @file
> +///   Contains an implementation of InterlockedCompareExchange16 on Itanium-
> +///   based architecture.
> +///
> +/// Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
> +/// Copyright (c) 2015, Linaro Ltd. All rights reserved.<BR>
> +/// This program and the accompanying materials
> +/// are licensed and made available under the terms and conditions of the BSD License
> +/// which accompanies this distribution.  The full text of the license may be found at
> +/// http://opensource.org/licenses/bsd-license.php.
> +///
> +/// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +/// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +///
> +/// Module Name:  InterlockedCompareExchange16.s
> +///
> +///
> +
> +.auto
> +.text
> +
> +.proc   InternalSyncCompareExchange16
> +.type   InternalSyncCompareExchange16, @function
> +InternalSyncCompareExchange16::
> +        zxt2                r33 = r33
> +        mov                 ar.ccv = r33
> +        cmpxchg2.rel        r8  = [r32], r34
> +        mf
> +        br.ret.sptk.many    b0
> +.endp   InternalSyncCompareExchange16
> diff --git a/MdePkg/Library/BaseSynchronizationLib/Synchronization.c b/MdePkg/Library/BaseSynchronizationLib/Synchronization.c
> index 0eea40ba1622..4218a265a0ec 100644
> --- a/MdePkg/Library/BaseSynchronizationLib/Synchronization.c
> +++ b/MdePkg/Library/BaseSynchronizationLib/Synchronization.c
> @@ -277,6 +277,37 @@ InterlockedDecrement (
>  }
>
>  /**
> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
> +
> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
> +  then Value is returned.  The compare exchange operation must be performed using
> +  MP safe mechanisms.
> +
> +  If Value is NULL, then ASSERT().
> +
> +  @param  Value         A pointer to the 16-bit value for the compare exchange
> +                        operation.
> +  @param  CompareValue  16-bit value used in compare operation.
> +  @param  ExchangeValue 16-bit value used in exchange operation.
> +
> +  @return The original *Value before exchange.
> +
> +**/
> +UINT16
> +EFIAPI
> +InterlockedCompareExchange16 (
> +  IN OUT  UINT16                    *Value,
> +  IN      UINT16                    CompareValue,
> +  IN      UINT16                    ExchangeValue
> +  )
> +{
> +  ASSERT (Value != NULL);
> +  return InternalSyncCompareExchange16 (Value, CompareValue, ExchangeValue);
> +}
> +
> +/**
>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>
>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
> diff --git a/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c b/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c
> index badf73c1a6ce..587f5a771c35 100644
> --- a/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c
> +++ b/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c
> @@ -293,6 +293,37 @@ InterlockedDecrement (
>  }
>
>  /**
> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
> +
> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
> +  then Value is returned.  The compare exchange operation must be performed using
> +  MP safe mechanisms.
> +
> +  If Value is NULL, then ASSERT().
> +
> +  @param  Value         A pointer to the 16-bit value for the compare exchange
> +                        operation.
> +  @param  CompareValue  A 16-bit value used in compare operation.
> +  @param  ExchangeValue A 16-bit value used in exchange operation.
> +
> +  @return The original *Value before exchange.
> +
> +**/
> +UINT16
> +EFIAPI
> +InterlockedCompareExchange16 (
> +  IN OUT  UINT16                    *Value,
> +  IN      UINT16                    CompareValue,
> +  IN      UINT16                    ExchangeValue
> +  )
> +{
> +  ASSERT (Value != NULL);
> +  return InternalSyncCompareExchange16 (Value, CompareValue, ExchangeValue);
> +}
> +
> +/**
>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>
>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
> diff --git a/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c b/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c
> index 9b20236acfa6..ca21f5dccee5 100644
> --- a/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c
> +++ b/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c
> @@ -295,6 +295,37 @@ InterlockedDecrement (
>  }
>
>  /**
> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
> +
> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
> +  then Value is returned.  The compare exchange operation must be performed using
> +  MP safe mechanisms.
> +
> +  If Value is NULL, then ASSERT().
> +
> +  @param  Value         A pointer to the 16-bit value for the compare exchange
> +                        operation.
> +  @param  CompareValue  A 16-bit value used in a compare operation.
> +  @param  ExchangeValue A 16-bit value used in an exchange operation.
> +
> +  @return The original *Value before exchange.
> +
> +**/
> +UINT16
> +EFIAPI
> +InterlockedCompareExchange16 (
> +  IN OUT  UINT16                    *Value,
> +  IN      UINT16                    CompareValue,
> +  IN      UINT16                    ExchangeValue
> +  )
> +{
> +  ASSERT (Value != NULL);
> +  return InternalSyncCompareExchange16 (Value, CompareValue, ExchangeValue);
> +}
> +
> +/**
>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>
>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
> diff --git a/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c b/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c
> index ceb80aed94f8..6347073fee51 100644
> --- a/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c
> +++ b/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c
> @@ -89,6 +89,50 @@ InternalSyncDecrement (
>
>
>  /**
> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
> +
> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
> +  then Value is returned.  The compare exchange operation must be performed using
> +  MP safe mechanisms.
> +
> +
> +  @param  Value         A pointer to the 16-bit value for the compare exchange
> +                        operation.
> +  @param  CompareValue  16-bit value used in compare operation.
> +  @param  ExchangeValue 16-bit value used in exchange operation.
> +
> +  @return The original *Value before exchange.
> +
> +**/
> +UINT16
> +EFIAPI
> +InternalSyncCompareExchange16 (
> +  IN OUT volatile  UINT16           *Value,
> +  IN      UINT16                    CompareValue,
> +  IN      UINT16                    ExchangeValue
> +  )
> +{
> +
> +
> +  __asm__ __volatile__ (
> +    "lock                 \n\t"
> +    "cmpxchgw    %3, %1       "
> +    : "=a" (CompareValue),
> +      "=m" (*Value)
> +    : "a"  (CompareValue),
> +      "r"  (ExchangeValue),
> +      "m"  (*Value)
> +    : "memory",
> +      "cc"
> +    );
> +
> +  return CompareValue;
> +}
> +
> +
> +/**
>    Performs an atomic compare exchange operation on a 32-bit unsigned integer.
>
>    Performs an atomic compare exchange operation on the 32-bit unsigned integer
> diff --git a/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm
> new file mode 100644
> index 000000000000..8fe2aae1a28b
> --- /dev/null
> +++ b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm
> @@ -0,0 +1,42 @@
> +;------------------------------------------------------------------------------
> +;
> +; Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
> +; Copyright (c) 2015, Linaro Ltd. All rights reserved.<BR>
> +; This program and the accompanying materials
> +; are licensed and made available under the terms and conditions of the BSD License
> +; which accompanies this distribution.  The full text of the license may be found at
> +; http://opensource.org/licenses/bsd-license.php.
> +;
> +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +;
> +; Module Name:
> +;
> +;   InterlockedCompareExchange16.Asm
> +;
> +; Abstract:
> +;
> +;   InterlockedCompareExchange16 function
> +;
> +; Notes:
> +;
> +;------------------------------------------------------------------------------
> +
> +    .code
> +
> +;------------------------------------------------------------------------------
> +; UINT16
> +; EFIAPI
> +; InterlockedCompareExchange16 (
> +;   IN      UINT16                    *Value,
> +;   IN      UINT16                    CompareValue,
> +;   IN      UINT16                    ExchangeValue
> +;   );
> +;------------------------------------------------------------------------------
> +InternalSyncCompareExchange16   PROC
> +    mov     eax, edx
> +    lock    cmpxchg [rcx], r8w
> +    ret
> +InternalSyncCompareExchange16   ENDP
> +
> +    END
> diff --git a/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c
> new file mode 100644
> index 000000000000..76aa6fbc0e81
> --- /dev/null
> +++ b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c
> @@ -0,0 +1,54 @@
> +/** @file
> +  InterlockedCompareExchange16 function
> +
> +  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
> +  Copyright (c) 2015, Linaro Ltd. All rights reserved.<BR>
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php.
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +/**
> +  Microsoft Visual Studio 7.1 Function Prototypes for I/O Intrinsics.
> +**/
> +
> +__int16 _InterlockedCompareExchange16(
> +   __int16 volatile * Destination,
> +   __int16 Exchange,
> +   __int16 Comperand
> +);
> +
> +#pragma intrinsic(_InterlockedCompareExchange16)
> +
> +/**
> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
> +
> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer specified
> +  by Value.  If Value is equal to CompareValue, then Value is set to ExchangeValue and
> +  CompareValue is returned.  If Value is not equal to CompareValue, then Value is returned.
> +  The compare exchange operation must be performed using MP safe mechanisms.
> +
> +  @param  Value         A pointer to the 16-bit value for the compare exchange
> +                        operation.
> +  @param  CompareValue  16-bit value used in compare operation.
> +  @param  ExchangeValue 16-bit value used in exchange operation.
> +
> +  @return The original *Value before exchange.
> +
> +**/
> +UINT16
> +EFIAPI
> +InternalSyncCompareExchange16 (
> +  IN      UINT16                    *Value,
> +  IN      UINT16                    CompareValue,
> +  IN      UINT16                    ExchangeValue
> +  )
> +{
> +  return _InterlockedCompareExchange16 (Value, ExchangeValue, CompareValue);
> +}
> +
> --
> 1.8.3.2
>

------------------------------------------------------------------------------
Dive into the World of Parallel Programming The Go Parallel Website, sponsored
by Intel and developed in partnership with Slashdot Media, is your hub for all
things parallel software development, from weekly thought leadership blogs to
news, videos, case studies, tutorials and more. Take a look and join the 
conversation now. http://goparallel.sourceforge.net/
diff mbox

Patch

diff --git a/MdePkg/Include/Library/SynchronizationLib.h b/MdePkg/Include/Library/SynchronizationLib.h
index f97569739914..7b97683ca0af 100644
--- a/MdePkg/Include/Library/SynchronizationLib.h
+++ b/MdePkg/Include/Library/SynchronizationLib.h
@@ -184,6 +184,32 @@  InterlockedDecrement (
 
 
 /**
+  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 16-bit unsigned integer
+  specified by Value.  If Value is equal to CompareValue, then Value is set to
+  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
+  then Value is returned.  The compare exchange operation must be performed using
+  MP safe mechanisms.
+
+  If Value is NULL, then ASSERT().
+
+  @param  Value         A pointer to the 16-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  16-bit value used in compare operation.
+  @param  ExchangeValue 16-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+**/
+UINT16
+EFIAPI
+InterlockedCompareExchange16 (
+  IN OUT  UINT16                    *Value,
+  IN      UINT16                    CompareValue,
+  IN      UINT16                    ExchangeValue
+  );
+
+/**
   Performs an atomic compare exchange operation on a 32-bit unsigned integer.
 
   Performs an atomic compare exchange operation on the 32-bit unsigned integer
diff --git a/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S b/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S
index 601b00495f26..ecb87fc12755 100644
--- a/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S
+++ b/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S
@@ -16,12 +16,56 @@ 
 .text
 .align 3
 
+GCC_ASM_EXPORT(InternalSyncCompareExchange16)
 GCC_ASM_EXPORT(InternalSyncCompareExchange32)
 GCC_ASM_EXPORT(InternalSyncCompareExchange64)
 GCC_ASM_EXPORT(InternalSyncIncrement)
 GCC_ASM_EXPORT(InternalSyncDecrement)
 
 /**
+  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 16-bit unsigned integer
+  specified by Value.  If Value is equal to CompareValue, then Value is set to
+  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
+  then Value is returned.  The compare exchange operation must be performed using
+  MP safe mechanisms.
+
+  @param  Value         A pointer to the 16-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  16-bit value used in compare operation.
+  @param  ExchangeValue 16-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+//UINT16
+//EFIAPI
+//InternalSyncCompareExchange16 (
+//  IN      volatile UINT16           *Value,
+//  IN      UINT16                    CompareValue,
+//  IN      UINT16                    ExchangeValue
+//  )
+ASM_PFX(InternalSyncCompareExchange16):
+  uxth    w1, w1
+  uxth    w2, w2
+  dmb     sy
+
+InternalSyncCompareExchange16Again:
+  ldxrh   w3, [x0]
+  cmp     w3, w1
+  bne     InternalSyncCompareExchange16Fail
+
+InternalSyncCompareExchange16Exchange:
+  stxrh   w4, w2, [x0]
+  cbnz    w4, InternalSyncCompareExchange16Again
+
+InternalSyncCompareExchange16Fail:
+  dmb     sy
+  mov     w0, w3
+  ret
+
+/**
   Performs an atomic compare exchange operation on a 32-bit unsigned integer.
 
   Performs an atomic compare exchange operation on the 32-bit unsigned integer
diff --git a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S
index 0128f8f016bd..d699eb40d2a2 100644
--- a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S
+++ b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S
@@ -1,6 +1,7 @@ 
 //  Implementation of synchronization functions for ARM architecture
 //
 //  Copyright (c) 2012-2015, ARM Limited. All rights reserved.
+//  Copyright (c) 2015, Linaro Limited. All rights reserved.
 //
 //  This program and the accompanying materials
 //  are licensed and made available under the terms and conditions of the BSD License
@@ -15,12 +16,55 @@ 
 .text
 .align 3
 
+GCC_ASM_EXPORT(InternalSyncCompareExchange16)
 GCC_ASM_EXPORT(InternalSyncCompareExchange32)
 GCC_ASM_EXPORT(InternalSyncCompareExchange64)
 GCC_ASM_EXPORT(InternalSyncIncrement)
 GCC_ASM_EXPORT(InternalSyncDecrement)
 
 /**
+  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 16-bit unsigned integer
+  specified by Value.  If Value is equal to CompareValue, then Value is set to
+  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
+  then Value is returned.  The compare exchange operation must be performed using
+  MP safe mechanisms.
+
+  @param  Value         A pointer to the 16-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  16-bit value used in compare operation.
+  @param  ExchangeValue 16-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+//UINT16
+//EFIAPI
+//InternalSyncCompareExchange16 (
+//  IN      volatile UINT16           *Value,
+//  IN      UINT16                    CompareValue,
+//  IN      UINT16                    ExchangeValue
+//  )
+ASM_PFX(InternalSyncCompareExchange16):
+  dmb
+
+InternalSyncCompareExchange16Again:
+  ldrexh  r3, [r0]
+  cmp     r3, r1
+  bne     InternalSyncCompareExchange16Fail
+
+InternalSyncCompareExchange16Exchange:
+  strexh  ip, r2, [r0]
+  cmp     ip, #0
+  bne     InternalSyncCompareExchange16Again
+
+InternalSyncCompareExchange16Fail:
+  dmb
+  mov     r0, r3
+  bx      lr
+
+/**
   Performs an atomic compare exchange operation on a 32-bit unsigned integer.
 
   Performs an atomic compare exchange operation on the 32-bit unsigned integer
diff --git a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm
index f9f80737774a..dbc599114093 100644
--- a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm
+++ b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm
@@ -1,6 +1,7 @@ 
 //  Implementation of synchronization functions for ARM architecture
 //
 //  Copyright (c) 2012-2015, ARM Limited. All rights reserved.
+//  Copyright (c) 2015, Linaro Limited. All rights reserved.
 //
 //  This program and the accompanying materials
 //  are licensed and made available under the terms and conditions of the BSD License
@@ -12,6 +13,7 @@ 
 //
 //
 
+    EXPORT  InternalSyncCompareExchange16
     EXPORT  InternalSyncCompareExchange32
     EXPORT  InternalSyncCompareExchange64
     EXPORT  InternalSyncIncrement
@@ -20,6 +22,48 @@ 
     AREA   ArmSynchronization, CODE, READONLY
 
 /**
+  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 16-bit unsigned integer
+  specified by Value.  If Value is equal to CompareValue, then Value is set to
+  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
+  then Value is returned.  The compare exchange operation must be performed using
+  MP safe mechanisms.
+
+  @param  Value         A pointer to the 16-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  16-bit value used in compare operation.
+  @param  ExchangeValue 16-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+//UINT16
+//EFIAPI
+//InternalSyncCompareExchange16 (
+//  IN      volatile UINT16           *Value,
+//  IN      UINT16                    CompareValue,
+//  IN      UINT16                    ExchangeValue
+//  )
+InternalSyncCompareExchange16
+  dmb
+
+InternalSyncCompareExchange16Again
+  ldrexh  r3, [r0]
+  cmp     r3, r1
+  bne     InternalSyncCompareExchange16Fail
+
+InternalSyncCompareExchange16Exchange
+  strexh  ip, r2, [r0]
+  cmp     ip, #0
+  bne     InternalSyncCompareExchange16Again
+
+InternalSyncCompareExchange16Fail
+  dmb
+  mov     r0, r3
+  bx      lr
+
+/**
   Performs an atomic compare exchange operation on a 32-bit unsigned integer.
 
   Performs an atomic compare exchange operation on the 32-bit unsigned integer
diff --git a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
index 5e3b4e6b9bf2..bd1bec3fb5e7 100755
--- a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
+++ b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
@@ -32,12 +32,14 @@ 
 [Sources.IA32]
   Ia32/InterlockedCompareExchange64.c | MSFT 
   Ia32/InterlockedCompareExchange32.c | MSFT 
+  Ia32/InterlockedCompareExchange16.c | MSFT
   Ia32/InterlockedDecrement.c | MSFT 
   Ia32/InterlockedIncrement.c | MSFT 
   SynchronizationMsc.c  | MSFT
 
   Ia32/InterlockedCompareExchange64.asm | INTEL 
   Ia32/InterlockedCompareExchange32.asm | INTEL 
+  Ia32/InterlockedCompareExchange16.asm | INTEL
   Ia32/InterlockedDecrement.asm | INTEL 
   Ia32/InterlockedIncrement.asm | INTEL 
   Synchronization.c | INTEL
@@ -48,9 +50,11 @@ 
 [Sources.X64]
   X64/InterlockedCompareExchange64.c | MSFT
   X64/InterlockedCompareExchange32.c | MSFT
+  X64/InterlockedCompareExchange16.c | MSFT
   
   X64/InterlockedCompareExchange64.asm | INTEL
   X64/InterlockedCompareExchange32.asm | INTEL
+  X64/InterlockedCompareExchange16.asm | INTEL
   
   X64/InterlockedDecrement.c | MSFT 
   X64/InterlockedIncrement.c | MSFT 
@@ -67,6 +71,7 @@ 
   Ipf/Synchronization.c
   Ipf/InterlockedCompareExchange64.s
   Ipf/InterlockedCompareExchange32.s
+  Ipf/InterlockedCompareExchange16.s
 
   Synchronization.c     | INTEL 
   SynchronizationMsc.c  | MSFT 
diff --git a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h
index e42824c75d12..76f702324156 100644
--- a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h
+++ b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h
@@ -63,6 +63,32 @@  InternalSyncDecrement (
 
 
 /**
+  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 16-bit unsigned integer
+  specified by Value.  If Value is equal to CompareValue, then Value is set to
+  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
+  then Value is returned.  The compare exchange operation must be performed using
+  MP safe mechanisms.
+
+  @param  Value         A pointer to the 16-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  A 16-bit value used in compare operation.
+  @param  ExchangeValue A 16-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+UINT16
+EFIAPI
+InternalSyncCompareExchange16 (
+  IN      volatile UINT16           *Value,
+  IN      UINT16                    CompareValue,
+  IN      UINT16                    ExchangeValue
+  );
+
+
+/**
   Performs an atomic compare exchange operation on a 32-bit unsigned integer.
 
   Performs an atomic compare exchange operation on the 32-bit unsigned integer
diff --git a/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c b/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c
index 9c34b9f128ed..a57860203b12 100644
--- a/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c
+++ b/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c
@@ -13,6 +13,37 @@ 
 **/
 
 /**
+  Performs an atomic compare exchange operation on a 16-bit
+  unsigned integer.
+
+  Performs an atomic compare exchange operation on the 16-bit
+  unsigned integer specified by Value.  If Value is equal to
+  CompareValue, then Value is set to ExchangeValue and
+  CompareValue is returned.  If Value is not equal to
+  CompareValue, then Value is returned. The compare exchange
+  operation must be performed using MP safe mechanisms.
+
+  @param  Value         A pointer to the 16-bit value for the
+                        compare exchange operation.
+  @param  CompareValue  16-bit value used in compare operation.
+  @param  ExchangeValue 16-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+UINT16
+EFIAPI
+InternalSyncCompareExchange16 (
+  IN      volatile UINT16           *Value,
+  IN      UINT16                    CompareValue,
+  IN      UINT16                    ExchangeValue
+  )
+{
+  return *Value != CompareValue ? *Value :
+           ((*Value = ExchangeValue), CompareValue);
+}
+
+/**
   Performs an atomic compare exchange operation on a 32-bit
   unsigned integer.
 
diff --git a/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c b/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c
index b5a7827fc0e8..bd81aad6c243 100644
--- a/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c
+++ b/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c
@@ -88,6 +88,48 @@  InternalSyncDecrement (
 }
 
 /**
+  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 16-bit unsigned integer
+  specified by Value.  If Value is equal to CompareValue, then Value is set to
+  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
+  then Value is returned.  The compare exchange operation must be performed using
+  MP safe mechanisms.
+
+
+  @param  Value         A pointer to the 16-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  16-bit value used in compare operation.
+  @param  ExchangeValue 16-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+UINT16
+EFIAPI
+InternalSyncCompareExchange16 (
+  IN OUT volatile  UINT16           *Value,
+  IN      UINT16                    CompareValue,
+  IN      UINT16                    ExchangeValue
+  )
+{
+
+  __asm__ __volatile__ (
+    "                     \n\t"
+    "lock                 \n\t"
+    "cmpxchgw    %1, %2   \n\t"
+    : "=a" (CompareValue)
+    : "q"  (ExchangeValue),
+      "m"  (*Value),
+      "0"  (CompareValue)
+    : "memory",
+      "cc"
+    );
+
+  return CompareValue;
+}
+
+/**
   Performs an atomic compare exchange operation on a 32-bit unsigned integer.
 
   Performs an atomic compare exchange operation on the 32-bit unsigned integer
diff --git a/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm
new file mode 100644
index 000000000000..f8705042661d
--- /dev/null
+++ b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm
@@ -0,0 +1,46 @@ 
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
+; Copyright (c) 2015, Linaro Ltd. All rights reserved.<BR>
+; This program and the accompanying materials
+; are licensed and made available under the terms and conditions of the BSD License
+; which accompanies this distribution.  The full text of the license may be found at
+; http://opensource.org/licenses/bsd-license.php.
+;
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;
+; Module Name:
+;
+;   InterlockedCompareExchange16.Asm
+;
+; Abstract:
+;
+;   InterlockedCompareExchange16 function
+;
+; Notes:
+;
+;------------------------------------------------------------------------------
+
+    .486
+    .model  flat,C
+    .code
+
+;------------------------------------------------------------------------------
+; UINT16
+; EFIAPI
+; InternalSyncCompareExchange16 (
+;   IN      UINT16                    *Value,
+;   IN      UINT16                    CompareValue,
+;   IN      UINT16                    ExchangeValue
+;   );
+;------------------------------------------------------------------------------
+InternalSyncCompareExchange16   PROC
+    mov     ecx, [esp + 4]
+    mov     eax, [esp + 8]
+    mov     edx, [esp + 12]
+    lock    cmpxchg [ecx], dx
+    ret
+InternalSyncCompareExchange16   ENDP
+
+    END
diff --git a/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c
new file mode 100644
index 000000000000..3d06dd9baa63
--- /dev/null
+++ b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c
@@ -0,0 +1,51 @@ 
+/** @file
+  InterlockedCompareExchange16 function
+
+  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2015, Linaro Ltd. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+
+
+/**
+  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 16-bit unsigned integer
+  specified by Value.  If Value is equal to CompareValue, then Value is set to
+  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
+  then Value is returned.  The compare exchange operation must be performed using
+  MP safe mechanisms.
+
+  @param  Value         A pointer to the 16-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  16-bit value used in compare operation.
+  @param  ExchangeValue 16-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+UINT16
+EFIAPI
+InternalSyncCompareExchange16 (
+  IN      UINT16                    *Value,
+  IN      UINT16                    CompareValue,
+  IN      UINT16                    ExchangeValue
+  )
+{
+  _asm {
+    mov     ecx, Value
+    mov     eax, CompareValue
+    mov     edx, ExchangeValue
+    lock    cmpxchg [ecx], dx
+  }
+}
+
diff --git a/MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s b/MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s
new file mode 100644
index 000000000000..1e56942a98cb
--- /dev/null
+++ b/MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s
@@ -0,0 +1,30 @@ 
+/// @file
+///   Contains an implementation of InterlockedCompareExchange16 on Itanium-
+///   based architecture.
+///
+/// Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
+/// Copyright (c) 2015, Linaro Ltd. All rights reserved.<BR>
+/// This program and the accompanying materials
+/// are licensed and made available under the terms and conditions of the BSD License
+/// which accompanies this distribution.  The full text of the license may be found at
+/// http://opensource.org/licenses/bsd-license.php.
+///
+/// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+/// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+///
+/// Module Name:  InterlockedCompareExchange16.s
+///
+///
+
+.auto
+.text
+
+.proc   InternalSyncCompareExchange16
+.type   InternalSyncCompareExchange16, @function
+InternalSyncCompareExchange16::
+        zxt2                r33 = r33
+        mov                 ar.ccv = r33
+        cmpxchg2.rel        r8  = [r32], r34
+        mf
+        br.ret.sptk.many    b0
+.endp   InternalSyncCompareExchange16
diff --git a/MdePkg/Library/BaseSynchronizationLib/Synchronization.c b/MdePkg/Library/BaseSynchronizationLib/Synchronization.c
index 0eea40ba1622..4218a265a0ec 100644
--- a/MdePkg/Library/BaseSynchronizationLib/Synchronization.c
+++ b/MdePkg/Library/BaseSynchronizationLib/Synchronization.c
@@ -277,6 +277,37 @@  InterlockedDecrement (
 }
 
 /**
+  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 16-bit unsigned integer
+  specified by Value.  If Value is equal to CompareValue, then Value is set to
+  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
+  then Value is returned.  The compare exchange operation must be performed using
+  MP safe mechanisms.
+
+  If Value is NULL, then ASSERT().
+
+  @param  Value         A pointer to the 16-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  16-bit value used in compare operation.
+  @param  ExchangeValue 16-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+UINT16
+EFIAPI
+InterlockedCompareExchange16 (
+  IN OUT  UINT16                    *Value,
+  IN      UINT16                    CompareValue,
+  IN      UINT16                    ExchangeValue
+  )
+{
+  ASSERT (Value != NULL);
+  return InternalSyncCompareExchange16 (Value, CompareValue, ExchangeValue);
+}
+
+/**
   Performs an atomic compare exchange operation on a 32-bit unsigned integer.
 
   Performs an atomic compare exchange operation on the 32-bit unsigned integer
diff --git a/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c b/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c
index badf73c1a6ce..587f5a771c35 100644
--- a/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c
+++ b/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c
@@ -293,6 +293,37 @@  InterlockedDecrement (
 }
 
 /**
+  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 16-bit unsigned integer
+  specified by Value.  If Value is equal to CompareValue, then Value is set to
+  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
+  then Value is returned.  The compare exchange operation must be performed using
+  MP safe mechanisms.
+
+  If Value is NULL, then ASSERT().
+
+  @param  Value         A pointer to the 16-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  A 16-bit value used in compare operation.
+  @param  ExchangeValue A 16-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+UINT16
+EFIAPI
+InterlockedCompareExchange16 (
+  IN OUT  UINT16                    *Value,
+  IN      UINT16                    CompareValue,
+  IN      UINT16                    ExchangeValue
+  )
+{
+  ASSERT (Value != NULL);
+  return InternalSyncCompareExchange16 (Value, CompareValue, ExchangeValue);
+}
+
+/**
   Performs an atomic compare exchange operation on a 32-bit unsigned integer.
 
   Performs an atomic compare exchange operation on the 32-bit unsigned integer
diff --git a/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c b/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c
index 9b20236acfa6..ca21f5dccee5 100644
--- a/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c
+++ b/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c
@@ -295,6 +295,37 @@  InterlockedDecrement (
 }
 
 /**
+  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 16-bit unsigned integer
+  specified by Value.  If Value is equal to CompareValue, then Value is set to
+  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
+  then Value is returned.  The compare exchange operation must be performed using
+  MP safe mechanisms.
+
+  If Value is NULL, then ASSERT().
+
+  @param  Value         A pointer to the 16-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  A 16-bit value used in a compare operation.
+  @param  ExchangeValue A 16-bit value used in an exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+UINT16
+EFIAPI
+InterlockedCompareExchange16 (
+  IN OUT  UINT16                    *Value,
+  IN      UINT16                    CompareValue,
+  IN      UINT16                    ExchangeValue
+  )
+{
+  ASSERT (Value != NULL);
+  return InternalSyncCompareExchange16 (Value, CompareValue, ExchangeValue);
+}
+
+/**
   Performs an atomic compare exchange operation on a 32-bit unsigned integer.
 
   Performs an atomic compare exchange operation on the 32-bit unsigned integer
diff --git a/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c b/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c
index ceb80aed94f8..6347073fee51 100644
--- a/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c
+++ b/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c
@@ -89,6 +89,50 @@  InternalSyncDecrement (
 
 
 /**
+  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 16-bit unsigned integer
+  specified by Value.  If Value is equal to CompareValue, then Value is set to
+  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
+  then Value is returned.  The compare exchange operation must be performed using
+  MP safe mechanisms.
+
+
+  @param  Value         A pointer to the 16-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  16-bit value used in compare operation.
+  @param  ExchangeValue 16-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+UINT16
+EFIAPI
+InternalSyncCompareExchange16 (
+  IN OUT volatile  UINT16           *Value,
+  IN      UINT16                    CompareValue,
+  IN      UINT16                    ExchangeValue
+  )
+{
+
+
+  __asm__ __volatile__ (
+    "lock                 \n\t"
+    "cmpxchgw    %3, %1       "
+    : "=a" (CompareValue),
+      "=m" (*Value)
+    : "a"  (CompareValue),
+      "r"  (ExchangeValue),
+      "m"  (*Value)
+    : "memory",
+      "cc"
+    );
+
+  return CompareValue;
+}
+
+
+/**
   Performs an atomic compare exchange operation on a 32-bit unsigned integer.
 
   Performs an atomic compare exchange operation on the 32-bit unsigned integer
diff --git a/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm
new file mode 100644
index 000000000000..8fe2aae1a28b
--- /dev/null
+++ b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm
@@ -0,0 +1,42 @@ 
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
+; Copyright (c) 2015, Linaro Ltd. All rights reserved.<BR>
+; This program and the accompanying materials
+; are licensed and made available under the terms and conditions of the BSD License
+; which accompanies this distribution.  The full text of the license may be found at
+; http://opensource.org/licenses/bsd-license.php.
+;
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;
+; Module Name:
+;
+;   InterlockedCompareExchange16.Asm
+;
+; Abstract:
+;
+;   InterlockedCompareExchange16 function
+;
+; Notes:
+;
+;------------------------------------------------------------------------------
+
+    .code
+
+;------------------------------------------------------------------------------
+; UINT16
+; EFIAPI
+; InterlockedCompareExchange16 (
+;   IN      UINT16                    *Value,
+;   IN      UINT16                    CompareValue,
+;   IN      UINT16                    ExchangeValue
+;   );
+;------------------------------------------------------------------------------
+InternalSyncCompareExchange16   PROC
+    mov     eax, edx
+    lock    cmpxchg [rcx], r8w
+    ret
+InternalSyncCompareExchange16   ENDP
+
+    END
diff --git a/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c
new file mode 100644
index 000000000000..76aa6fbc0e81
--- /dev/null
+++ b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c
@@ -0,0 +1,54 @@ 
+/** @file
+  InterlockedCompareExchange16 function
+
+  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2015, Linaro Ltd. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+/**
+  Microsoft Visual Studio 7.1 Function Prototypes for I/O Intrinsics.
+**/
+
+__int16 _InterlockedCompareExchange16(
+   __int16 volatile * Destination,
+   __int16 Exchange,
+   __int16 Comperand
+);
+
+#pragma intrinsic(_InterlockedCompareExchange16)
+
+/**
+  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 16-bit unsigned integer specified
+  by Value.  If Value is equal to CompareValue, then Value is set to ExchangeValue and
+  CompareValue is returned.  If Value is not equal to CompareValue, then Value is returned.
+  The compare exchange operation must be performed using MP safe mechanisms.
+
+  @param  Value         A pointer to the 16-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  16-bit value used in compare operation.
+  @param  ExchangeValue 16-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+UINT16
+EFIAPI
+InternalSyncCompareExchange16 (
+  IN      UINT16                    *Value,
+  IN      UINT16                    CompareValue,
+  IN      UINT16                    ExchangeValue
+  )
+{
+  return _InterlockedCompareExchange16 (Value, ExchangeValue, CompareValue);
+}
+