241 lines
5.1 KiB
C++
241 lines
5.1 KiB
C++
#pragma once
|
|
#include "arch/MMU.h"
|
|
#include "fs/OpenFileDescription.h"
|
|
#include "fs/VFS.h"
|
|
#include "lib/Mutex.h"
|
|
#include "memory/AddressSpace.h"
|
|
#include <bits/signal.h>
|
|
#include <luna/Bitset.h>
|
|
#include <luna/LinkedList.h>
|
|
#include <luna/OwnedPtr.h>
|
|
#include <luna/Result.h>
|
|
#include <luna/Stack.h>
|
|
#include <luna/StaticString.h>
|
|
#include <luna/String.h>
|
|
|
|
#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<Process>
|
|
{
|
|
Atomic<i64> thread_count;
|
|
|
|
pid_t id;
|
|
Atomic<pid_t> pgid { 0 };
|
|
Atomic<pid_t> sid { 0 };
|
|
|
|
bool has_called_exec { false };
|
|
|
|
mode_t umask { 0 };
|
|
|
|
int promises { -1 };
|
|
int execpromises { -1 };
|
|
|
|
Process* parent { nullptr };
|
|
|
|
MutexLocked<Credentials> auth { Credentials { 0, 0, 0, 0, 0, 0 } };
|
|
|
|
MutexLocked<Vector<gid_t>> extra_groups { {} };
|
|
|
|
Credentials credentials();
|
|
Result<Vector<gid_t>> copy_groups();
|
|
|
|
MutexLocked<OwnedPtr<AddressSpace>> address_space;
|
|
|
|
MutexLocked<Option<FileDescriptor>[FD_MAX]> fd_table = {};
|
|
|
|
Timer real_timer;
|
|
Timer virtual_timer;
|
|
Timer profiling_timer;
|
|
|
|
Clock virtual_clock;
|
|
Clock profiling_clock;
|
|
|
|
bool is_kernel { false };
|
|
|
|
Option<Timer> posix_timers[MAX_POSIX_TIMERS];
|
|
Mutex posix_timer_mutex;
|
|
|
|
StaticString<128> cmdline;
|
|
|
|
Atomic<u64> user_ticks_self = 0;
|
|
Atomic<u64> kernel_ticks_self = 0;
|
|
Atomic<u64> user_ticks_children = 0;
|
|
Atomic<u64> kernel_ticks_children = 0;
|
|
|
|
Result<int> allocate_timerid();
|
|
Result<Timer*> resolve_timerid(int id);
|
|
|
|
Result<int> allocate_fd(int min, FileDescriptor& descriptor);
|
|
Result<FileDescriptor*> resolve_fd(int fd);
|
|
Result<SharedPtr<VFS::Inode>> resolve_atfile(int dirfd, const String& path, bool allow_empty_path,
|
|
bool follow_last_symlink,
|
|
SharedPtr<VFS::Inode>* parent_inode = nullptr);
|
|
|
|
String current_directory_path = {};
|
|
SharedPtr<VFS::Inode> current_directory = {};
|
|
|
|
SharedPtr<VFS::Inode> 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<Thread>
|
|
{
|
|
Process* process;
|
|
|
|
pid_t tid;
|
|
|
|
Registers regs;
|
|
|
|
Atomic<u64> ticks_left;
|
|
Atomic<u64> sleep_ticks_left;
|
|
|
|
Atomic<u64> user_ticks_self = 0;
|
|
Atomic<u64> kernel_ticks_self = 0;
|
|
|
|
Stack stack;
|
|
Stack kernel_stack;
|
|
|
|
struct sigaction signal_handlers[NSIG];
|
|
Bitset<sigset_t> signal_mask { 0 };
|
|
Bitset<sigset_t> pending_signals { 0 };
|
|
bool interrupted { false };
|
|
|
|
Atomic<pid_t> 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<OwnedPtr<AddressSpace>&>::wrap([&](OwnedPtr<AddressSpace>& 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<u64> push_mem_on_stack(const u8* mem, usize size);
|
|
Result<u64> 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<Thread*> new_thread();
|
|
|
|
pid_t next_thread_id();
|
|
|
|
extern LinkedList<Thread> g_threads;
|
|
extern LinkedList<Process> g_processes;
|