Home | History | Annotate | Download | only in XenBusDxe
      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
     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