merged cleanup
This commit is contained in:
@ -2,27 +2,29 @@
|
||||
#include "kernel/Globals.h"
|
||||
|
||||
void TreeAllocator::init() {
|
||||
this->free_start = (tree_block_t*)this->heap_start;
|
||||
this->free_start->allocated = false;
|
||||
this->free_start->left = nullptr;
|
||||
this->free_start->right = nullptr;
|
||||
this->free_start->parent = nullptr;
|
||||
this->free_start->red = false; // The root is always black
|
||||
this->free_start->next = (list_block_t*)this->free_start;
|
||||
this->free_start->previous = (list_block_t*)this->free_start;
|
||||
free_start = reinterpret_cast<tree_block_t*>(heap_start);
|
||||
free_start->allocated = false;
|
||||
free_start->left = nullptr;
|
||||
free_start->right = nullptr;
|
||||
free_start->parent = nullptr;
|
||||
free_start->red = false; // The root is always black
|
||||
free_start->next = reinterpret_cast<list_block_t*>(free_start);
|
||||
free_start->previous = reinterpret_cast<list_block_t*>(free_start);
|
||||
|
||||
log.info() << "Initialized Tree Allocator" << endl;
|
||||
}
|
||||
|
||||
void TreeAllocator::dump_free_memory() {
|
||||
kout << "Free Memory:" << endl;
|
||||
list_block_t* current = (list_block_t*)this->heap_start;
|
||||
list_block_t* current = reinterpret_cast<list_block_t*>(heap_start);
|
||||
do {
|
||||
if (!current->allocated) {
|
||||
kout << " - Free Block at " << (unsigned int)current << ", Size: " << (unsigned int)current->next - (unsigned int)current << endl;
|
||||
kout << " - Free Block at " << reinterpret_cast<unsigned int>(current) << ", Size: "
|
||||
<< reinterpret_cast<unsigned int>(current->next) - reinterpret_cast<unsigned int>(current)
|
||||
<< endl;
|
||||
}
|
||||
current = current->next;
|
||||
} while ((unsigned int)current != this->heap_start);
|
||||
} while (reinterpret_cast<unsigned int>(current) != heap_start);
|
||||
}
|
||||
|
||||
void* TreeAllocator::alloc(unsigned int req_size) {
|
||||
@ -43,7 +45,7 @@ void* TreeAllocator::alloc(unsigned int req_size) {
|
||||
}
|
||||
|
||||
// Finds smallest block that is large enough
|
||||
tree_block_t* best_fit = this->rbt_search_bestfit(rreq_size);
|
||||
tree_block_t* best_fit = rbt_search_bestfit(rreq_size);
|
||||
if (best_fit == nullptr) {
|
||||
log.error() << " - No block found" << endl;
|
||||
return nullptr;
|
||||
@ -54,8 +56,8 @@ void* TreeAllocator::alloc(unsigned int req_size) {
|
||||
return nullptr;
|
||||
}
|
||||
best_fit->allocated = true;
|
||||
unsigned int size = this->get_size(best_fit);
|
||||
log.trace() << " - Found best-fit: " << hex << (unsigned int)best_fit << endl;
|
||||
unsigned int size = get_size(best_fit);
|
||||
log.trace() << " - Found best-fit: " << hex << reinterpret_cast<unsigned int>(best_fit) << endl;
|
||||
|
||||
// HACK: I didn't want to handle situations with only one block (where the tree root would
|
||||
// get removed), so I make sure there are always at least 2 blocks by inserting a dummy
|
||||
@ -63,19 +65,20 @@ void* TreeAllocator::alloc(unsigned int req_size) {
|
||||
// I should change this so it only happens when only one block exists in the freelist
|
||||
tree_block_t dummy;
|
||||
dummy.allocated = false;
|
||||
this->rbt_insert(&dummy); // I use the address of the stack allocated struct because it is
|
||||
rbt_insert(&dummy); // I use the address of the stack allocated struct because it is
|
||||
// removed before exiting the function
|
||||
|
||||
this->rbt_remove(best_fit); // BUG: Can trigger bluescreen
|
||||
rbt_remove(best_fit); // BUG: Can trigger bluescreen
|
||||
if (size > HEAP_MIN_FREE_BLOCK_SIZE + rreq_size + sizeof(list_block_t)) {
|
||||
// Block can be cut
|
||||
log.trace() << " - Allocating " << dec << rreq_size << " Bytes with cutting" << endl;
|
||||
|
||||
// [best_fit_start | sizeof(list_block_t) | rreq_size | new_block_start]
|
||||
tree_block_t* new_block = (tree_block_t*)((char*)best_fit + sizeof(list_block_t) + rreq_size);
|
||||
tree_block_t* new_block
|
||||
= reinterpret_cast<tree_block_t*>(reinterpret_cast<char*>(best_fit) + sizeof(list_block_t) + rreq_size);
|
||||
new_block->allocated = false;
|
||||
this->dll_insert(best_fit, new_block);
|
||||
this->rbt_insert(new_block);
|
||||
dll_insert(best_fit, new_block);
|
||||
rbt_insert(new_block);
|
||||
} else {
|
||||
// Don't cut block
|
||||
// The block is already correctly positioned in the linked list so we only
|
||||
@ -84,16 +87,18 @@ void* TreeAllocator::alloc(unsigned int req_size) {
|
||||
}
|
||||
|
||||
// HACK: Remove the dummy element
|
||||
this->rbt_remove(&dummy);
|
||||
rbt_remove(&dummy);
|
||||
|
||||
log.trace() << " - Returned address " << hex << (unsigned int)((char*)best_fit + sizeof(list_block_t)) << endl;
|
||||
return (void*)((char*)best_fit + sizeof(list_block_t));
|
||||
log.trace() << " - Returned address " << hex
|
||||
<< reinterpret_cast<unsigned int>(reinterpret_cast<char*>(best_fit) + sizeof(list_block_t))
|
||||
<< endl;
|
||||
return reinterpret_cast<void*>(reinterpret_cast<char*>(best_fit) + sizeof(list_block_t));
|
||||
}
|
||||
|
||||
void TreeAllocator::free(void* ptr) {
|
||||
log.info() << "Freeing " << hex << (unsigned int)ptr << endl;
|
||||
log.info() << "Freeing " << hex << reinterpret_cast<unsigned int>(ptr) << endl;
|
||||
|
||||
list_block_t* block = (list_block_t*)((char*)ptr - sizeof(list_block_t));
|
||||
list_block_t* block = reinterpret_cast<list_block_t*>(reinterpret_cast<char*>(ptr) - sizeof(list_block_t));
|
||||
if (!block->allocated) {
|
||||
// Block already free
|
||||
return;
|
||||
@ -105,25 +110,25 @@ void TreeAllocator::free(void* ptr) {
|
||||
|
||||
if (next->allocated && previous->allocated) {
|
||||
// No merge
|
||||
this->rbt_insert((tree_block_t*)block);
|
||||
rbt_insert(reinterpret_cast<tree_block_t*>(block));
|
||||
return;
|
||||
}
|
||||
|
||||
// HACK: Same as when allocating
|
||||
tree_block_t dummy;
|
||||
dummy.allocated = false;
|
||||
this->rbt_insert(&dummy); // I use the address of the stack allocated struct because it is
|
||||
rbt_insert(&dummy); // I use the address of the stack allocated struct because it is
|
||||
|
||||
if (!next->allocated) {
|
||||
// Merge forward
|
||||
log.trace() << " - Merging forward" << endl;
|
||||
|
||||
// Remove the next block from all lists as it is now part of our freed block
|
||||
this->dll_remove(next);
|
||||
this->rbt_remove((tree_block_t*)next); // BUG: Bluescreen if next is the only block in the freelist
|
||||
dll_remove(next);
|
||||
rbt_remove(reinterpret_cast<tree_block_t*>(next)); // BUG: Bluescreen if next is the only block in the freelist
|
||||
if (previous->allocated) {
|
||||
// Don't insert if removed later because of backward merge
|
||||
this->rbt_insert((tree_block_t*)block);
|
||||
rbt_insert(reinterpret_cast<tree_block_t*>(block));
|
||||
}
|
||||
}
|
||||
|
||||
@ -133,26 +138,26 @@ void TreeAllocator::free(void* ptr) {
|
||||
|
||||
// Remove the current block from all lists as it is now part of the previous block
|
||||
// It doesn't have to be removed from rbt as it wasn't in there as it was allocated before
|
||||
this->dll_remove(block);
|
||||
this->rbt_remove((tree_block_t*)previous);
|
||||
this->rbt_insert((tree_block_t*)previous); // Reinsert with new size
|
||||
dll_remove(block);
|
||||
rbt_remove(reinterpret_cast<tree_block_t*>(previous));
|
||||
rbt_insert(reinterpret_cast<tree_block_t*>(previous)); // Reinsert with new size
|
||||
}
|
||||
|
||||
// HACK: Same as when allocating
|
||||
this->rbt_remove(&dummy);
|
||||
rbt_remove(&dummy);
|
||||
}
|
||||
|
||||
unsigned int TreeAllocator::get_size(list_block_t* block) const {
|
||||
if (block->next == block) {
|
||||
// Only one block exists
|
||||
return this->heap_end - ((unsigned int)block + sizeof(list_block_t));
|
||||
return heap_end - (reinterpret_cast<unsigned int>(block) + sizeof(list_block_t));
|
||||
}
|
||||
|
||||
if ((unsigned int)block->next > (unsigned int)block) {
|
||||
if (reinterpret_cast<unsigned int>(block->next) > reinterpret_cast<unsigned int>(block)) {
|
||||
// Next block is placed later in memory
|
||||
return (unsigned int)block->next - ((unsigned int)block + sizeof(list_block_t));
|
||||
return reinterpret_cast<unsigned int>(block->next) - (reinterpret_cast<unsigned int>(block) + sizeof(list_block_t));
|
||||
}
|
||||
|
||||
// Next block is placed earlier in memory which means block is at memory end
|
||||
return (unsigned int)this->heap_end - ((unsigned int)block + sizeof(list_block_t));
|
||||
return reinterpret_cast<unsigned int>(heap_end) - (reinterpret_cast<unsigned int>(block) + sizeof(list_block_t));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user