From 234904bf9bfcab26790decbae2603874a1731daf Mon Sep 17 00:00:00 2001 From: ice-bit Date: Wed, 18 Sep 2019 12:25:55 +0200 Subject: [PATCH] Added some kheap parts...not ready yet --- kernel/drivers/kheap.c | 106 ++++++++++++++++++++++++++++++++++ kernel/drivers/kheap.h | 50 ++++++++++++++++ kernel/drivers/ordered_list.c | 2 +- 3 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 kernel/drivers/kheap.c create mode 100644 kernel/drivers/kheap.h diff --git a/kernel/drivers/kheap.c b/kernel/drivers/kheap.c new file mode 100644 index 0000000..334718d --- /dev/null +++ b/kernel/drivers/kheap.c @@ -0,0 +1,106 @@ +#include "kheap.h" + +/* The following function is a simple method to find the smallest hole that + * fit user space request, since we will do this process many times, it's a good + * idea to wrap it in a function */ +static int32_t find_smallest_hole(uint32_t size, uint8_t page_align, heap_t *heap) { + uint32_t i = 0; + while(i < heap->index.size) { + header_t *header = (header_t*)lookup_ordered_list(i, &heap->index); + if(page_align > 0) { + uint32_t loc = (uint32_t)header; + int32_t offset = 0; + if((loc+sizeof(header_t)) & 0xFFFFF000 != 0) // Page aligned memory + offset = 0x1000 - (loc+sizeof(header_t))%0x1000; + int32_t hole_size = (int32_t)header->size - offset; + if(hole_size >= (int32_t)size) + break; + } else if(header->size >= size) + break; + i++; + } + // Return something according to the iterator + if(i == heap->index.size) + return -1; // Nothing found + else + return i; +} + +static int8_t header_t_less_than(void *a, void *b) { + return (((header_t*)a)->size < ((header_t*)b)->size)?1:0; +} + +heap_t *create_heap(uint32_t start, uint32_t end, uint32_t max, uint8_t supervisor, uint8_t readonly) { + heap_t *heap = (heap_t*)kmalloc(sizeof(heap_t)); //TODO: implement kmalloc + + ASSERT(start%0x1000 == 0); + ASSERT(end%0x1000 == 0); + + // Init heap's index + heap->index = place_ordered_list((void*)start, HEAP_INDEX_SIZE, &header_t_less_than); + + // Shift start address to the corrent position, where we can put on data + start += sizeof(type_t)*HEAP_INDEX_SIZE; + + // Check if start address is page-aligned + if(start & 0xFFFFF000 != 0) { + start &= 0xFFFFF000; + start += 0x1000; + } + + // Fill the heap structure with start, end and max addresses + heap->start_address = start; + heap->end_address = end; + heap->max_address = max; + heap->supervisor = supervisor; + heap->readonly = readonly; + + // Let's create one large hole in the new index + header_t *hole = (header_t*)start; + hole->size = end-start; + hole->magic = HEAP_MAGIC; + hole->is_hole = 1; + insert_ordered_list((void*)hole, &heap->index); + + return heap; +} + +static void expand(uint32_t new_size, heap_t *heap) { + // Before anything else let's check that new size is greater than older one + ASSERT(new_size > heap->end_address - heap->start_address); + if(new_size&0xFFFFF000 != 0) { + new_size &= 0xFFFFF000; + new_size += 0x1000; + } + // Check if new size is not greater than maximum size + ASSERT(heap->start_address+new_size <= heap->max_address); + + uint32_t old_size = heap->end_address-heap->start_address; + uint32_t i = old_size; + while(i < new_size) { + alloc_frame(get_page(heap->start_address+i, 1, kernel_directory), // FIXME: + (heap->supervisor)?1:0, (heap->readonly)?0:1); + } +} + +static uint32_t contract(uint32_t new_size, heap_t *heap) { + // This function will be literally the opposite of the previous one + ASSERT(new_size < heap->end_address-heap->start_address); + + if(new_size&0x1000) { + new_size &= 0x1000; + new_size += 0x1000; + } + + if(new_size < HEAP_MIN_SIZE) + new_size = HEAP_MIN_SIZE; + uint32_t old_size = heap->end_address-heap->start_address; + uint32_t i = old_size - 0x1000; + while(new_size < i) { + free_frame(get_page(heap->start_address+i, 0, kernel_directory)); + i -= 0x1000; + } + heap->end_address = heap->start_address + new_size; + return new_size; +} + diff --git a/kernel/drivers/kheap.h b/kernel/drivers/kheap.h new file mode 100644 index 0000000..ce79ce8 --- /dev/null +++ b/kernel/drivers/kheap.h @@ -0,0 +1,50 @@ +/* This heap algorithm uses two different data structures: blocks and holes. + * Blocks: Contiguous areas of memory containing user data + * Holes: Special kind of blocks that are not in use, this is the result + * of free() operation. Those spaces lend to a common problem called "Fragmentation"; + * where malloc() cannot use those spaces anymore because they are too small for any + * kind of program. Any modern OS must have a solution to avoid this problem, but to keep + * things simple as possible i wont implement anything like that. + * Blocks/holes contains informations like the magic number(error checking), the type of + * chunk(hole or block) and the size, while the footer contains only a pointer to the header + * (and obviously an error checking flag). + */ +#ifndef KHEAP_H +#define KHEAP_H + +#define KHEAP_START 0xC0000000 // starting location can be different +#define KHEAP_INITIAL_SIZE 0x100000 +#define HEAP_INDEX_SIZE 0x20000 +#define HEAP_MAGIC 0x123890AB +#define HEAP_MIN_SIZE 0x70000 + +#include +#include "ordered_list.h" + +// Data structure for single block/hole +typedef struct { + uint32_t magic; // Magic number for error checking + uint8_t is_hole; // 1 if its an hole, 0 for a block + uint32_t size; // Size of the block +} header_t; + +typedef struct { + uint32_t magic; + header_t *header; // Pointer to the head +} footer_t; + +typedef struct { + ordered_list_t index; + uint32_t start_address; // Start of allocated space + uint32_t end_address; // End of allocated space + uint32_t max_address; // Maximum size, heap can be expanded to + uint8_t supervisor; + uint8_t readonly; +} heap_t; + +// Heap functions +heap_t *create_heap(uint32_t start, uint32_t end, uint32_t max, uint8_t supervisor, uint8_t readonly); +void *alloc(uint32_t size, uint8_t page_align, heap_t *heap); +void free(void *p, heap_t *heap); + +#endif \ No newline at end of file diff --git a/kernel/drivers/ordered_list.c b/kernel/drivers/ordered_list.c index fdfc21f..4288698 100644 --- a/kernel/drivers/ordered_list.c +++ b/kernel/drivers/ordered_list.c @@ -29,7 +29,7 @@ ordered_list_t place_ordered_list(void *addr, uint32_t max_size, lessthan_predic // Destroy an ordered list void destroy_ordered_list(ordered_list_t *array) { - // Not ready yet + // Not ready yet TODO: } // Insert item into the array