forked from Bananymous/banan-os
Kernel: Rework all signal code
Signal handling code was way too complex. Now everything is simplified and there is no need for ThreadBlockers. Only complication that this patch includes is that blocking syscalls have to manually be made interruptable by signal. There might be some clever solution to combat this is make this happen automatically.
This commit is contained in:
parent
cdcc36efde
commit
1c78671078
|
@ -31,10 +31,6 @@ signal_trampoline:
|
||||||
movq 120(%rsp), %rax
|
movq 120(%rsp), %rax
|
||||||
call *%rax
|
call *%rax
|
||||||
|
|
||||||
movq $SYS_SIGNAL_DONE, %rax
|
|
||||||
movq 128(%rsp), %rbx
|
|
||||||
int $0x80
|
|
||||||
|
|
||||||
popq %r15
|
popq %r15
|
||||||
popq %r14
|
popq %r14
|
||||||
popq %r13
|
popq %r13
|
||||||
|
|
|
@ -25,19 +25,9 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
NotStarted,
|
NotStarted,
|
||||||
Executing,
|
Executing,
|
||||||
Terminating,
|
|
||||||
Terminated
|
Terminated
|
||||||
};
|
};
|
||||||
|
|
||||||
class TerminateBlocker
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TerminateBlocker(Thread&);
|
|
||||||
~TerminateBlocker();
|
|
||||||
private:
|
|
||||||
Thread& m_thread;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static BAN::ErrorOr<Thread*> create_kernel(entry_t, void*, Process*);
|
static BAN::ErrorOr<Thread*> create_kernel(entry_t, void*, Process*);
|
||||||
static BAN::ErrorOr<Thread*> create_userspace(Process*);
|
static BAN::ErrorOr<Thread*> create_userspace(Process*);
|
||||||
|
@ -47,15 +37,20 @@ namespace Kernel
|
||||||
void setup_exec();
|
void setup_exec();
|
||||||
void setup_process_cleanup();
|
void setup_process_cleanup();
|
||||||
|
|
||||||
bool has_signal_to_execute() const;
|
// Adds pending signals to thread if possible and
|
||||||
void set_signal_done(int signal);
|
// returns true, if thread is going to trigger signal
|
||||||
|
bool is_interrupted_by_signal();
|
||||||
|
|
||||||
|
// Returns true if pending signal can be added to thread
|
||||||
|
bool can_add_signal_to_execute() const;
|
||||||
|
bool will_execute_signal() const;
|
||||||
void handle_signal(int signal = 0);
|
void handle_signal(int signal = 0);
|
||||||
bool add_signal(int signal);
|
bool add_signal(int signal);
|
||||||
|
|
||||||
void set_return_rsp(uintptr_t& rsp) { m_return_rsp = &rsp; }
|
void set_return_rsp(uintptr_t& rsp) { m_return_rsp = &rsp; }
|
||||||
void set_return_rip(uintptr_t& rip) { m_return_rip = &rip; }
|
void set_return_rip(uintptr_t& rip) { m_return_rip = &rip; }
|
||||||
uintptr_t& return_rsp() { ASSERT(m_return_rsp); return *m_return_rsp; }
|
uintptr_t return_rsp() { ASSERT(m_return_rsp); return *m_return_rsp; }
|
||||||
uintptr_t& return_rip() { ASSERT(m_return_rip); return *m_return_rip; }
|
uintptr_t return_rip() { ASSERT(m_return_rip); return *m_return_rip; }
|
||||||
|
|
||||||
pid_t tid() const { return m_tid; }
|
pid_t tid() const { return m_tid; }
|
||||||
|
|
||||||
|
@ -65,7 +60,8 @@ namespace Kernel
|
||||||
uintptr_t rip() const { return m_rip; }
|
uintptr_t rip() const { return m_rip; }
|
||||||
|
|
||||||
void set_started() { ASSERT(m_state == State::NotStarted); m_state = State::Executing; }
|
void set_started() { ASSERT(m_state == State::NotStarted); m_state = State::Executing; }
|
||||||
void set_terminating();
|
// Thread will no longer execute. If called on current thread, does not return
|
||||||
|
void terminate();
|
||||||
State state() const { return m_state; }
|
State state() const { return m_state; }
|
||||||
|
|
||||||
vaddr_t stack_base() const { return m_stack->vaddr(); }
|
vaddr_t stack_base() const { return m_stack->vaddr(); }
|
||||||
|
@ -116,11 +112,8 @@ namespace Kernel
|
||||||
|
|
||||||
uint64_t m_signal_pending_mask { 0 };
|
uint64_t m_signal_pending_mask { 0 };
|
||||||
uint64_t m_signal_block_mask { 0 };
|
uint64_t m_signal_block_mask { 0 };
|
||||||
int m_handling_signal { 0 };
|
|
||||||
static_assert(_SIGMAX < 64);
|
static_assert(_SIGMAX < 64);
|
||||||
|
|
||||||
uint64_t m_terminate_blockers { 0 };
|
|
||||||
|
|
||||||
#if __enable_sse
|
#if __enable_sse
|
||||||
alignas(16) uint8_t m_sse_storage[512] {};
|
alignas(16) uint8_t m_sse_storage[512] {};
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#include <kernel/FS/Inode.h>
|
#include <kernel/FS/Inode.h>
|
||||||
#include <kernel/LockGuard.h>
|
#include <kernel/LockGuard.h>
|
||||||
#include <kernel/Thread.h>
|
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
@ -60,7 +59,6 @@ namespace Kernel
|
||||||
BAN::ErrorOr<BAN::RefPtr<Inode>> Inode::find_inode(BAN::StringView name)
|
BAN::ErrorOr<BAN::RefPtr<Inode>> Inode::find_inode(BAN::StringView name)
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
Thread::TerminateBlocker blocker(Thread::current());
|
|
||||||
if (!mode().ifdir())
|
if (!mode().ifdir())
|
||||||
return BAN::Error::from_errno(ENOTDIR);
|
return BAN::Error::from_errno(ENOTDIR);
|
||||||
return find_inode_impl(name);
|
return find_inode_impl(name);
|
||||||
|
@ -69,7 +67,6 @@ namespace Kernel
|
||||||
BAN::ErrorOr<void> Inode::list_next_inodes(off_t offset, DirectoryEntryList* list, size_t list_len)
|
BAN::ErrorOr<void> Inode::list_next_inodes(off_t offset, DirectoryEntryList* list, size_t list_len)
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
Thread::TerminateBlocker blocker(Thread::current());
|
|
||||||
if (!mode().ifdir())
|
if (!mode().ifdir())
|
||||||
return BAN::Error::from_errno(ENOTDIR);
|
return BAN::Error::from_errno(ENOTDIR);
|
||||||
return list_next_inodes_impl(offset, list, list_len);
|
return list_next_inodes_impl(offset, list, list_len);
|
||||||
|
@ -78,7 +75,6 @@ namespace Kernel
|
||||||
BAN::ErrorOr<void> Inode::create_file(BAN::StringView name, mode_t mode, uid_t uid, gid_t gid)
|
BAN::ErrorOr<void> Inode::create_file(BAN::StringView name, mode_t mode, uid_t uid, gid_t gid)
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
Thread::TerminateBlocker blocker(Thread::current());
|
|
||||||
if (!this->mode().ifdir())
|
if (!this->mode().ifdir())
|
||||||
return BAN::Error::from_errno(ENOTDIR);
|
return BAN::Error::from_errno(ENOTDIR);
|
||||||
if (Mode(mode).ifdir())
|
if (Mode(mode).ifdir())
|
||||||
|
@ -89,7 +85,6 @@ namespace Kernel
|
||||||
BAN::ErrorOr<void> Inode::create_directory(BAN::StringView name, mode_t mode, uid_t uid, gid_t gid)
|
BAN::ErrorOr<void> Inode::create_directory(BAN::StringView name, mode_t mode, uid_t uid, gid_t gid)
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
Thread::TerminateBlocker blocker(Thread::current());
|
|
||||||
if (!this->mode().ifdir())
|
if (!this->mode().ifdir())
|
||||||
return BAN::Error::from_errno(ENOTDIR);
|
return BAN::Error::from_errno(ENOTDIR);
|
||||||
if (!Mode(mode).ifdir())
|
if (!Mode(mode).ifdir())
|
||||||
|
@ -100,7 +95,6 @@ namespace Kernel
|
||||||
BAN::ErrorOr<void> Inode::unlink(BAN::StringView name)
|
BAN::ErrorOr<void> Inode::unlink(BAN::StringView name)
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
Thread::TerminateBlocker blocker(Thread::current());
|
|
||||||
if (!mode().ifdir())
|
if (!mode().ifdir())
|
||||||
return BAN::Error::from_errno(ENOTDIR);
|
return BAN::Error::from_errno(ENOTDIR);
|
||||||
if (name == "."sv || name == ".."sv)
|
if (name == "."sv || name == ".."sv)
|
||||||
|
@ -111,7 +105,6 @@ namespace Kernel
|
||||||
BAN::ErrorOr<BAN::String> Inode::link_target()
|
BAN::ErrorOr<BAN::String> Inode::link_target()
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
Thread::TerminateBlocker blocker(Thread::current());
|
|
||||||
if (!mode().iflnk())
|
if (!mode().iflnk())
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
return link_target_impl();
|
return link_target_impl();
|
||||||
|
@ -120,7 +113,6 @@ namespace Kernel
|
||||||
BAN::ErrorOr<size_t> Inode::read(off_t offset, BAN::ByteSpan buffer)
|
BAN::ErrorOr<size_t> Inode::read(off_t offset, BAN::ByteSpan buffer)
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
Thread::TerminateBlocker blocker(Thread::current());
|
|
||||||
if (mode().ifdir())
|
if (mode().ifdir())
|
||||||
return BAN::Error::from_errno(EISDIR);
|
return BAN::Error::from_errno(EISDIR);
|
||||||
return read_impl(offset, buffer);
|
return read_impl(offset, buffer);
|
||||||
|
@ -129,7 +121,6 @@ namespace Kernel
|
||||||
BAN::ErrorOr<size_t> Inode::write(off_t offset, BAN::ConstByteSpan buffer)
|
BAN::ErrorOr<size_t> Inode::write(off_t offset, BAN::ConstByteSpan buffer)
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
Thread::TerminateBlocker blocker(Thread::current());
|
|
||||||
if (mode().ifdir())
|
if (mode().ifdir())
|
||||||
return BAN::Error::from_errno(EISDIR);
|
return BAN::Error::from_errno(EISDIR);
|
||||||
return write_impl(offset, buffer);
|
return write_impl(offset, buffer);
|
||||||
|
@ -138,7 +129,6 @@ namespace Kernel
|
||||||
BAN::ErrorOr<void> Inode::truncate(size_t size)
|
BAN::ErrorOr<void> Inode::truncate(size_t size)
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
Thread::TerminateBlocker blocker(Thread::current());
|
|
||||||
if (mode().ifdir())
|
if (mode().ifdir())
|
||||||
return BAN::Error::from_errno(EISDIR);
|
return BAN::Error::from_errno(EISDIR);
|
||||||
return truncate_impl(size);
|
return truncate_impl(size);
|
||||||
|
@ -148,14 +138,12 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
ASSERT((mode & Inode::Mode::TYPE_MASK) == 0);
|
ASSERT((mode & Inode::Mode::TYPE_MASK) == 0);
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
Thread::TerminateBlocker blocker(Thread::current());
|
|
||||||
return chmod_impl(mode);
|
return chmod_impl(mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Inode::has_data() const
|
bool Inode::has_data() const
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
Thread::TerminateBlocker blocker(Thread::current());
|
|
||||||
return has_data_impl();
|
return has_data_impl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -257,7 +257,10 @@ namespace Kernel
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
m_exit_status.exit_code = __WGENEXITCODE(status, signal);
|
m_exit_status.exit_code = __WGENEXITCODE(status, signal);
|
||||||
for (auto* thread : m_threads)
|
for (auto* thread : m_threads)
|
||||||
thread->set_terminating();
|
if (thread != &Thread::current())
|
||||||
|
thread->terminate();
|
||||||
|
if (this == &Process::current())
|
||||||
|
Thread::current().terminate();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Process::proc_meminfo(off_t offset, BAN::ByteSpan buffer) const
|
size_t Process::proc_meminfo(off_t offset, BAN::ByteSpan buffer) const
|
||||||
|
@ -334,7 +337,7 @@ namespace Kernel
|
||||||
BAN::ErrorOr<long> Process::sys_exit(int status)
|
BAN::ErrorOr<long> Process::sys_exit(int status)
|
||||||
{
|
{
|
||||||
exit(status, 0);
|
exit(status, 0);
|
||||||
Thread::TerminateBlocker _(Thread::current());
|
Thread::current().terminate();
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1235,6 +1238,8 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
CriticalScope _;
|
CriticalScope _;
|
||||||
process.m_signal_pending_mask |= 1 << signal;
|
process.m_signal_pending_mask |= 1 << signal;
|
||||||
|
// FIXME: This is super hacky
|
||||||
|
Scheduler::get().unblock_thread(process.m_threads.front()->tid());
|
||||||
}
|
}
|
||||||
return (pid > 0) ? BAN::Iteration::Break : BAN::Iteration::Continue;
|
return (pid > 0) ? BAN::Iteration::Break : BAN::Iteration::Continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -258,10 +258,8 @@ namespace Kernel
|
||||||
current->set_started();
|
current->set_started();
|
||||||
start_thread(current->rsp(), current->rip());
|
start_thread(current->rsp(), current->rip());
|
||||||
case Thread::State::Executing:
|
case Thread::State::Executing:
|
||||||
while (current->has_signal_to_execute())
|
while (current->can_add_signal_to_execute())
|
||||||
current->handle_signal();
|
current->handle_signal();
|
||||||
// fall through
|
|
||||||
case Thread::State::Terminating:
|
|
||||||
continue_thread(current->rsp(), current->rip());
|
continue_thread(current->rsp(), current->rip());
|
||||||
case Thread::State::Terminated:
|
case Thread::State::Terminated:
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
|
|
|
@ -225,7 +225,6 @@ namespace Kernel
|
||||||
|
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
Thread::TerminateBlocker blocker(Thread::current());
|
|
||||||
if (!m_disk_cache.has_value())
|
if (!m_disk_cache.has_value())
|
||||||
return read_sectors_impl(lba, sector_count, buffer);
|
return read_sectors_impl(lba, sector_count, buffer);
|
||||||
}
|
}
|
||||||
|
@ -233,8 +232,6 @@ namespace Kernel
|
||||||
for (uint64_t offset = 0; offset < sector_count; offset++)
|
for (uint64_t offset = 0; offset < sector_count; offset++)
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
Thread::TerminateBlocker blocker(Thread::current());
|
|
||||||
|
|
||||||
auto sector_buffer = buffer.slice(offset * sector_size(), sector_size());
|
auto sector_buffer = buffer.slice(offset * sector_size(), sector_size());
|
||||||
if (m_disk_cache->read_from_cache(lba + offset, sector_buffer))
|
if (m_disk_cache->read_from_cache(lba + offset, sector_buffer))
|
||||||
continue;
|
continue;
|
||||||
|
@ -251,7 +248,6 @@ namespace Kernel
|
||||||
|
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
Thread::TerminateBlocker blocker(Thread::current());
|
|
||||||
if (!m_disk_cache.has_value())
|
if (!m_disk_cache.has_value())
|
||||||
return write_sectors_impl(lba, sector_count, buffer);
|
return write_sectors_impl(lba, sector_count, buffer);
|
||||||
}
|
}
|
||||||
|
@ -259,8 +255,6 @@ namespace Kernel
|
||||||
for (uint8_t offset = 0; offset < sector_count; offset++)
|
for (uint8_t offset = 0; offset < sector_count; offset++)
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
Thread::TerminateBlocker blocker(Thread::current());
|
|
||||||
|
|
||||||
auto sector_buffer = buffer.slice(offset * sector_size(), sector_size());
|
auto sector_buffer = buffer.slice(offset * sector_size(), sector_size());
|
||||||
if (m_disk_cache->write_to_cache(lba + offset, sector_buffer, true).is_error())
|
if (m_disk_cache->write_to_cache(lba + offset, sector_buffer, true).is_error())
|
||||||
TRY(write_sectors_impl(lba + offset, 1, sector_buffer));
|
TRY(write_sectors_impl(lba + offset, 1, sector_buffer));
|
||||||
|
|
|
@ -26,12 +26,6 @@ namespace Kernel
|
||||||
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);
|
||||||
|
|
||||||
if (syscall == SYS_SIGNAL_DONE)
|
|
||||||
{
|
|
||||||
Thread::current().set_signal_done((int)arg1);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if __enable_sse
|
#if __enable_sse
|
||||||
Thread::current().save_sse();
|
Thread::current().save_sse();
|
||||||
#endif
|
#endif
|
||||||
|
@ -154,9 +148,6 @@ namespace Kernel
|
||||||
case SYS_SIGNAL:
|
case SYS_SIGNAL:
|
||||||
ret = Process::current().sys_signal((int)arg1, (void (*)(int))arg2);
|
ret = Process::current().sys_signal((int)arg1, (void (*)(int))arg2);
|
||||||
break;
|
break;
|
||||||
case SYS_SIGNAL_DONE:
|
|
||||||
// Handled above
|
|
||||||
ASSERT_NOT_REACHED();
|
|
||||||
case SYS_TCSETPGRP:
|
case SYS_TCSETPGRP:
|
||||||
ret = Process::current().sys_tcsetpgrp((int)arg1, (pid_t)arg2);
|
ret = Process::current().sys_tcsetpgrp((int)arg1, (pid_t)arg2);
|
||||||
break;
|
break;
|
||||||
|
@ -230,10 +221,14 @@ namespace Kernel
|
||||||
if (ret.is_error() && ret.error().is_kernel_error())
|
if (ret.is_error() && ret.error().is_kernel_error())
|
||||||
Kernel::panic("Kernel error while returning to userspace {}", ret.error());
|
Kernel::panic("Kernel error while returning to userspace {}", ret.error());
|
||||||
|
|
||||||
|
auto& current_thread = Thread::current();
|
||||||
|
if (current_thread.can_add_signal_to_execute())
|
||||||
|
current_thread.handle_signal();
|
||||||
|
|
||||||
ASSERT(Kernel::Thread::current().state() == Kernel::Thread::State::Executing);
|
ASSERT(Kernel::Thread::current().state() == Kernel::Thread::State::Executing);
|
||||||
|
|
||||||
#if __enable_sse
|
#if __enable_sse
|
||||||
Thread::current().load_sse();
|
current_thread.load_sse();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ret.is_error())
|
if (ret.is_error())
|
||||||
|
|
|
@ -303,10 +303,14 @@ namespace Kernel
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
while (!m_output.flush)
|
while (!m_output.flush)
|
||||||
{
|
{
|
||||||
|
if (Thread::current().is_interrupted_by_signal())
|
||||||
|
return BAN::Error::from_errno(EINTR);
|
||||||
m_lock.unlock();
|
m_lock.unlock();
|
||||||
m_output.semaphore.block();
|
m_output.semaphore.block();
|
||||||
m_lock.lock();
|
m_lock.lock();
|
||||||
}
|
}
|
||||||
|
if (Thread::current().is_interrupted_by_signal())
|
||||||
|
return BAN::Error::from_errno(EINTR);
|
||||||
|
|
||||||
if (m_output.bytes == 0)
|
if (m_output.bytes == 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#include <BAN/Errors.h>
|
#include <BAN/Errors.h>
|
||||||
#include <BAN/ScopeGuard.h>
|
#include <BAN/ScopeGuard.h>
|
||||||
|
#include <kernel/GDT.h>
|
||||||
#include <kernel/InterruptController.h>
|
#include <kernel/InterruptController.h>
|
||||||
|
#include <kernel/InterruptStack.h>
|
||||||
#include <kernel/Memory/kmalloc.h>
|
#include <kernel/Memory/kmalloc.h>
|
||||||
#include <kernel/Memory/PageTableScope.h>
|
#include <kernel/Memory/PageTableScope.h>
|
||||||
#include <kernel/Process.h>
|
#include <kernel/Process.h>
|
||||||
|
@ -25,63 +27,13 @@ namespace Kernel
|
||||||
memcpy((void*)rsp, (void*)&value, sizeof(uintptr_t));
|
memcpy((void*)rsp, (void*)&value, sizeof(uintptr_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
Thread::TerminateBlocker::TerminateBlocker(Thread& thread)
|
void Thread::terminate()
|
||||||
: m_thread(thread)
|
|
||||||
{
|
{
|
||||||
CriticalScope _;
|
CriticalScope _;
|
||||||
|
ASSERT(this == &Thread::current());
|
||||||
// FIXME: this should not be a requirement
|
m_state = Thread::State::Terminated;
|
||||||
ASSERT(&thread == &Thread::current());
|
if (this == &Thread::current())
|
||||||
|
|
||||||
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;
|
|
||||||
Scheduler::get().execute_current_thread();
|
Scheduler::get().execute_current_thread();
|
||||||
}
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
Scheduler::get().reschedule();
|
|
||||||
}
|
|
||||||
|
|
||||||
Thread::TerminateBlocker::~TerminateBlocker()
|
|
||||||
{
|
|
||||||
CriticalScope _;
|
|
||||||
|
|
||||||
m_thread.m_terminate_blockers--;
|
|
||||||
|
|
||||||
if (m_thread.state() == State::Executing || m_thread.m_terminate_blockers > 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (m_thread.state() == State::Terminating && m_thread.m_terminate_blockers == 0)
|
|
||||||
{
|
|
||||||
m_thread.m_state = State::Terminated;
|
|
||||||
Scheduler::get().execute_current_thread();
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT_NOT_REACHED();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Thread::set_terminating()
|
|
||||||
{
|
|
||||||
CriticalScope _;
|
|
||||||
if (m_terminate_blockers == 0)
|
|
||||||
{
|
|
||||||
m_state = State::Terminated;
|
|
||||||
if (this == &Thread::current())
|
|
||||||
Scheduler::get().execute_current_thread();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_state = State::Terminating;
|
|
||||||
if (this == &Thread::current())
|
|
||||||
Scheduler::get().unblock_thread(tid());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static pid_t s_next_tid = 1;
|
static pid_t s_next_tid = 1;
|
||||||
|
@ -245,27 +197,30 @@ namespace Kernel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Thread::has_signal_to_execute() const
|
bool Thread::is_interrupted_by_signal()
|
||||||
{
|
{
|
||||||
if (!is_userspace() || m_handling_signal || m_state != State::Executing)
|
while (can_add_signal_to_execute())
|
||||||
|
handle_signal();
|
||||||
|
return will_execute_signal();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Thread::can_add_signal_to_execute() const
|
||||||
|
{
|
||||||
|
if (!is_userspace() || m_state != State::Executing)
|
||||||
|
return false;
|
||||||
|
auto& interrupt_stack = *reinterpret_cast<InterruptStack*>(interrupt_stack_base() + interrupt_stack_size() - sizeof(InterruptStack));
|
||||||
|
if (!GDT::is_user_segment(interrupt_stack.cs))
|
||||||
return false;
|
return false;
|
||||||
uint64_t full_pending_mask = m_signal_pending_mask | m_process->m_signal_pending_mask;
|
uint64_t full_pending_mask = m_signal_pending_mask | m_process->m_signal_pending_mask;
|
||||||
return full_pending_mask & ~m_signal_block_mask;
|
return full_pending_mask & ~m_signal_block_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Thread::set_signal_done(int signal)
|
bool Thread::will_execute_signal() const
|
||||||
{
|
{
|
||||||
ASSERT(!interrupts_enabled());
|
if (!is_userspace() || m_state != State::Executing)
|
||||||
if (m_handling_signal == 0)
|
return false;
|
||||||
derrorln("set_signal_done called while not handling singal");
|
auto& interrupt_stack = *reinterpret_cast<InterruptStack*>(interrupt_stack_base() + interrupt_stack_size() - sizeof(InterruptStack));
|
||||||
else if (m_handling_signal != signal)
|
return interrupt_stack.rip == (uintptr_t)signal_trampoline;
|
||||||
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)
|
void Thread::handle_signal(int signal)
|
||||||
|
@ -273,7 +228,9 @@ namespace Kernel
|
||||||
ASSERT(!interrupts_enabled());
|
ASSERT(!interrupts_enabled());
|
||||||
ASSERT(&Thread::current() == this);
|
ASSERT(&Thread::current() == this);
|
||||||
ASSERT(is_userspace());
|
ASSERT(is_userspace());
|
||||||
ASSERT(!m_handling_signal);
|
|
||||||
|
auto& interrupt_stack = *reinterpret_cast<InterruptStack*>(interrupt_stack_base() + interrupt_stack_size() - sizeof(InterruptStack));
|
||||||
|
ASSERT(GDT::is_user_segment(interrupt_stack.cs));
|
||||||
|
|
||||||
if (signal == 0)
|
if (signal == 0)
|
||||||
{
|
{
|
||||||
|
@ -292,9 +249,6 @@ namespace Kernel
|
||||||
ASSERT(signal <= _SIGMAX);
|
ASSERT(signal <= _SIGMAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
uintptr_t& return_rsp = this->return_rsp();
|
|
||||||
uintptr_t& return_rip = this->return_rip();
|
|
||||||
|
|
||||||
vaddr_t signal_handler = process().m_signal_handlers[signal];
|
vaddr_t signal_handler = process().m_signal_handlers[signal];
|
||||||
|
|
||||||
m_signal_pending_mask &= ~(1ull << signal);
|
m_signal_pending_mask &= ~(1ull << signal);
|
||||||
|
@ -305,14 +259,11 @@ namespace Kernel
|
||||||
else if (signal_handler != (vaddr_t)SIG_DFL)
|
else if (signal_handler != (vaddr_t)SIG_DFL)
|
||||||
{
|
{
|
||||||
// call userspace signal handlers
|
// call userspace signal handlers
|
||||||
// FIXME: signal trampoline should take a hash etc
|
interrupt_stack.rsp -= 128; // skip possible red-zone
|
||||||
// to only allow marking signals done from it
|
write_to_stack(interrupt_stack.rsp, interrupt_stack.rip);
|
||||||
m_handling_signal = signal;
|
write_to_stack(interrupt_stack.rsp, signal);
|
||||||
return_rsp += 128; // skip possible red-zone
|
write_to_stack(interrupt_stack.rsp, signal_handler);
|
||||||
write_to_stack(return_rsp, return_rip);
|
interrupt_stack.rip = (uintptr_t)signal_trampoline;
|
||||||
write_to_stack(return_rsp, signal);
|
|
||||||
write_to_stack(return_rsp, signal_handler);
|
|
||||||
return_rip = (uintptr_t)signal_trampoline;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -393,8 +344,8 @@ namespace Kernel
|
||||||
|
|
||||||
void Thread::on_exit()
|
void Thread::on_exit()
|
||||||
{
|
{
|
||||||
set_terminating();
|
ASSERT(this == &Thread::current());
|
||||||
TerminateBlocker(*this);
|
terminate();
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,6 @@ __BEGIN_DECLS
|
||||||
#define SYS_DUP2 37
|
#define SYS_DUP2 37
|
||||||
#define SYS_KILL 39
|
#define SYS_KILL 39
|
||||||
#define SYS_SIGNAL 40
|
#define SYS_SIGNAL 40
|
||||||
#define SYS_SIGNAL_DONE 41
|
|
||||||
#define SYS_TCSETPGRP 42
|
#define SYS_TCSETPGRP 42
|
||||||
#define SYS_GET_PID 43
|
#define SYS_GET_PID 43
|
||||||
#define SYS_GET_PGID 44
|
#define SYS_GET_PGID 44
|
||||||
|
|
Loading…
Reference in New Issue