#pragma once #include "arch/MMU.h" #include "fs/OpenFileDescription.h" #include "fs/VFS.h" #include "lib/Mutex.h" #include "memory/AddressSpace.h" #include #include #include #include #include #include #include #include #ifdef ARCH_X86_64 #include "arch/x86_64/CPU.h" #else #error "Unknown architecture." #endif constexpr int MAX_POSIX_TIMERS = 64; constexpr i64 PROCESS_SHOULD_REAP = -1; class Timer; enum class ThreadState { None, Idle, Runnable, Sleeping, Waiting, Stopped, Exited, Dying }; static constexpr int FD_MAX = 64; struct Credentials { u32 uid { 0 }; u32 euid { 0 }; u32 suid { 0 }; u32 gid { 0 }; u32 egid { 0 }; u32 sgid { 0 }; }; struct Process : public LinkedListNode { Atomic thread_count; pid_t id; Atomic pgid { 0 }; Atomic sid { 0 }; bool has_called_exec { false }; mode_t umask { 0 }; int promises { -1 }; int execpromises { -1 }; Process* parent { nullptr }; MutexLocked auth { Credentials { 0, 0, 0, 0, 0, 0 } }; MutexLocked> extra_groups { {} }; Credentials credentials(); Result> copy_groups(); MutexLocked> address_space; MutexLocked[FD_MAX]> fd_table = {}; Timer real_timer; Timer virtual_timer; Timer profiling_timer; Clock virtual_clock; Clock profiling_clock; bool is_kernel { false }; Option posix_timers[MAX_POSIX_TIMERS]; Mutex posix_timer_mutex; StaticString<128> cmdline; Atomic user_ticks_self = 0; Atomic kernel_ticks_self = 0; Atomic user_ticks_children = 0; Atomic kernel_ticks_children = 0; Result allocate_timerid(); Result resolve_timerid(int id); Result allocate_fd(int min, FileDescriptor& descriptor); Result resolve_fd(int fd); Result> resolve_atfile(int dirfd, const String& path, bool allow_empty_path, bool follow_last_symlink, SharedPtr* parent_inode = nullptr); String current_directory_path = {}; SharedPtr current_directory = {}; SharedPtr controlling_terminal; int status { 0 }; void send_signal(int signo); bool is_session_leader() { return id == sid; } bool alive() { return thread_count > 0; } bool dead() { return thread_count == 0; } static Process* current(); [[noreturn]] void exit(int status); }; struct Thread : public LinkedListNode { Process* process; pid_t tid; Registers regs; Atomic ticks_left; Atomic sleep_ticks_left; Atomic user_ticks_self = 0; Atomic kernel_ticks_self = 0; Stack stack; Stack kernel_stack; struct sigaction signal_handlers[NSIG]; Bitset signal_mask { 0 }; Bitset pending_signals { 0 }; bool interrupted { false }; Atomic child_being_waited_for = -2; bool unrestricted_task { false }; FPData fp_data; ThreadState state = ThreadState::Runnable; bool is_kernel { false }; StaticString<128> cmdline; PageDirectory* self_directory() const { PageDirectory* result; auto lambda = Function&>::wrap([&](OwnedPtr& space) { result = space->page_directory(); }).release_value(); process->address_space.with_lock(move(lambda)); return result; } PageDirectory* active_directory { nullptr }; void quit(); void exit(bool yield = true); bool is_idle() { return state == ThreadState::Idle; } void wake_up() { state = ThreadState::Runnable; } void init_regs_kernel(); void init_regs_user(); void set_arguments(u64 arg1, u64 arg2, u64 arg3, u64 arg4); void set_ip(u64 ip); u64 ip() const; void set_sp(u64 sp); u64 sp() const; void set_return(u64 ret); u64 return_register(); void process_pending_signals(Registers* current_regs); int pending_signal_count(); int pending_signal(); bool will_ignore_pending_signal(); bool deliver_signal(int signo, Registers* current_regs); void sigreturn(Registers* current_regs); Result push_mem_on_stack(const u8* mem, usize size); Result pop_mem_from_stack(u8* mem, usize size); bool check_stack_on_exception(u64 stack_pointer); void stop(); void resume(); void send_signal(int signo); static void init(); }; void switch_context(Thread* old_thread, Thread* new_thread, Registers* regs); bool is_in_kernel(Registers* regs); Result new_thread(); pid_t next_thread_id(); extern LinkedList g_threads; extern LinkedList g_processes;