1

merged cleanup

This commit is contained in:
2022-07-24 21:12:31 +02:00
parent 5ff3d72bfd
commit 6481bae5f6
92 changed files with 663 additions and 755 deletions

View File

@ -20,8 +20,8 @@ void BumpAllocator::init() {
/* Hier muess Code eingefuegt werden */
this->allocations = 0;
this->next = (unsigned char*)heap_start;
allocations = 0;
next = reinterpret_cast<unsigned char*>(heap_start);
log.info() << "Initialized Bump Allocator" << endl;
}
@ -36,8 +36,8 @@ void BumpAllocator::dump_free_memory() {
/* Hier muess Code eingefuegt werden */
kout << "Freier Speicher:" << endl
<< " - Next: " << hex << (unsigned int)this->next
<< ", Allocations: " << dec << this->allocations << endl;
<< " - Next: " << hex << reinterpret_cast<unsigned int>(next)
<< ", Allocations: " << dec << allocations << endl;
}
/*****************************************************************************
@ -51,14 +51,14 @@ void* BumpAllocator::alloc(unsigned int req_size) {
log.debug() << "Requested " << hex << req_size << " Bytes" << endl;
if (req_size + (unsigned int)this->next > this->heap_end) {
if (req_size + reinterpret_cast<unsigned int>(next) > heap_end) {
log.error() << " - More memory requested than available :(" << endl;
return nullptr;
}
void* allocated = this->next;
this->next = (unsigned char*)((unsigned int)this->next + req_size);
this->allocations = this->allocations + 1;
void* allocated = next;
next = reinterpret_cast<unsigned char*>(reinterpret_cast<unsigned int>(next) + req_size);
allocations = allocations + 1;
log.trace() << " - Allocated " << hex << req_size << " Bytes." << endl;
@ -71,5 +71,5 @@ void* BumpAllocator::alloc(unsigned int req_size) {
* Beschreibung: Nicht implementiert. *
*****************************************************************************/
void BumpAllocator::free(void* ptr) {
log.error() << " mm_free: ptr= " << hex << (unsigned int)ptr << ", not supported" << endl;
log.error() << " mm_free: ptr= " << hex << reinterpret_cast<unsigned int>(ptr) << ", not supported" << endl;
}

View File

@ -9,8 +9,8 @@
* Autor: Michael Schoettner, HHU, 3.3.2022 *
*****************************************************************************/
#ifndef __BumpAllocator_include__
#define __BumpAllocator_include__
#ifndef BumpAllocator_include__
#define BumpAllocator_include__
#include "kernel/Allocator.h"
#include "user/lib/Logger.h"
@ -27,6 +27,8 @@ public:
BumpAllocator() : log("BMP-Alloc") {}; // Allocator() called implicitely in C++
// ~BumpAllocator() override = default;
void init() override;
void dump_free_memory() override;
void* alloc(unsigned int req_size) override;

View File

@ -32,10 +32,10 @@ void LinkedListAllocator::init() {
/* Hier muess Code eingefuegt werden */
this->free_start = (free_block_t*)this->heap_start;
this->free_start->allocated = false;
this->free_start->size = this->heap_size - sizeof(free_block_t);
this->free_start->next = this->free_start; // Only one block, points to itself
free_start = reinterpret_cast<free_block_t*>(heap_start);
free_start->allocated = false;
free_start->size = heap_size - sizeof(free_block_t);
free_start->next = free_start; // Only one block, points to itself
log.info() << "Initialized LinkedList Allocator" << endl;
}
@ -51,14 +51,14 @@ void LinkedListAllocator::dump_free_memory() {
kout << "Freier Speicher:" << endl;
if (this->free_start == nullptr) {
if (free_start == nullptr) {
kout << " - No free Blocks" << endl;
} else {
kout << " - Freelist start: " << hex << (unsigned int)this->free_start << endl;
kout << " - Freelist start: " << hex << reinterpret_cast<unsigned int>(free_start) << endl;
free_block_t* current = this->free_start;
free_block_t* current = free_start;
do {
kout << " - Free Block (Start: " << hex << (unsigned int)current
kout << " - Free Block (Start: " << hex << reinterpret_cast<unsigned int>(current)
<< " Size: " << hex << current->size << ")" << endl;
current = current->next;
} while (current != free_start);
@ -71,16 +71,16 @@ void LinkedListAllocator::dump_free_memory() {
* Beschreibung: Einen neuen Speicherblock allozieren. *
*****************************************************************************/
void* LinkedListAllocator::alloc(unsigned int req_size) {
this->lock.acquire();
lock.acquire();
/* Hier muess Code eingefuegt werden */
// NOTE: next pointer zeigt auf headeranfang, returned wird zeiger auf anfang des nutzbaren freispeichers
log.debug() << "Requested " << hex << req_size << " Bytes" << endl;
if (this->free_start == nullptr) {
if (free_start == nullptr) {
log.error() << " - No free memory remaining :(" << endl;
this->lock.release();
lock.release();
return nullptr;
}
@ -91,7 +91,7 @@ void* LinkedListAllocator::alloc(unsigned int req_size) {
log.trace() << " - Rounded to word border (+" << dec << req_size_diff << " bytes)" << endl;
}
free_block_t* current = this->free_start;
free_block_t* current = free_start;
do {
if (current->size >= rreq_size) { // Size doesn't contain header, only usable
// Current block large enough
@ -106,7 +106,7 @@ void* LinkedListAllocator::alloc(unsigned int req_size) {
// In case of only one freeblock:
// [current | new_next]
free_block_t* new_next =
(free_block_t*)((unsigned int)current + sizeof(free_block_t) + rreq_size);
reinterpret_cast<free_block_t*>(reinterpret_cast<unsigned int>(current) + sizeof(free_block_t) + rreq_size);
// If only one block exists, current->next is current
// This shouldn't be a problem since the block gets removed from the list later
@ -118,18 +118,18 @@ void* LinkedListAllocator::alloc(unsigned int req_size) {
current->size = rreq_size;
// Next-fit
this->free_start = new_next;
free_start = new_next;
log.trace() << " - Allocated " << hex << rreq_size << " Bytes with cutting" << endl;
} else {
// Block too small to be cut, allocate whole block
// Next-fit
this->free_start = current->next; // Pointer keeps pointing to current if last block
if (this->free_start == current) {
free_start = current->next; // Pointer keeps pointing to current if last block
if (free_start == current) {
// No free block remaining
log.trace() << " - Disabled freelist" << endl;
this->free_start = nullptr;
free_start = nullptr;
}
log.trace() << " - Allocated " << hex << current->size << " Bytes without cutting" << endl;
@ -155,16 +155,16 @@ void* LinkedListAllocator::alloc(unsigned int req_size) {
// }
// log.debug() << "Finished check" << endl;
log.debug() << "Returning memory address " << hex << ((unsigned int)current + sizeof(free_block_t)) << endl;
this->lock.release();
return (void*)((unsigned int)current + sizeof(free_block_t)); // Speicheranfang, nicht header
log.debug() << "returning memory address " << hex << reinterpret_cast<unsigned int>(current) + sizeof(free_block_t) << endl;
lock.release();
return reinterpret_cast<void*>(reinterpret_cast<unsigned int>(current) + sizeof(free_block_t)); // Speicheranfang, nicht header
}
current = current->next;
} while (current != this->free_start); // Stop when arriving at the first block again
} while (current != free_start); // Stop when arriving at the first block again
log.error() << " - More memory requested than available :(" << endl;
this->lock.release();
lock.release();
return nullptr;
}
@ -174,35 +174,35 @@ void* LinkedListAllocator::alloc(unsigned int req_size) {
* Beschreibung: Einen Speicherblock freigeben. *
*****************************************************************************/
void LinkedListAllocator::free(void* ptr) {
this->lock.acquire();
lock.acquire();
/* Hier muess Code eingefuegt werden */
// Account for header
free_block_t* block_start = (free_block_t*)((unsigned int)ptr - sizeof(free_block_t));
free_block_t* block_start = reinterpret_cast<free_block_t*>(reinterpret_cast<unsigned int>(ptr) - sizeof(free_block_t));
log.debug() << "Freeing " << hex << (unsigned int)ptr << ", Size: " << block_start->size << endl;
log.debug() << "Freeing " << hex << reinterpret_cast<unsigned int>(ptr) << ", Size: " << block_start->size << endl;
if (!block_start->allocated) {
log.error() << "Block already free" << endl;
this->lock.release();
lock.release();
return;
}
// Reenable the freelist if no block was available
// This also means that no merging can be done
if (this->free_start == nullptr) {
this->free_start = block_start;
if (free_start == nullptr) {
free_start = block_start;
block_start->allocated = false;
block_start->next = block_start;
log.trace() << " - Enabling freelist with one block" << endl;
this->lock.release();
lock.release();
return;
}
free_block_t* next_block =
(free_block_t*)((unsigned int)block_start + sizeof(free_block_t) + block_start->size);
reinterpret_cast<free_block_t*>(reinterpret_cast<unsigned int>(block_start) + sizeof(free_block_t) + block_start->size);
// Find the next free block, multiple next blocks can be allocated so walk through them
free_block_t* next_free = block_start->next;
@ -212,7 +212,7 @@ void LinkedListAllocator::free(void* ptr) {
free_block_t* previous_free = LinkedListAllocator::find_previous_block(next_free);
free_block_t* previous_free_next =
(free_block_t*)((unsigned int)previous_free + sizeof(free_block_t) + previous_free->size);
reinterpret_cast<free_block_t*>(reinterpret_cast<unsigned int>(previous_free) + sizeof(free_block_t) + previous_free->size);
// We have: [previous_free | previous_free_next | <> | block_start | next_block | <> | next_free]
// The <> spaces don't have to exist and next_block could be the same as next_free
@ -254,10 +254,10 @@ void LinkedListAllocator::free(void* ptr) {
// If thats the case I should set the next pointer to the next adjacent block
// when allocating a new block
if (this->free_start == next_free) {
if (free_start == next_free) {
// next_free is now invalid after merge
log.trace() << " - Moving freelist start to " << hex << (unsigned int)block_start << endl;
this->free_start = block_start;
log.trace() << " - Moving freelist start to " << hex << reinterpret_cast<unsigned int>(block_start) << endl;
free_start = block_start;
}
} else {
// Can't merge forward so size stays the same
@ -283,16 +283,16 @@ void LinkedListAllocator::free(void* ptr) {
// For pointers to block_start the same as above applies
// so I don't think I have to manage anything else here
if (this->free_start == block_start) {
if (free_start == block_start) {
// block_start is now invalid after merge
log.trace() << " - Moving freelist start to " << hex << (unsigned int)previous_free << endl;
this->free_start = previous_free;
log.trace() << " - Moving freelist start to " << hex << reinterpret_cast<unsigned int>(previous_free) << endl;
free_start = previous_free;
}
}
// Depending on the merging this might write into the block, but doesn't matter
block_start->allocated = false;
this->lock.release();
lock.release();
}
free_block_t* LinkedListAllocator::find_previous_block(free_block_t* next_block) {

View File

@ -9,8 +9,8 @@
* Autor: Michael Schoettner, HHU, 13.6.2020 *
*****************************************************************************/
#ifndef __LinkedListAllocator_include__
#define __LinkedListAllocator_include__
#ifndef LinkedListAllocator_include__
#define LinkedListAllocator_include__
#include "kernel/Allocator.h"
#include "lib/SpinLock.h"
@ -47,6 +47,8 @@ public:
LinkedListAllocator() : log("LL-Alloc") {}
// ~LinkedListAllocator() override = default;
void init() override;
void dump_free_memory() override;
void* alloc(unsigned int req_size) override;

View File

@ -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));
}

View File

@ -1,5 +1,5 @@
#ifndef __TreeAllocator_include__
#define __TreeAllocator_include__
#ifndef TreeAllocator_include__
#define TreeAllocator_include__
#include "kernel/Allocator.h"
#include "user/lib/Logger.h"
@ -40,7 +40,7 @@ private:
// Returns the size of the usable memory of a block
unsigned int get_size(list_block_t* block) const;
unsigned int get_size(tree_block_t* block) const { return this->get_size((list_block_t*)block); }
unsigned int get_size(tree_block_t* block) const { return get_size(reinterpret_cast<list_block_t*>(block)); }
void dump_free_memory(tree_block_t* node);
@ -57,10 +57,12 @@ private:
void rbt_fix_remove(tree_block_t* x);
tree_block_t* rbt_search_bestfit(tree_block_t* node, unsigned int req_size);
tree_block_t* rbt_search_bestfit(unsigned int req_size) { return this->rbt_search_bestfit(this->free_start, req_size); }
tree_block_t* rbt_search_bestfit(unsigned int req_size) { return rbt_search_bestfit(free_start, req_size); }
void dll_insert(list_block_t* previous, list_block_t* node);
void dll_insert(tree_block_t* previous, tree_block_t* node) { this->dll_insert((list_block_t*)previous, (list_block_t*)node); }
void dll_insert(tree_block_t* previous, tree_block_t* node) {
dll_insert(reinterpret_cast<list_block_t*>(previous), reinterpret_cast<list_block_t*>(node));
}
void dll_remove(list_block_t* node);
public:
@ -68,6 +70,8 @@ public:
TreeAllocator() : log("RBT-Alloc") {};
// ~TreeAllocator() override = default;
void init() override;
void dump_free_memory() override;
void* alloc(unsigned int req_size) override;

View File

@ -1,12 +1,11 @@
#include "kernel/allocator/TreeAllocator.h"
#include "kernel/Globals.h"
// RBT code taken from https://github.com/Bibeknam/algorithmtutorprograms
// START copy from algorithmtutorprograms
void TreeAllocator::rbt_transplant(tree_block_t* a, tree_block_t* b) {
if (a->parent == nullptr) {
this->free_start = b;
free_start = b;
} else if (a == a->parent->left) {
a->parent->left = b;
} else {
@ -25,11 +24,11 @@ void TreeAllocator::rbt_insert(tree_block_t* node) {
node->red = true; // new node must be red
tree_block_t* y = nullptr;
tree_block_t* x = this->free_start;
tree_block_t* x = free_start;
while (x != nullptr) {
y = x;
if (this->get_size(node) < this->get_size(x)) {
if (get_size(node) < get_size(x)) {
x = x->left;
} else {
x = x->right;
@ -39,8 +38,8 @@ void TreeAllocator::rbt_insert(tree_block_t* node) {
// y is parent of x
node->parent = y;
if (y == nullptr) {
this->free_start = node;
} else if (this->get_size(node) < this->get_size(y)) {
free_start = node;
} else if (get_size(node) < get_size(y)) {
y->left = node;
} else {
y->right = node;
@ -58,7 +57,7 @@ void TreeAllocator::rbt_insert(tree_block_t* node) {
}
// Fix the tree
this->rbt_fix_insert(node);
rbt_fix_insert(node);
}
// fix the red-black tree
@ -77,12 +76,12 @@ void TreeAllocator::rbt_fix_insert(tree_block_t* k) {
if (k == k->parent->left) {
// case 3.2.2
k = k->parent;
this->rbt_rot_r(k);
rbt_rot_r(k);
}
// case 3.2.1
k->parent->red = false;
k->parent->parent->red = true;
this->rbt_rot_l(k->parent->parent);
rbt_rot_l(k->parent->parent);
}
} else {
u = k->parent->parent->right; // uncle
@ -97,19 +96,19 @@ void TreeAllocator::rbt_fix_insert(tree_block_t* k) {
if (k == k->parent->right) {
// mirror case 3.2.2
k = k->parent;
this->rbt_rot_l(k);
rbt_rot_l(k);
}
// mirror case 3.2.1
k->parent->red = false;
k->parent->parent->red = true;
this->rbt_rot_r(k->parent->parent);
rbt_rot_r(k->parent->parent);
}
}
if (k == this->free_start) {
if (k == free_start) {
break;
}
}
this->free_start->red = false;
free_start->red = false;
}
// rotate left at node x
@ -121,7 +120,7 @@ void TreeAllocator::rbt_rot_l(tree_block_t* x) {
}
y->parent = x->parent;
if (x->parent == nullptr) {
this->free_start = y;
free_start = y;
} else if (x == x->parent->left) {
x->parent->left = y;
} else {
@ -140,7 +139,7 @@ void TreeAllocator::rbt_rot_r(tree_block_t* x) {
}
y->parent = x->parent;
if (x->parent == nullptr) {
this->free_start = y;
free_start = y;
} else if (x == x->parent->right) {
x->parent->right = y;
} else {
@ -166,43 +165,43 @@ void TreeAllocator::rbt_remove(tree_block_t* z) {
bool y_original_red = y->red;
if (z->left == nullptr) {
x = z->right;
this->rbt_transplant(z, z->right);
rbt_transplant(z, z->right);
} else if (z->right == nullptr) {
x = z->left;
this->rbt_transplant(z, z->left);
rbt_transplant(z, z->left);
} else {
y = this->rbt_minimum(z->right);
y = rbt_minimum(z->right);
y_original_red = y->red;
x = y->right;
if (y->parent == z) {
x->parent = y;
} else {
this->rbt_transplant(y, y->right);
rbt_transplant(y, y->right);
y->right = z->right;
y->right->parent = y;
}
this->rbt_transplant(z, y);
rbt_transplant(z, y);
y->left = z->left;
y->left->parent = y;
y->red = z->red;
}
if (!y_original_red) {
this->rbt_fix_remove(x);
rbt_fix_remove(x);
}
}
// fix the rb tree modified by the delete operation
void TreeAllocator::rbt_fix_remove(tree_block_t* x) {
tree_block_t* s;
while (x != this->free_start && !x->red) {
while (x != free_start && !x->red) {
if (x == x->parent->left) {
s = x->parent->right;
if (s->red) {
// case 3.1
s->red = false;
x->parent->red = true;
this->rbt_rot_l(x->parent);
rbt_rot_l(x->parent);
s = x->parent->right;
}
@ -215,7 +214,7 @@ void TreeAllocator::rbt_fix_remove(tree_block_t* x) {
// case 3.3
s->left->red = false;
s->red = true;
this->rbt_rot_r(s);
rbt_rot_r(s);
s = x->parent->right;
}
@ -223,8 +222,8 @@ void TreeAllocator::rbt_fix_remove(tree_block_t* x) {
s->red = x->parent->red;
x->parent->red = false;
s->right->red = false;
this->rbt_rot_l(x->parent);
x = this->free_start;
rbt_rot_l(x->parent);
x = free_start;
}
} else {
s = x->parent->left;
@ -232,7 +231,7 @@ void TreeAllocator::rbt_fix_remove(tree_block_t* x) {
// case 3.1
s->red = false;
x->parent->red = true;
this->rbt_rot_r(x->parent);
rbt_rot_r(x->parent);
s = x->parent->left;
}
@ -245,7 +244,7 @@ void TreeAllocator::rbt_fix_remove(tree_block_t* x) {
// case 3.3
s->right->red = false;
s->red = true;
this->rbt_rot_l(s);
rbt_rot_l(s);
s = x->parent->left;
}
@ -253,8 +252,8 @@ void TreeAllocator::rbt_fix_remove(tree_block_t* x) {
s->red = x->parent->red;
x->parent->red = false;
s->left->red = false;
this->rbt_rot_r(x->parent);
x = this->free_start;
rbt_rot_r(x->parent);
x = free_start;
}
}
}
@ -268,17 +267,17 @@ tree_block_t* TreeAllocator::rbt_search_bestfit(tree_block_t* node, unsigned int
return nullptr;
}
if (req_size < this->get_size(node)) {
if (node->left != nullptr && this->get_size(node->left) >= req_size) {
return this->rbt_search_bestfit(node->left, req_size);
if (req_size < get_size(node)) {
if (node->left != nullptr && get_size(node->left) >= req_size) {
return rbt_search_bestfit(node->left, req_size);
}
return node;
}
if (req_size > this->get_size(node)) {
if (node->right != nullptr && this->get_size(node->right) >= req_size) {
return this->rbt_search_bestfit(node->right, req_size);
if (req_size > get_size(node)) {
if (node->right != nullptr && get_size(node->right) >= req_size) {
return rbt_search_bestfit(node->right, req_size);
}
// Block doesn't fit