1 /** @file
2 Implementation of TestAndClearBit using compare-exchange primitive
3
4 Copyright (C) 2015, Linaro Ltd.
5 Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
6
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
11
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14
15 **/
16
17 #include <Base.h>
18 #include <Library/SynchronizationLib.h>
19
20 INT32
21 EFIAPI
TestAndClearBit(IN INT32 Bit,IN VOID * Address)22 TestAndClearBit (
23 IN INT32 Bit,
24 IN VOID *Address
25 )
26 {
27 UINT16 Word, Read;
28 UINT16 Mask;
29
30 //
31 // Calculate the effective address relative to 'Address' based on the
32 // higher order bits of 'Bit'. Use signed shift instead of division to
33 // ensure we round towards -Inf, and end up with a positive shift in
34 // 'Bit', even if 'Bit' itself is negative.
35 //
36 Address = (VOID*)((UINT8*) Address + ((Bit >> 4) * sizeof(UINT16)));
37 Mask = 1U << (Bit & 15);
38
39 for (Word = *(UINT16 *) Address; Word & Mask; Word = Read) {
40 Read = InterlockedCompareExchange16 (Address, Word, Word & ~Mask);
41 if (Read == Word) {
42 return 1;
43 }
44 }
45 return 0;
46 }
47