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