Message ID | 1424940605-23342-1-git-send-email-ard.biesheuvel@linaro.org |
---|---|
State | New |
Headers | show |
On 26 February 2015 at 08:50, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote: > Hello all, > > This is the latest version of the InterlockedCompareExchange16() patch. > Michael has kindly confirmed (thanks Michael) that it does the right > thing for IPF, but also spotted some issues with the Intel asm versions. > > The patch below has the fixes suggested by Michael applied. > > I thought there was little point in resending the entire series, so I > am resending just this patch. > > The entire series can be found here > https://git.linaro.org/people/ard.biesheuvel/uefi-next.git/shortlog/refs/heads/linaro-topic-xen > Hello all, I was wondering if people are now ok with this patch? It is gating the merge of the entire 29-patch series, so I would really like to get this accepted. Laszlo has already kindly volunteered to apply the whole series, but we need someone from team-Intel to greenlight it. Thanks, Ard. > ---------->8---------------- > 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> > Acked-by: Jordan Justen <jordan.l.justen@intel.com> > Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> > --- > MdePkg/Include/Library/SynchronizationLib.h | 26 +++++++++++ > .../AArch64/Synchronization.S | 44 ++++++++++++++++++ > .../BaseSynchronizationLib/Arm/Synchronization.S | 44 ++++++++++++++++++ > .../BaseSynchronizationLib/Arm/Synchronization.asm | 44 ++++++++++++++++++ > .../BaseSynchronizationLib.inf | 5 ++ > .../BaseSynchronizationLibInternals.h | 26 +++++++++++ > .../BaseSynchronizationLib/Ebc/Synchronization.c | 31 +++++++++++++ > .../BaseSynchronizationLib/Ia32/GccInline.c | 42 +++++++++++++++++ > .../Ia32/InterlockedCompareExchange16.asm | 46 ++++++++++++++++++ > .../Ia32/InterlockedCompareExchange16.c | 51 ++++++++++++++++++++ > .../Ipf/InterlockedCompareExchange16.s | 30 ++++++++++++ > .../BaseSynchronizationLib/Synchronization.c | 31 +++++++++++++ > .../BaseSynchronizationLib/SynchronizationGcc.c | 31 +++++++++++++ > .../BaseSynchronizationLib/SynchronizationMsc.c | 31 +++++++++++++ > .../Library/BaseSynchronizationLib/X64/GccInline.c | 44 ++++++++++++++++++ > .../X64/InterlockedCompareExchange16.asm | 42 +++++++++++++++++ > .../X64/InterlockedCompareExchange16.c | 54 ++++++++++++++++++++++ > 17 files changed, 622 insertions(+) > create mode 100644 MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm > create mode 100644 MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c > create mode 100644 MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s > create mode 100644 MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm > create mode 100644 MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c > > 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..7d14e8e830c5 > --- /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 ax, [esp + 8] > + mov dx, [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..102173b11e30 > --- /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 ax, CompareValue > + mov dx, 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..e01e9fa92875 > --- /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 ax, dx > + 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/
On 27 February 2015 at 22:55, Kinney, Michael D <michael.d.kinney@intel.com> wrote: > Laszlo, > > You are welcome to apply the patch set. Thanks for helping. > Thanks everyone I have updated the public branch with Michael's R-b and rebased onto the latest upstream (1 minor merge conflict) Regards, Ard, > -----Original Message----- > From: Ard Biesheuvel [mailto:ard.biesheuvel@linaro.org] > Sent: Friday, February 27, 2015 1:02 PM > To: edk2-devel@lists.sourceforge.net; Olivier Martin; Laszlo Ersek; Justen, Jordan L; Kinney, Michael D > Cc: Ard Biesheuvel > Subject: Re: [PATCH v5a 14/29] MdePkg/BaseSynchronizationLib: Add InterlockedCompareExchange16 > > On 26 February 2015 at 08:50, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote: >> Hello all, >> >> This is the latest version of the InterlockedCompareExchange16() patch. >> Michael has kindly confirmed (thanks Michael) that it does the right >> thing for IPF, but also spotted some issues with the Intel asm versions. >> >> The patch below has the fixes suggested by Michael applied. >> >> I thought there was little point in resending the entire series, so I >> am resending just this patch. >> >> The entire series can be found here >> https://git.linaro.org/people/ard.biesheuvel/uefi-next.git/shortlog/refs/heads/linaro-topic-xen >> > > Hello all, > > I was wondering if people are now ok with this patch? > > It is gating the merge of the entire 29-patch series, so I would > really like to get this accepted. Laszlo has already kindly > volunteered to apply the whole series, but we need someone from > team-Intel to greenlight it. > > Thanks, > Ard. > > >> ---------->8---------------- >> 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> >> Acked-by: Jordan Justen <jordan.l.justen@intel.com> >> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> >> --- >> MdePkg/Include/Library/SynchronizationLib.h | 26 +++++++++++ >> .../AArch64/Synchronization.S | 44 ++++++++++++++++++ >> .../BaseSynchronizationLib/Arm/Synchronization.S | 44 ++++++++++++++++++ >> .../BaseSynchronizationLib/Arm/Synchronization.asm | 44 ++++++++++++++++++ >> .../BaseSynchronizationLib.inf | 5 ++ >> .../BaseSynchronizationLibInternals.h | 26 +++++++++++ >> .../BaseSynchronizationLib/Ebc/Synchronization.c | 31 +++++++++++++ >> .../BaseSynchronizationLib/Ia32/GccInline.c | 42 +++++++++++++++++ >> .../Ia32/InterlockedCompareExchange16.asm | 46 ++++++++++++++++++ >> .../Ia32/InterlockedCompareExchange16.c | 51 ++++++++++++++++++++ >> .../Ipf/InterlockedCompareExchange16.s | 30 ++++++++++++ >> .../BaseSynchronizationLib/Synchronization.c | 31 +++++++++++++ >> .../BaseSynchronizationLib/SynchronizationGcc.c | 31 +++++++++++++ >> .../BaseSynchronizationLib/SynchronizationMsc.c | 31 +++++++++++++ >> .../Library/BaseSynchronizationLib/X64/GccInline.c | 44 ++++++++++++++++++ >> .../X64/InterlockedCompareExchange16.asm | 42 +++++++++++++++++ >> .../X64/InterlockedCompareExchange16.c | 54 ++++++++++++++++++++++ >> 17 files changed, 622 insertions(+) >> create mode 100644 MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm >> create mode 100644 MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c >> create mode 100644 MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s >> create mode 100644 MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm >> create mode 100644 MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c >> >> 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..7d14e8e830c5 >> --- /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 ax, [esp + 8] >> + mov dx, [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..102173b11e30 >> --- /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 ax, CompareValue >> + mov dx, 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..e01e9fa92875 >> --- /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 ax, dx >> + 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 --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..7d14e8e830c5 --- /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 ax, [esp + 8] + mov dx, [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..102173b11e30 --- /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 ax, CompareValue + mov dx, 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..e01e9fa92875 --- /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 ax, dx + 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); +} +