Kernel: Cleanup returns from any kind on interrupts

This commit is contained in:
Bananymous 2023-08-01 14:23:50 +03:00
parent 13852e865c
commit 217dbca7b7
6 changed files with 57 additions and 71 deletions

View File

@ -138,7 +138,10 @@ namespace IDT
extern "C" void cpp_isr_handler(uint64_t isr, uint64_t error, Kernel::InterruptStack& interrupt_stack, const Registers* regs) extern "C" void cpp_isr_handler(uint64_t isr, uint64_t error, Kernel::InterruptStack& interrupt_stack, const Registers* regs)
{ {
Kernel::Thread::current().save_sse(); bool from_userspace = (interrupt_stack.cs & 0b11) == 0b11;
if (from_userspace)
Kernel::Thread::current().save_sse();
pid_t tid = Kernel::Scheduler::current_tid(); pid_t tid = Kernel::Scheduler::current_tid();
pid_t pid = tid ? Kernel::Process::current().pid() : 0; pid_t pid = tid ? Kernel::Process::current().pid() : 0;
@ -198,22 +201,23 @@ namespace IDT
Kernel::panic("Unhandled exception"); Kernel::panic("Unhandled exception");
} }
switch (Kernel::Thread::current().state()) // Don't continue exection when terminated
{ if (Kernel::Thread::current().state() == Kernel::Thread::State::Terminated)
case Kernel::Thread::State::Terminating:
ASSERT_NOT_REACHED();
case Kernel::Thread::State::Terminated:
Kernel::Scheduler::get().execute_current_thread(); Kernel::Scheduler::get().execute_current_thread();
default:
break; if (from_userspace)
{
ASSERT(Kernel::Thread::current().state() != Kernel::Thread::State::Terminating);
Kernel::Thread::current().load_sse();
} }
Kernel::Thread::current().load_sse();
} }
extern "C" void cpp_irq_handler(uint64_t irq, Kernel::InterruptStack& interrupt_stack) extern "C" void cpp_irq_handler(uint64_t irq, Kernel::InterruptStack& interrupt_stack)
{ {
Kernel::Thread::current().save_sse(); bool from_userspace = (interrupt_stack.cs & 0b11) & 0b11;
if (from_userspace)
Kernel::Thread::current().save_sse();
if (Kernel::Scheduler::current_tid()) if (Kernel::Scheduler::current_tid())
{ {
@ -239,17 +243,15 @@ namespace IDT
Kernel::Scheduler::get().reschedule_if_idling(); Kernel::Scheduler::get().reschedule_if_idling();
switch (Kernel::Thread::current().state()) // Don't continue exection when terminated
{ if (Kernel::Thread::current().state() == Kernel::Thread::State::Terminated)
case Kernel::Thread::State::Terminating:
ASSERT_NOT_REACHED();
case Kernel::Thread::State::Terminated:
Kernel::Scheduler::get().execute_current_thread(); Kernel::Scheduler::get().execute_current_thread();
default:
break;
}
Kernel::Thread::current().load_sse(); if (from_userspace)
{
ASSERT(Kernel::Thread::current().state() != Kernel::Thread::State::Terminating);
Kernel::Thread::current().load_sse();
}
} }
static void flush_idt() static void flush_idt()

View File

@ -43,7 +43,7 @@ namespace Kernel
~Process(); ~Process();
void cleanup_function(); void cleanup_function();
void exit(int status); void exit(int status, int signal);
void add_thread(Thread*); void add_thread(Thread*);
void on_thread_exit(Thread&); void on_thread_exit(Thread&);

View File

@ -116,7 +116,6 @@ namespace Kernel
alignas(16) uint8_t m_sse_storage[512]; alignas(16) uint8_t m_sse_storage[512];
friend class TerminateBlocker;
friend class Scheduler; friend class Scheduler;
}; };

View File

@ -14,6 +14,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <stdio.h> #include <stdio.h>
#include <sys/sysmacros.h> #include <sys/sysmacros.h>
#include <sys/wait.h>
namespace Kernel namespace Kernel
{ {
@ -178,17 +179,17 @@ namespace Kernel
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
} }
void Process::exit(int status) void Process::exit(int status, int signal)
{ {
LockGuard _(m_lock); LockGuard _(m_lock);
m_exit_status.exit_code = status; m_exit_status.exit_code = __WGENEXITCODE(status, signal);
for (auto* thread : m_threads) for (auto* thread : m_threads)
thread->set_terminating(); thread->set_terminating();
} }
BAN::ErrorOr<long> Process::sys_exit(int status) BAN::ErrorOr<long> Process::sys_exit(int status)
{ {
exit(status); exit(status, 0);
Thread::TerminateBlocker _(Thread::current()); Thread::TerminateBlocker _(Thread::current());
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
} }
@ -427,11 +428,8 @@ namespace Kernel
int Process::block_until_exit() int Process::block_until_exit()
{ {
ASSERT(s_process_lock.is_locked());
ASSERT(this != &Process::current()); ASSERT(this != &Process::current());
s_process_lock.unlock();
m_lock.lock(); m_lock.lock();
m_exit_status.waiting++; m_exit_status.waiting++;
while (!m_exit_status.exited) while (!m_exit_status.exited)
@ -445,8 +443,6 @@ namespace Kernel
m_exit_status.waiting--; m_exit_status.waiting--;
m_lock.unlock(); m_lock.unlock();
s_process_lock.lock();
return ret; return ret;
} }
@ -458,10 +454,12 @@ namespace Kernel
if (options) if (options)
return BAN::Error::from_errno(EINVAL); return BAN::Error::from_errno(EINVAL);
LockGuard _(s_process_lock); {
for (auto* process : s_processes) LockGuard _(s_process_lock);
if (process->pid() == pid) for (auto* process : s_processes)
target = process; if (process->pid() == pid)
target = process;
}
if (target == nullptr) if (target == nullptr)
return BAN::Error::from_errno(ECHILD); return BAN::Error::from_errno(ECHILD);
@ -580,7 +578,6 @@ namespace Kernel
BAN::ErrorOr<long> Process::sys_read(int fd, void* buffer, size_t count) BAN::ErrorOr<long> Process::sys_read(int fd, void* buffer, size_t count)
{ {
Thread::TerminateBlocker blocker(Thread::current());
LockGuard _(m_lock); LockGuard _(m_lock);
return TRY(m_open_file_descriptors.read(fd, buffer, count)); return TRY(m_open_file_descriptors.read(fd, buffer, count));
} }

View File

@ -21,6 +21,8 @@ namespace Kernel
extern "C" long cpp_syscall_handler(int syscall, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4, uintptr_t arg5, InterruptStack& interrupt_stack) extern "C" long cpp_syscall_handler(int syscall, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4, uintptr_t arg5, InterruptStack& interrupt_stack)
{ {
ASSERT((interrupt_stack.cs & 0b11) == 0b11);
Thread::current().set_return_rsp(interrupt_stack.rsp); Thread::current().set_return_rsp(interrupt_stack.rsp);
Thread::current().set_return_rip(interrupt_stack.rip); Thread::current().set_return_rip(interrupt_stack.rip);
@ -175,16 +177,11 @@ namespace Kernel
asm volatile("cli"); asm volatile("cli");
switch (Thread::current().state()) // Don't continue exection when terminated
{ if (Kernel::Thread::current().state() == Kernel::Thread::State::Terminated)
case Thread::State::Terminating: Kernel::Scheduler::get().execute_current_thread();
ASSERT_NOT_REACHED();
case Thread::State::Terminated:
Scheduler::get().execute_current_thread();
default:
break;
}
ASSERT(Kernel::Thread::current().state() != Kernel::Thread::State::Terminating);
Thread::current().load_sse(); Thread::current().load_sse();
if (ret.is_error()) if (ret.is_error())

View File

@ -29,36 +29,32 @@ namespace Kernel
Thread::TerminateBlocker::TerminateBlocker(Thread& thread) Thread::TerminateBlocker::TerminateBlocker(Thread& thread)
: m_thread(thread) : m_thread(thread)
{ {
CriticalScope _;
if (m_thread.state() == State::Executing || m_thread.m_terminate_blockers > 0)
{ {
CriticalScope _; m_thread.m_terminate_blockers++;
return;
if (m_thread.state() == State::Executing || m_thread.m_terminate_blockers > 0)
{
m_thread.m_terminate_blockers++;
return;
}
if (m_thread.state() == State::Terminating && m_thread.m_terminate_blockers == 0)
m_thread.m_state = State::Terminated;
} }
if (m_thread.state() == State::Terminating && m_thread.m_terminate_blockers == 0)
m_thread.m_state = State::Terminated;
while (true) while (true)
Scheduler::get().reschedule(); Scheduler::get().reschedule();
} }
Thread::TerminateBlocker::~TerminateBlocker() Thread::TerminateBlocker::~TerminateBlocker()
{ {
{ CriticalScope _;
CriticalScope _;
m_thread.m_terminate_blockers--;
if (m_thread.state() == State::Executing || m_thread.m_terminate_blockers > 0) m_thread.m_terminate_blockers--;
return;
if (m_thread.state() == State::Terminating && m_thread.m_terminate_blockers == 0) if (m_thread.state() == State::Executing || m_thread.m_terminate_blockers > 0)
m_thread.m_state = State::Terminated; return;
}
if (m_thread.state() == State::Terminating && m_thread.m_terminate_blockers == 0)
m_thread.m_state = State::Terminated;
while (true) while (true)
Scheduler::get().reschedule(); Scheduler::get().reschedule();
@ -299,11 +295,8 @@ namespace Kernel
case SIGTRAP: case SIGTRAP:
case SIGXCPU: case SIGXCPU:
case SIGXFSZ: case SIGXFSZ:
{ process().exit(128 + signal, signal | 0x80);
auto message = BAN::String::formatted("killed by signal {}\n", signal); break;
(void)process().tty().write(0, message.data(), message.size());
}
// fall through
// Abnormal termination of the process // Abnormal termination of the process
case SIGALRM: case SIGALRM:
@ -317,10 +310,8 @@ namespace Kernel
case SIGPOLL: case SIGPOLL:
case SIGPROF: case SIGPROF:
case SIGVTALRM: case SIGVTALRM:
{ process().exit(128 + signal, signal);
process().exit(128 + signal);
break; break;
}
// Ignore the signal // Ignore the signal
case SIGCHLD: case SIGCHLD: