From: Michael D. Lowis Date: Thu, 9 Apr 2015 02:07:31 +0000 (-0400) Subject: Started a more general implementation of splaytree X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=3df31b75effd307a229340eff4005dda68380d8f;p=archive%2Fatc.git Started a more general implementation of splaytree --- diff --git a/source/runtime/heap.c b/source/runtime/heap.c index f4be807..6331669 100644 --- a/source/runtime/heap.c +++ b/source/runtime/heap.c @@ -5,25 +5,46 @@ #include "heap.h" #include -heap_t* heap_create(void) +static int range_compare(uintptr_t val, uintptr_t start, uintptr_t end) { - return (heap_t*)calloc(1u, sizeof(heap_t));; + if (val < start) + return -1; + else if (val >= end) + return 1; + else + return 0; } -static void destroy_large_blocks(block_t* current) { - while (NULL != current) { - block_t* deadite = current; - current = current->next; - free(deadite); - } +static int segment_compare(uintptr_t key, segment_t* seg) +{ + uintptr_t start = (uintptr_t)(seg->start); + uintptr_t end = (uintptr_t)(seg->end); + return range_compare(key, start, end); +} + +static int block_compare(uintptr_t key, block_t* block) +{ + uintptr_t start = (uintptr_t)(block->data); + uintptr_t end = (uintptr_t)(start + block->size); + return range_compare(key, start, end); +} + +heap_t* heap_create(void) +{ + heap_t* heap = (heap_t*)calloc(1u, sizeof(heap_t)); + heap->segments = splaytree_create((del_fn_t)segment_destroy, (cmp_fn_t)segment_compare); + heap->blocks = splaytree_create((del_fn_t)free, (cmp_fn_t)block_compare); + heap->greylist = NULL; + return heap; } void heap_destroy(heap_t* heap) { unsigned int i; /* Free all the large blocks */ - destroy_large_blocks(heap->blocks); - destroy_large_blocks(heap->greylist); + splaytree_destroy(heap->segments); + splaytree_destroy(heap->blocks); + splaytree_destroy(heap->greylist); /* Free all of the small block segments */ for (i = 0; i < NUM_HEAP_STACKS; i++) { segment_destroy(heap->heaps[i].available); @@ -37,8 +58,10 @@ 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; /* If we dont have any available segments, allocate a new one */ - if (NULL == heap->heaps[index].available) + if (NULL == heap->heaps[index].available) { heap->heaps[index].available = segment_create(num_slots, heap->heaps[index].available); + splaytree_insert(heap->segments, (uintptr_t)&(heap->heaps[index].available->start[0]), 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 */ @@ -55,9 +78,8 @@ static void* allocate_large_block(heap_t* heap, uintptr_t num_slots) { uintptr_t size = (num_slots * sizeof(uintptr_t)); block_t* blk = (block_t*)malloc(sizeof(block_t) + size); - blk->next = heap->blocks; blk->size = size; - heap->blocks = blk; + splaytree_insert(heap->blocks, (uintptr_t)&blk->data[0], blk); return (&blk->data[0]); } @@ -75,69 +97,27 @@ void* heap_allocate(heap_t* heap, uintptr_t num_slots) 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].available; curr != NULL; curr = curr->next) { - segment_clear_map(heap->heaps[i].available); - } - } + heap->blocks = splaytree_create((del_fn_t)free, (cmp_fn_t)block_compare); } void heap_finish_collection(heap_t* heap) { - destroy_large_blocks(heap->greylist); - heap->greylist = NULL; -} - -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].available; curr != NULL; curr = curr->next) { -// obj = segment_find_and_mark(heap->heaps[i].available, addr); -// if (NULL != obj) { -// i = NUM_HEAP_STACKS; -// break; -// } -// } -// } -// return obj; - (void)heap; - (void)addr; - return NULL; -} - -static void* block_find_and_mark(heap_t* heap, uintptr_t addr) { -// void* obj = NULL; -// block_t* prev = NULL; -// block_t* curr = heap->greylist; -// while (curr != NULL) { -// uintptr_t start = (uintptr_t)&(curr->data[0]); -// uintptr_t end = start + curr->size; -// if ((start <= addr) && (addr < end)) { -// /* Remove it from the grey list */ -// if (prev == NULL) -// heap->greylist = curr->next; -// else -// prev->next = curr->next; -// /* Add it to the in-use list and break */ -// curr->next = heap->blocks; -// heap->blocks = curr->next; -// break; -// } -// prev = curr; -// curr = curr->next; -// } -// return obj; - (void)heap; - (void)addr; - return NULL; + splaytree_destroy(heap->greylist); } void* heap_find_and_mark(heap_t* heap, uintptr_t addr) { - void* obj = subheap_find_and_mark(heap, addr); - if (NULL == obj) - obj = block_find_and_mark(heap, addr); + void* obj = NULL; + segment_t* seg = splaytree_lookup(heap->segments, addr); + if (NULL != seg) { + obj = segment_find_and_mark(seg, addr); + } else { + block_t* block = splaytree_delete(heap->greylist, addr); + if (NULL != block) { + splaytree_insert(heap->blocks, addr, block); + obj = &block->data[0]; + } + } return obj; } diff --git a/source/runtime/heap.h b/source/runtime/heap.h index 9544b8e..7779c8d 100644 --- a/source/runtime/heap.h +++ b/source/runtime/heap.h @@ -6,6 +6,7 @@ #define HEAP_H #include "segment.h" +#include "splaytree.h" #define MIN_NUM_SLOTS (1u) @@ -16,7 +17,6 @@ #define NUM_HEAP_STACKS (MAX_NUM_SLOTS) typedef struct block_t { - struct block_t* next; uintptr_t size; uintptr_t data[]; } block_t; @@ -26,8 +26,9 @@ typedef struct { segment_t* available; segment_t* full; } heaps[NUM_HEAP_STACKS]; - block_t* blocks; - block_t* greylist; + splaytree_t* segments; + splaytree_t* blocks; + splaytree_t* greylist; } heap_t; heap_t* heap_create(void); diff --git a/source/runtime/splaytree.c b/source/runtime/splaytree.c index 79114ab..0f761cf 100644 --- a/source/runtime/splaytree.c +++ b/source/runtime/splaytree.c @@ -5,106 +5,70 @@ #include "splaytree.h" #include -splaytree_t* splaytree_create(void) -{ - splaytree_t* splaytree = (splaytree_t*)malloc(sizeof(splaytree_t)); - splaytree->root = NULL; - return splaytree; -} - -static void destroy_node(node_t* node) -{ - if (NULL != node) { - destroy_node(node->left); - destroy_node(node->right); - free(node); - } -} - -void splaytree_destroy(splaytree_t* tree) -{ - destroy_node(tree->root); - free(tree); -} - -static node_t* create_node(node_type_t tag, void* value) +static node_t* create_node(void* value) { node_t* node = (node_t*)malloc(sizeof(node_t*)); - node->tag = tag; - node->ptr.raw = value; - node->left = NULL; - node->right = NULL; + node->value = value; + node->left = NULL; + node->right = NULL; return node; } -static uintptr_t get_start_addr(node_t* curr) +static node_t** next_node(splaytree_t* tree, node_t* curr, uintptr_t address) { - if (curr->tag == SEGMENT) - return (uintptr_t)(curr->ptr.segment->start); + if (tree->compare(address, curr->value) < 0) + return &(curr->left); else - return (uintptr_t)(curr->ptr.block->data); + return &(curr->right); } -static uintptr_t get_end_addr(node_t* curr) +splaytree_t* splaytree_create(del_fn_t delfn, cmp_fn_t cmp_fn) { - if (curr->tag == SEGMENT) - return (uintptr_t)(curr->ptr.segment->end); - else - return (uintptr_t)(curr->ptr.block->data + curr->ptr.block->size); + splaytree_t* tree = (splaytree_t*)malloc(sizeof(splaytree_t)); + tree->destroy = delfn; + tree->compare = cmp_fn; + tree->root = NULL; + return tree; } -static node_t** next_node(node_t* curr, uintptr_t address) +void splaytree_destroy(splaytree_t* tree) { - uintptr_t curr_address = get_start_addr(curr); - if (address < curr_address) - return &(curr->left); - else - return &(curr->right); + (void)tree; } -void splaytree_insert(splaytree_t* tree, node_type_t tag, void* value) +void splaytree_insert(splaytree_t* tree, uintptr_t key, void* value) { - /* Get the address of the start of the range */ - uintptr_t address; - if (SEGMENT == tag) - address = (uintptr_t)((segment_t*)value)->start; - else - address = (uintptr_t)((block_t*)value)->data; /* Insert the item into the tree */ - if (tree->root == NULL) - tree->root = create_node(tag, value); - else { + if (tree->root == NULL) { + tree->root = create_node(value); + } else { node_t** current = &(tree->root); while(*current != NULL) { - current = next_node(*current, address); + current = next_node(tree, *current, key); } - *current = create_node(tag, value); + *current = create_node(value); } } -node_type_t splaytree_lookup(splaytree_t* tree, uintptr_t address, void** value) +void* splaytree_lookup(splaytree_t* tree, uintptr_t key) { - node_type_t tag = NONE; node_t* current = tree->root; - while(current != NULL) { - uintptr_t start = get_start_addr(current); - uintptr_t end = get_end_addr(current); - if ((start <= address) && (address < end)) { - tag = current->tag; - *value = current->ptr.raw; - break; - } else if (start < address) { + while (current != NULL) { + int cmp_val = tree->compare(key, current); + if (cmp_val == 0) + return current->value; + else if (cmp_val < 0) current = current->left; - } else { + else current = current->right; - } } - return tag; + return NULL; } -void splaytree_delete(splaytree_t* tree, uintptr_t address) +void* splaytree_delete(splaytree_t* tree, uintptr_t key) { (void)tree; - (void)address; + (void)key; + return NULL; } diff --git a/source/runtime/splaytree.h b/source/runtime/splaytree.h index 71dc690..edd2faa 100644 --- a/source/runtime/splaytree.h +++ b/source/runtime/splaytree.h @@ -6,33 +6,31 @@ #define SPLAYTREE_H #include -#include "heap.h" -typedef enum { SEGMENT, BLOCK, NONE } node_type_t; +typedef void (*del_fn_t)(void* value); + +typedef int (*cmp_fn_t)(uintptr_t key, void* value); typedef struct node_t { - node_type_t tag; - union { - segment_t* segment; - block_t* block; - void* raw; - } ptr; + void* value; struct node_t* left; struct node_t* right; } node_t; typedef struct splaytree_t { - node_t* root; + del_fn_t destroy; + cmp_fn_t compare; + node_t* root; } splaytree_t; -splaytree_t* splaytree_create(void); +splaytree_t* splaytree_create(del_fn_t delfn, cmp_fn_t cmp_fn); void splaytree_destroy(splaytree_t* tree); -void splaytree_insert(splaytree_t* tree, node_type_t tag, void* value); +void splaytree_insert(splaytree_t* tree, uintptr_t key, void* value); -node_type_t splaytree_lookup(splaytree_t* tree, uintptr_t address, void** value); +void* splaytree_lookup(splaytree_t* tree, uintptr_t key); -void splaytree_delete(splaytree_t* tree, uintptr_t address); +void* splaytree_delete(splaytree_t* tree, uintptr_t key); #endif /* SPLAYTREE_H */ diff --git a/tests/test_heap.c b/tests/test_heap.c index 5e46ad5..4667639 100644 --- a/tests/test_heap.c +++ b/tests/test_heap.c @@ -42,10 +42,11 @@ TEST_SUITE(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); + CHECK(false); + //heap_t* heap = heap_create(); + //CHECK(NULL != heap_allocate(heap, 65)); + //CHECK(heap->blocks != NULL); + //CHECK(heap->blocks->next == NULL); + //heap_destroy(heap); } } diff --git a/tests/test_splaytree.c b/tests/test_splaytree.c index e4a783c..6223e20 100644 --- a/tests/test_splaytree.c +++ b/tests/test_splaytree.c @@ -4,11 +4,11 @@ TEST_SUITE(SplayTree) { /* Verify: splaytree_create *************************************************************************/ - TEST(Verify_Create_allocates_and_initializes_an_empty_tree) { - splaytree_t* tree = splaytree_create(); - CHECK(tree->root == NULL); - splaytree_destroy(tree); - } + //TEST(Verify_Create_allocates_and_initializes_an_empty_tree) { + // splaytree_t* tree = splaytree_create(); + // CHECK(tree->root == NULL); + // splaytree_destroy(tree); + //} /* Verify: splaytree_create *************************************************************************/