diff options
| author | Matteo Gmür <matteo.gmuer1@ost.ch> | 2025-05-11 08:48:57 +0000 |
|---|---|---|
| committer | Matteo Gmür <matteo.gmuer1@ost.ch> | 2025-05-11 08:48:57 +0000 |
| commit | 833cd6446d9981a262959749c0e248e33b54c174 (patch) | |
| tree | 4378760ddf5d6034d2c702274a6757940e7afe44 /arch/x86_64/src | |
| parent | 955ab48fe6329b2cbc8c5855a8ba7290185d0ea3 (diff) | |
| download | teachos-833cd6446d9981a262959749c0e248e33b54c174.tar.xz teachos-833cd6446d9981a262959749c0e248e33b54c174.zip | |
Adjust user heap allocator with expanding heap functionality
Diffstat (limited to 'arch/x86_64/src')
3 files changed, 70 insertions, 5 deletions
diff --git a/arch/x86_64/src/context_switching/syscall/main.cpp b/arch/x86_64/src/context_switching/syscall/main.cpp index 93fc613..996d7fb 100644 --- a/arch/x86_64/src/context_switching/syscall/main.cpp +++ b/arch/x86_64/src/context_switching/syscall/main.cpp @@ -2,7 +2,7 @@ namespace teachos::arch::context_switching::syscall { - auto syscall(type syscall_number, arguments args) -> error + auto syscall(type syscall_number, arguments args) -> response { asm volatile("mov %[input], %%rax" : /* no output from call */ @@ -18,9 +18,18 @@ namespace teachos::arch::context_switching::syscall asm volatile("syscall"); - error error{}; - asm volatile("mov %%rax, %[output]" : [output] "=m"(error)); - return error; + error error_code{}; + asm volatile("mov %%rax, %[output]" : [output] "=m"(error_code)); + + arguments values{}; + asm volatile("mov %%rdi, %[output]" : [output] "=m"(values.arg_0)); + asm volatile("mov %%rsi, %[output]" : [output] "=m"(values.arg_1)); + asm volatile("mov %%rdx, %[output]" : [output] "=m"(values.arg_2)); + asm volatile("mov %%r10, %[output]" : [output] "=m"(values.arg_3)); + asm volatile("mov %%r8, %[output]" : [output] "=m"(values.arg_4)); + asm volatile("mov %%r9, %[output]" : [output] "=m"(values.arg_5)); + + return {error_code, values}; } } // namespace teachos::arch::context_switching::syscall diff --git a/arch/x86_64/src/context_switching/syscall/syscall_handler.cpp b/arch/x86_64/src/context_switching/syscall/syscall_handler.cpp index da9eb1b..b88f273 100644 --- a/arch/x86_64/src/context_switching/syscall/syscall_handler.cpp +++ b/arch/x86_64/src/context_switching/syscall/syscall_handler.cpp @@ -16,6 +16,20 @@ namespace teachos::arch::context_switching::syscall video::vga::text::newline(); return error::OK; } + + auto expand_user_heap() -> error + { + arguments args{}; + asm volatile("mov %[input], %%rdi" + : /* no output from call */ + : [input] "m"(args.arg_0) + : "memory"); + asm volatile("mov %[input], %%rsi" + : /* no output from call */ + : [input] "m"(args.arg_1) + : "memory"); + return error::OUT_OF_MEMORY; + } } // namespace auto syscall_handler() -> void @@ -46,6 +60,9 @@ namespace teachos::arch::context_switching::syscall case type::WRITE: result = write_to_vga_buffer(arg_0); break; + case type::EXPAND_HEAP: + result = expand_user_heap(); + break; default: teachos::arch::exception_handling::panic("[Syscall Handler] Invalid syscall number"); break; diff --git a/arch/x86_64/src/memory/heap/user_heap_allocator.cpp b/arch/x86_64/src/memory/heap/user_heap_allocator.cpp index 6843d66..ce8b0fa 100644 --- a/arch/x86_64/src/memory/heap/user_heap_allocator.cpp +++ b/arch/x86_64/src/memory/heap/user_heap_allocator.cpp @@ -1,5 +1,6 @@ #include "arch/memory/heap/user_heap_allocator.hpp" +#include "arch/context_switching/syscall/main.hpp" #include "arch/exception_handling/assert.hpp" #include "arch/exception_handling/panic.hpp" @@ -18,7 +19,7 @@ namespace teachos::arch::memory::heap heap_size > min_allocatable_size(), "[Linked List Allocator] Total heap size can not be smaller than minimum of 16 bytes to hold " "atleast one memory hole entry"); - first = new (reinterpret_cast<void *>(heap_start)) memory_block(heap_size, nullptr); + // first = new (reinterpret_cast<void *>(heap_start)) memory_block(heap_size, nullptr); } auto user_heap_allocator::allocate(std::size_t size) -> void * @@ -57,6 +58,30 @@ namespace teachos::arch::memory::heap current = current->next; } + current = expand_heap_if_full(); + + if (current != nullptr) + { + if (current->size == total_size) + { + auto const memory_address = remove_free_memory_block(previous, current); + new (memory_address) std::size_t(total_size); + mutex.unlock(); + return reinterpret_cast<void *>(reinterpret_cast<std::size_t>(memory_address) + sizeof(std::size_t)); + } + else if (current->size >= total_size + min_allocatable_size()) + { + // Ensure that the allocated size block is atleast 16 bytes (required because if we free the hole afterwards + // there needs to be enough space for a memory block). Therefore we allocate more than is actually required if + // the total size was less and simply deallocate it as well + auto const max_size = std::max(total_size, min_allocatable_size()); + auto const memory_address = split_free_memory_block(previous, current, max_size); + new (memory_address) std::size_t(max_size); + mutex.unlock(); + return reinterpret_cast<void *>(reinterpret_cast<std::size_t>(memory_address) + sizeof(std::size_t)); + } + } + exception_handling::panic("[Linked List Allocator] Out of memory"); } @@ -91,6 +116,20 @@ namespace teachos::arch::memory::heap mutex.unlock(); } + auto user_heap_allocator::expand_heap_if_full() -> memory_block * + { + context_switching::syscall::arguments args{}; + auto const result = context_switching::syscall::syscall(context_switching::syscall::type::EXPAND_HEAP, args); + + if (!result.error_code) + { + uint64_t const heap_start = result.values.arg_0; + uint64_t const heap_size = result.values.arg_1; + return new (reinterpret_cast<void *>(heap_start)) memory_block(heap_size, nullptr); + } + return nullptr; + } + auto user_heap_allocator::remove_free_memory_block(memory_block * previous_block, memory_block * current_block) -> void * { |
