Added some kheap parts...not ready yet
This commit is contained in:
parent
7f737e6f02
commit
234904bf9b
106
kernel/drivers/kheap.c
Normal file
106
kernel/drivers/kheap.c
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
|
50
kernel/drivers/kheap.h
Normal file
50
kernel/drivers/kheap.h
Normal file
@ -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 <stdint.h>
|
||||||
|
#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
|
@ -29,7 +29,7 @@ ordered_list_t place_ordered_list(void *addr, uint32_t max_size, lessthan_predic
|
|||||||
|
|
||||||
// Destroy an ordered list
|
// Destroy an ordered list
|
||||||
void destroy_ordered_list(ordered_list_t *array) {
|
void destroy_ordered_list(ordered_list_t *array) {
|
||||||
// Not ready yet
|
// Not ready yet TODO:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert item into the array
|
// Insert item into the array
|
||||||
|
Loading…
Reference in New Issue
Block a user