]> git.mdlowis.com Git - archive/atc.git/commitdiff
move segments to a full list when they have been fully allocated
authorMichael D. Lowis <mike@mdlowis.com>
Tue, 7 Apr 2015 02:22:09 +0000 (22:22 -0400)
committerMichael D. Lowis <mike@mdlowis.com>
Tue, 7 Apr 2015 02:22:09 +0000 (22:22 -0400)
source/runtime/heap.c
source/runtime/heap.h
tests/test_heap.c

index 58fac98073b2be931e0c967c5ab714993aa35d86..66ab2cd4c5c4f7b9901a2c6cbf3bb69ac7e9c5ec 100644 (file)
@@ -26,7 +26,7 @@ void heap_destroy(heap_t* heap)
     destroy_large_blocks(heap->greylist);
     /* Free all of the small block segments */
     for (i = 0; i < NUM_HEAP_STACKS; i++) {
-        segment_destroy(heap->heaps[i]);
+        segment_destroy(heap->heaps[i].available);
     }
     /* Free the heap itself */
     free(heap);
@@ -34,12 +34,21 @@ void heap_destroy(heap_t* heap)
 
 static void* allocate_small_block(heap_t* heap, uintptr_t num_slots)
 {
+    void* object;
     uintptr_t index = (num_slots >= MIN_NUM_SLOTS) ? (num_slots - HEAP_INDEX_OFFSET) : 0;
-    segment_t* current = heap->heaps[index];
-    if ((NULL == current) || segment_full(current)) {
-        heap->heaps[index] = segment_create(num_slots, current);
+    /* If we dont have any available segments, allocate a new one */
+    if (NULL == heap->heaps[index].available)
+        heap->heaps[index].available = segment_create(num_slots, heap->heaps[index].available);
+    /* Allocate the object */
+    object = segment_alloc(heap->heaps[index].available);
+    /* If we filled it up then move it to the full list */
+    if (segment_full(heap->heaps[index].available)) {
+        segment_t* current = heap->heaps[index].available;
+        heap->heaps[index].available = heap->heaps[index].available->next;
+        current->next = heap->heaps[index].full;
+        heap->heaps[index].full = current;
     }
-    return segment_alloc(heap->heaps[index]);
+    return object;
 }
 
 static void* allocate_large_block(heap_t* heap, uintptr_t num_slots)
@@ -68,8 +77,8 @@ void heap_start_collection(heap_t* heap)
     heap->greylist = heap->blocks;
     heap->blocks = NULL;
     for (uintptr_t i = 0; i < NUM_HEAP_STACKS; i++) {
-        for(segment_t* curr = heap->heaps[i]; curr != NULL; curr = curr->next) {
-            segment_clear_map(heap->heaps[i]);
+        for(segment_t* curr = heap->heaps[i].available; curr != NULL; curr = curr->next) {
+            segment_clear_map(heap->heaps[i].available);
         }
     }
 }
@@ -83,8 +92,8 @@ void heap_finish_collection(heap_t* heap)
 static void* subheap_find_and_mark(heap_t* heap, uintptr_t addr) {
     void* obj = NULL;
     for (uintptr_t i = 0; i < NUM_HEAP_STACKS; i++) {
-        for(segment_t* curr = heap->heaps[i]; curr != NULL; curr = curr->next) {
-            obj = segment_find_and_mark(heap->heaps[i], addr);
+        for(segment_t* curr = heap->heaps[i].available; curr != NULL; curr = curr->next) {
+            obj = segment_find_and_mark(heap->heaps[i].available, addr);
             if (NULL != obj) {
                 i = NUM_HEAP_STACKS;
                 break;
index 39b2a92257aff6a3024c368e6fba1c147d4f319c..9544b8e309e8b5c71284565da31b267055881985 100644 (file)
@@ -22,7 +22,10 @@ typedef struct block_t {
 } block_t;
 
 typedef struct {
-    segment_t* heaps[NUM_HEAP_STACKS];
+    struct {
+        segment_t* available;
+        segment_t* full;
+    } heaps[NUM_HEAP_STACKS];
     block_t* blocks;
     block_t* greylist;
 } heap_t;
index 13acbdcd9cc49796febda2e323dc9814d680aa41..5e46ad5ca37a9ac3eb98dd2342af689fbb9fb843 100644 (file)
@@ -18,27 +18,26 @@ TEST_SUITE(Heap) {
     TEST(Verify_Allocate_should_allocate_a_new_segment_if_the_subheap_is_empty) {
         heap_t* heap = heap_create();
         CHECK(NULL != heap_allocate(heap, 1));
-        CHECK(heap->heaps[0] != NULL);
+        CHECK(heap->heaps[0].available != NULL);
         heap_destroy(heap);
     }
 
     TEST(Verify_Allocate_should_allocate_a_new_segment_if_the_current_segment_is_full) {
         heap_t* heap = heap_create();
-        segment_t* prev;
         CHECK(NULL != heap_allocate(heap, 1));
-        CHECK(heap->heaps[0] != NULL);
-        prev = heap->heaps[0];
-        prev->blockmap[0] = 0;
+        heap->heaps[0].available->blockmap[0] = 1 << ((sizeof(uint16_t) * 8) - 1);
+        heap->heaps[0].available->blockmap[16] = 1 << ((sizeof(uint16_t) * 8) - 1);
         CHECK(NULL != heap_allocate(heap, 1));
-        CHECK(heap->heaps[0] != prev);
-        CHECK(heap->heaps[0]->next == prev);
+        CHECK(heap->heaps[0].available == NULL);
+        CHECK(heap->heaps[0].full != NULL);
+        CHECK(heap->heaps[0].full->next == NULL);
         heap_destroy(heap);
     }
 
     TEST(Verify_Allocate_should_allocate_the_minimum_size_if_num_slots_is_less_than_the_minimum) {
         heap_t* heap = heap_create();
         CHECK(NULL != heap_allocate(heap, 0));
-        CHECK(heap->heaps[0] != NULL);
+        CHECK(heap->heaps[0].available != NULL);
         heap_destroy(heap);
     }