Luna/kernel/src/thread/Thread.cpp

173 lines
4.6 KiB
C++
Raw Normal View History

#include "thread/Thread.h"
2023-07-10 17:46:57 +00:00
#include "Log.h"
#include "memory/MemoryManager.h"
#include "thread/Scheduler.h"
#include <bits/atfile.h>
#include <bits/open-flags.h>
#include <luna/Alloc.h>
2022-12-17 09:50:49 +00:00
#include <luna/Atomic.h>
#include <luna/PathParser.h>
2022-12-17 09:50:49 +00:00
static Atomic<u64> g_next_id;
2022-12-19 11:43:23 +00:00
LinkedList<Thread> g_threads;
2022-12-17 09:50:49 +00:00
void Thread::init()
{
g_next_id = 2;
2022-12-17 09:50:49 +00:00
}
Result<Thread*> new_thread()
{
2023-01-10 18:31:41 +00:00
Thread* const thread = TRY(make<Thread>());
thread->id = g_next_id++;
return thread;
2023-01-02 12:07:29 +00:00
}
Result<int> Thread::allocate_fd(int min)
{
if (min < 0 || min >= FD_MAX) return err(EINVAL);
for (int i = min; i < FD_MAX; i++)
{
// FIXME: Possible race condition if multiple threads share a FileDescriptorTable? Let's not worry about it for
// now, we're still a long way away from reaching that point.
if (!fd_table[i].has_value()) { return i; }
}
return err(EMFILE);
}
Result<FileDescriptor*> Thread::resolve_fd(int fd)
{
if (fd < 0 || fd >= FD_MAX) return err(EBADF);
Option<FileDescriptor>& maybe_descriptor = fd_table[fd];
if (!maybe_descriptor.has_value()) return err(EBADF);
return maybe_descriptor.value_ptr();
}
Result<SharedPtr<VFS::Inode>> Thread::resolve_atfile(int dirfd, const String& path, bool allow_empty_path,
bool follow_last_symlink, SharedPtr<VFS::Inode>* parent_inode)
{
if (parent_inode) *parent_inode = this->current_directory;
if (PathParser::is_absolute(path.view()))
return VFS::resolve_path(path.chars(), this->auth, {}, follow_last_symlink);
if (dirfd == AT_FDCWD)
return VFS::resolve_path(path.chars(), this->auth, this->current_directory, follow_last_symlink);
auto descriptor = TRY(resolve_fd(dirfd));
if (parent_inode) *parent_inode = descriptor->inode;
if (path.is_empty() && allow_empty_path) return descriptor->inode;
return VFS::resolve_path(path.chars(), this->auth, descriptor->inode, follow_last_symlink);
}
[[noreturn]] void Thread::exit_and_signal_parent(u8 _status)
{
2023-07-10 11:04:47 +00:00
if (this->id == 1) fail("the init process exited");
if (is_kernel) state = ThreadState::Dying;
else
{
Scheduler::for_each_child(this, [](Thread* child) {
child->parent = Scheduler::init_thread();
return true;
});
if (parent && parent->state == ThreadState::Waiting)
{
auto child = *parent->child_being_waited_for;
if (child == -1 || child == (pid_t)id)
{
parent->child_being_waited_for = (pid_t)id;
parent->wake_up();
}
}
state = ThreadState::Exited;
}
status = _status;
kernel_yield();
unreachable();
}
enum class DefaultSignalAction
{
Ignore,
Terminate,
};
static constexpr DefaultSignalAction default_actions[] = {
DefaultSignalAction::Terminate // SIGABRT
};
2023-07-10 17:46:57 +00:00
void Thread::process_pending_signals(Registers* current_regs)
{
for (int i = 0; i < NSIG; i++)
{
if (signal_mask & (1 << i)) continue;
if (pending_signals & (1 << i))
{
int signo = i + 1;
pending_signals &= ~(1 << i);
kinfoln("signal: executing signal %d for thread %ld", signo, id);
auto handler = signal_handlers[i];
if (handler.sa_handler == SIG_IGN)
{
kinfoln("signal: ignoring signal (handler=SIG_IGN)");
return;
}
if (handler.sa_handler == SIG_DFL)
{
default_signal:
if (id == 1)
{
kwarnln("signal: init got a signal it has no handler for, ignoring");
return;
}
kinfoln("signal: using default behavior (handler=SIG_DFL)");
auto action = default_actions[i];
switch (action)
{
case DefaultSignalAction::Ignore: return;
// FIXME: Add signal exit codes.
case DefaultSignalAction::Terminate: exit_and_signal_parent(255);
}
2023-07-10 17:46:57 +00:00
}
// If we fail to deliver the signal (usually because there's not enough space on the stack), execute the
// default action.
if (!deliver_signal(signo, current_regs)) goto default_signal;
return;
}
}
}
bool FileDescriptor::should_append()
{
return flags & O_APPEND;
}
2023-03-19 10:25:14 +00:00
bool FileDescriptor::should_block()
{
return !(flags & O_NONBLOCK);
2023-03-19 10:25:14 +00:00
}
bool FileDescriptor::is_readable()
{
return flags & O_RDONLY;
}
bool FileDescriptor::is_writable()
{
return flags & O_WRONLY;
}