Left Shift in C++ - Unexpected Result

0

Issue: uint32_t entry = (uint16_t )1 << (bitPosition && 0xf);

I'm about to code a memory allocator that uses a bit map in order to track allocated/free pages.

     void
PageAllocator::deallocate( uintptr_t memoryAddress )
{
logInfoEvent_m( "function = %s, file = %s, line = %i.",
                __PRETTY_FUNCTION__,
                __FILE__,
                __LINE__
              );

uint32_t    pageNb      = memoryAddress / memory::pageSize_c;
uint32_t    index       = pageNb / bitsPerBitmapEntry_c;
uint32_t    bitPosition = pageNb % bitsPerBitmapEntry_c;

uint32_t    entry       = (uint32_t )1 << (bitPosition && 0x0f);
__pageAllocatorBitmap[index] = ((uint32_t )1 << (bitPosition && 0x0f));

logInfoEvent_m( "  ____freeing page: address = 0x%*x; pageNb = %d; index = %d; bit position = %d; entry = %d; bit map entry 0x%*x.",

During initialization the function is called for all available pages. I'm getting following result:

    index = 1; bit position = 0; entry = 1; bit map entry 0x00000001.

but for this line the result is incorrect:

    index = 1; bit position = 5; entry = 2; bit map entry 0x00000002.

For position with value 0 the result is correct. For any other value that position holds the value for entry is "2" which is not correct. My expectation for position = 5 is entry = 32 decimal (0x20).

Environment: g++ (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0 GNU assembler (GNU Binutils for Ubuntu) 2.30

I have been reading previous post, but all the hints I found there where not helping to solve the problem. I know, that shifting beyond 32-bit is unpredictable.

Any clue what I'm doing wrong here. Sorry for disturbing the community.

c++
asked on Stack Overflow Jul 12, 2020 by Heinz • edited Jul 12, 2020 by Waqar

2 Answers

3

entry and __pageAllocatorBitmap[index] can only value 1 or 2 because bitPosition && 0xf is a boolean expression valuing 0 or 1, so you can only get 1 (1 << 0) or 2 (1 << 1)

you want to shift depending on the 4 lower bits of bitPosition, so just replace

uint32_t entry = (uint32_t )1 << (bitPosition && 0xf);
__pageAllocatorBitmap[index] = ((uint32_t )1 << (bitPosition && 0x0f));

by

uint32_t entry = (uint32_t )1 << (bitPosition & 0xf);
__pageAllocatorBitmap[index] = ((uint32_t )1 << (bitPosition & 0x0f));

or

uint32_t entry = (uint32_t )1 << (bitPosition & 0xf);
__pageAllocatorBitmap[index] = entry;
answered on Stack Overflow Jul 12, 2020 by bruno • edited Jul 12, 2020 by bruno
0

Sorry for that stupid error!

However, with the solution proposed my code crashes with QEMU as emulator.

void
PageAllocator::deallocate( uintptr_t memoryAddress )
{
   logInfoEvent_m( "function = %s, file = %s, line = %i.",
                   __PRETTY_FUNCTION__,
                   __FILE__,
                   __LINE__
                 );

    uint32_t    pageNb      = memoryAddress / memory::pageSize_c;
    uint32_t    index       = pageNb / bitsPerBitmapEntry_c;
     uint8_t        bitPosition = pageNb % bitsPerBitmapEntry_c;

    uint32_t    entry1      = (uint32_t )1 <<  2;
    uint32_t    entry2      = (uint32_t )1 << 31;

    //uint8_t       shift       = 2;
    //uint32_t  entry3      = (uint32_t )1 <<  (shift & 0x1f);
    //__pageAllocatorBitmap[index] = ((uint32_t )1 << (bitPosition && 0x0f));

    logInfoEvent_m( "  ____freeing page: address = 0x%*x; pageNb = %d; index = %d; bit position = %d; entry1 = %d; entry2 = 0x%*x; bit map entry 0x%*x.",
                16, memoryAddress,
                pageNb,
                index, 
                bitPosition,
                entry1,
                8, entry2,
                //8, entry3,
                8, __pageAllocatorBitmap[index]
              );

With a fixed value in shift statement the result is:

____ INFO:   ____freeing page: address = 0x0000000001000000; pageNb = 8; index = 0; bit position = 8; entry1 = 4; entry2 = 0x80000000; bit map entry 0x00000000.

which what I'm expecting.

However, with a shift from a variable the code just crashes:

void
PageAllocator::deallocate( uintptr_t memoryAddress )
{
    logInfoEvent_m( "function = %s, file = %s, line = %i.",
                    __PRETTY_FUNCTION__,
                    __FILE__,
                    __LINE__
                  );

    uint32_t    pageNb      = memoryAddress / memory::pageSize_c;
    uint32_t    index       = pageNb / bitsPerBitmapEntry_c;
    uint8_t     bitPosition = pageNb % bitsPerBitmapEntry_c;

    uint32_t    entry1      = (uint32_t )1 <<  2;
    uint32_t    entry2      = (uint32_t )1 << 31;

    uint8_t     shift       = 2;
    uint32_t    entry3      = (uint32_t )1 <<  (shift & 0x1f);

with that lst statement qemu just crashes.

g++: (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0 GNU assembler (GNU Binutils for Ubuntu) 2.30 qemu: qemu-system-x86_64

Any additional idea what I'm doing wrong? Thanks for any advice.

answered on Stack Overflow Jul 27, 2020 by Heinz

User contributions licensed under CC BY-SA 3.0