From e86e755c51725e11dba767254dc67325f9153091 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Mon, 31 Jul 2023 22:28:18 +0300 Subject: [PATCH] Kernel: Generally improve signals --- kernel/arch/x86_64/IDT.cpp | 22 +++++++++++++++++++++- kernel/include/kernel/Scheduler.h | 3 +-- kernel/kernel/Process.cpp | 6 +++--- kernel/kernel/Scheduler.cpp | 3 +-- kernel/kernel/Syscall.cpp | 11 +++++++++++ kernel/kernel/Thread.cpp | 20 +++++++++----------- 6 files changed, 46 insertions(+), 19 deletions(-) diff --git a/kernel/arch/x86_64/IDT.cpp b/kernel/arch/x86_64/IDT.cpp index 81bb07d1..b0a4eeb7 100644 --- a/kernel/arch/x86_64/IDT.cpp +++ b/kernel/arch/x86_64/IDT.cpp @@ -189,12 +189,22 @@ namespace IDT break; } - Kernel::Thread::current().handle_signal(-signal); + Kernel::Thread::current().handle_signal(signal); } else { Kernel::panic("Unhandled exception"); } + + switch (Kernel::Thread::current().state()) + { + case Kernel::Thread::State::Terminating: + ASSERT_NOT_REACHED(); + case Kernel::Thread::State::Terminated: + Kernel::Scheduler::get().execute_current_thread(); + default: + break; + } } extern "C" void cpp_irq_handler(uint64_t irq, Kernel::InterruptStack& interrupt_stack) @@ -222,6 +232,16 @@ namespace IDT InterruptController::get().eoi(irq); Kernel::Scheduler::get().reschedule_if_idling(); + + switch (Kernel::Thread::current().state()) + { + case Kernel::Thread::State::Terminating: + ASSERT_NOT_REACHED(); + case Kernel::Thread::State::Terminated: + Kernel::Scheduler::get().execute_current_thread(); + default: + break; + } } static void flush_idt() diff --git a/kernel/include/kernel/Scheduler.h b/kernel/include/kernel/Scheduler.h index 9a18f896..55b2ca70 100644 --- a/kernel/include/kernel/Scheduler.h +++ b/kernel/include/kernel/Scheduler.h @@ -30,6 +30,7 @@ namespace Kernel static bool is_valid_tid(pid_t tid); + [[noreturn]] void execute_current_thread(); [[noreturn]] void delete_current_process_and_thread(); private: @@ -39,7 +40,6 @@ namespace Kernel [[nodiscard]] bool save_current_thread(); void remove_and_advance_current_thread(); void advance_current_thread(); - [[noreturn]] void execute_current_thread(); BAN::ErrorOr add_thread(Thread*); @@ -75,7 +75,6 @@ namespace Kernel uint64_t m_last_reschedule = 0; - friend class Thread; friend class Process; }; diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index 0a0856a6..7add607c 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -418,9 +418,9 @@ namespace Kernel m_userspace_info.argc = str_argv.size(); asm volatile("cli"); - m_threads.front()->setup_exec(); } + m_threads.front()->setup_exec(); Scheduler::get().execute_current_thread(); ASSERT_NOT_REACHED(); } @@ -867,8 +867,8 @@ namespace Kernel ASSERT(this == &Process::current()); CriticalScope _; - Thread::current().handle_signal(-signal); - ASSERT_NOT_REACHED(); + Thread::current().handle_signal(signal); + return 0; } BAN::ErrorOr Process::sys_tcsetpgrp(int fd, pid_t pgid) diff --git a/kernel/kernel/Scheduler.cpp b/kernel/kernel/Scheduler.cpp index 58c3aac5..3ce0beda 100644 --- a/kernel/kernel/Scheduler.cpp +++ b/kernel/kernel/Scheduler.cpp @@ -86,7 +86,6 @@ namespace Kernel void Scheduler::reschedule() { - VERIFY_STI(); DISABLE_INTERRUPTS(); if (save_current_thread()) @@ -247,7 +246,7 @@ namespace Kernel current->set_started(); start_thread(current->rsp(), current->rip()); case Thread::State::Executing: - while (current->has_signal_to_execute() && current->state() == Thread::State::Executing) + while (current->has_signal_to_execute()) current->handle_signal(); // fall through case Thread::State::Terminating: diff --git a/kernel/kernel/Syscall.cpp b/kernel/kernel/Syscall.cpp index 9b1895cd..2b8afff9 100644 --- a/kernel/kernel/Syscall.cpp +++ b/kernel/kernel/Syscall.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include @@ -172,6 +173,16 @@ namespace Kernel asm volatile("cli"); + switch (Thread::current().state()) + { + case Thread::State::Terminating: + ASSERT_NOT_REACHED(); + case Thread::State::Terminated: + Scheduler::get().execute_current_thread(); + default: + break; + } + if (ret.is_error()) return -ret.error().get_error_code(); return ret.value(); diff --git a/kernel/kernel/Thread.cpp b/kernel/kernel/Thread.cpp index 00d9ffd5..8b34c8b7 100644 --- a/kernel/kernel/Thread.cpp +++ b/kernel/kernel/Thread.cpp @@ -218,7 +218,7 @@ namespace Kernel bool Thread::has_signal_to_execute() const { - if (!m_process || m_handling_signal) + if (!is_userspace() || m_handling_signal || m_state != State::Executing) return false; uint64_t full_pending_mask = m_signal_pending_mask | m_process->m_signal_pending_mask; return full_pending_mask & ~m_signal_block_mask; @@ -229,10 +229,14 @@ namespace Kernel ASSERT(!interrupts_enabled()); if (m_handling_signal == 0) derrorln("set_signal_done called while not handling singal"); - if (m_handling_signal != signal) + else if (m_handling_signal != signal) derrorln("set_signal_done called with invalid signal"); else m_handling_signal = 0; + + if (m_handling_signal == 0) + while (has_signal_to_execute()) + handle_signal(); } void Thread::handle_signal(int signal) @@ -240,6 +244,7 @@ namespace Kernel ASSERT(!interrupts_enabled()); ASSERT(&Thread::current() == this); ASSERT(is_userspace()); + ASSERT(!m_handling_signal); if (signal == 0) { @@ -252,16 +257,10 @@ namespace Kernel } ASSERT(signal <= _SIGMAX); } - else if (signal > 0) - { - uint64_t full_pending_mask = m_signal_pending_mask | process().m_signal_pending_mask; - uint64_t mask = 1ull << signal; - ASSERT(full_pending_mask & mask); - ASSERT(!(m_signal_block_mask & mask)); - } else { - signal = -signal; + ASSERT(signal >= _SIGMIN); + ASSERT(signal <= _SIGMAX); } uintptr_t& return_rsp = this->return_rsp(); @@ -284,7 +283,6 @@ namespace Kernel write_to_stack(return_rsp, signal); write_to_stack(return_rsp, signal_handler); return_rip = (uintptr_t)signal_trampoline; - return; } else {