diff --git a/kernel/src/thread/Scheduler.cpp b/kernel/src/thread/Scheduler.cpp index c6b7fe90..a6b91f90 100644 --- a/kernel/src/thread/Scheduler.cpp +++ b/kernel/src/thread/Scheduler.cpp @@ -4,6 +4,7 @@ #include "arch/MMU.h" #include "memory/KernelVM.h" #include "memory/MemoryManager.h" +#include #include static Thread g_idle; @@ -44,12 +45,19 @@ namespace Scheduler return &g_idle; } - Result kernel_thread_alloc_stack_and_append_impl(Thread* thread) + Result new_kernel_thread_impl(Thread* thread) { - // FIXME: We will leak the thread if VM allocation or alloc_at fail. + // If anything fails, make sure to clean up. + auto thread_guard = make_scope_guard([&] { delete thread; }); + u64 thread_stack_vm = TRY(KernelVM::alloc_several_pages(4)); + auto vm_guard = make_scope_guard([&] { KernelVM::free_several_pages(thread_stack_vm, 4); }); + TRY(MemoryManager::alloc_at(thread_stack_vm, 4, MMU::NoExecute | MMU::ReadWrite)); + thread_guard.deactivate(); + vm_guard.deactivate(); + Stack thread_stack{thread_stack_vm, ARCH_PAGE_SIZE * 4}; thread->set_sp(thread_stack.top()); @@ -66,7 +74,7 @@ namespace Scheduler thread->init_regs_kernel(); thread->set_ip(address); - return kernel_thread_alloc_stack_and_append_impl(thread); + return new_kernel_thread_impl(thread); } Result new_kernel_thread(void (*func)(void)) @@ -75,7 +83,7 @@ namespace Scheduler thread->init_regs_kernel(); thread->set_ip((u64)func); - return kernel_thread_alloc_stack_and_append_impl(thread); + return new_kernel_thread_impl(thread); } Result new_kernel_thread(void (*func)(void*), void* arg) @@ -85,7 +93,7 @@ namespace Scheduler thread->set_ip((u64)func); thread->set_arguments((u64)arg, 0, 0, 0); - return kernel_thread_alloc_stack_and_append_impl(thread); + return new_kernel_thread_impl(thread); } Thread* pick_task() diff --git a/luna/include/luna/ScopeGuard.h b/luna/include/luna/ScopeGuard.h new file mode 100644 index 00000000..4d214002 --- /dev/null +++ b/luna/include/luna/ScopeGuard.h @@ -0,0 +1,28 @@ +#pragma once + +template class ScopeGuard +{ + public: + ScopeGuard(const Callback& callback) : m_callback(callback) + { + } + + void deactivate() + { + m_activated = false; + } + + ~ScopeGuard() + { + if (m_activated) m_callback(); + } + + private: + bool m_activated{true}; + Callback m_callback; +}; + +template [[nodiscard]] ScopeGuard make_scope_guard(const Callback& callback) +{ + return {callback}; +} \ No newline at end of file