diff --git a/kernel/arch/i386/Thread.S b/kernel/arch/i386/Thread.S index e31f3787..af2cb91c 100644 --- a/kernel/arch/i386/Thread.S +++ b/kernel/arch/i386/Thread.S @@ -15,7 +15,6 @@ start_thread: movl 8(%esp), %ecx movl 4(%esp), %esp movl $0, %ebp - movl $0, (%esp) pushl $exit_thread_trampoline sti jmp *%ecx diff --git a/kernel/arch/x86_64/Thread.S b/kernel/arch/x86_64/Thread.S index a75600c9..3c72cb17 100644 --- a/kernel/arch/x86_64/Thread.S +++ b/kernel/arch/x86_64/Thread.S @@ -14,7 +14,6 @@ start_thread: movq %rdi, %rsp popq %rdi movq $0, %rbp - movq $0, (%rsp) pushq $exit_thread_trampoline sti jmp *%rsi diff --git a/kernel/include/kernel/Process.h b/kernel/include/kernel/Process.h index 7713afaf..11a45d01 100644 --- a/kernel/include/kernel/Process.h +++ b/kernel/include/kernel/Process.h @@ -23,9 +23,11 @@ namespace Kernel public: static BAN::ErrorOr> create_kernel(entry_t, void*); - ~Process() {} + ~Process(); - BAN::ErrorOr add_thread(entry_t, void*); + void exit(); + + BAN::ErrorOr add_thread(entry_t, void*); void on_thread_exit(Thread&); BAN::ErrorOr init_stdio(); diff --git a/kernel/include/kernel/Thread.h b/kernel/include/kernel/Thread.h index 5e4139e3..c401dcc3 100644 --- a/kernel/include/kernel/Thread.h +++ b/kernel/include/kernel/Thread.h @@ -18,6 +18,13 @@ namespace Kernel public: using entry_t = void(*)(void*); + enum class State + { + NotStarted, + Executing, + Terminating, + }; + public: static BAN::ErrorOr create(entry_t, void* = nullptr, BAN::RefPtr = nullptr); ~Thread(); @@ -29,8 +36,9 @@ namespace Kernel uintptr_t rsp() const { return m_rsp; } uintptr_t rip() const { return m_rip; } - void set_started() { m_started = true; } - bool started() const { return m_started; } + void set_started() { ASSERT(m_state == State::NotStarted); m_state = State::Executing; } + State state() const { return m_state; } + void terminate() { m_state = State::Terminating; } static Thread& current() ; BAN::RefPtr process(); @@ -46,8 +54,10 @@ namespace Kernel uintptr_t m_rip = 0; uintptr_t m_rsp = 0; const pid_t m_tid = 0; - bool m_started = false; + State m_state { State::NotStarted }; BAN::RefPtr m_process; + + friend class Scheduler; }; } \ No newline at end of file diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index 62f2ceee..e6f95156 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -23,7 +23,12 @@ namespace Kernel , m_tty(TTY::current()) { } - BAN::ErrorOr Process::add_thread(entry_t entry, void* data) + Process::~Process() + { + exit(); + } + + BAN::ErrorOr Process::add_thread(entry_t entry, void* data) { Thread* thread = TRY(Thread::create(entry, data, this)); @@ -32,10 +37,10 @@ namespace Kernel if (auto res = Scheduler::get().add_thread(thread); res.is_error()) { m_threads.pop_back(); - return res; + return res.release_error(); } - return {}; + return thread; } void Process::on_thread_exit(Thread& thread) @@ -46,6 +51,17 @@ namespace Kernel m_threads.remove(i); } + void Process::exit() + { + LockGuard _(m_lock); + for (auto* thread : m_threads) + thread->terminate(); + while (!m_threads.empty()) + PIT::sleep(1); + for (auto& open_fd : m_open_files) + open_fd.inode = nullptr; + } + BAN::ErrorOr Process::init_stdio() { if (!m_open_files.empty()) diff --git a/kernel/kernel/Scheduler.cpp b/kernel/kernel/Scheduler.cpp index df089066..728503cf 100644 --- a/kernel/kernel/Scheduler.cpp +++ b/kernel/kernel/Scheduler.cpp @@ -16,8 +16,8 @@ namespace Kernel { - extern "C" void start_thread(uintptr_t rsp, uintptr_t rip); - extern "C" void continue_thread(uintptr_t rsp, uintptr_t rip); + extern "C" [[noreturn]] void start_thread(uintptr_t rsp, uintptr_t rip); + extern "C" [[noreturn]] void continue_thread(uintptr_t rsp, uintptr_t rip); extern "C" uintptr_t read_rip(); static Scheduler* s_instance = nullptr; @@ -166,14 +166,17 @@ namespace Kernel Thread& current = current_thread(); - if (current.started()) + switch (current.state()) { - continue_thread(current.rsp(), current.rip()); - } - else - { - current.set_started(); - start_thread(current.rsp(), current.rip()); + case Thread::State::NotStarted: + current.set_started(); + start_thread(current.rsp(), current.rip()); + case Thread::State::Executing: + continue_thread(current.rsp(), current.rip()); + case Thread::State::Terminating: + ENABLE_INTERRUPTS(); + current.on_exit(); + ASSERT_NOT_REACHED(); } ASSERT_NOT_REACHED();