Fixes and improvements in mmgr.c
Bug fixes in page allocator Significant performance improvements
This commit is contained in:
94
src/mmgr.c
94
src/mmgr.c
@@ -6,6 +6,8 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#define MAX_CACHE_SIZE 32
|
||||||
|
|
||||||
struct page_map_t
|
struct page_map_t
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
@@ -15,6 +17,12 @@ struct page_map_t
|
|||||||
*/
|
*/
|
||||||
unsigned long *bitmap;
|
unsigned long *bitmap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Stores a list of available blocks of memory to speed up allocation.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
unsigned long *cache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The size of the bitmap in bytes.
|
* @brief The size of the bitmap in bytes.
|
||||||
*
|
*
|
||||||
@@ -50,60 +58,77 @@ const int bitmap_word_size = 8 * sizeof(*page_map.bitmap);
|
|||||||
|
|
||||||
int split_block(int index)
|
int split_block(int index)
|
||||||
{
|
{
|
||||||
if(index)
|
if (index)
|
||||||
{
|
{
|
||||||
int bitmap_index = index / bitmap_word_size;
|
unsigned long bitmap_index = index / bitmap_word_size;
|
||||||
int bitmap_offset = index % bitmap_word_size;
|
unsigned long bitmap_offset = index % bitmap_word_size;
|
||||||
page_map.bitmap[bitmap_index] &= ~(1 << bitmap_offset);
|
page_map.bitmap[bitmap_index] &= ~((unsigned long)1 << bitmap_offset);
|
||||||
index *= 2;
|
index *= 2;
|
||||||
bitmap_index = index / bitmap_word_size;
|
bitmap_index = index / bitmap_word_size;
|
||||||
bitmap_offset = index / bitmap_word_size;
|
bitmap_offset = index % bitmap_word_size;
|
||||||
page_map.bitmap[bitmap_index] |= 1 << bitmap_offset;
|
page_map.bitmap[bitmap_index] |= (unsigned long)1 << bitmap_offset;
|
||||||
page_map.bitmap[bitmap_index] |= 1 << (bitmap_offset ^ 1);
|
page_map.bitmap[bitmap_index] |= (unsigned long)1 << (bitmap_offset ^ 1);
|
||||||
|
unsigned long depth = llog2(index + 1) - 1;
|
||||||
|
unsigned long cache_start = llog2(bitmap_word_size);
|
||||||
|
if(depth >= cache_start && page_map.cache[depth - cache_start] == 0)
|
||||||
|
{
|
||||||
|
page_map.cache[depth - cache_start] = index + 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
int find_free_region(int height)
|
int find_free_region(int height)
|
||||||
{
|
{
|
||||||
if(height > page_map.height || height < 0)
|
if (height > page_map.height || height < 0)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else if(height <= page_map.height - ilog2(bitmap_word_size))
|
else if (height <= page_map.height - ilog2(bitmap_word_size))
|
||||||
{
|
{
|
||||||
for(int index = (1 << (page_map.height - height)) / bitmap_word_size;
|
if(page_map.cache[page_map.height - height - llog2(bitmap_word_size)])
|
||||||
index < (1 << (page_map.height - height + 1)) / bitmap_word_size;
|
|
||||||
index++)
|
|
||||||
{
|
{
|
||||||
if(page_map.bitmap[index] != 0)
|
unsigned long index = page_map.cache[page_map.height - height - llog2(bitmap_word_size)];
|
||||||
|
page_map.cache[page_map.height - height - llog2(bitmap_word_size)] = 0;
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
unsigned long start = (1 << (page_map.height - height)) / bitmap_word_size;
|
||||||
|
unsigned long end = ((1 << (page_map.height - height + 1)) / bitmap_word_size);
|
||||||
|
for (int index = start; index < end; index++)
|
||||||
{
|
{
|
||||||
return bitmap_word_size * index + __builtin_ctz(page_map.bitmap[index]);
|
if (page_map.bitmap[index] != 0)
|
||||||
|
{
|
||||||
|
return bitmap_word_size * index + __builtin_ctzl(page_map.bitmap[index]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
static const int bitmasks[] = {0x00000002, 0x0000000C, 0x000000F0, 0x0000FF00, 0xFFFF0000};
|
#if __SIZEOF_LONG__ == 8
|
||||||
|
static const unsigned long bitmasks[] = {0x00000002, 0x0000000C, 0x000000F0, 0x0000FF00, 0xFFFF0000, 0xFFFFFFFF00000000};
|
||||||
|
#else
|
||||||
|
static const unsigned long bitmasks[] = {0x00000002, 0x0000000C, 0x000000F0, 0x0000FF00, 0xFFFF0000};
|
||||||
|
#endif
|
||||||
int depth = page_map.height - height;
|
int depth = page_map.height - height;
|
||||||
if(page_map.bitmap[0] & bitmasks[depth])
|
if (page_map.bitmap[0] & bitmasks[depth])
|
||||||
{
|
{
|
||||||
return __builtin_ctz(page_map.bitmap[0] & bitmasks[depth]);
|
return __builtin_ctzl(page_map.bitmap[0] & bitmasks[depth]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return split_block(find_free_region(height + 1));
|
return split_block(find_free_region(height + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
physaddr_t reserve_region(size_t size)
|
physaddr_t reserve_region(size_t size)
|
||||||
{
|
{
|
||||||
int height = llog2(size / page_map.block_size);
|
int height = llog2(size / page_map.block_size);
|
||||||
int index = find_free_region(height);
|
int index = find_free_region(height);
|
||||||
if(index)
|
if (index)
|
||||||
{
|
{
|
||||||
int bitmap_index = index / bitmap_word_size;
|
int bitmap_index = index / bitmap_word_size;
|
||||||
int bitmap_offset = index % bitmap_word_size;
|
int bitmap_offset = index % bitmap_word_size;
|
||||||
page_map.bitmap[bitmap_index] &= ~(1 << bitmap_offset);
|
page_map.bitmap[bitmap_index] &= ~((unsigned long)1 << bitmap_offset);
|
||||||
return (page_map.block_size << height) * (index - (1 << (page_map.height - height)));
|
return (page_map.block_size << height) * (index - ((unsigned long)1 << (page_map.height - height)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -114,18 +139,29 @@ physaddr_t reserve_region(size_t size)
|
|||||||
int free_region(physaddr_t location, size_t size)
|
int free_region(physaddr_t location, size_t size)
|
||||||
{
|
{
|
||||||
int height = llog2(size / page_map.block_size);
|
int height = llog2(size / page_map.block_size);
|
||||||
int index = (location / (page_map.block_size * (1 << height))) + (1 << (page_map.height - height));
|
int index = (location / (page_map.block_size * ((unsigned long)1 << height))) + (1 << (page_map.height - height));
|
||||||
int bitmap_index = index / bitmap_word_size;
|
int bitmap_index = index / bitmap_word_size;
|
||||||
int bitmap_offset = index % bitmap_word_size;
|
int bitmap_offset = index % bitmap_word_size;
|
||||||
page_map.bitmap[bitmap_index] |= 1 << bitmap_offset;
|
page_map.bitmap[bitmap_index] |= (unsigned long)1 << bitmap_offset;
|
||||||
while(page_map.bitmap[bitmap_index] & (1 << (bitmap_offset ^ 1)))
|
unsigned long cache_start = llog2(bitmap_word_size);
|
||||||
|
while (page_map.bitmap[bitmap_index] & ((unsigned long)1 << (bitmap_offset ^ 1)))
|
||||||
{
|
{
|
||||||
page_map.bitmap[bitmap_index] &= ~(1 << bitmap_offset);
|
unsigned long depth = llog2(index + 1) - 1;
|
||||||
page_map.bitmap[bitmap_index] &= ~(1 << (bitmap_offset ^ 1));
|
if(page_map.cache[depth - cache_start] == (index ^ 1))
|
||||||
|
{
|
||||||
|
page_map.cache[depth - cache_start] = ENOMEM;
|
||||||
|
}
|
||||||
|
page_map.bitmap[bitmap_index] &= ~((unsigned long)1 << bitmap_offset);
|
||||||
|
page_map.bitmap[bitmap_index] &= ~((unsigned long)1 << (bitmap_offset ^ 1));
|
||||||
index /= 2;
|
index /= 2;
|
||||||
bitmap_index = index / bitmap_word_size;
|
bitmap_index = index / bitmap_word_size;
|
||||||
bitmap_offset = index % bitmap_word_size;
|
bitmap_offset = index % bitmap_word_size;
|
||||||
page_map.bitmap[bitmap_index] |= 1 << bitmap_offset;
|
page_map.bitmap[bitmap_index] |= (unsigned long)1 << bitmap_offset;
|
||||||
|
}
|
||||||
|
unsigned long depth = llog2(index + 1) - 1;
|
||||||
|
if (depth >= cache_start && page_map.cache[depth - cache_start] == 0)
|
||||||
|
{
|
||||||
|
page_map.cache[depth - cache_start] = index;
|
||||||
}
|
}
|
||||||
return ENONE;
|
return ENONE;
|
||||||
}
|
}
|
||||||
@@ -157,9 +193,11 @@ void *page_map_end()
|
|||||||
|
|
||||||
enum error_t initialize_page_map(struct memory_map_t *map, void *base, size_t memory_size, unsigned long block_size)
|
enum error_t initialize_page_map(struct memory_map_t *map, void *base, size_t memory_size, unsigned long block_size)
|
||||||
{
|
{
|
||||||
|
static unsigned long page_map_cache[MAX_CACHE_SIZE];
|
||||||
// Round memory_size up to nearest power of 2
|
// Round memory_size up to nearest power of 2
|
||||||
memory_size = 1 << llog2(memory_size);
|
memory_size = 1 << llog2(memory_size);
|
||||||
page_map.bitmap = (unsigned long*) base;
|
page_map.bitmap = (unsigned long*) base;
|
||||||
|
page_map.cache = page_map_cache;
|
||||||
page_map.bitmap_size = (memory_size / page_size) / 4;
|
page_map.bitmap_size = (memory_size / page_size) / 4;
|
||||||
page_map.block_size = block_size;
|
page_map.block_size = block_size;
|
||||||
page_map.height = llog2(memory_size / block_size);
|
page_map.height = llog2(memory_size / block_size);
|
||||||
@@ -229,6 +267,10 @@ enum error_t initialize_page_map(struct memory_map_t *map, void *base, size_t me
|
|||||||
location += chunk_size;
|
location += chunk_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for(int i = 0; i < MAX_CACHE_SIZE; i++)
|
||||||
|
{
|
||||||
|
page_map.cache[i] = 0;
|
||||||
|
}
|
||||||
return ENONE;
|
return ENONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user