summaryrefslogtreecommitdiff
path: root/src/kernel/mem/heap.c
diff options
context:
space:
mode:
authorAlexis211 <alexis211@gmail.com>2010-09-10 18:46:00 +0200
committerAlexis211 <alexis211@gmail.com>2010-09-10 18:46:00 +0200
commitaba6ed4b91aff5d914be11704e34de75bfd4d003 (patch)
tree3d5cf90e9ccad09d352c6a61e90027ef552dd87f /src/kernel/mem/heap.c
parent5fc3baaa17a6ffb34490bb8accb86f53ef3d6d15 (diff)
downloadTCE-aba6ed4b91aff5d914be11704e34de75bfd4d003.tar.gz
TCE-aba6ed4b91aff5d914be11704e34de75bfd4d003.zip
Each thread has its own stack. Added simple unit tests for kmalloc,kfree
Found a bug in heap_contract (not sure) but didn't fix it.
Diffstat (limited to 'src/kernel/mem/heap.c')
-rw-r--r--src/kernel/mem/heap.c26
1 files changed, 18 insertions, 8 deletions
diff --git a/src/kernel/mem/heap.c b/src/kernel/mem/heap.c
index b7f6c97..79ef81e 100644
--- a/src/kernel/mem/heap.c
+++ b/src/kernel/mem/heap.c
@@ -1,5 +1,8 @@
#include "heap.h"
#include "paging.h"
+#include <core/sys.h>
+
+#include <lib/stdlib.h>
#define HEAP_MAGIC 0xBAD0BEEF
#define HEAP_MIN_SIZE 0x4000
@@ -11,7 +14,7 @@ static void heapIdx_insert(struct heap *heap, struct heap_header *e) {
if ((heap->idxused + sizeof(struct heap_header*) + (size_t)heap->idx) >= heap->start_addr) return;
uint32_t iterator = 0, pos;
- while (iterator < heap->idxused && heap->idx[iterator]->size < e->size) {
+ while (iterator < heap->idxused && heap->idx[iterator]->size <= e->size) {
if (heap->idx[iterator] == e) return;
iterator++;
}
@@ -122,15 +125,19 @@ static uint32_t heap_expand(struct heap *heap, size_t quantity) {
/* For internal use only. Called by heap_free when necessary. Reduces the heap's size. */
static void heap_contract(struct heap *heap) {
+ return; //TODO: this function bugs everything
+
+
struct heap_footer *last_footer = (struct heap_footer*)(heap->end_addr - sizeof(struct heap_footer));
struct heap_header *last_header = last_footer->header;
if (last_header->is_hole == 0) return;
+ if (last_header->size <= 0x1000) return;
- size_t quantity = 0;
- while ((heap->end_addr - heap->start_addr) - quantity > HEAP_MIN_SIZE &&
- (last_header->size - quantity) > 0x1000)
- quantity += 0x1000;
+ size_t quantity = ((heap->end_addr - heap->start_addr) & 0xFFFFF000) - 0x1000;
+ while ((heap->end_addr - heap->start_addr) - quantity < HEAP_MIN_SIZE ||
+ last_header->size - 0x4000 < quantity)
+ quantity -= 0x1000;
if (quantity == 0) return;
size_t newEnd = heap->end_addr - quantity;
@@ -149,6 +156,7 @@ static void heap_contract(struct heap *heap) {
/* Alocate some bytes on the heap. */
void* heap_alloc(struct heap *heap, size_t sz) {
+ ASSERT(heap > 0xE0000000);
size_t newsize = sz + sizeof(struct heap_header) + sizeof(struct heap_footer);
uint32_t iterator = 0;
@@ -158,17 +166,19 @@ void* heap_alloc(struct heap *heap, size_t sz) {
}
if (iterator == heap->idxused) { //No hole is big enough
- if (heap_expand(heap, (sz & 0xFFFFF000) + 0x1000) == 0) return 0; //FAILED
+ if (heap_expand(heap,
+ MAX((heap->end_addr - heap->start_addr) & 0xFFFFF000, (newsize & 0xFFFFF000) + 0x1000)
+ ) == 0) return 0; //FAILED
return heap_alloc(heap, sz);
}
struct heap_header *loc = heap->idx[iterator];
+ heapIdx_remove(heap, loc);
struct heap_footer *footer = (struct heap_footer*)((size_t)loc + loc->size - sizeof(struct heap_footer));
loc->is_hole = 0;
- heapIdx_remove(heap, loc);
//If we have enough space to create a USEFUL new hole next to the allocated block, do it.
- //If we do not, we might return a block that is a few bytes bigger than neede.
+ //If we do not, we might return a block that is a few bytes bigger than needed.
if (loc->size > (newsize + sizeof(struct heap_header) + sizeof(struct heap_footer))) {
loc->size = newsize;