Variable block descriptor size in bitmap_alloc
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -17,3 +17,4 @@ autom4te.cache
|
|||||||
include/config.h*
|
include/config.h*
|
||||||
missing
|
missing
|
||||||
stamp-h1
|
stamp-h1
|
||||||
|
tests/test_bitmapalloc
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
* @brief
|
* @brief
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
typedef struct
|
typedef struct bitmap_heap_descriptor_t
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @brief The underlying bitmap representing the availability of chunks of
|
* @brief The underlying bitmap representing the availability of chunks of
|
||||||
@@ -60,6 +60,42 @@ typedef struct
|
|||||||
*/
|
*/
|
||||||
unsigned long free_block_count;
|
unsigned long free_block_count;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Bitmask used to isolate only those bits which indicate the
|
||||||
|
* availability of a block. Useful when several bits are used to represent
|
||||||
|
* the state of a single block. See `block_bits`.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
unsigned long mask;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The number of bits required to represent the state of each block.
|
||||||
|
*
|
||||||
|
* If the value is greater than 1, the most significant bit describing each
|
||||||
|
* block shall indicate its availability. Less significant bits shall
|
||||||
|
* represent other aspects of the block's state. The number of trailing
|
||||||
|
* zeroes in `mask` shall be used to calculate this quantity.
|
||||||
|
*
|
||||||
|
* This qualtity is assumed to be a power of 2, and less than or equal to
|
||||||
|
* the number of bits in an unsigned long. Therefore, acceptable values for
|
||||||
|
* this quantity are as follows: 1, 2, 4, 8, 16, 32[, 64].
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
unsigned long block_bits;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The number of blocks described by a single unsigned long contained
|
||||||
|
* in `bitmap`. Equal to (8 * sizeof(unsigned long)) / block_bits.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
unsigned long blocks_in_word;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Memory will be allocated relative to this location.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
unsigned long offset;
|
||||||
|
|
||||||
} bitmap_heap_descriptor_t;
|
} bitmap_heap_descriptor_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -73,7 +109,8 @@ typedef struct
|
|||||||
* @param size
|
* @param size
|
||||||
* @return unsigned long
|
* @return unsigned long
|
||||||
*/
|
*/
|
||||||
unsigned long reserve_region(bitmap_heap_descriptor_t *heap, unsigned long size);
|
unsigned long reserve_region(bitmap_heap_descriptor_t *heap,
|
||||||
|
unsigned long size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Marks the region of memory indicated by `location` and `size` as
|
* @brief Marks the region of memory indicated by `location` and `size` as
|
||||||
@@ -97,13 +134,12 @@ void free_region(bitmap_heap_descriptor_t *heap, unsigned long location,
|
|||||||
* @param block_size The minimum unit of allocation
|
* @param block_size The minimum unit of allocation
|
||||||
* @return unsigned long
|
* @return unsigned long
|
||||||
*/
|
*/
|
||||||
unsigned long bitmap_size(const memory_map_t *map, unsigned long block_size);
|
unsigned long bitmap_size(const memory_map_t *map, unsigned long block_size, unsigned long block_bits);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Builds the heap's internal structures according to the memory
|
* @brief Builds the heap's internal structures according to the memory
|
||||||
* layout provided in `map`. Assumes that the layout in `map` refers to the
|
* layout provided in `map`. All locations in `map` are relative to the `offset`
|
||||||
* caller's virtual address space, and utilizes some of the memory marked as
|
* field in `heap`.
|
||||||
* 'available' to store the heap's internal structures.
|
|
||||||
*
|
*
|
||||||
* A callback function `mmap` may be provided, which will be used to map the
|
* A callback function `mmap` may be provided, which will be used to map the
|
||||||
* space required by the heap to store its internal bitmaps. If `mmap` is NULL,
|
* space required by the heap to store its internal bitmaps. If `mmap` is NULL,
|
||||||
@@ -111,43 +147,34 @@ unsigned long bitmap_size(const memory_map_t *map, unsigned long block_size);
|
|||||||
*
|
*
|
||||||
* There are several requirements for the initial state of the `heap` structure:
|
* There are several requirements for the initial state of the `heap` structure:
|
||||||
*
|
*
|
||||||
* - The `cache` field must be defined, and point to an array of unsigned longs
|
* - The `bitmap` field may point to a pre-allocated region of memory which will
|
||||||
* of sufficient size.
|
* be used to store the heap's internal bitmap. If this field is NULL, part of
|
||||||
|
* the heap will be used to store the bitmap, and `mmap`, if not NULL, will be
|
||||||
|
* called to map that region of memory.
|
||||||
*
|
*
|
||||||
* - The `block_size` field must be set to the desired smallest unit of allocation.
|
* - The `cache` field may point to an array of unsigned longs of sufficient
|
||||||
*
|
* size, which will be used to speed up memory allocation. If this field is
|
||||||
* @param heap A pointer to the structure describing the heap
|
* NULL, caching will not be performed.
|
||||||
* @param map A pointer to the structure providing an initial memory layout
|
|
||||||
* @param mmap A callback function used to map memory in the virtual address space
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
int initialize_virtual_heap(bitmap_heap_descriptor_t *heap, const memory_map_t *map,
|
|
||||||
int (*mmap)(void *location, unsigned long size));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Builds the heap's internal structures according to the memory
|
|
||||||
* layout provided in `map`. Assumes that physical memory space is being alocated,
|
|
||||||
* and therefore does not make assumptions about the caller's address space or
|
|
||||||
* attempt to utilize the memory inside the heap. The caller is responsible for
|
|
||||||
* providing space to store the heap's internal structures.
|
|
||||||
*
|
|
||||||
* There are several requirements for the initial state of the `heap` structure:
|
|
||||||
*
|
|
||||||
* - The `bitmap` field must be defined, and sufficient memory reserved at that
|
|
||||||
* location to contain the heap's bitmap.
|
|
||||||
*
|
|
||||||
* - The `cache` field must be defined, and point to an array of unsigned longs
|
|
||||||
* of sufficient size.
|
|
||||||
*
|
*
|
||||||
* - The `cache_capacity` field must be set to the size of the array pointed to
|
* - The `cache_capacity` field must be set to the size of the array pointed to
|
||||||
* by `cache`
|
* by `cache`.
|
||||||
*
|
*
|
||||||
* - The `block_size` field must be set to the desired smallest unit of allocation.
|
* - The `block_size` field must be set to the desired smallest unit of
|
||||||
|
* allocation.
|
||||||
|
*
|
||||||
|
* - The `block_bits` field must be set to the number of bits required to store
|
||||||
|
* a block's metadata.
|
||||||
|
*
|
||||||
|
* - The `offset` field must be set to the first location to allocate memory
|
||||||
|
* from. Locations in `map` will be interpreted as relative to `offset`.
|
||||||
*
|
*
|
||||||
* @param heap A pointer to the structure describing the heap
|
* @param heap A pointer to the structure describing the heap
|
||||||
* @param map A pointer to the structure providing an initial memory layout
|
* @param map A pointer to the structure providing an initial memory layout
|
||||||
* @return int 0 upon success; nonzero upon failure
|
* @param mmap A callback function used to map memory in the virtual address
|
||||||
|
* space
|
||||||
|
* @return int 0 upon success, nonzero upon failure.
|
||||||
*/
|
*/
|
||||||
int initialize_physical_heap(bitmap_heap_descriptor_t *heap, const memory_map_t *map);
|
int initialize_heap(bitmap_heap_descriptor_t *heap, memory_map_t *map,
|
||||||
|
int (*mmap)(void *location, unsigned long size));
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -8,6 +8,6 @@
|
|||||||
* NOMEM shall be returned by any malloc-like function upon failure, rather than
|
* NOMEM shall be returned by any malloc-like function upon failure, rather than
|
||||||
* NULL.
|
* NULL.
|
||||||
*/
|
*/
|
||||||
#define NOMEM ~0
|
#define NOMEM ((unsigned long)~0)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -2,17 +2,19 @@
|
|||||||
#include "libmalloc/common.h"
|
#include "libmalloc/common.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
/*
|
static const int BIT_AVAIL = 0;
|
||||||
* The number of bits contained in a single integer inside the heap's bitmap.
|
static const int BIT_USED = 1;
|
||||||
* Should be either 32 or 64 depending on the host machine.
|
|
||||||
*/
|
|
||||||
static const int bitmap_word_size = 8 * sizeof(unsigned long);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sets all elements in the cache's underlying array to 0.
|
* Sets all elements in the cache's underlying array to 0.
|
||||||
*/
|
*/
|
||||||
static inline void clear_cache(bitmap_heap_descriptor_t *heap)
|
static inline void clear_cache(bitmap_heap_descriptor_t *heap)
|
||||||
{
|
{
|
||||||
|
if(heap->cache == (unsigned long*)0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for(int i = 0; i < heap->cache_capacity; i++)
|
for(int i = 0; i < heap->cache_capacity; i++)
|
||||||
{
|
{
|
||||||
heap->cache[i] = 0;
|
heap->cache[i] = 0;
|
||||||
@@ -34,22 +36,48 @@ static inline void clear_bitmap(bitmap_heap_descriptor_t *heap)
|
|||||||
* Sets bit `index` in the heap's bitmap, marking the underlying block as
|
* Sets bit `index` in the heap's bitmap, marking the underlying block as
|
||||||
* available.
|
* available.
|
||||||
*/
|
*/
|
||||||
static inline void set_bit(bitmap_heap_descriptor_t *heap, int index)
|
static inline void set_bit(bitmap_heap_descriptor_t *heap, int index, int bit)
|
||||||
{
|
{
|
||||||
int bitmap_index = index / bitmap_word_size;
|
if(bit < heap->block_bits)
|
||||||
int bitmap_offset = index % bitmap_word_size;
|
{
|
||||||
heap->bitmap[bitmap_index] |= (unsigned long)1 << bitmap_offset;
|
int bitmap_index = index / heap->blocks_in_word;
|
||||||
|
int bitmap_offset = index % heap->blocks_in_word;
|
||||||
|
unsigned long mask = (unsigned long)1 << (heap->block_bits * (bitmap_offset + 1) - 1 - bit);
|
||||||
|
heap->bitmap[bitmap_index] |= mask;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clears bit `index` in the heap's bitmap, marking the underlying block as
|
* Clears bit `index` in the heap's bitmap, marking the underlying block as
|
||||||
* reserved.
|
* reserved.
|
||||||
*/
|
*/
|
||||||
static inline void clear_bit(bitmap_heap_descriptor_t *heap, int index)
|
static inline void clear_bit(bitmap_heap_descriptor_t *heap, int index, int bit)
|
||||||
{
|
{
|
||||||
int bitmap_index = index / bitmap_word_size;
|
if(bit < heap->block_bits)
|
||||||
int bitmap_offset = index % bitmap_word_size;
|
{
|
||||||
heap->bitmap[bitmap_index] &= ~((unsigned long)1 << bitmap_offset);
|
int bitmap_index = index / heap->blocks_in_word;
|
||||||
|
int bitmap_offset = index % heap->blocks_in_word;
|
||||||
|
unsigned long mask = ~((unsigned long)1
|
||||||
|
<< (heap->block_bits * (bitmap_offset + 1) - 1 - bit));
|
||||||
|
heap->bitmap[bitmap_index] &= mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tests whether the block at bit `index` is available. If so, returns nonzero,
|
||||||
|
* else returns 0.
|
||||||
|
*/
|
||||||
|
static inline int test_bit(bitmap_heap_descriptor_t *heap, int index, int bit)
|
||||||
|
{
|
||||||
|
if(bit > (heap->block_bits - 1))
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
unsigned long mask = ((unsigned long)1
|
||||||
|
<< (heap->block_bits * ((index % heap->blocks_in_word) + 1)
|
||||||
|
- 1
|
||||||
|
- bit));
|
||||||
|
return (heap->bitmap[index / heap->blocks_in_word] & mask) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -57,33 +85,57 @@ static inline void clear_bit(bitmap_heap_descriptor_t *heap, int index)
|
|||||||
* blocks as available. Operation is used while spltting a block to reserve one
|
* blocks as available. Operation is used while spltting a block to reserve one
|
||||||
* of its child blocks.
|
* of its child blocks.
|
||||||
*/
|
*/
|
||||||
static inline void set_pair(bitmap_heap_descriptor_t *heap, int index)
|
static inline void set_pair(bitmap_heap_descriptor_t *heap, int index, int bit)
|
||||||
{
|
{
|
||||||
int bitmap_index = index / bitmap_word_size;
|
if(bit < heap->block_bits)
|
||||||
int bitmap_offset = index % bitmap_word_size;
|
{
|
||||||
heap->bitmap[bitmap_index] |= (unsigned long)1 << bitmap_offset;
|
int bitmap_index = index / heap->blocks_in_word;
|
||||||
heap->bitmap[bitmap_index] |= (unsigned long)1 << (bitmap_offset ^ 1);
|
int bitmap_offset = index % heap->blocks_in_word;
|
||||||
|
|
||||||
|
unsigned long mask_a = (unsigned long)1 << (heap->block_bits * (bitmap_offset + 1) - 1 - bit);
|
||||||
|
unsigned long mask_b = (unsigned long)1 << (heap->block_bits * ((bitmap_offset ^ 1) + 1) - 1 - bit);
|
||||||
|
|
||||||
|
heap->bitmap[bitmap_index] |= mask_a;
|
||||||
|
heap->bitmap[bitmap_index] |= mask_b;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clears bit `index` and its buddy in the heap's bitmap, marking the underlying
|
* Clears bit `index` and its buddy in the heap's bitmap, marking the underlying
|
||||||
* blocks as reserved. Used when merging two child blocks into a single parent block.
|
* blocks as reserved. Used when merging two child blocks into a single parent
|
||||||
|
* block.
|
||||||
*/
|
*/
|
||||||
static inline void clear_pair(bitmap_heap_descriptor_t *heap, int index)
|
static inline void clear_pair(bitmap_heap_descriptor_t *heap, int index, int bit)
|
||||||
{
|
{
|
||||||
int bitmap_index = index / bitmap_word_size;
|
if(bit < heap->block_bits)
|
||||||
int bitmap_offset = index % bitmap_word_size;
|
{
|
||||||
heap->bitmap[bitmap_index] &= ~((unsigned long)1 << bitmap_offset);
|
int bitmap_index = index / heap->blocks_in_word;
|
||||||
heap->bitmap[bitmap_index] &= ~((unsigned long)1 << (bitmap_offset ^ 1));
|
int bitmap_offset = index % heap->blocks_in_word;
|
||||||
|
|
||||||
|
unsigned long mask_a = ~((unsigned long)1 << (heap->block_bits * (bitmap_offset + 1) - 1 - bit));
|
||||||
|
unsigned long mask_b = ~((unsigned long)1 << (heap->block_bits * ((bitmap_offset ^ 1) + 1) - 1 - bit));
|
||||||
|
|
||||||
|
heap->bitmap[bitmap_index] &= mask_a;
|
||||||
|
heap->bitmap[bitmap_index] &= mask_b;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Computes the location in the cache that `index` would be stored at, if it
|
* Computes the location in the cache that `index` would be stored at, if it
|
||||||
* were cached.
|
* were cached.
|
||||||
*/
|
*/
|
||||||
static inline int cache_location_from_index(int index)
|
static inline int cache_location_from_index(bitmap_heap_descriptor_t *heap, int index)
|
||||||
{
|
{
|
||||||
return llog2(index + 1) - llog2(bitmap_word_size) - 1;
|
return llog2(index + 1) - llog2(heap->blocks_in_word) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Computes the location in the cache that blocks at the indicated height are
|
||||||
|
* cached at.
|
||||||
|
*/
|
||||||
|
static inline int cache_location_from_height(bitmap_heap_descriptor_t *heap, int height)
|
||||||
|
{
|
||||||
|
return heap->height - height - llog2(heap->blocks_in_word);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -92,9 +144,17 @@ static inline int cache_location_from_index(int index)
|
|||||||
*/
|
*/
|
||||||
static inline int check_cache(bitmap_heap_descriptor_t *heap, int height)
|
static inline int check_cache(bitmap_heap_descriptor_t *heap, int height)
|
||||||
{
|
{
|
||||||
unsigned long n = heap->cache[heap->height - height - llog2(bitmap_word_size)];
|
if(heap->cache != (unsigned long*)0)
|
||||||
heap->cache[heap->height - height - llog2(bitmap_word_size)] = 0;
|
{
|
||||||
|
int loc = cache_location_from_height(heap, height);
|
||||||
|
unsigned long n = heap->cache[loc];
|
||||||
|
heap->cache[loc] = 0;
|
||||||
return n;
|
return n;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -103,11 +163,18 @@ static inline int check_cache(bitmap_heap_descriptor_t *heap, int height)
|
|||||||
*/
|
*/
|
||||||
static inline void store_cache(bitmap_heap_descriptor_t *heap, int index)
|
static inline void store_cache(bitmap_heap_descriptor_t *heap, int index)
|
||||||
{
|
{
|
||||||
int level = cache_location_from_index(index);
|
if(heap->cache != (unsigned long*)0)
|
||||||
|
{
|
||||||
|
int level = cache_location_from_index(heap, index);
|
||||||
if(level >= 0 && heap->cache[level] == 0)
|
if(level >= 0 && heap->cache[level] == 0)
|
||||||
{
|
{
|
||||||
heap->cache[level] = index;
|
heap->cache[level] = index;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -116,11 +183,18 @@ static inline void store_cache(bitmap_heap_descriptor_t *heap, int index)
|
|||||||
*/
|
*/
|
||||||
static inline void uncache(bitmap_heap_descriptor_t *heap, int index)
|
static inline void uncache(bitmap_heap_descriptor_t *heap, int index)
|
||||||
{
|
{
|
||||||
int level = cache_location_from_index(index);
|
if(heap->cache != (unsigned long*)0)
|
||||||
|
{
|
||||||
|
int level = cache_location_from_index(heap, index);
|
||||||
if(level >= 0 && heap->cache[level] == index)
|
if(level >= 0 && heap->cache[level] == index)
|
||||||
{
|
{
|
||||||
heap->cache[level] = 0;
|
heap->cache[level] = 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -133,9 +207,9 @@ static inline int split_block(bitmap_heap_descriptor_t *heap, int index)
|
|||||||
{
|
{
|
||||||
if(index)
|
if(index)
|
||||||
{
|
{
|
||||||
clear_bit(heap, index);
|
clear_bit(heap, index, BIT_AVAIL);
|
||||||
index *= 2;
|
index *= 2;
|
||||||
set_pair(heap, index);
|
set_pair(heap, index, BIT_AVAIL);
|
||||||
store_cache(heap, index + 1);
|
store_cache(heap, index + 1);
|
||||||
}
|
}
|
||||||
return index;
|
return index;
|
||||||
@@ -152,12 +226,12 @@ static inline int split_block(bitmap_heap_descriptor_t *heap, int index)
|
|||||||
*/
|
*/
|
||||||
static int merge_block(bitmap_heap_descriptor_t *heap, int index)
|
static int merge_block(bitmap_heap_descriptor_t *heap, int index)
|
||||||
{
|
{
|
||||||
while(index > 1 && (heap->bitmap[index / bitmap_word_size] & ((unsigned long)1 << ((index % bitmap_word_size) ^ 1))))
|
while(index > 1 && test_bit(heap, index ^ 1, BIT_AVAIL))
|
||||||
{
|
{
|
||||||
uncache(heap, index ^ 1);
|
uncache(heap, index ^ 1);
|
||||||
clear_pair(heap, index);
|
clear_pair(heap, index, BIT_AVAIL);
|
||||||
index /= 2;
|
index /= 2;
|
||||||
set_bit(heap, index);
|
set_bit(heap, index, BIT_AVAIL);
|
||||||
}
|
}
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
@@ -174,20 +248,21 @@ static int find_free_region(bitmap_heap_descriptor_t *heap, int height)
|
|||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (height <= heap->height - ilog2(bitmap_word_size))
|
else if (height <= heap->height - ilog2(heap->blocks_in_word))
|
||||||
{
|
{
|
||||||
unsigned long cached_index = check_cache(heap, height);
|
unsigned long cached_index = check_cache(heap, height);
|
||||||
if(cached_index)
|
if(cached_index)
|
||||||
{
|
{
|
||||||
return cached_index;
|
return cached_index;
|
||||||
}
|
}
|
||||||
unsigned long start = (1 << (heap->height - height)) / bitmap_word_size;
|
unsigned long start = (1 << (heap->height - height)) / heap->blocks_in_word;
|
||||||
unsigned long end = ((1 << (heap->height - height + 1)) / bitmap_word_size);
|
unsigned long end = ((1 << (heap->height - height + 1)) / heap->blocks_in_word);
|
||||||
for (int index = start; index < end; index++)
|
for (int index = start; index < end; index++)
|
||||||
{
|
{
|
||||||
if (heap->bitmap[index] != 0)
|
unsigned long avail_mask = heap->bitmap[index] & heap->mask;
|
||||||
|
if (avail_mask != 0)
|
||||||
{
|
{
|
||||||
return bitmap_word_size * index + __builtin_ctzl(heap->bitmap[index]);
|
return heap->blocks_in_word * index + (__builtin_ctzl(avail_mask) / heap->block_bits);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -198,25 +273,144 @@ static int find_free_region(bitmap_heap_descriptor_t *heap, int height)
|
|||||||
#else
|
#else
|
||||||
static const unsigned long bitmasks[] = {0x00000002, 0x0000000C, 0x000000F0, 0x0000FF00, 0xFFFF0000};
|
static const unsigned long bitmasks[] = {0x00000002, 0x0000000C, 0x000000F0, 0x0000FF00, 0xFFFF0000};
|
||||||
#endif
|
#endif
|
||||||
int depth = heap->height - height;
|
int bitmask_index = heap->height - height + llog2(heap->block_bits);
|
||||||
if (heap->bitmap[0] & bitmasks[depth])
|
if (heap->bitmap[0] & bitmasks[bitmask_index] & heap->mask)
|
||||||
{
|
{
|
||||||
return __builtin_ctzl(heap->bitmap[0] & bitmasks[depth]);
|
return __builtin_ctzl(heap->bitmap[0] & bitmasks[bitmask_index] & heap->mask) / heap->block_bits;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return split_block(heap, find_free_region(heap, height + 1));
|
return split_block(heap, find_free_region(heap, height + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned long compute_memory_size(const memory_map_t *map)
|
||||||
|
{
|
||||||
|
// Find the last available region in the memory map.
|
||||||
|
int map_index = map->size - 1;
|
||||||
|
while(map->array[map_index].type != M_AVAILABLE)
|
||||||
|
{
|
||||||
|
map_index--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return map->array[map_index].location + map->array[map_index].size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned long generate_mask(unsigned long block_bits)
|
||||||
|
{
|
||||||
|
unsigned long blocks_in_word = 8 * sizeof(unsigned long) / block_bits;
|
||||||
|
unsigned long mask = 0;
|
||||||
|
for(unsigned long i = 1; i <= blocks_in_word; i++)
|
||||||
|
{
|
||||||
|
mask |= 1UL << (i * block_bits - 1UL);
|
||||||
|
}
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int construct_heap_desc(bitmap_heap_descriptor_t *heap, const memory_map_t *map)
|
||||||
|
{
|
||||||
|
if(heap->block_bits == 0 || heap->block_bits > (8 * sizeof(*heap->bitmap)))
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if(heap->block_size == 0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if((1 << llog2(heap->block_bits)) != heap->block_bits)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long memory_size = compute_memory_size(map);
|
||||||
|
heap->blocks_in_word = 8 * sizeof(*heap->bitmap) / heap->block_bits;
|
||||||
|
heap->bitmap_size = heap->block_bits * (memory_size / heap->block_size) / 4;
|
||||||
|
heap->bitmap_size = 1 << llog2(heap->bitmap_size);
|
||||||
|
heap->height = llog2(memory_size / heap->block_size);
|
||||||
|
heap->free_block_count = 0;
|
||||||
|
heap->mask = generate_mask(heap->block_bits);
|
||||||
|
|
||||||
|
if(heap->bitmap_size <= sizeof(*heap->bitmap))
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if(heap->bitmap_size >= memory_size && heap->bitmap == (unsigned long*)0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void initialize_bitmap(bitmap_heap_descriptor_t *heap, const memory_map_t *map)
|
||||||
|
{
|
||||||
|
clear_bitmap(heap);
|
||||||
|
for(int i = 0; i < map->size; i++)
|
||||||
|
{
|
||||||
|
if(map->array[i].type != M_AVAILABLE)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long location = (map->array[i].location + heap->block_size - 1);// & ~(heap->block_size - 1);
|
||||||
|
location -= location % heap->block_size;
|
||||||
|
unsigned long region_end = map->array[i].location + map->array[i].size;
|
||||||
|
|
||||||
|
while(location + heap->block_size <= region_end)
|
||||||
|
{
|
||||||
|
int bit_offset = (location / heap->block_size) % heap->blocks_in_word;
|
||||||
|
int bitmap_index = ((1UL << (heap->height - 0)) / heap->blocks_in_word) + (location / heap->block_size) / heap->blocks_in_word;
|
||||||
|
unsigned long chunk_size = (heap->blocks_in_word - bit_offset) * heap->block_size;
|
||||||
|
if(bit_offset == 0 && (region_end - location) >= chunk_size)
|
||||||
|
{
|
||||||
|
// Set all bits in the word
|
||||||
|
heap->bitmap[bitmap_index] = heap->mask & ~0;
|
||||||
|
heap->free_block_count += heap->blocks_in_word;
|
||||||
|
}
|
||||||
|
else if(bit_offset == 0)
|
||||||
|
{
|
||||||
|
// Set the first 'count' bits
|
||||||
|
int count = (region_end - location) / heap->block_size;
|
||||||
|
heap->bitmap[bitmap_index] |= heap->mask & ((1UL << (heap->block_bits * count)) - 1);
|
||||||
|
heap->free_block_count += count;
|
||||||
|
}
|
||||||
|
else if((region_end - location) >= chunk_size)
|
||||||
|
{
|
||||||
|
// Set all bits starting at 'bit_offset'
|
||||||
|
heap->bitmap[bitmap_index] |= heap->mask & ~((1UL << (heap->block_bits * bit_offset)) - 1);
|
||||||
|
heap->free_block_count += heap->blocks_in_word - bit_offset;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Set all bits starting at 'bit_offset' up to 'count'
|
||||||
|
int count = (region_end - location) / heap->block_size;
|
||||||
|
heap->bitmap[bitmap_index] |= heap->mask & ((1UL << (heap->block_bits * count)) - 1) & ~((1UL << (heap->block_bits * bit_offset)) - 1);
|
||||||
|
heap->free_block_count += count - bit_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge 'buddies' when both available
|
||||||
|
unsigned long mask = ((1UL << (2 * heap->block_bits)) - 1) & heap->mask;
|
||||||
|
for(int j = 0; j < heap->blocks_in_word / 2; j++)
|
||||||
|
{
|
||||||
|
if((heap->bitmap[bitmap_index] & mask) == mask)
|
||||||
|
{
|
||||||
|
merge_block(heap, bitmap_index * heap->blocks_in_word + j * 2);
|
||||||
|
}
|
||||||
|
mask <<= 2 * heap->block_bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
location += chunk_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsigned long reserve_region(bitmap_heap_descriptor_t *heap, unsigned long size)
|
unsigned long reserve_region(bitmap_heap_descriptor_t *heap, unsigned long size)
|
||||||
{
|
{
|
||||||
int height = llog2(size / heap->block_size);
|
int height = llog2((size - 1) / heap->block_size + 1);
|
||||||
int index = find_free_region(heap, height);
|
int index = find_free_region(heap, height);
|
||||||
if(index)
|
if(index)
|
||||||
{
|
{
|
||||||
clear_bit(heap, index);
|
clear_bit(heap, index, BIT_AVAIL);
|
||||||
|
set_bit(heap, index, BIT_USED);
|
||||||
heap->free_block_count -= 1 << height;
|
heap->free_block_count -= 1 << height;
|
||||||
return (heap->block_size << height) * (index - ((unsigned long)1 << (heap->height - height)));
|
return heap->offset + (heap->block_size << height) * (index - ((unsigned long)1 << (heap->height - height)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -226,107 +420,54 @@ unsigned long reserve_region(bitmap_heap_descriptor_t *heap, unsigned long size)
|
|||||||
|
|
||||||
void free_region(bitmap_heap_descriptor_t *heap, unsigned long location, unsigned long size)
|
void free_region(bitmap_heap_descriptor_t *heap, unsigned long location, unsigned long size)
|
||||||
{
|
{
|
||||||
|
location -= heap->offset;
|
||||||
int height = llog2(size / heap->block_size);
|
int height = llog2(size / heap->block_size);
|
||||||
int index = (location / (heap->block_size * ((unsigned long)1 << height))) + (1 << (heap->height - height));
|
int index = (location / (heap->block_size * ((unsigned long)1 << height))) + (1 << (heap->height - height));
|
||||||
set_bit(heap, index);
|
while(!test_bit(heap, index, BIT_USED))
|
||||||
|
{
|
||||||
|
height++;
|
||||||
|
index /= 2;
|
||||||
|
}
|
||||||
|
set_bit(heap, index, BIT_AVAIL);
|
||||||
|
clear_bit(heap, index, BIT_USED);
|
||||||
index = merge_block(heap, index);
|
index = merge_block(heap, index);
|
||||||
store_cache(heap, index);
|
store_cache(heap, index);
|
||||||
heap->free_block_count += 1 << height;
|
heap->free_block_count += 1 << height;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long bitmap_size(const memory_map_t *map, unsigned long block_size)
|
unsigned long bitmap_size(const memory_map_t *map, unsigned long block_size, unsigned long block_bits)
|
||||||
{
|
{
|
||||||
// Find the last available region in the memory map.
|
return 1UL << llog2((block_bits * compute_memory_size(map) / block_size) / 4);
|
||||||
int map_index = map->size - 1;
|
|
||||||
while(map->array[map_index].type != M_AVAILABLE)
|
|
||||||
{
|
|
||||||
map_index--;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Take memory_size to be the last available location in the memory map.
|
|
||||||
// Round memory_size up to nearest power of 2
|
|
||||||
unsigned long memory_size = 1 << llog2(map->array[map_index].location + map->array[map_index].size);
|
|
||||||
return (memory_size / block_size) / 4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int initialize_virtual_heap(bitmap_heap_descriptor_t *heap, const memory_map_t *map, int (*mmap)(void *location, unsigned long size))
|
int initialize_heap(bitmap_heap_descriptor_t *heap, memory_map_t *map, int (*mmap)(void *location, unsigned long size))
|
||||||
{
|
{
|
||||||
/* Not yet implemented */
|
if(construct_heap_desc(heap, map))
|
||||||
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
int initialize_physical_heap(bitmap_heap_descriptor_t *heap, const memory_map_t *map)
|
|
||||||
{
|
|
||||||
// Find the last available region in the memory map.
|
|
||||||
int map_index = map->size - 1;
|
|
||||||
while(map->array[map_index].type != M_AVAILABLE)
|
|
||||||
{
|
|
||||||
map_index--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Take memory_size to be the last available location in the memory map.
|
if(heap->bitmap == (unsigned long*)0)
|
||||||
// Round memory_size up to nearest power of 2
|
|
||||||
unsigned long memory_size = 1 << llog2(map->array[map_index].location + map->array[map_index].size);
|
|
||||||
heap->bitmap_size = (memory_size / heap->block_size) / 4;
|
|
||||||
heap->height = llog2(memory_size / heap->block_size);
|
|
||||||
heap->free_block_count = 0;
|
|
||||||
clear_bitmap(heap);
|
|
||||||
for(int i = 0; i < map->size; i++)
|
|
||||||
{
|
{
|
||||||
if(map->array[i].type != M_AVAILABLE)
|
int map_index = 0;
|
||||||
|
while(map->array[map_index].size < heap->bitmap_size)
|
||||||
{
|
{
|
||||||
continue;
|
map_index++;
|
||||||
|
if(map_index >= map->size)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long location = (map->array[i].location + heap->block_size - 1) & ~(heap->block_size - 1);
|
heap->bitmap = (unsigned long*)(heap->offset + map->array[map_index].location);
|
||||||
unsigned long region_end = map->array[i].location + map->array[i].size;
|
memmap_insert_region(map, map->array[map_index].location, heap->bitmap_size, M_UNAVAILABLE);
|
||||||
|
if(mmap && mmap(heap->bitmap, heap->bitmap_size))
|
||||||
while(location + heap->block_size <= region_end)
|
|
||||||
{
|
{
|
||||||
int bit_offset = (location / heap->block_size) % bitmap_word_size;
|
return -1;
|
||||||
int bitmap_index = ((1 << (heap->height - 0)) / bitmap_word_size) + (location / heap->block_size) / bitmap_word_size;
|
|
||||||
unsigned long chunk_size = (bitmap_word_size - bit_offset) * heap->block_size;
|
|
||||||
if(bit_offset == 0 && (region_end - location) >= chunk_size)
|
|
||||||
{
|
|
||||||
// Set all bits in the word
|
|
||||||
heap->bitmap[bitmap_index] = ~0;
|
|
||||||
heap->free_block_count += bitmap_word_size;
|
|
||||||
}
|
}
|
||||||
else if(bit_offset == 0)
|
|
||||||
{
|
|
||||||
// Set the first 'count' bits
|
|
||||||
int count = (region_end - location) / heap->block_size;
|
|
||||||
heap->bitmap[bitmap_index] |= (1 << count) - 1;
|
|
||||||
heap->free_block_count += count;
|
|
||||||
}
|
|
||||||
else if((region_end - location) >= chunk_size)
|
|
||||||
{
|
|
||||||
// Set all bits starting at 'bit_offset'
|
|
||||||
heap->bitmap[bitmap_index] |= ~((1 << bit_offset) - 1);
|
|
||||||
heap->free_block_count += bitmap_word_size - bit_offset;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Set all bits starting at 'bit_offset' up to 'count'
|
|
||||||
int count = (region_end - location) / heap->block_size;
|
|
||||||
heap->bitmap[bitmap_index] |= ((1 << count) - 1) & ~((1 << bit_offset) - 1);
|
|
||||||
heap->free_block_count += count - bit_offset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge 'buddies' when both available
|
initialize_bitmap(heap, map);
|
||||||
unsigned long mask = 3;
|
|
||||||
for(int j = 0; j < bitmap_word_size / 2; j++)
|
|
||||||
{
|
|
||||||
if((heap->bitmap[bitmap_index] & mask) == mask)
|
|
||||||
{
|
|
||||||
merge_block(heap, bitmap_index * bitmap_word_size + j * 2);
|
|
||||||
}
|
|
||||||
mask <<= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
location += chunk_size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
clear_cache(heap);
|
clear_cache(heap);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
if BUILD_TESTS
|
if BUILD_TESTS
|
||||||
noinst_PROGRAMS = test_buddyalloc
|
noinst_PROGRAMS = test_bitmapalloc
|
||||||
|
|
||||||
test_buddyalloc_SOURCES = test_buddyalloc.c
|
test_bitmapalloc_SOURCES = test_bitmapalloc.c
|
||||||
test_buddyalloc_LDADD = ../src/libmalloc.a
|
test_bitmapalloc_LDADD = ../src/libmalloc.a
|
||||||
endif
|
endif
|
||||||
160
tests/test_bitmapalloc.c
Normal file
160
tests/test_bitmapalloc.c
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
#include "libmalloc/bitmap_alloc.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
typedef struct memblock_t
|
||||||
|
{
|
||||||
|
unsigned long size;
|
||||||
|
unsigned long location;
|
||||||
|
} memblock_t;
|
||||||
|
|
||||||
|
void print_heap_desc(bitmap_heap_descriptor_t *heap)
|
||||||
|
{
|
||||||
|
printf("heap = {\n"
|
||||||
|
"\t.bitmap = %p\n"
|
||||||
|
"\t.bitmap_size = %i\n"
|
||||||
|
"\t.cache = %p\n"
|
||||||
|
"\t.cache_capacity = %i\n"
|
||||||
|
"\t.block_size = %i\n"
|
||||||
|
"\t.height = %i\n"
|
||||||
|
"\t.free_block_count = %i\n"
|
||||||
|
"\t.mask = %lX\n"
|
||||||
|
"\t.block_bits = %i\n"
|
||||||
|
"\t.blocks_in_word = %i\n"
|
||||||
|
"\t.offset = %p\n"
|
||||||
|
"}\n",
|
||||||
|
heap->bitmap,
|
||||||
|
heap->bitmap_size,
|
||||||
|
heap->cache,
|
||||||
|
heap->cache_capacity,
|
||||||
|
heap->block_size,
|
||||||
|
heap->height,
|
||||||
|
heap->free_block_count,
|
||||||
|
heap->mask,
|
||||||
|
heap->block_bits,
|
||||||
|
heap->blocks_in_word,
|
||||||
|
heap->offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_memory_map(memory_map_t *map)
|
||||||
|
{
|
||||||
|
printf("map = {\n"
|
||||||
|
"\t.size = %i\n"
|
||||||
|
"\t.capacity = %i\n"
|
||||||
|
"\t.array = {",
|
||||||
|
map->size,
|
||||||
|
map->capacity);
|
||||||
|
for(int i = 0; i < map->size; i++)
|
||||||
|
{
|
||||||
|
printf("{.type = %i, .location = %lX, .size = %i} ", \
|
||||||
|
map->array[i].type,
|
||||||
|
map->array[i].location,
|
||||||
|
map->array[i].size);
|
||||||
|
}
|
||||||
|
printf("}\n}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_heap(unsigned long size, unsigned long block_size, unsigned long bits, int result)
|
||||||
|
{
|
||||||
|
printf("[TEST] Bitmap allocator: memory=%lX, block_size=%lu, block_bits=%lu\n", size, block_size, bits);
|
||||||
|
const int memory_map_capacity = 32;
|
||||||
|
const int cache_capacity = 20;
|
||||||
|
memory_region_t arr[memory_map_capacity];
|
||||||
|
unsigned long heap_cache[cache_capacity];
|
||||||
|
void *heap_data = malloc(size);
|
||||||
|
|
||||||
|
memory_map_t memory_map = {
|
||||||
|
.array = arr,
|
||||||
|
.capacity = memory_map_capacity,
|
||||||
|
.size = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
bitmap_heap_descriptor_t heap = {
|
||||||
|
.bitmap = NULL,
|
||||||
|
.block_size = block_size,
|
||||||
|
.cache = heap_cache,
|
||||||
|
.cache_capacity = cache_capacity,
|
||||||
|
.block_bits = bits,
|
||||||
|
.offset = (unsigned long)heap_data
|
||||||
|
};
|
||||||
|
|
||||||
|
memmap_insert_region(&memory_map, 0, size, M_AVAILABLE);
|
||||||
|
int status = initialize_heap(&heap, &memory_map, NULL);
|
||||||
|
assert(!(!status != !result));
|
||||||
|
if(status)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
print_heap_desc(&heap);
|
||||||
|
print_memory_map(&memory_map);
|
||||||
|
|
||||||
|
unsigned long total_blocks = heap.free_block_count;
|
||||||
|
|
||||||
|
memblock_t *reserved_blocks = malloc(sizeof(memblock_t) * size / heap.block_size);
|
||||||
|
unsigned long count = 0;
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
memblock_t next_block;
|
||||||
|
next_block.size = heap.block_size * (rand() % 8 + 1);
|
||||||
|
next_block.location = reserve_region(&heap, next_block.size);
|
||||||
|
if(next_block.location != NOMEM)
|
||||||
|
{
|
||||||
|
char *s = (char*)next_block.location;
|
||||||
|
for(int i = 0; i < next_block.size; i++)
|
||||||
|
{
|
||||||
|
s[i] = (char)rand();
|
||||||
|
}
|
||||||
|
reserved_blocks[count] = next_block;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("\tOut of memory: %i free blocks left, %i total blocks, %i allocations. Tried to allocate %i bytes.\n", heap.free_block_count, total_blocks, count, next_block.size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
assert(reserved_blocks[i].location >= heap.offset);
|
||||||
|
assert(reserved_blocks[i].location + reserved_blocks[i].size <= heap.offset + size);
|
||||||
|
for(int j = i + 1; j < count; j++)
|
||||||
|
{
|
||||||
|
assert((reserved_blocks[j].location + reserved_blocks[j].size) <= reserved_blocks[i].location
|
||||||
|
|| reserved_blocks[j].location >= (reserved_blocks[i].location + reserved_blocks[i].size));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
free_region(&heap, reserved_blocks[i].location, bits < 2 ? reserved_blocks[i].size : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(heap.free_block_count == total_blocks);
|
||||||
|
free(reserved_blocks);
|
||||||
|
free(heap_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **args)
|
||||||
|
{
|
||||||
|
srand(time(0));
|
||||||
|
test_heap(32, 1, 1, 1);
|
||||||
|
test_heap(256, 0, 1, 1);
|
||||||
|
test_heap(256, 1, 0, 1);
|
||||||
|
test_heap(256, 1, 3, 1);
|
||||||
|
test_heap(256, 1, 128, 1);
|
||||||
|
test_heap(256, 1, 4, 1);
|
||||||
|
|
||||||
|
for(int bs = 1; bs <= 32; bs++)
|
||||||
|
{
|
||||||
|
unsigned long n = (8 * sizeof(unsigned long)) - 1 - __builtin_clzl((unsigned long) bs);
|
||||||
|
for(int bits = 1; bits <= (8 * sizeof(unsigned long)) && (2 * bits) < (8 * (1 << n)); bits <<= 1)
|
||||||
|
{
|
||||||
|
test_heap(1024, bs, bits, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
#include "libmalloc/bitmap_alloc.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
int main(int argc, char **args)
|
|
||||||
{
|
|
||||||
const int memory_map_capacity = 32;
|
|
||||||
const int heap_size = 1 << 20;
|
|
||||||
const int cache_capacity = 20;
|
|
||||||
memory_region_t arr[memory_map_capacity];
|
|
||||||
unsigned long heap_cache[cache_capacity];
|
|
||||||
|
|
||||||
memory_map_t memory_map = {
|
|
||||||
.array = arr,
|
|
||||||
.capacity = memory_map_capacity,
|
|
||||||
.size = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
bitmap_heap_descriptor_t heap = {
|
|
||||||
.bitmap = malloc(heap_size / 4),
|
|
||||||
.block_size = 1,
|
|
||||||
.cache = heap_cache,
|
|
||||||
.cache_capacity = cache_capacity
|
|
||||||
};
|
|
||||||
|
|
||||||
memmap_insert_region(&memory_map, 0, heap_size, M_AVAILABLE);
|
|
||||||
initialize_physical_heap(&heap, &memory_map);
|
|
||||||
|
|
||||||
unsigned long *reserved_blocks = malloc(sizeof(unsigned long) * heap_size);
|
|
||||||
for(int i = 0; i < heap_size; i++)
|
|
||||||
{
|
|
||||||
reserved_blocks[i] = reserve_region(&heap, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*for(int i = 0; i < heap_size; i++)
|
|
||||||
{
|
|
||||||
for(int j = i + 1; j < heap_size; j++)
|
|
||||||
{
|
|
||||||
assert(reserved_blocks[i] != reserved_blocks[j]);
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
for(int i = 0; i < heap_size; i++)
|
|
||||||
{
|
|
||||||
free_region(&heap, reserved_blocks[i], 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(heap.free_block_count == heap_size);
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user