This implements the following synchronization primitives for AArch64 (GCC) and ARM (GCC & RVCT):
InternalSyncCompareExchange32 InternalSyncCompareExchange64 InternalSyncIncrement InternalSyncDecrement
Note: these functions are implemented using the exclusive monitor, which implies that they can only be used after the caches (and hence the MMU) have been enabled.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Olivier Martin olivier.martin@arm.com Signed-off-by: Ard Biesheuvel ard.biesheuvel@linaro.org --- .../AArch64/Synchronization.S | 159 +++++++++++++++++++ .../AArch64/Synchronization.c | 115 -------------- .../BaseSynchronizationLib/Arm/Synchronization.S | 167 ++++++++++++++++++++ .../BaseSynchronizationLib/Arm/Synchronization.asm | 168 +++++++++++++++++++++ .../BaseSynchronizationLib/Arm/Synchronization.c | 115 -------------- .../BaseSynchronizationLib.inf | 5 +- 6 files changed, 497 insertions(+), 232 deletions(-) create mode 100644 MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S delete mode 100644 MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.c create mode 100644 MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S create mode 100644 MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm delete mode 100644 MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.c mode change 100644 => 100755 MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
diff --git a/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S b/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S new file mode 100644 index 000000000000..601b00495f26 --- /dev/null +++ b/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S @@ -0,0 +1,159 @@ +// Implementation of synchronization functions for ARM architecture (AArch64) +// +// 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 +// 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. +// +// + +.text +.align 3 + +GCC_ASM_EXPORT(InternalSyncCompareExchange32) +GCC_ASM_EXPORT(InternalSyncCompareExchange64) +GCC_ASM_EXPORT(InternalSyncIncrement) +GCC_ASM_EXPORT(InternalSyncDecrement) + +/** + Performs an atomic compare exchange operation on a 32-bit unsigned integer. + + Performs an atomic compare exchange operation on the 32-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 32-bit value for the compare exchange + operation. + @param CompareValue 32-bit value used in compare operation. + @param ExchangeValue 32-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +//UINT32 +//EFIAPI +//InternalSyncCompareExchange32 ( +// IN volatile UINT32 *Value, +// IN UINT32 CompareValue, +// IN UINT32 ExchangeValue +// ) +ASM_PFX(InternalSyncCompareExchange32): + dmb sy + +InternalSyncCompareExchange32Again: + ldxr w3, [x0] + cmp w3, w1 + bne InternalSyncCompareExchange32Fail + +InternalSyncCompareExchange32Exchange: + stxr w4, w2, [x0] + cbnz w4, InternalSyncCompareExchange32Again + +InternalSyncCompareExchange32Fail: + dmb sy + mov w0, w3 + ret + +/** + Performs an atomic compare exchange operation on a 64-bit unsigned integer. + + Performs an atomic compare exchange operation on the 64-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 64-bit value for the compare exchange + operation. + @param CompareValue 64-bit value used in compare operation. + @param ExchangeValue 64-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +//UINT64 +//EFIAPI +//InternalSyncCompareExchange64 ( +// IN volatile UINT64 *Value, +// IN UINT64 CompareValue, +// IN UINT64 ExchangeValue +// ) +ASM_PFX(InternalSyncCompareExchange64): + dmb sy + +InternalSyncCompareExchange64Again: + ldxr x3, [x0] + cmp x3, x1 + bne InternalSyncCompareExchange64Fail + +InternalSyncCompareExchange64Exchange: + stxr w4, x2, [x0] + cbnz w4, InternalSyncCompareExchange64Again + +InternalSyncCompareExchange64Fail: + dmb sy + mov x0, x3 + ret + +/** + Performs an atomic increment of an 32-bit unsigned integer. + + Performs an atomic increment of the 32-bit unsigned integer specified by + Value and returns the incremented value. The increment operation must be + performed using MP safe mechanisms. The state of the return value is not + guaranteed to be MP safe. + + @param Value A pointer to the 32-bit value to increment. + + @return The incremented value. + +**/ +//UINT32 +//EFIAPI +//InternalSyncIncrement ( +// IN volatile UINT32 *Value +// ) +ASM_PFX(InternalSyncIncrement): + dmb sy +TryInternalSyncIncrement: + ldxr w1, [x0] + add w1, w1, #1 + stxr w2, w1, [x0] + cbnz w2, TryInternalSyncIncrement + dmb sy + ret + +/** + Performs an atomic decrement of an 32-bit unsigned integer. + + Performs an atomic decrement of the 32-bit unsigned integer specified by + Value and returns the decrement value. The decrement operation must be + performed using MP safe mechanisms. The state of the return value is not + guaranteed to be MP safe. + + @param Value A pointer to the 32-bit value to decrement. + + @return The decrement value. + +**/ +//UINT32 +//EFIAPI +//InternalSyncDecrement ( +// IN volatile UINT32 *Value +// ) +ASM_PFX(InternalSyncDecrement): + dmb sy +TryInternalSyncDecrement: + ldxr w1, [x0] + sub w1, w1, #1 + stxr w2, w1, [x0] + cbnz w2, TryInternalSyncDecrement + dmb sy + ret diff --git a/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.c b/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.c deleted file mode 100644 index 2e619ccf873f..000000000000 --- a/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.c +++ /dev/null @@ -1,115 +0,0 @@ -/** @file - Implementation of synchronization functions. Still needs to be ported - - Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR> - Portions copyright (c) 2008 - 2009, Apple Inc. 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 32-bit unsigned integer. - - Performs an atomic compare exchange operation on the 32-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 32-bit value for the compare exchange - operation. - @param CompareValue 32-bit value used in compare operation. - @param ExchangeValue 32-bit value used in exchange operation. - - @return The original *Value before exchange. - -**/ -UINT32 -EFIAPI -InternalSyncCompareExchange32 ( - IN volatile UINT32 *Value, - IN UINT32 CompareValue, - IN UINT32 ExchangeValue - ) -{ - return *Value != CompareValue ? *Value : - ((*Value = ExchangeValue), CompareValue); -} - -/** - Performs an atomic compare exchange operation on a 64-bit unsigned integer. - - Performs an atomic compare exchange operation on the 64-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 64-bit value for the compare exchange - operation. - @param CompareValue 64-bit value used in compare operation. - @param ExchangeValue 64-bit value used in exchange operation. - - @return The original *Value before exchange. - -**/ -UINT64 -EFIAPI -InternalSyncCompareExchange64 ( - IN volatile UINT64 *Value, - IN UINT64 CompareValue, - IN UINT64 ExchangeValue - ) -{ - return *Value != CompareValue ? *Value : - ((*Value = ExchangeValue), CompareValue); -} - -/** - Performs an atomic increment of an 32-bit unsigned integer. - - Performs an atomic increment of the 32-bit unsigned integer specified by - Value and returns the incremented value. The increment operation must be - performed using MP safe mechanisms. The state of the return value is not - guaranteed to be MP safe. - - @param Value A pointer to the 32-bit value to increment. - - @return The incremented value. - -**/ -UINT32 -EFIAPI -InternalSyncIncrement ( - IN volatile UINT32 *Value - ) -{ - return ++*Value; -} - -/** - Performs an atomic decrement of an 32-bit unsigned integer. - - Performs an atomic decrement of the 32-bit unsigned integer specified by - Value and returns the decrement value. The decrement operation must be - performed using MP safe mechanisms. The state of the return value is not - guaranteed to be MP safe. - - @param Value A pointer to the 32-bit value to decrement. - - @return The decrement value. - -**/ -UINT32 -EFIAPI -InternalSyncDecrement ( - IN volatile UINT32 *Value - ) -{ - return --*Value; -} diff --git a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S new file mode 100644 index 000000000000..6a6a60466c8e --- /dev/null +++ b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S @@ -0,0 +1,167 @@ +// Implementation of synchronization functions for ARM architecture +// +// Copyright (c) 2012-2015, ARM Limited. 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. +// +// + +.text +.align 3 + +GCC_ASM_EXPORT(InternalSyncCompareExchange32) +GCC_ASM_EXPORT(InternalSyncCompareExchange64) +GCC_ASM_EXPORT(InternalSyncIncrement) +GCC_ASM_EXPORT(InternalSyncDecrement) + +/** + Performs an atomic compare exchange operation on a 32-bit unsigned integer. + + Performs an atomic compare exchange operation on the 32-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 32-bit value for the compare exchange + operation. + @param CompareValue 32-bit value used in compare operation. + @param ExchangeValue 32-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +//UINT32 +//EFIAPI +//InternalSyncCompareExchange32 ( +// IN volatile UINT32 *Value, +// IN UINT32 CompareValue, +// IN UINT32 ExchangeValue +// ) +ASM_PFX(InternalSyncCompareExchange32): + dmb + +InternalSyncCompareExchange32Again: + ldrex r3, [r0] + cmp r3, r1 + bne InternalSyncCompareExchange32Fail + +InternalSyncCompareExchange32Exchange: + strex ip, r2, [r0] + cmp ip, #0 + bne InternalSyncCompareExchange32Again + +InternalSyncCompareExchange32Fail: + dmb + mov r0, r3 + bx lr + +/** + Performs an atomic compare exchange operation on a 64-bit unsigned integer. + + Performs an atomic compare exchange operation on the 64-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 64-bit value for the compare exchange + operation. + @param CompareValue 64-bit value used in compare operation. + @param ExchangeValue 64-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +//UINT64 +//EFIAPI +//InternalSyncCompareExchange64 ( +// IN volatile UINT64 *Value, // r0-r1 +// IN UINT64 CompareValue, // r2-r3 +// IN UINT64 ExchangeValue // r4-r5 +// ) +ASM_PFX(InternalSyncCompareExchange64): + push { r4-r7 } + ldrd r4, r5, [sp, #16] + dmb + +InternalSyncCompareExchange64Again: + ldrexd r6, r7, [r0] + cmp r6, r2 + cmpeq r7, r3 + bne InternalSyncCompareExchange64Fail + +InternalSyncCompareExchange64Exchange: + strexd ip, r4, r5, [r0] + cmp ip, #0 + bne InternalSyncCompareExchange64Again + +InternalSyncCompareExchange64Fail: + dmb + mov r0, r6 + mov r1, r7 + pop { r4-r7 } + bx lr + +/** + Performs an atomic increment of an 32-bit unsigned integer. + + Performs an atomic increment of the 32-bit unsigned integer specified by + Value and returns the incremented value. The increment operation must be + performed using MP safe mechanisms. The state of the return value is not + guaranteed to be MP safe. + + @param Value A pointer to the 32-bit value to increment. + + @return The incremented value. + +**/ +//UINT32 +//EFIAPI +//InternalSyncIncrement ( +// IN volatile UINT32 *Value +// ) +ASM_PFX(InternalSyncIncrement): + dmb +TryInternalSyncIncrement: + ldrex r1, [r0] + add r1, r1, #1 + strex r2, r1, [r0] + cmp r2, #0 + bne TryInternalSyncIncrement + dmb + bx lr + +/** + Performs an atomic decrement of an 32-bit unsigned integer. + + Performs an atomic decrement of the 32-bit unsigned integer specified by + Value and returns the decrement value. The decrement operation must be + performed using MP safe mechanisms. The state of the return value is not + guaranteed to be MP safe. + + @param Value A pointer to the 32-bit value to decrement. + + @return The decrement value. + +**/ +//UINT32 +//EFIAPI +//InternalSyncDecrement ( +// IN volatile UINT32 *Value +// ) +ASM_PFX(InternalSyncDecrement): + dmb +TryInternalSyncDecrement: + ldrex r1, [r0] + sub r1, r1, #1 + strex r2, r1, [r0] + cmp r2, #0 + bne TryInternalSyncDecrement + dmb + bx lr diff --git a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm new file mode 100644 index 000000000000..df007b6301b3 --- /dev/null +++ b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm @@ -0,0 +1,168 @@ +// Implementation of synchronization functions for ARM architecture +// +// Copyright (c) 2012-2015, ARM Limited. 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. +// +// + + EXPORT InternalSyncCompareExchange32 + EXPORT InternalSyncCompareExchange64 + EXPORT InternalSyncIncrement + EXPORT InternalSyncDecrement + + AREA ArmSynchronization, CODE, READONLY + +/** + Performs an atomic compare exchange operation on a 32-bit unsigned integer. + + Performs an atomic compare exchange operation on the 32-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 32-bit value for the compare exchange + operation. + @param CompareValue 32-bit value used in compare operation. + @param ExchangeValue 32-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +//UINT32 +//EFIAPI +//InternalSyncCompareExchange32 ( +// IN volatile UINT32 *Value, +// IN UINT32 CompareValue, +// IN UINT32 ExchangeValue +// ) +InternalSyncCompareExchange32 + dmb + +InternalSyncCompareExchange32Again + ldrex r3, [r0] + cmp r3, r1 + bne InternalSyncCompareExchange32Fail + +InternalSyncCompareExchange32Exchange + strex ip, r2, [r0] + cmp ip, #0 + bne InternalSyncCompareExchange32Again + +InternalSyncCompareExchange32Fail + dmb + mov r0, r3 + bx lr + +/** + Performs an atomic compare exchange operation on a 64-bit unsigned integer. + + Performs an atomic compare exchange operation on the 64-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 64-bit value for the compare exchange + operation. + @param CompareValue 64-bit value used in compare operation. + @param ExchangeValue 64-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +//UINT64 +//EFIAPI +//InternalSyncCompareExchange64 ( +// IN volatile UINT64 *Value, // r0-r1 +// IN UINT64 CompareValue, // r2-r3 +// IN UINT64 ExchangeValue +// ) +InternalSyncCompareExchange64 + push { r4-r7 } + ldrd r4, r5, [sp, #16] + dmb + +InternalSyncCompareExchange64Again + ldrexd r6, r7, [r0] + cmp r6, r2 + cmpeq r7, r3 + bne InternalSyncCompareExchange64Fail + +InternalSyncCompareExchange64Exchange + strexd ip, r4, r5, [r0] + cmp ip, #0 + bne InternalSyncCompareExchange64Again + +InternalSyncCompareExchange64Fail + dmb + mov r0, r6 + mov r1, r7 + pop { r4-r7 } + bx lr + +/** + Performs an atomic increment of an 32-bit unsigned integer. + + Performs an atomic increment of the 32-bit unsigned integer specified by + Value and returns the incremented value. The increment operation must be + performed using MP safe mechanisms. The state of the return value is not + guaranteed to be MP safe. + + @param Value A pointer to the 32-bit value to increment. + + @return The incremented value. + +**/ +//UINT32 +//EFIAPI +//InternalSyncIncrement ( +// IN volatile UINT32 *Value +// ) +InternalSyncIncrement + dmb +TryInternalSyncIncrement + ldrex r1, [r0] + add r1, r1, #1 + strex r2, r1, [r0] + cmp r2, #0 + bne TryInternalSyncIncrement + dmb + bx lr + +/** + Performs an atomic decrement of an 32-bit unsigned integer. + + Performs an atomic decrement of the 32-bit unsigned integer specified by + Value and returns the decrement value. The decrement operation must be + performed using MP safe mechanisms. The state of the return value is not + guaranteed to be MP safe. + + @param Value A pointer to the 32-bit value to decrement. + + @return The decrement value. + +**/ +//UINT32 +//EFIAPI +//InternalSyncDecrement ( +// IN volatile UINT32 *Value +// ) +InternalSyncDecrement + dmb +TryInternalSyncDecrement + ldrex r1, [r0] + sub r1, r1, #1 + strex r2, r1, [r0] + cmp r2, #0 + bne TryInternalSyncDecrement + dmb + bx lr + + END diff --git a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.c b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.c deleted file mode 100644 index 9ddaa098b22f..000000000000 --- a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.c +++ /dev/null @@ -1,115 +0,0 @@ -/** @file - Implementation of synchronization functions. Still needs to be ported - - Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR> - Portions copyright (c) 2008 - 2009, Apple Inc. 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 32-bit unsigned integer. - - Performs an atomic compare exchange operation on the 32-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 32-bit value for the compare exchange - operation. - @param CompareValue 32-bit value used in compare operation. - @param ExchangeValue 32-bit value used in exchange operation. - - @return The original *Value before exchange. - -**/ -UINT32 -EFIAPI -InternalSyncCompareExchange32 ( - IN volatile UINT32 *Value, - IN UINT32 CompareValue, - IN UINT32 ExchangeValue - ) -{ - return *Value != CompareValue ? *Value : - ((*Value = ExchangeValue), CompareValue); -} - -/** - Performs an atomic compare exchange operation on a 64-bit unsigned integer. - - Performs an atomic compare exchange operation on the 64-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 64-bit value for the compare exchange - operation. - @param CompareValue 64-bit value used in compare operation. - @param ExchangeValue 64-bit value used in exchange operation. - - @return The original *Value before exchange. - -**/ -UINT64 -EFIAPI -InternalSyncCompareExchange64 ( - IN volatile UINT64 *Value, - IN UINT64 CompareValue, - IN UINT64 ExchangeValue - ) -{ - return *Value != CompareValue ? *Value : - ((*Value = ExchangeValue), CompareValue); -} - -/** - Performs an atomic increment of an 32-bit unsigned integer. - - Performs an atomic increment of the 32-bit unsigned integer specified by - Value and returns the incremented value. The increment operation must be - performed using MP safe mechanisms. The state of the return value is not - guaranteed to be MP safe. - - @param Value A pointer to the 32-bit value to increment. - - @return The incremented value. - -**/ -UINT32 -EFIAPI -InternalSyncIncrement ( - IN volatile UINT32 *Value - ) -{ - return ++*Value; -} - -/** - Performs an atomic decrement of an 32-bit unsigned integer. - - Performs an atomic decrement of the 32-bit unsigned integer specified by - Value and returns the decrement value. The decrement operation must be - performed using MP safe mechanisms. The state of the return value is not - guaranteed to be MP safe. - - @param Value A pointer to the 32-bit value to decrement. - - @return The decrement value. - -**/ -UINT32 -EFIAPI -InternalSyncDecrement ( - IN volatile UINT32 *Value - ) -{ - return --*Value; -} diff --git a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf old mode 100644 new mode 100755 index bf9cf67a85cc..5e3b4e6b9bf2 --- a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf +++ b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf @@ -78,11 +78,12 @@
[Sources.ARM] Synchronization.c - Arm/Synchronization.c + Arm/Synchronization.asm | RVCT + Arm/Synchronization.S | GCC
[Sources.AARCH64] Synchronization.c - AArch64/Synchronization.c + AArch64/Synchronization.S
[Packages] MdePkg/MdePkg.dec
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 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 +++++++++++++ .../Library/BaseSynchronizationLib/X64/GccInline.c | 44 ++++++++++++++++++ .../X64/InterlockedCompareExchange16.asm | 42 +++++++++++++++++ .../X64/InterlockedCompareExchange16.c | 54 ++++++++++++++++++++++ 15 files changed, 560 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..cb951e15234c 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 + +InternalSyncCompareExchange16Again: + ldxrh w3, [x0] + cmp w3, w1 + bne InternalSyncCompareExchange16Fail + +InternalSyncCompareExchange16Exchange: + stxrh w4, w2, [x0] + cbnz w4, InternalSyncCompareExchange16Again + +InternalSyncCompareExchange16Fail: + dmb + 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 6a6a60466c8e..32470e213ab6 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 df007b6301b3..364ae0db8574 100644 --- a/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm +++ b/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm @@ -1,6 +1,7 @@ // Implementation of synchronization functions for ARM architecture // // Copyright (c) 2012-2015, ARM Limited. All rights reserved. +// Copyright (c) 2015, Linaro Limited. All rights reserved. // // This program and the accompanying materials // are licensed and made available under the terms and conditions of the BSD License @@ -12,6 +13,7 @@ // //
+ EXPORT InternalSyncCompareExchange16 EXPORT InternalSyncCompareExchange32 EXPORT InternalSyncCompareExchange64 EXPORT InternalSyncIncrement @@ -20,6 +22,48 @@ AREA ArmSynchronization, CODE, READONLY
/** + Performs an atomic compare exchange operation on a 16-bit unsigned integer. + + Performs an atomic compare exchange operation on the 16-bit unsigned integer + specified by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue, + then Value is returned. The compare exchange operation must be performed using + MP safe mechanisms. + + @param Value A pointer to the 16-bit value for the compare exchange + operation. + @param CompareValue 16-bit value used in compare operation. + @param ExchangeValue 16-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +//UINT16 +//EFIAPI +//InternalSyncCompareExchange16 ( +// IN volatile UINT16 *Value, +// IN UINT16 CompareValue, +// IN UINT16 ExchangeValue +// ) +InternalSyncCompareExchange16 + dmb + +InternalSyncCompareExchange16Again + ldrexh r3, [r0] + cmp r3, r1 + bne InternalSyncCompareExchange16Fail + +InternalSyncCompareExchange16Exchange + strexh ip, r2, [r0] + cmp ip, #0 + bne InternalSyncCompareExchange16Again + +InternalSyncCompareExchange16Fail + dmb + mov r0, r3 + bx lr + +/** Performs an atomic compare exchange operation on a 32-bit unsigned integer.
Performs an atomic compare exchange operation on the 32-bit unsigned integer diff --git a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf index 5e3b4e6b9bf2..bd1bec3fb5e7 100755 --- a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf +++ b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf @@ -32,12 +32,14 @@ [Sources.IA32] Ia32/InterlockedCompareExchange64.c | MSFT Ia32/InterlockedCompareExchange32.c | MSFT + Ia32/InterlockedCompareExchange16.c | MSFT Ia32/InterlockedDecrement.c | MSFT Ia32/InterlockedIncrement.c | MSFT SynchronizationMsc.c | MSFT
Ia32/InterlockedCompareExchange64.asm | INTEL Ia32/InterlockedCompareExchange32.asm | INTEL + Ia32/InterlockedCompareExchange16.asm | INTEL Ia32/InterlockedDecrement.asm | INTEL Ia32/InterlockedIncrement.asm | INTEL Synchronization.c | INTEL @@ -48,9 +50,11 @@ [Sources.X64] X64/InterlockedCompareExchange64.c | MSFT X64/InterlockedCompareExchange32.c | MSFT + X64/InterlockedCompareExchange16.c | MSFT
X64/InterlockedCompareExchange64.asm | INTEL X64/InterlockedCompareExchange32.asm | INTEL + X64/InterlockedCompareExchange16.asm | INTEL
X64/InterlockedDecrement.c | MSFT X64/InterlockedIncrement.c | MSFT @@ -67,6 +71,7 @@ Ipf/Synchronization.c Ipf/InterlockedCompareExchange64.s Ipf/InterlockedCompareExchange32.s + Ipf/InterlockedCompareExchange16.s
Synchronization.c | INTEL SynchronizationMsc.c | MSFT diff --git a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h index e42824c75d12..76f702324156 100644 --- a/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h +++ b/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h @@ -63,6 +63,32 @@ InternalSyncDecrement (
/** + Performs an atomic compare exchange operation on a 16-bit unsigned integer. + + Performs an atomic compare exchange operation on the 16-bit unsigned integer + specified by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue, + then Value is returned. The compare exchange operation must be performed using + MP safe mechanisms. + + @param Value A pointer to the 16-bit value for the compare exchange + operation. + @param CompareValue A 16-bit value used in compare operation. + @param ExchangeValue A 16-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT16 +EFIAPI +InternalSyncCompareExchange16 ( + IN volatile UINT16 *Value, + IN UINT16 CompareValue, + IN UINT16 ExchangeValue + ); + + +/** Performs an atomic compare exchange operation on a 32-bit unsigned integer.
Performs an atomic compare exchange operation on the 32-bit unsigned integer diff --git a/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c b/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c index 9c34b9f128ed..a57860203b12 100644 --- a/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c +++ b/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c @@ -13,6 +13,37 @@ **/
/** + Performs an atomic compare exchange operation on a 16-bit + unsigned integer. + + Performs an atomic compare exchange operation on the 16-bit + unsigned integer specified by Value. If Value is equal to + CompareValue, then Value is set to ExchangeValue and + CompareValue is returned. If Value is not equal to + CompareValue, then Value is returned. The compare exchange + operation must be performed using MP safe mechanisms. + + @param Value A pointer to the 16-bit value for the + compare exchange operation. + @param CompareValue 16-bit value used in compare operation. + @param ExchangeValue 16-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT16 +EFIAPI +InternalSyncCompareExchange16 ( + IN volatile UINT16 *Value, + IN UINT16 CompareValue, + IN UINT16 ExchangeValue + ) +{ + return *Value != CompareValue ? *Value : + ((*Value = ExchangeValue), CompareValue); +} + +/** Performs an atomic compare exchange operation on a 32-bit unsigned integer.
diff --git a/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c b/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c index b5a7827fc0e8..bd81aad6c243 100644 --- a/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c +++ b/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c @@ -88,6 +88,48 @@ InternalSyncDecrement ( }
/** + Performs an atomic compare exchange operation on a 16-bit unsigned integer. + + Performs an atomic compare exchange operation on the 16-bit unsigned integer + specified by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue, + then Value is returned. The compare exchange operation must be performed using + MP safe mechanisms. + + + @param Value A pointer to the 16-bit value for the compare exchange + operation. + @param CompareValue 16-bit value used in compare operation. + @param ExchangeValue 16-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT16 +EFIAPI +InternalSyncCompareExchange16 ( + IN OUT volatile UINT16 *Value, + IN UINT16 CompareValue, + IN UINT16 ExchangeValue + ) +{ + + __asm__ __volatile__ ( + " \n\t" + "lock \n\t" + "cmpxchgw %1, %2 \n\t" + : "=a" (CompareValue) + : "q" (ExchangeValue), + "m" (*Value), + "0" (CompareValue) + : "memory", + "cc" + ); + + return CompareValue; +} + +/** Performs an atomic compare exchange operation on a 32-bit unsigned integer.
Performs an atomic compare exchange operation on the 32-bit unsigned integer diff --git a/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm new file mode 100644 index 000000000000..f8705042661d --- /dev/null +++ b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.asm @@ -0,0 +1,46 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.<BR> +; Copyright (c) 2015, Linaro Ltd. All rights reserved.<BR> +; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; Module Name: +; +; InterlockedCompareExchange16.Asm +; +; Abstract: +; +; InterlockedCompareExchange16 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .486 + .model flat,C + .code + +;------------------------------------------------------------------------------ +; UINT16 +; EFIAPI +; InternalSyncCompareExchange16 ( +; IN UINT16 *Value, +; IN UINT16 CompareValue, +; IN UINT16 ExchangeValue +; ); +;------------------------------------------------------------------------------ +InternalSyncCompareExchange16 PROC + mov ecx, [esp + 4] + mov eax, [esp + 8] + mov edx, [esp + 12] + lock cmpxchg [ecx], dx + ret +InternalSyncCompareExchange16 ENDP + + END diff --git a/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c new file mode 100644 index 000000000000..3d06dd9baa63 --- /dev/null +++ b/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c @@ -0,0 +1,51 @@ +/** @file + InterlockedCompareExchange16 function + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR> + Copyright (c) 2015, Linaro Ltd. All rights reserved.<BR> + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + Performs an atomic compare exchange operation on a 16-bit unsigned integer. + + Performs an atomic compare exchange operation on the 16-bit unsigned integer + specified by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue, + then Value is returned. The compare exchange operation must be performed using + MP safe mechanisms. + + @param Value A pointer to the 16-bit value for the compare exchange + operation. + @param CompareValue 16-bit value used in compare operation. + @param ExchangeValue 16-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT16 +EFIAPI +InternalSyncCompareExchange16 ( + IN UINT16 *Value, + IN UINT16 CompareValue, + IN UINT16 ExchangeValue + ) +{ + _asm { + mov ecx, Value + mov eax, CompareValue + mov edx, ExchangeValue + lock cmpxchg [ecx], dx + } +} + diff --git a/MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s b/MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s new file mode 100644 index 000000000000..1e56942a98cb --- /dev/null +++ b/MdePkg/Library/BaseSynchronizationLib/Ipf/InterlockedCompareExchange16.s @@ -0,0 +1,30 @@ +/// @file +/// Contains an implementation of InterlockedCompareExchange16 on Itanium- +/// based architecture. +/// +/// Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR> +/// Copyright (c) 2015, Linaro Ltd. All rights reserved.<BR> +/// This program and the accompanying materials +/// are licensed and made available under the terms and conditions of the BSD License +/// which accompanies this distribution. The full text of the license may be found at +/// http://opensource.org/licenses/bsd-license.php. +/// +/// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +/// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +/// +/// Module Name: InterlockedCompareExchange16.s +/// +/// + +.auto +.text + +.proc InternalSyncCompareExchange16 +.type InternalSyncCompareExchange16, @function +InternalSyncCompareExchange16:: + zxt2 r33 = r33 + mov ar.ccv = r33 + cmpxchg2.rel r8 = [r32], r34 + mf + br.ret.sptk.many b0 +.endp InternalSyncCompareExchange16 diff --git a/MdePkg/Library/BaseSynchronizationLib/Synchronization.c b/MdePkg/Library/BaseSynchronizationLib/Synchronization.c index 0eea40ba1622..4218a265a0ec 100644 --- a/MdePkg/Library/BaseSynchronizationLib/Synchronization.c +++ b/MdePkg/Library/BaseSynchronizationLib/Synchronization.c @@ -277,6 +277,37 @@ InterlockedDecrement ( }
/** + Performs an atomic compare exchange operation on a 16-bit unsigned integer. + + Performs an atomic compare exchange operation on the 16-bit unsigned integer + specified by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue, + then Value is returned. The compare exchange operation must be performed using + MP safe mechanisms. + + If Value is NULL, then ASSERT(). + + @param Value A pointer to the 16-bit value for the compare exchange + operation. + @param CompareValue 16-bit value used in compare operation. + @param ExchangeValue 16-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT16 +EFIAPI +InterlockedCompareExchange16 ( + IN OUT UINT16 *Value, + IN UINT16 CompareValue, + IN UINT16 ExchangeValue + ) +{ + ASSERT (Value != NULL); + return InternalSyncCompareExchange16 (Value, CompareValue, ExchangeValue); +} + +/** Performs an atomic compare exchange operation on a 32-bit unsigned integer.
Performs an atomic compare exchange operation on the 32-bit unsigned integer diff --git a/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c b/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c index ceb80aed94f8..6347073fee51 100644 --- a/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c +++ b/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c @@ -89,6 +89,50 @@ InternalSyncDecrement (
/** + Performs an atomic compare exchange operation on a 16-bit unsigned integer. + + Performs an atomic compare exchange operation on the 16-bit unsigned integer + specified by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue, + then Value is returned. The compare exchange operation must be performed using + MP safe mechanisms. + + + @param Value A pointer to the 16-bit value for the compare exchange + operation. + @param CompareValue 16-bit value used in compare operation. + @param ExchangeValue 16-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT16 +EFIAPI +InternalSyncCompareExchange16 ( + IN OUT volatile UINT16 *Value, + IN UINT16 CompareValue, + IN UINT16 ExchangeValue + ) +{ + + + __asm__ __volatile__ ( + "lock \n\t" + "cmpxchgw %3, %1 " + : "=a" (CompareValue), + "=m" (*Value) + : "a" (CompareValue), + "r" (ExchangeValue), + "m" (*Value) + : "memory", + "cc" + ); + + return CompareValue; +} + + +/** Performs an atomic compare exchange operation on a 32-bit unsigned integer.
Performs an atomic compare exchange operation on the 32-bit unsigned integer diff --git a/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm new file mode 100644 index 000000000000..8fe2aae1a28b --- /dev/null +++ b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.asm @@ -0,0 +1,42 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.<BR> +; Copyright (c) 2015, Linaro Ltd. All rights reserved.<BR> +; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; Module Name: +; +; InterlockedCompareExchange16.Asm +; +; Abstract: +; +; InterlockedCompareExchange16 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINT16 +; EFIAPI +; InterlockedCompareExchange16 ( +; IN UINT16 *Value, +; IN UINT16 CompareValue, +; IN UINT16 ExchangeValue +; ); +;------------------------------------------------------------------------------ +InternalSyncCompareExchange16 PROC + mov eax, edx + lock cmpxchg [rcx], r8w + ret +InternalSyncCompareExchange16 ENDP + + END diff --git a/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c new file mode 100644 index 000000000000..76aa6fbc0e81 --- /dev/null +++ b/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c @@ -0,0 +1,54 @@ +/** @file + InterlockedCompareExchange16 function + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR> + Copyright (c) 2015, Linaro Ltd. All rights reserved.<BR> + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +/** + Microsoft Visual Studio 7.1 Function Prototypes for I/O Intrinsics. +**/ + +__int16 _InterlockedCompareExchange16( + __int16 volatile * Destination, + __int16 Exchange, + __int16 Comperand +); + +#pragma intrinsic(_InterlockedCompareExchange16) + +/** + Performs an atomic compare exchange operation on a 16-bit unsigned integer. + + Performs an atomic compare exchange operation on the 16-bit unsigned integer specified + by Value. If Value is equal to CompareValue, then Value is set to ExchangeValue and + CompareValue is returned. If Value is not equal to CompareValue, then Value is returned. + The compare exchange operation must be performed using MP safe mechanisms. + + @param Value A pointer to the 16-bit value for the compare exchange + operation. + @param CompareValue 16-bit value used in compare operation. + @param ExchangeValue 16-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT16 +EFIAPI +InternalSyncCompareExchange16 ( + IN UINT16 *Value, + IN UINT16 CompareValue, + IN UINT16 ExchangeValue + ) +{ + return _InterlockedCompareExchange16 (Value, ExchangeValue, CompareValue); +} +