#include "thread/Thread.h" #include "memory/MemoryManager.h" #include #include #include #include #include static Atomic g_next_id; LinkedList g_threads; void Thread::init() { g_next_id = 2; } Result new_thread() { Thread* const thread = TRY(make()); thread->id = g_next_id++; return thread; } Result 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 Thread::resolve_fd(int fd) { if (fd < 0 || fd >= FD_MAX) return err(EBADF); Option& maybe_descriptor = fd_table[fd]; if (!maybe_descriptor.has_value()) return err(EBADF); return maybe_descriptor.value_ptr(); } Result> Thread::resolve_atfile(int dirfd, const String& path, bool allow_empty_path, bool follow_last_symlink, SharedPtr* 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); } bool FileDescriptor::should_append() { return flags & O_APPEND; } bool FileDescriptor::should_block() { return !(flags & O_NONBLOCK); } bool FileDescriptor::is_readable() { return flags & O_RDONLY; } bool FileDescriptor::is_writable() { return flags & O_WRONLY; }