1

I'm writting a bitmap physical memory manager and i want implement a function that checks if a n bits are free starting from an specific bit. Right now I use this function that checks if a single bit is free and i call it n times to see if n bits are free but i think it is not very efficient to do it this way:

inline static bool physical_memory_map_test(uint32_t bit)
{
    return physical_memory.blocks[bit/32] & (1 << bit % 32);
}

So I want to implemnt something like this: (the "" contains pseudo code):

static bool physical_memory_map_test(uint32_t starting_bit, uint32_t count)
{
    int excess = (starting_bit%32 + count) -32;
    if(excess < 0)
        return (physical_memory.blocks[bit/32] & "-excess number of 1s" << bit % 32)) && (physical_memory.blocks[bit/32] & "count + excess number of 1s" << bit % 32));

    return physical_memory.blocks[bit/32] & ("count number of ones, if count is 3, this should be 111" << bit % 32); 
}

Or something better to check if all the bits are 0 (return true) or if at least one of them is a 1(return false) How could i do that?

  • If you want the total number of set bits in an integer type, you want a `popcount`, which is available as a machine instruction in some architectures, and as a compiler-builtin too. If you want to count *adjacent* set bits, you may find `ffs()` or `clz/ctz` or `lzcnt/tzcnt` or `bsf/bsr` or the equivalent builtins interesting. – EOF Aug 23 '16 at 10:06
  • If you want to check that `n` *consecutive* bits are free you can examine then 32 at a time, except for the first and last few. – Weather Vane Aug 23 '16 at 10:09

1 Answers1

5

Since you are checking a range of uint32_t words, you will end up with a loop. Your task is to make it loop by 32 bits instead of looping by 1 bit.

You need to check partial 32-bit words at both ends:

Bit groups

In order to do that you need to construct a mask with k lower bits set to 1, and upper (32-k) set to 0. You can do it like this:

uint32_t mask_K = ~(~0U << k);

Use

if (block & mask_K)

to test the lower k bits;

if (block & ~mask_K)

tests the upper k bits.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • The computation of `mask_K` would appear to invoke UB for `k` = 31. – njuffa Aug 23 '16 at 14:34
  • I usually use `~(~0U << k)` for building a 32-bit mask with `k` consecutive 1-bits (0 <= k < 32), maybe that would suit your purpose? – njuffa Aug 23 '16 at 17:31
  • I've played with this a bit, why not `uint32_t k = 32, mask = ~0;` to build the mask and then `while (k--) mask >>= 1;` which creates the identical mask of `1111...1111` to `1`. The reverse can be done with `~0u << k`? Just a thought. – David C. Rankin Aug 23 '16 at 19:02
  • @DavidC.Rankin as a rule, code without a loop or a conditional is faster than a code that does the same thing, but uses a loop or a conditional. The reverse is perfect, though. – Sergey Kalinichenko Aug 23 '16 at 19:39
  • I got you, that's the part that I missed in the question. I was under the impression that `k` was a loop variable to begin with so it didn't snap that shifting `mask >>= 1;` may not be possible in the context of the question. Makes sense. Thanks. – David C. Rankin Aug 23 '16 at 20:04
  • Does the case where the ranges starts and ends in the same block of 32 bits need to be handled as a special case? – samgak Aug 24 '16 at 00:39
  • 1
    @samgak Yes, you do need to handle them as a special case - essentially, you bitwise-AND the masks together before checking the range. – Sergey Kalinichenko Aug 24 '16 at 01:44