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.
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;
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.
User contributions licensed under CC BY-SA 3.0