diff options
| author | Matteo Gmür <matteo.gmuer1@ost.ch> | 2024-12-02 10:17:36 +0000 |
|---|---|---|
| committer | Matteo Gmür <matteo.gmuer1@ost.ch> | 2024-12-02 10:17:36 +0000 |
| commit | a5e5eabd32872f81a7190589aa648dc0e1963888 (patch) | |
| tree | 63d91dc24a3caacbcfd736ec190579e33823a89f /arch/x86_64/src/memory | |
| parent | f880939eb5f1b5e70b15d6614cc440c09a0d9fd1 (diff) | |
| download | teachos-a5e5eabd32872f81a7190589aa648dc0e1963888.tar.xz teachos-a5e5eabd32872f81a7190589aa648dc0e1963888.zip | |
Fix algorithm issues with linked list allocator
Diffstat (limited to 'arch/x86_64/src/memory')
| -rw-r--r-- | arch/x86_64/src/memory/heap/linked_list_allocator.cpp | 64 |
1 files changed, 31 insertions, 33 deletions
diff --git a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp index 07d7e5e..706f43e 100644 --- a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp +++ b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp @@ -27,29 +27,14 @@ namespace teachos::arch::memory::heap exception_handling::assert(size > min_allocatable_size(), "[Linked List Allocator] Allocated memory cannot be smaller than 16 bytes"); - auto & previous = first; - auto & current = first; + memory_block * previous = nullptr; + auto current = first; while (current != nullptr) { if (current->size >= size + min_allocatable_size()) { - return split_free_memory_block(current, size); - } - - if (current->size >= size) - { - if (previous != current) - { - previous->next = current->next; - } - else - { - first = current->next; - } - - clear_memory_block_header(current); - return static_cast<void *>(current); + return split_free_memory_block(previous, current, size); } previous = current; @@ -66,8 +51,8 @@ namespace teachos::arch::memory::heap auto const start_address = reinterpret_cast<std::size_t>(pointer); auto const end_address = start_address + size; - auto & previous = first; - auto & current = first; + memory_block * previous = nullptr; + auto current = first; while (current != nullptr) { @@ -78,23 +63,35 @@ namespace teachos::arch::memory::heap break; } - previous->next = current; + previous = current; current = current->next; } coalesce_free_memory_block(previous, current, pointer, size); } - auto linked_list_allocator::split_free_memory_block(memory_block *& current_block, std::size_t size) -> void * + auto linked_list_allocator::split_free_memory_block(memory_block * previous_block, memory_block * current_block, + std::size_t size) -> void * { auto const start_address = reinterpret_cast<std::size_t>(current_block); auto const end_address = start_address + size; - current_block = + auto const new_block = new (reinterpret_cast<void *>(end_address)) memory_block(current_block->size - size, current_block->next); + // If we want to allocate into the first block that is before any other free block, then there exists no previous + // free block (nullptr). Therefore we have to overwrite the first block instead of overwriting its next value. + if (previous_block == nullptr) + { + first = new_block; + } + else + { + previous_block->next = new_block; + } + clear_memory_block_header(current_block); return reinterpret_cast<void *>(start_address); } - auto linked_list_allocator::coalesce_free_memory_block(memory_block *& previous_block, memory_block *& current_block, + auto linked_list_allocator::coalesce_free_memory_block(memory_block * previous_block, memory_block * current_block, void * pointer, std::size_t size) -> void { auto const start_address = reinterpret_cast<std::size_t>(pointer); @@ -105,14 +102,6 @@ namespace teachos::arch::memory::heap auto block_size = size; auto next_block = current_block; - // Heap memory has been completly used up and therefore the inital free pointer is null and this deallocation will - // result in the first inital pointer in our linked list of free memory blocks. - if (previous_block == nullptr) - { - previous_block = new (pointer) memory_block(block_size, next_block); - return; - } - // If the block we want to deallocate is before another free block and we can therefore combine both into one. // This is done by deleting the current free block and creating a new block at the start address of the block to // deallocate with both the size of the block to deallcoate and the free block next to it. @@ -127,7 +116,8 @@ namespace teachos::arch::memory::heap // If the block we want to deallocate is behind another free block and we can therefore combine both into one. // This is done by simply changin the size of the previous block to include the size of the block to deallocate. // This is done, because the previous block might still be referencered by the next field of other memory blocks. - if (start_address == (reinterpret_cast<std::size_t>(previous_block) + previous_block->size)) + if (previous_block != nullptr && + start_address == (reinterpret_cast<std::size_t>(previous_block) + previous_block->size)) { block_size += previous_block->size; @@ -137,6 +127,14 @@ namespace teachos::arch::memory::heap } auto const new_block = new (pointer) memory_block(block_size, next_block); + // If we want to deallocate the first block that is before any other free block, then there exists no previous free + // block (nullptr). Therefore we have to overwrite the first block instead of overwriting its + // next value. + if (previous_block == nullptr) + { + first = new_block; + return; + } previous_block->next = new_block; } |
