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