aboutsummaryrefslogtreecommitdiff
path: root/arch/x86_64/src
diff options
context:
space:
mode:
authorMatteo Gmür <matteo.gmuer1@ost.ch>2025-05-11 08:48:57 +0000
committerMatteo Gmür <matteo.gmuer1@ost.ch>2025-05-11 08:48:57 +0000
commit833cd6446d9981a262959749c0e248e33b54c174 (patch)
tree4378760ddf5d6034d2c702274a6757940e7afe44 /arch/x86_64/src
parent955ab48fe6329b2cbc8c5855a8ba7290185d0ea3 (diff)
downloadteachos-833cd6446d9981a262959749c0e248e33b54c174.tar.xz
teachos-833cd6446d9981a262959749c0e248e33b54c174.zip
Adjust user heap allocator with expanding heap functionality
Diffstat (limited to 'arch/x86_64/src')
-rw-r--r--arch/x86_64/src/context_switching/syscall/main.cpp17
-rw-r--r--arch/x86_64/src/context_switching/syscall/syscall_handler.cpp17
-rw-r--r--arch/x86_64/src/memory/heap/user_heap_allocator.cpp41
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 *
{