From 9b89163eea30762f7ab91dcdc414820173cbf858 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Sat, 28 Feb 2015 20:31:54 +0000 Subject: [PATCH] MdePkg/BaseSynchronizationLib: Add InterlockedCompareExchange16 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 Acked-by: Jordan Justen Reviewed-by: Michael Kinney Signed-off-by: Ard Biesheuvel Signed-off-by: Laszlo Ersek git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16966 6f19259b-4bc3-4df7-8a09-765794883524 --- MdePkg/Include/Library/SynchronizationLib.h | 26 +++++++++ .../AArch64/Synchronization.S | 44 +++++++++++++++ .../Arm/Synchronization.S | 44 +++++++++++++++ .../Arm/Synchronization.asm | 44 +++++++++++++++ .../BaseSynchronizationLib.inf | 5 ++ .../BaseSynchronizationLibInternals.h | 26 +++++++++ .../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 +++++++++++ .../SynchronizationGcc.c | 31 +++++++++++ .../SynchronizationMsc.c | 31 +++++++++++ .../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 f975697399..7b97683ca0 100644 --- a/MdePkg/Include/Library/SynchronizationLib.h +++ b/MdePkg/Include/Library/SynchronizationLib.h @@ -183,6 +183,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. diff --git a/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S b/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S index 601b00495f..ecb87fc127 100644 --- a/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S +++ b/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S @@ -16,11 +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): + 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. diff --git a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S index 0128f8f016..d699eb40d2 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,11 +16,54 @@ .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. diff --git a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm index f9f8073777..dbc5991140 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 @@ -19,6 +21,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. diff --git a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf index 5e3b4e6b9b..bd1bec3fb5 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 e42824c75d..76f7023241 100644 --- a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h +++ b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h @@ -62,6 +62,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. diff --git a/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c b/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c index 9c34b9f128..a57860203b 100644 --- a/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c +++ b/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c @@ -12,6 +12,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 b5a7827fc0..bd81aad6c2 100644 --- a/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c +++ b/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c @@ -87,6 +87,48 @@ InternalSyncDecrement ( return Result; } +/** + 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. diff --git a/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm new file mode 100644 index 0000000000..7d14e8e830 --- /dev/null +++ b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm @@ -0,0 +1,46 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; Copyright (c) 2015, Linaro Ltd. All rights reserved.
+; 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 0000000000..102173b11e --- /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.
+ Copyright (c) 2015, Linaro Ltd. All rights reserved.
+ 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 0000000000..1e56942a98 --- /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.
+/// Copyright (c) 2015, Linaro Ltd. All rights reserved.
+/// 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 0eea40ba16..4218a265a0 100644 --- a/MdePkg/Library/BaseSynchronizationLib/Synchronization.c +++ b/MdePkg/Library/BaseSynchronizationLib/Synchronization.c @@ -276,6 +276,37 @@ InterlockedDecrement ( return InternalSyncDecrement (Value); } +/** + 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. diff --git a/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c b/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c index badf73c1a6..587f5a771c 100644 --- a/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c +++ b/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c @@ -292,6 +292,37 @@ InterlockedDecrement ( return InternalSyncDecrement (Value); } +/** + 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. diff --git a/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c b/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c index 9b20236acf..ca21f5dcce 100644 --- a/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c +++ b/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c @@ -294,6 +294,37 @@ InterlockedDecrement ( return InternalSyncDecrement (Value); } +/** + 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. diff --git a/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c b/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c index ceb80aed94..6347073fee 100644 --- a/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c +++ b/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c @@ -88,6 +88,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. diff --git a/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm new file mode 100644 index 0000000000..e01e9fa928 --- /dev/null +++ b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm @@ -0,0 +1,42 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; Copyright (c) 2015, Linaro Ltd. All rights reserved.
+; 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 0000000000..76aa6fbc0e --- /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.
+ Copyright (c) 2015, Linaro Ltd. All rights reserved.
+ 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); +} +