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
20INT32
21EFIAPI
22TestAndClearBit (
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