forked from Bananymous/banan-os
Kernel: Cleanup returns from any kind on interrupts
This commit is contained in:
parent
13852e865c
commit
217dbca7b7
|
@ -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()
|
||||||
|
|
|
@ -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&);
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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:
|
||||||
|
|
Loading…
Reference in New Issue