234 lines
6.5 KiB
C
234 lines
6.5 KiB
C
#pragma once
|
|
|
|
#include <stdint.h>
|
|
#include <kernel/types.h>
|
|
#include <kernel/vfs.h>
|
|
#include <kernel/tree.h>
|
|
#include <kernel/list.h>
|
|
#include <kernel/spinlock.h>
|
|
#include <kernel/arch/x86_64/pml.h>
|
|
#include <sys/types.h>
|
|
#include <sys/time.h>
|
|
#include <sys/signal_defs.h>
|
|
|
|
#define PROC_REUSE_FDS 0x0001
|
|
#define KERNEL_STACK_SIZE 0x9000
|
|
#define USER_ROOT_UID 0
|
|
|
|
typedef struct {
|
|
intptr_t refcount;
|
|
union PML * directory;
|
|
spin_lock_t lock;
|
|
} page_directory_t;
|
|
|
|
typedef struct {
|
|
uintptr_t sp; /* 0 */
|
|
uintptr_t bp; /* 8 */
|
|
uintptr_t ip; /* 16 */
|
|
uintptr_t tls_base; /* 24 */
|
|
uintptr_t saved[5]; /* XXX Arch dependent */
|
|
/**
|
|
* 32: rbx
|
|
* 40: r12
|
|
* 48: r13
|
|
* 56: r14
|
|
* 64: r15
|
|
*/
|
|
} kthread_context_t;
|
|
|
|
typedef struct thread {
|
|
kthread_context_t context;
|
|
uint8_t fp_regs[512];
|
|
page_directory_t * page_directory;
|
|
} thread_t;
|
|
|
|
typedef struct image {
|
|
uintptr_t entry;
|
|
uintptr_t heap;
|
|
uintptr_t stack;
|
|
uintptr_t shm_heap;
|
|
uintptr_t userstack;
|
|
spin_lock_t lock;
|
|
} image_t;
|
|
|
|
typedef struct file_descriptors {
|
|
fs_node_t ** entries;
|
|
uint64_t * offsets;
|
|
int * modes;
|
|
size_t length;
|
|
size_t capacity;
|
|
size_t refs;
|
|
spin_lock_t lock;
|
|
} fd_table_t;
|
|
|
|
#define PROC_FLAG_IS_TASKLET 0x01
|
|
#define PROC_FLAG_FINISHED 0x02
|
|
#define PROC_FLAG_STARTED 0x04
|
|
#define PROC_FLAG_RUNNING 0x08
|
|
#define PROC_FLAG_SLEEP_INT 0x10
|
|
#define PROC_FLAG_SUSPENDED 0x20
|
|
|
|
typedef struct process {
|
|
pid_t id; /* PID */
|
|
pid_t group; /* thread group */
|
|
pid_t job; /* tty job */
|
|
pid_t session; /* tty session */
|
|
int status; /* status code */
|
|
unsigned int flags; /* finished, started, running, isTasklet */
|
|
int owner;
|
|
|
|
uid_t user;
|
|
uid_t real_user;
|
|
|
|
gid_t user_group;
|
|
gid_t real_user_group;
|
|
|
|
unsigned int mask;
|
|
|
|
char * name;
|
|
char * description;
|
|
char ** cmdline;
|
|
|
|
char * wd_name;
|
|
fs_node_t * wd_node;
|
|
fd_table_t * fds; /* File descriptor table */
|
|
|
|
tree_node_t * tree_entry;
|
|
struct regs * syscall_registers;
|
|
struct regs * interrupt_registers;
|
|
list_t * wait_queue;
|
|
list_t * shm_mappings;
|
|
list_t * node_waits;
|
|
list_t * signal_queue;
|
|
char * signal_kstack;
|
|
|
|
node_t sched_node;
|
|
node_t sleep_node;
|
|
node_t * timed_sleep_node;
|
|
node_t * timeout_node;
|
|
|
|
struct timeval start;
|
|
int awoken_index;
|
|
|
|
thread_t thread;
|
|
thread_t signal_state;
|
|
image_t image;
|
|
|
|
spin_lock_t sched_lock;
|
|
|
|
uintptr_t signals[NUMSIGNALS+1];
|
|
|
|
int supplementary_group_count;
|
|
gid_t * supplementary_group_list;
|
|
} process_t;
|
|
|
|
typedef struct {
|
|
uint64_t end_tick;
|
|
uint64_t end_subtick;
|
|
process_t * process;
|
|
int is_fswait;
|
|
} sleeper_t;
|
|
|
|
struct ProcessorLocal {
|
|
/**
|
|
* @brief The running process on this core.
|
|
*
|
|
* The current_process is a pointer to the process struct for
|
|
* the process, userspace-thread, or kernel tasklet currently
|
|
* executing. Once the scheduler is active, this should always
|
|
* be set. If a core is not currently doing, its current_process
|
|
* should be the core's idle task.
|
|
*
|
|
* Because a process's data can be modified by nested interrupt
|
|
* contexts, we mark them as volatile to avoid making assumptions
|
|
* based on register-stored cached values.
|
|
*/
|
|
volatile process_t * current_process;
|
|
/**
|
|
* @brief Idle loop.
|
|
*
|
|
* This is a special kernel tasklet that sits in a loop
|
|
* waiting for an interrupt from a preemption source or hardware
|
|
* device. Its context should never be saved, it should never
|
|
* be added to a sleep queue, and it should be scheduled whenever
|
|
* there is nothing else to do.
|
|
*/
|
|
process_t * kernel_idle_task;
|
|
/**
|
|
* @brief Process this core was last scheduled to run.
|
|
*/
|
|
volatile process_t * previous_process;
|
|
|
|
int cpu_id;
|
|
union PML * current_pml;
|
|
|
|
struct regs * interrupt_registers;
|
|
|
|
#ifdef __x86_64__
|
|
int lapic_id;
|
|
/* Processor information loaded at startup. */
|
|
int cpu_model;
|
|
int cpu_family;
|
|
char cpu_model_name[48];
|
|
const char * cpu_manufacturer;
|
|
#endif
|
|
};
|
|
|
|
extern struct ProcessorLocal processor_local_data[32];
|
|
extern int processor_count;
|
|
|
|
/**
|
|
* @brief Core-local kernel data.
|
|
*
|
|
* x86-64: Marking this as __seg_gs makes it %gs-base-relative.
|
|
*/
|
|
static struct ProcessorLocal __seg_gs * const this_core = 0;
|
|
|
|
extern unsigned long process_append_fd(process_t * proc, fs_node_t * node);
|
|
extern long process_move_fd(process_t * proc, long src, long dest);
|
|
extern void initialize_process_tree(void);
|
|
extern process_t * process_from_pid(pid_t pid);
|
|
|
|
extern void process_delete(process_t * proc);
|
|
extern void make_process_ready(volatile process_t * proc);
|
|
extern volatile process_t * next_ready_process(void);
|
|
extern int wakeup_queue(list_t * queue);
|
|
extern int wakeup_queue_interrupted(list_t * queue);
|
|
extern int sleep_on(list_t * queue);
|
|
extern int sleep_on_unlocking(list_t * queue, spin_lock_t * release);
|
|
extern int process_alert_node(process_t * process, void * value);
|
|
extern void sleep_until(process_t * process, unsigned long seconds, unsigned long subseconds);
|
|
extern void switch_task(uint8_t reschedule);
|
|
extern int process_wait_nodes(process_t * process,fs_node_t * nodes[], int timeout);
|
|
extern process_t * process_get_parent(process_t * process);
|
|
extern int process_is_ready(process_t * proc);
|
|
extern void wakeup_sleepers(unsigned long seconds, unsigned long subseconds);
|
|
extern void task_exit(int retval);
|
|
extern __attribute__((noreturn)) void switch_next(void);
|
|
extern int process_awaken_from_fswait(process_t * process, int index);
|
|
extern void process_awaken_signal(process_t * process);
|
|
extern void process_release_directory(page_directory_t * dir);
|
|
extern process_t * spawn_worker_thread(void (*entrypoint)(void * argp), const char * name, void * argp);
|
|
extern pid_t fork(void);
|
|
extern pid_t clone(uintptr_t new_stack, uintptr_t thread_func, uintptr_t arg);
|
|
extern int waitpid(int pid, int * status, int options);
|
|
extern int exec(const char * path, int argc, char *const argv[], char *const env[], int interp_depth);
|
|
|
|
extern tree_t * process_tree; /* Parent->Children tree */
|
|
extern list_t * process_list; /* Flat storage */
|
|
extern list_t * process_queue; /* Ready queue */
|
|
extern list_t * sleep_queue;
|
|
|
|
extern void arch_enter_tasklet(void);
|
|
extern __attribute__((noreturn)) void arch_resume_user(void);
|
|
extern __attribute__((noreturn)) void arch_restore_context(volatile thread_t * buf);
|
|
extern __attribute__((returns_twice)) int arch_save_context(volatile thread_t * buf);
|
|
extern void arch_restore_floating(process_t * proc);
|
|
extern void arch_save_floating(process_t * proc);
|
|
extern void arch_set_kernel_stack(uintptr_t);
|
|
extern void arch_enter_user(uintptr_t entrypoint, int argc, char * argv[], char * envp[], uintptr_t stack);
|
|
__attribute__((noreturn))
|
|
extern void arch_enter_signal_handler(uintptr_t,int);
|
|
extern void arch_wakeup_others(void);
|
|
|