Added alloc function(heap)
This commit is contained in:
parent
234904bf9b
commit
eff64e81c2
31
kernel/cpu/assert.c
Normal file
31
kernel/cpu/assert.c
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#include "assert.h"
|
||||||
|
|
||||||
|
// We panic when we find a critical error, this function is called by assert macro
|
||||||
|
extern void panic(const char *message, const char *file, uint32_t line) {
|
||||||
|
asm volatile("cli"); // Disable interrupts
|
||||||
|
|
||||||
|
kprint("PANIC(");
|
||||||
|
kprint(message);
|
||||||
|
kprint(") at ");
|
||||||
|
kprint(file);
|
||||||
|
kprint(":");
|
||||||
|
kprint_dec(line);
|
||||||
|
kprint("\n");
|
||||||
|
// Now hang on for ever
|
||||||
|
for(;;);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for assertion failed, this function call by assert macro
|
||||||
|
extern void panic_assert(const char *file, uint32_t line, const char *desc) {
|
||||||
|
asm volatile("cli"); // Disable interrupts
|
||||||
|
|
||||||
|
kprint("ASSERTION-FAILED(");
|
||||||
|
kprint(desc);
|
||||||
|
kprint(") at ");
|
||||||
|
kprint(file);
|
||||||
|
kprint(":");
|
||||||
|
kprint_dec(line);
|
||||||
|
kprint("\n");
|
||||||
|
// Now hang on forever
|
||||||
|
for(;;);
|
||||||
|
}
|
21
kernel/cpu/assert.h
Normal file
21
kernel/cpu/assert.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/**************************************
|
||||||
|
* iceOS Kernel *
|
||||||
|
* Developed by Marco 'icebit' Cetica *
|
||||||
|
* (c) 2019 *
|
||||||
|
* Released under GPLv3 *
|
||||||
|
* https://github.com/ice-bit/iceOS *
|
||||||
|
***************************************/
|
||||||
|
#ifndef ASSERT_H
|
||||||
|
#define ASSERT_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "../drivers/tty.h"
|
||||||
|
// These functions are used for error checking
|
||||||
|
|
||||||
|
#define PANIC(msg) panic(msg, __FILE__, __LINE__);
|
||||||
|
#define ASSERT(b) ((b) ? (void)0 : panic_assert(__FILE__, __LINE__, #b))
|
||||||
|
|
||||||
|
extern void panic(const char *message, const char *file, uint32_t line);
|
||||||
|
extern void panic_assert(const char *file, uint32_t line, const char *desc);
|
||||||
|
|
||||||
|
#endif
|
@ -1,5 +1,11 @@
|
|||||||
#include "kheap.h"
|
#include "kheap.h"
|
||||||
|
|
||||||
|
// Extern variables are declared in the linker script
|
||||||
|
extern uint32_t end;
|
||||||
|
uint32_t placement_addr = (uint32_t)&end;
|
||||||
|
extern page_directory_t *kernel_directory; // FIXME:
|
||||||
|
heap_t *kheap = 0;
|
||||||
|
|
||||||
/* The following function is a simple method to find the smallest hole that
|
/* 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
|
* fit user space request, since we will do this process many times, it's a good
|
||||||
* idea to wrap it in a function */
|
* idea to wrap it in a function */
|
||||||
@ -78,7 +84,7 @@ static void expand(uint32_t new_size, heap_t *heap) {
|
|||||||
uint32_t old_size = heap->end_address-heap->start_address;
|
uint32_t old_size = heap->end_address-heap->start_address;
|
||||||
uint32_t i = old_size;
|
uint32_t i = old_size;
|
||||||
while(i < new_size) {
|
while(i < new_size) {
|
||||||
alloc_frame(get_page(heap->start_address+i, 1, kernel_directory), // FIXME:
|
alloc_frame(get_page(heap->start_address+i, 1, kernel_directory),
|
||||||
(heap->supervisor)?1:0, (heap->readonly)?0:1);
|
(heap->supervisor)?1:0, (heap->readonly)?0:1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -104,3 +110,99 @@ static uint32_t contract(uint32_t new_size, heap_t *heap) {
|
|||||||
return new_size;
|
return new_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *alloc(uint32_t size, uint8_t page_align, heap_t *heap) {
|
||||||
|
uint32_t new_size = size + sizeof(header_t) + sizeof(footer_t);
|
||||||
|
int32_t i = find_smallest_hole(new_size, page_align, heap);
|
||||||
|
// Error checking for "no hole available"
|
||||||
|
if(i == -1) {
|
||||||
|
// Save previous data
|
||||||
|
uint32_t old_len = heap->end_address - heap->start_address;
|
||||||
|
uint32_t old_end_addr = heap->end_address;
|
||||||
|
|
||||||
|
// Allocate more space
|
||||||
|
expand(old_len+new_size, heap);
|
||||||
|
uint32_t new_len = heap->end_address-heap->start_address;
|
||||||
|
|
||||||
|
i = 0; // Endmost header in location
|
||||||
|
uint32_t idx = -1; // Endmost header's index
|
||||||
|
uint32_t value = 0x0; // Endmost header's value
|
||||||
|
while(i < heap->index.size) {
|
||||||
|
uint32_t tmp = (uint32_t)lookup_ordered_list(i, &heap->index);
|
||||||
|
if(tmp > value) {
|
||||||
|
value = tmp;
|
||||||
|
idx = i;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
// In case we did not find any headers, we need to add one
|
||||||
|
if(idx == -1) {
|
||||||
|
header_t *head = (header_t*)old_end_addr;
|
||||||
|
head->magic = HEAP_MAGIC;
|
||||||
|
head->size = new_len - old_len;
|
||||||
|
head->is_hole = 1;
|
||||||
|
footer_t *foot = (footer_t*) (old_end_addr + head->size - sizeof(footer_t));
|
||||||
|
foot->magic = HEAP_MAGIC;
|
||||||
|
foot->header = head;
|
||||||
|
insert_ordered_list((void*)head, &heap->index);
|
||||||
|
} else {
|
||||||
|
header_t *head = lookup_ordered_list(idx, &heap->index);
|
||||||
|
head->size += new_len - old_len;
|
||||||
|
// Rewrite the footer
|
||||||
|
footer_t *foot = (footer_t*) ((uint32_t)head + head->size - sizeof(footer_t));
|
||||||
|
foot->header = head;
|
||||||
|
foot->magic = HEAP_MAGIC;
|
||||||
|
}
|
||||||
|
// Now that we have enough space, use recursing to call this function again
|
||||||
|
return alloc(size, page_align, heap);
|
||||||
|
}
|
||||||
|
|
||||||
|
header_t *origin_hole_header = (header_t*)lookup_ordered_list(i, &heap->index);
|
||||||
|
uint32_t origin_hole_p = (uint32_t)origin_hole_header;
|
||||||
|
uint32_t origin_hole_s = origin_hole_header->size;
|
||||||
|
// Now check if we should split the hole into two parts
|
||||||
|
if(origin_hole_s-new_size < sizeof(header_t)+sizeof(header_t)) {
|
||||||
|
size += origin_hole_s-new_size;
|
||||||
|
new_size = origin_hole_s;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now check if we need page-aligned data
|
||||||
|
if(page_align && origin_hole_p&0xFFFFF000) {
|
||||||
|
uint32_t new_location = origin_hole_p + 0x1000 - (origin_hole_p&0xFFF) - sizeof(header_t);
|
||||||
|
header_t *hole_header = (header_t*)origin_hole_p;
|
||||||
|
hole_header -= 0x1000 - (origin_hole_p&0xFFF) - sizeof(header_t);
|
||||||
|
hole_header->magic = HEAP_MAGIC;
|
||||||
|
hole_header->is_hole = 1;
|
||||||
|
footer_t *hole_footer = (footer_t*) ((uint32_t)new_location - sizeof(footer_t));
|
||||||
|
hole_footer->magic = HEAP_MAGIC;
|
||||||
|
hole_footer->header = hole_header;
|
||||||
|
origin_hole_p = new_location;
|
||||||
|
origin_hole_s = origin_hole_s - hole_header->size;
|
||||||
|
} else // Otherwise delete this hole from the index since we don't need it anymore
|
||||||
|
remove_ordered_list(i, &heap->index);
|
||||||
|
|
||||||
|
// Since we're creating a new hole at the old hole's address we can reuse the old hole
|
||||||
|
header_t *block_header = (header_t*)origin_hole_p;
|
||||||
|
block_header->magic = HEAP_MAGIC;
|
||||||
|
block_header->is_hole = 0;
|
||||||
|
block_header->size = new_size;
|
||||||
|
// Now overwrite original footer
|
||||||
|
footer_t *block_footer = (footer_t*)(origin_hole_p + sizeof(header_t) + size);
|
||||||
|
block_footer->magic = HEAP_MAGIC;
|
||||||
|
block_footer->header = block_header;
|
||||||
|
|
||||||
|
// If the new block have positive size, then write a new hole after new block
|
||||||
|
if(origin_hole_s - new_size > 0) {
|
||||||
|
header_t *hole_head = (header_t*)(origin_hole_p * sizeof(header_t) + size + sizeof(footer_t));
|
||||||
|
hole_head->magic = HEAP_MAGIC;
|
||||||
|
hole_head->is_hole = 1;
|
||||||
|
hole_head->size = origin_hole_s - (new_size);
|
||||||
|
footer_t *hole_foot = (footer_t*)((uint32_t)hole_head + origin_hole_s - new_size - sizeof(footer_t));
|
||||||
|
if((uint32_t)hole_foot < heap->end_address) {
|
||||||
|
hole_foot->magic = HEAP_MAGIC;
|
||||||
|
hole_foot->header = hole_head;
|
||||||
|
}
|
||||||
|
insert_ordered_list((void*)hole_head, &heap->index);
|
||||||
|
}
|
||||||
|
// Finally, return the new hole
|
||||||
|
return (void*)(uint32_t)block_header+sizeof(header_t));
|
||||||
|
}
|
@ -1,3 +1,17 @@
|
|||||||
|
/**************************************
|
||||||
|
* iceOS Kernel *
|
||||||
|
* Developed by Marco 'icebit' Cetica *
|
||||||
|
* (c) 2019 *
|
||||||
|
* Released under GPLv3 *
|
||||||
|
* https://github.com/ice-bit/iceOS *
|
||||||
|
***************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/*** Heap implementation from James Molloy's tutorial:
|
||||||
|
* http://www.jamesmolloy.co.uk/tutorial_html/7.-The%20Heap.html ***/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* This heap algorithm uses two different data structures: blocks and holes.
|
/* This heap algorithm uses two different data structures: blocks and holes.
|
||||||
* Blocks: Contiguous areas of memory containing user data
|
* Blocks: Contiguous areas of memory containing user data
|
||||||
* Holes: Special kind of blocks that are not in use, this is the result
|
* Holes: Special kind of blocks that are not in use, this is the result
|
||||||
|
@ -34,7 +34,7 @@ void destroy_ordered_list(ordered_list_t *array) {
|
|||||||
|
|
||||||
// Insert item into the array
|
// Insert item into the array
|
||||||
void insert_ordered_list(type_t item, ordered_list_t *array) {
|
void insert_ordered_list(type_t item, ordered_list_t *array) {
|
||||||
ASSERT(array->less_then); // TODO: implement assert
|
ASSERT(array->less_then);
|
||||||
uint32_t iterator = 0;
|
uint32_t iterator = 0;
|
||||||
while(iterator < array->size && array->less_then(array->array[iterator], item))
|
while(iterator < array->size && array->less_then(array->array[iterator], item))
|
||||||
iterator++;
|
iterator++;
|
||||||
|
@ -1,3 +1,10 @@
|
|||||||
|
/**************************************
|
||||||
|
* iceOS Kernel *
|
||||||
|
* Developed by Marco 'icebit' Cetica *
|
||||||
|
* (c) 2019 *
|
||||||
|
* Released under GPLv3 *
|
||||||
|
* https://github.com/ice-bit/iceOS *
|
||||||
|
***************************************/
|
||||||
#ifndef ORDERED_LIST
|
#ifndef ORDERED_LIST
|
||||||
#define ORDERED_LIST
|
#define ORDERED_LIST
|
||||||
|
|
||||||
|
@ -69,6 +69,29 @@ void kprint(uint8_t *buf) {
|
|||||||
kprint_c(buf, strlen(buf), WHITE, BLACK);
|
kprint_c(buf, strlen(buf), WHITE, BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void kprint_dec(uint32_t num) {
|
||||||
|
if(num == 0) {
|
||||||
|
const uint8_t buf = (uint8_t)'0';
|
||||||
|
kprint_c(buf, strlen(buf), WHITE, BLACK);;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int32_t acc = num;
|
||||||
|
uint8_t c[32];
|
||||||
|
uint32_t i = 0;
|
||||||
|
while(acc > 0) {
|
||||||
|
c[i] = '0' + acc%10;
|
||||||
|
acc /= 10;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
c[i] = 0;
|
||||||
|
uint8_t c2[32];
|
||||||
|
c2[i--] = 0;
|
||||||
|
uint32_t j = 0;
|
||||||
|
while(i >= 0)
|
||||||
|
c2[i--] = c[j++];
|
||||||
|
kprint(c2);
|
||||||
|
}
|
||||||
|
|
||||||
void init_prompt() {
|
void init_prompt() {
|
||||||
uint8_t *prompt = (uint8_t*)"\nring0@iceOS-$ ";
|
uint8_t *prompt = (uint8_t*)"\nring0@iceOS-$ ";
|
||||||
kprint_c(prompt, strlen(prompt), LIGHT_RED, BLACK);
|
kprint_c(prompt, strlen(prompt), LIGHT_RED, BLACK);
|
||||||
|
@ -53,6 +53,7 @@ void cursor_adv();
|
|||||||
void backspace();
|
void backspace();
|
||||||
void kprint_c(uint8_t *buf, uint32_t len, uint8_t fg, uint8_t bg);
|
void kprint_c(uint8_t *buf, uint32_t len, uint8_t fg, uint8_t bg);
|
||||||
void kprint(uint8_t *buf);
|
void kprint(uint8_t *buf);
|
||||||
|
void kprint_dec(uint32_t num);
|
||||||
void init_prompt();
|
void init_prompt();
|
||||||
void clear_prompt();
|
void clear_prompt();
|
||||||
void clear_row(uint8_t row);
|
void clear_row(uint8_t row);
|
||||||
|
Loading…
Reference in New Issue
Block a user