]> git.mdlowis.com Git - archive/atc.git/commitdiff
Finished initial implementation of heap module
authorMike D. Lowis <mike.lowis@gentex.com>
Wed, 1 Apr 2015 14:37:56 +0000 (10:37 -0400)
committerMike D. Lowis <mike.lowis@gentex.com>
Wed, 1 Apr 2015 14:37:56 +0000 (10:37 -0400)
build.rb
source/runtime/heap.c
source/runtime/heap.h
tests/test_heap.c

index 5d048de29a8e3aa76365ad0fddcf6a2d8aba4905..7508bde578944dd3a63ca7598ba15bc3d577b648 100755 (executable)
--- a/build.rb
+++ b/build.rb
@@ -1,4 +1,4 @@
-#!/usr/bin/ruby
+#!/usr/bin/env ruby
 
 require_relative 'modules/build-system/setup'
 
index 2b4b095674f8968a6d9b335ae051d741e98a02a7..5c64b64f84cd4b322998afcef7324dcf451b9363 100644 (file)
@@ -7,13 +7,20 @@
 
 heap_t* heap_create(void)
 {
-    heap_t* heap = (heap_t*)calloc(1u, sizeof(heap_t));
-    return heap;
+    return (heap_t*)calloc(1u, sizeof(heap_t));;
 }
 
 void heap_destroy(heap_t* heap)
 {
     int i;
+    block_t* current = heap->blocks;
+    /* Free all the large blocks */
+    while (NULL != current) {
+        block_t* deadite = current;
+        current = deadite->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) {
@@ -23,13 +30,13 @@ void heap_destroy(heap_t* heap)
             free(deadite);
         }
     }
+    /* Free the heap itself */
     free(heap);
 }
 
-void* allocate_small_block(heap_t* heap, uintptr_t num_slots)
+static void* allocate_small_block(heap_t* heap, uintptr_t num_slots)
 {
-    uintptr_t index = num_slots - HEAP_INDEX_OFFSET;
-    printf("index: %d, %d\n", (unsigned int)index, (unsigned int)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));
@@ -41,9 +48,12 @@ void* allocate_small_block(heap_t* heap, uintptr_t num_slots)
     return segment_alloc(heap->heaps[index]->segment);
 }
 
-void* allocate_large_block(heap_t* heap, uintptr_t num_slots)
+static void* allocate_large_block(heap_t* heap, uintptr_t num_slots)
 {
-    return NULL;
+    block_t* blk = (block_t*)malloc(sizeof(block_t) + (num_slots * sizeof(uintptr_t)));
+    blk->next = heap->blocks;
+    heap->blocks = blk;
+    return (&blk->data[0]);
 }
 
 void* heap_allocate(heap_t* heap, uintptr_t num_slots)
index 54ae44212ee4dc3e99889d7f8e2d19d288edccc1..926b6bfcfb55b016bd576f0dc92a64c7568614aa 100644 (file)
@@ -7,22 +7,27 @@
 
 #include "segment.h"
 
-#define MIN_NUM_SLOTS (2u)
+#define MIN_NUM_SLOTS (1u)
 
-#define MAX_NUM_SLOTS ((sizeof(uintptr_t)*8u) - 1u)
+#define MAX_NUM_SLOTS (sizeof(uintptr_t) * 8u)
 
 #define HEAP_INDEX_OFFSET (MIN_NUM_SLOTS)
 
-#define NUM_HEAP_STACKS ((sizeof(uintptr_t) * 8u) - 1)
+#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 {
-    uintptr_t bytes_allocated;
     segnode_t* heaps[NUM_HEAP_STACKS];
+    block_t* blocks;
 } heap_t;
 
 heap_t* heap_create(void);
index 83316e6f86e1f931faa42858337551e9b0e40fbd..5087d70ef2da628c90668c38fd45d762acf1380c 100644 (file)
@@ -7,11 +7,45 @@ TEST_SUITE(Heap) {
     TEST(Verify_Create_allocates_and_initializes_a_heap) {
         heap_t* heap = heap_create();
         CHECK(heap != NULL);
-
-        CHECK(NULL != heap_allocate(heap, 63));
+        CHECK(NULL != heap_allocate(heap, 64));
+        CHECK(NULL != heap_allocate(heap, 65));
         heap_destroy(heap);
     }
 
-    /* Verify: segment_alloc
+    /* Verify: heap_alloc
      *************************************************************************/
+    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);
+        heap_destroy(heap);
+    }
+
+    TEST(Verify_Allocate_should_allocate_a_new_segment_if_the_current_segment_is_full) {
+        heap_t* heap = heap_create();
+        segnode_t* prev_seg_node;
+        CHECK(NULL != heap_allocate(heap, 1));
+        CHECK(heap->heaps[0] != NULL);
+        prev_seg_node = heap->heaps[0];
+        prev_seg_node->segment->blockmap[0] = 0;
+        CHECK(NULL != heap_allocate(heap, 1));
+        CHECK(heap->heaps[0] != prev_seg_node);
+        CHECK(heap->heaps[0]->next == prev_seg_node);
+        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);
+        heap_destroy(heap);
+    }
+
+    TEST(Verify_Allocate_should_allocate_a_large_block_if_the_number_of_slots_is_greater_than_the_max) {
+        heap_t* heap = heap_create();
+        CHECK(NULL != heap_allocate(heap, 65));
+        CHECK(heap->blocks != NULL);
+        CHECK(heap->blocks->next == NULL);
+        heap_destroy(heap);
+    }
 }