VirtualBox

Changeset 87193 in vbox for trunk/src/VBox/Runtime/common


Ignore:
Timestamp:
Jan 7, 2021 8:59:58 PM (4 years ago)
Author:
vboxsync
Message:

iprt/asm.h: Added generic C version of ASMBitNextClear & ASMBitFirstSet. Fixes to ASMBitFirstClear. bugref:9898

Location:
trunk/src/VBox/Runtime/common/asm
Files:
2 edited
2 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/asm/ASMBitFirstClear-generic.cpp

    r87192 r87193  
    3939    const volatile size_t RT_FAR *pu = (const volatile size_t RT_FAR *)pvBitmap;
    4040    Assert(!(cBits & 31));
     41    Assert(!((uintptr_t)pvBitmap & 3));
    4142
     43#if ARCH_BITS > 32
     44    /* Deal with misaligned bitmaps (happens all the time via ASMBitNextClear()). */
     45    if (!((uintptr_t)pvBitmap & 7) && cBits >= 32)
     46    {
     47        uint32_t u32 = *(const volatile uint32_t RT_FAR *)pu;
     48        if (u32 != UINT32_MAX)
     49        {
     50            size_t const iBaseBit = ((uintptr_t)pu - (uintptr_t)pvBitmap) * 8;
     51            return iBaseBit + ASMBitFirstSetU32(~RT_LE2H_U32(u32)) - 1;
     52        }
     53        pu     = (const volatile size_t RT_FAR *)((uintptr_t)pu + sizeof(uint32_t));
     54        cBits -= 32;
     55    }
     56#endif
     57
     58    /* Main search loop: */
    4259    while (cBits >= sizeof(size_t) * 8)
    4360    {
     
    5370            return iBaseBit + ASMBitFirstSetU64(~RT_LE2H_U64(u)) - 1;
    5471#else
    55 # error "ARCH_BITS or RT_BIG_ENDIAN/RT_LITTLE_ENDIAN is not supported" /** @todo figure out bitmaps on bigendian systems! */
     72# error "ARCH_BITS is not supported"
    5673#endif
    5774        }
     
    6279
    6380#if ARCH_BITS > 32
    64     if (cBits >= 32)
     81    /* Final 32-bit item (unlikely)? */
     82    if (cBits < 32)
     83    { }
     84    else
    6585    {
    6686        uint32_t u32 = *(const volatile uint32_t RT_FAR *)pu;
  • trunk/src/VBox/Runtime/common/asm/ASMBitFirstSet-generic.cpp

    r87192 r87193  
    11/* $Id$ */
    22/** @file
    3  * IPRT - ASMBitFirstClear - generic C implementation.
     3 * IPRT - ASMBitFirstSet - generic C implementation.
    44 */
    55
     
    3535
    3636
    37 DECLASM(int32_t) ASMBitFirstClear(const volatile void RT_FAR *pvBitmap, uint32_t cBits) RT_NOTHROW_DEF
     37DECLASM(int32_t) ASMBitFirstSet(const volatile void RT_FAR *pvBitmap, uint32_t cBits) RT_NOTHROW_DEF
    3838{
    3939    const volatile size_t RT_FAR *pu = (const volatile size_t RT_FAR *)pvBitmap;
    4040    Assert(!(cBits & 31));
     41    Assert(!((uintptr_t)pvBitmap & 3));
    4142
     43#if ARCH_BITS > 32
     44    /* Deal with misaligned bitmaps (happens all the time via ASMBitNextClear()). */
     45    if (!((uintptr_t)pvBitmap & 7) && cBits >= 32)
     46    {
     47        uint32_t u32 = *(const volatile uint32_t RT_FAR *)pu;
     48        if (u32 != UINT32_MAX)
     49        {
     50            size_t const iBaseBit = ((uintptr_t)pu - (uintptr_t)pvBitmap) * 8;
     51            return iBaseBit + ASMBitFirstSetU32(RT_LE2H_U32(u32)) - 1;
     52        }
     53        pu     = (const volatile size_t RT_FAR *)((uintptr_t)pu + sizeof(uint32_t));
     54        cBits -= 32;
     55    }
     56#endif
     57
     58    /* Main search loop: */
    4259    while (cBits >= sizeof(size_t) * 8)
    4360    {
    4461        size_t u = *pu;
    45         if (u == ~(size_t)0)
     62        if (u == 0)
    4663        { }
    4764        else
     
    4966            size_t const iBaseBit = ((uintptr_t)pu - (uintptr_t)pvBitmap) * 8;
    5067#if ARCH_BITS == 32
    51             return iBaseBit + ASMBitFirstSetU32(~RT_LE2H_U32(u)) - 1;
     68            return iBaseBit + ASMBitFirstSetU32(RT_LE2H_U32(u)) - 1;
    5269#elif ARCH_BITS == 64
    53             return iBaseBit + ASMBitFirstSetU64(~RT_LE2H_U64(u)) - 1;
     70            return iBaseBit + ASMBitFirstSetU64(RT_LE2H_U64(u)) - 1;
    5471#else
    55 # error "ARCH_BITS or RT_BIG_ENDIAN/RT_LITTLE_ENDIAN is not supported" /** @todo figure out bitmaps on bigendian systems! */
     72# error "ARCH_BITS is not supported"
    5673#endif
    5774        }
     
    6279
    6380#if ARCH_BITS > 32
    64     if (cBits >= 32)
     81    /* Final 32-bit item (unlikely)? */
     82    if (cBits < 32)
     83    { }
     84    else
    6585    {
    6686        uint32_t u32 = *(const volatile uint32_t RT_FAR *)pu;
     
    6888        {
    6989            size_t const iBaseBit = ((uintptr_t)pu - (uintptr_t)pvBitmap) * 8;
    70             return iBaseBit + ASMBitFirstSetU32(~RT_LE2H_U32(u32)) - 1;
     90            return iBaseBit + ASMBitFirstSetU32(RT_LE2H_U32(u32)) - 1;
    7191        }
    7292    }
  • trunk/src/VBox/Runtime/common/asm/ASMBitNextClear-generic.cpp

    r87192 r87193  
    11/* $Id$ */
    22/** @file
    3  * IPRT - ASMBitFirstClear - generic C implementation.
     3 * IPRT - ASMBitNextClear - generic C implementation.
    44 */
    55
     
    3535
    3636
    37 DECLASM(int32_t) ASMBitFirstClear(const volatile void RT_FAR *pvBitmap, uint32_t cBits) RT_NOTHROW_DEF
     37DECLASM(int) ASMBitNextClear(const volatile void RT_FAR *pvBitmap, uint32_t cBits, uint32_t iBitPrev) RT_NOTHROW_DEF
    3838{
    39     const volatile size_t RT_FAR *pu = (const volatile size_t RT_FAR *)pvBitmap;
     39    const volatile uint32_t RT_FAR *pau32Bitmap = (const volatile uint32_t RT_FAR *)pvBitmap;
     40    int                             iBit = ++iBitPrev & 31;
    4041    Assert(!(cBits & 31));
     42    Assert(!((uintptr_t)pvBitmap & 3));
     43    if (iBit)
     44    {
     45        /*
     46         * Inspect the 32-bit word containing the unaligned bit.
     47         */
     48        uint32_t  u32 = ~RT_LE2H_U32(pau32Bitmap[iBitPrev / 32]) >> iBit;
     49        if (u32)
     50            return iBitPrev + ASMBitFirstSetU32(u32) - 1;
    4151
    42     while (cBits >= sizeof(size_t) * 8)
    43     {
    44         size_t u = *pu;
    45         if (u == ~(size_t)0)
    46         { }
    47         else
    48         {
    49             size_t const iBaseBit = ((uintptr_t)pu - (uintptr_t)pvBitmap) * 8;
    50 #if ARCH_BITS == 32
    51             return iBaseBit + ASMBitFirstSetU32(~RT_LE2H_U32(u)) - 1;
    52 #elif ARCH_BITS == 64
    53             return iBaseBit + ASMBitFirstSetU64(~RT_LE2H_U64(u)) - 1;
    54 #else
    55 # error "ARCH_BITS or RT_BIG_ENDIAN/RT_LITTLE_ENDIAN is not supported" /** @todo figure out bitmaps on bigendian systems! */
    56 #endif
    57         }
    58 
    59         pu++;
    60         cBits -= sizeof(size_t) * 8;
     52        /*
     53         * Skip ahead and see if there is anything left to search.
     54         */
     55        iBitPrev |= 31;
     56        iBitPrev++;
     57        if (cBits <= (uint32_t)iBitPrev)
     58            return -1;
    6159    }
    6260
    63 #if ARCH_BITS > 32
    64     if (cBits >= 32)
    65     {
    66         uint32_t u32 = *(const volatile uint32_t RT_FAR *)pu;
    67         if (u32 != UINT32_MAX)
    68         {
    69             size_t const iBaseBit = ((uintptr_t)pu - (uintptr_t)pvBitmap) * 8;
    70             return iBaseBit + ASMBitFirstSetU32(~RT_LE2H_U32(u32)) - 1;
    71         }
    72     }
    73 #endif
    74 
    75     return -1;
     61    /*
     62     * 32-bit aligned search, let ASMBitFirstClear do the dirty work.
     63     */
     64    iBit = ASMBitFirstClear(&pau32Bitmap[iBitPrev / 32], cBits - iBitPrev);
     65    if (iBit >= 0)
     66        iBit += iBitPrev;
     67    return iBit;
    7668}
    7769
  • trunk/src/VBox/Runtime/common/asm/asm-fake.cpp

    r87192 r87193  
    297297}
    298298
    299 RTDECL(int) ASMBitNextClear(const volatile void *pvBitmap, uint32_t cBits, uint32_t iBitPrev)
    300 {
    301     const volatile uint8_t *pau8Bitmap = (const volatile uint8_t *)pvBitmap;
    302     int                      iBit = ++iBitPrev & 7;
    303     if (iBit)
    304     {
    305         /*
    306          * Inspect the byte containing the unaligned bit.
    307          */
    308         uint8_t u8 = ~pau8Bitmap[iBitPrev / 8] >> iBit;
    309         if (u8)
    310         {
    311             iBit = 0;
    312             while (!(u8 & 1))
    313             {
    314                 u8 >>= 1;
    315                 iBit++;
    316             }
    317             return iBitPrev + iBit;
    318         }
    319 
    320         /*
    321          * Skip ahead and see if there is anything left to search.
    322          */
    323         iBitPrev |= 7;
    324         iBitPrev++;
    325         if (cBits <= iBitPrev)
    326             return -1;
    327     }
    328 
    329     /*
    330      * Byte search, let ASMBitFirstClear do the dirty work.
    331      */
    332     iBit = ASMBitFirstClear(&pau8Bitmap[iBitPrev / 8], cBits - iBitPrev);
    333     if (iBit >= 0)
    334         iBit += iBitPrev;
    335     return iBit;
    336 }
    337 
    338 RTDECL(int) ASMBitFirstSet(const volatile void *pvBitmap, uint32_t cBits)
    339 {
    340     uint32_t           iBit = 0;
    341     uint8_t volatile *pu8 = (uint8_t volatile *)pvBitmap;
    342     while (iBit < cBits)
    343     {
    344         uint8_t u8 = *pu8;
    345         if (u8 != 0)
    346         {
    347             while (!(u8 & 1))
    348             {
    349                 u8 >>= 1;
    350                 iBit++;
    351             }
    352             if (iBit >= cBits)
    353                 return -1;
    354             return iBit;
    355         }
    356 
    357         iBit += 8;
    358         pu8++;
    359     }
    360     return -1;
    361 }
    362 
    363299RTDECL(int) ASMBitNextSet(const volatile void *pvBitmap, uint32_t cBits, uint32_t iBitPrev)
    364300{
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette