/* Free all the large blocks */
while (NULL != current) {
block_t* deadite = current;
- current = deadite->next;
+ current = current->next;
free(deadite);
}
/* Free all of the small block segments */
for (i = 0; i < NUM_HEAP_STACKS; i++) {
- segnode_t* curr = heap->heaps[i];
- while (NULL != curr) {
- segnode_t* deadite = curr;
- curr = deadite->next;
- segment_destroy(deadite->segment);
- free(deadite);
- }
+ segment_destroy(heap->heaps[i]);
}
/* Free the heap itself */
free(heap);
static void* allocate_small_block(heap_t* heap, uintptr_t num_slots)
{
uintptr_t index = (num_slots >= MIN_NUM_SLOTS) ? (num_slots - HEAP_INDEX_OFFSET) : 0;
- segnode_t* node = heap->heaps[index];
- if ((NULL == node) || segment_full(node->segment)) {
- segnode_t* newnode = (segnode_t*)malloc(sizeof(segnode_t));
- newnode->segment = segment_create(num_slots);
- newnode->next = node;
- heap->heaps[index] = newnode;
- node = newnode;
+ segment_t* current = heap->heaps[index];
+ if ((NULL == current) || segment_full(current)) {
+ heap->heaps[index] = segment_create(num_slots, current);
}
- return segment_alloc(heap->heaps[index]->segment);
+ return segment_alloc(heap->heaps[index]);
}
static void* allocate_large_block(heap_t* heap, uintptr_t num_slots)
#define NUM_HEAP_STACKS (MAX_NUM_SLOTS)
-typedef struct segnode_t {
- segment_t* segment;
- struct segnode_t* next;
-} segnode_t;
-
typedef struct block_t {
struct block_t* next;
uintptr_t data[];
} block_t;
typedef struct {
- segnode_t* heaps[NUM_HEAP_STACKS];
+ segment_t* heaps[NUM_HEAP_STACKS];
block_t* blocks;
} heap_t;
return lookup[((uint32_t)((bitmap & -bitmap) * 0x077CB531U)) >> 27];
}
-segment_t* segment_create(uintptr_t blocksize)
+segment_t* segment_create(uintptr_t num_slots, segment_t* next)
{
- segment_t* seg = (segment_t*)malloc(sizeof(segment_t));
- seg->blocksize = blocksize;
- seg->start = (uintptr_t*)malloc(sizeof(uintptr_t) * blocksize * NUM_BLOCKS);
- seg->end = (seg->start + (blocksize * NUM_BLOCKS));
+ size_t segsize = sizeof(uintptr_t) * num_slots * NUM_BLOCKS;
+ segment_t* seg = (segment_t*)malloc(sizeof(segment_t) + segsize);
+ seg->next = next;
+ seg->blocksize = num_slots;
+ seg->end = (seg->start + (num_slots * NUM_BLOCKS));
memset(seg->blockmap, 0xFFu, sizeof(seg->blockmap));
return seg;
}
void segment_destroy(segment_t* seg)
{
- free(seg->start);
- free(seg);
+ segment_t* curr = seg;
+ while (NULL != curr) {
+ segment_t* deadite = curr;
+ curr = curr->next;
+ free(deadite);
+ }
}
bool segment_full(segment_t* seg) {
#define BLOCKMAP_SIZE ((sizeof(uint16_t) * 8) + 1)
-typedef struct {
+typedef struct segment_t {
+ struct segment_t* next;
uintptr_t blocksize;
- uintptr_t* start;
- uintptr_t* end;
uint16_t blockmap[BLOCKMAP_SIZE];
+ uintptr_t* end;
+ uintptr_t start[];
} segment_t;
-segment_t* segment_create(uintptr_t blocksize);
+segment_t* segment_create(uintptr_t blocksize, segment_t* next);
void segment_destroy(segment_t* seg);
TEST(Verify_Allocate_should_allocate_a_new_segment_if_the_current_segment_is_full) {
heap_t* heap = heap_create();
- segnode_t* prev_seg_node;
+ segment_t* prev;
CHECK(NULL != heap_allocate(heap, 1));
CHECK(heap->heaps[0] != NULL);
- prev_seg_node = heap->heaps[0];
- prev_seg_node->segment->blockmap[0] = 0;
+ prev = heap->heaps[0];
+ prev->blockmap[0] = 0;
CHECK(NULL != heap_allocate(heap, 1));
- CHECK(heap->heaps[0] != prev_seg_node);
- CHECK(heap->heaps[0]->next == prev_seg_node);
+ CHECK(heap->heaps[0] != prev);
+ CHECK(heap->heaps[0]->next == prev);
heap_destroy(heap);
}
*************************************************************************/
TEST(Verify_Create_allocates_and_initializes_a_segment) {
int i;
- segment_t* seg = segment_create(2u);
+ segment_t* seg = segment_create(2u, NULL);
CHECK(seg->blocksize == 2u);
CHECK(seg->start != NULL);
CHECK(seg->end == (seg->start + (NUM_BLOCKS * 2u)));
/* Verify: segment_alloc
*************************************************************************/
TEST(Verify_alloc_allocates_the_first_block) {
- segment_t* seg = segment_create(2u);
+ segment_t* seg = segment_create(2u, NULL);
void* obj = segment_alloc(seg);
CHECK(obj == seg->start);
segment_destroy(seg);
}
TEST(Verify_alloc_allocates_the_second_block) {
- segment_t* seg = segment_create(2u);
+ segment_t* seg = segment_create(2u, NULL);
seg->blockmap[1] = UINT16_MAX-1;
void* obj = segment_alloc(seg);
CHECK(obj == &seg->start[2]);
}
TEST(Verify_alloc_allocates_the_sixteenth_block) {
- segment_t* seg = segment_create(2u);
+ segment_t* seg = segment_create(2u, NULL);
seg->blockmap[0] = UINT16_MAX-1;
seg->blockmap[1] = 0u;
void* obj = segment_alloc(seg);
}
TEST(Verify_alloc_allocates_blocks_consecutively) {
- segment_t* seg = segment_create(2u);
+ segment_t* seg = segment_create(2u, NULL);
void* obj1 = segment_alloc(seg);
void* obj2 = segment_alloc(seg);
void* obj3 = segment_alloc(seg);
}
TEST(Verify_alloc_allocates_blocks_consecutively_across_bitmap_boundaries) {
- segment_t* seg = segment_create(2u);
+ segment_t* seg = segment_create(2u, NULL);
seg->blockmap[1] = 1 << 15;
void* obj1 = segment_alloc(seg);
void* obj2 = segment_alloc(seg);
}
TEST(Verify_alloc_returns_NULL_if_no_blocks_available) {
- segment_t* seg = segment_create(2u);
+ segment_t* seg = segment_create(2u, NULL);
seg->blockmap[0] = 0;
void* obj = segment_alloc(seg);
CHECK(obj == NULL);