artrecks wrote:but in the case of using a bitmap, the size of the bitmap will be the size of the ram / 8 ( since each byte has 8 bits ). How can someone allocate a dynamic bitmap?
Mostly, you are handed or should be prepared to be handed a series of memory ranges instead of one large big ol' block of free memory at once. If you did get handed a big ol' large free range, and only one mine you. This entire process would be much easier since you would simply check if the range is large enough, then if it is subtract that amount from it for the bitmap.
CountOf4096ByteMemoryPages=FreeMemoryInBytes>>12;
SizeOfBitmapInBytes=CountOf4096ByteMemoryPages/8;
Unfortunately, like I said above the general case will be that RAM will be slightly fragmented. You can still expect a rather large free range on a system with a large amount of memory, but you will also get small ranges which fill in the gaps between BIOS areas and such other things (especially, in lower memory).
But do not fear since there is a way to get around this daunting brain teaser, and it sports some nice cookies at the end. Well.. no cookies but it would be nice if it did.
Two Pass
This is most likely the simple one to implement since it requires very little complexity. You can even implement this outside the memory manager if you wish. The idea is to scan over the list of free memory ranges, and pick the largest then hand this to the memory manager and let it use it for initialization to create the bitmap in.
// GRUB, gives us a memory map.
.... .. code .. ..
// (FIRST PASS) Lets scan this memory map, and pick the largest range.
.... .. code .. ..
// Subtract the amount we need for our bitmap, from this largest range.
... ... . code ... .
// (SECOND PASS) Start adding memory to our bitmap..
Linked
This one is
not very helpful when implementing a basic bitmap, which needs to be contiguous in memory unless you are aiming for a implementation that fits into some _really_ fragmented memory. The idea is that your implementation, (which may be a bitmap, stack, or tree), can handle being fragmented. The most perfect fragment size is going to be a page of memory which is by default 4096 bytes on the IA32 when not using any extensions. What you want to do is always have
one handy free page lying around doing nothing.. the way to do this is to always check if you have one.
Code: Select all
void memory_manager_init(unsigned long pageOffset, unsigned long pageCount)
{
static unsigned long lazy_page = 0xFFFFFFFF;
for(; pageOffset < ((pageCount * 4096) + pageOffset); pageOffset += 4096)
{
if(lazy_page == 0xFFFFFFFF)
{
lazy_page = pageOffset;
}else{
// add pageOffset into the (fragmented bitmap, stack, or tree).
// if you need a extra page for more storage get it from lazy_page
// (set lazy_page to 0xFFFFFFFF if you use it)
}
}
return;
}
This is a mock up example of the function calling the memory manager initialization function... or add memory function -
whatever it might be.
Code: Select all
for(... loop through GRUB memory map ...)
{
memory_manager_init(grub_mem_map_entry->address>>12, grub_mem_map_entry->sizeInBytes>>12);
}
You could add some code to also ensure that each address and size reside on a page boundary to prevent a rare and strange bug which I have yet to encounter when using GRUB, but just FYI.