diff options
Diffstat (limited to 'kernel/features/proc.c')
-rw-r--r-- | kernel/features/proc.c | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/kernel/features/proc.c b/kernel/features/proc.c new file mode 100644 index 0000000..a14aaea --- /dev/null +++ b/kernel/features/proc.c @@ -0,0 +1,104 @@ +// MIT License, Copyright (c) 2020 Marvin Borner + +#include <cpu.h> +#include <interrupts.h> +#include <load.h> +#include <mem.h> +#include <print.h> +#include <proc.h> +#include <str.h> +#include <timer.h> + +u32 pid = 0; +struct proc *root; +struct proc *current; +struct proc *last; + +void scheduler(struct regs *regs) +{ + if (current) + memcpy(¤t->regs, regs, sizeof(struct regs)); + + timer_handler(); + + if (current && current->next) + current = current->next; + else + current = root; + + while (current->state == PROC_ASLEEP) + if (!current->next) + current = root; + else + current = current->next; + + /* proc_print(); */ + memcpy(regs, ¤t->regs, sizeof(struct regs)); + + if (regs->cs != GDT_USER_CODE_OFFSET) { + regs->gs = GDT_USER_DATA_OFFSET; + regs->fs = GDT_USER_DATA_OFFSET; + regs->es = GDT_USER_DATA_OFFSET; + regs->ds = GDT_USER_DATA_OFFSET; + regs->ss = GDT_USER_DATA_OFFSET; + regs->cs = GDT_USER_CODE_OFFSET; + regs->eflags = EFLAGS_ALWAYS | EFLAGS_INTERRUPTS; + } + printf("%d", current->pid); +} + +void proc_print() +{ + struct proc *proc = root; + + printf("\n"); + while (proc) { + printf("Process %d [%s]: %s\n", proc->pid, + proc->state == PROC_RUNNING ? "running" : "sleeping", proc->name); + proc = proc->next; + } + printf("\n"); +} + +void proc_attach(struct proc *proc) +{ + if (!last->next) { + last->next = proc; + } else { + struct proc *save = last; + while (save->next) + save = save->next; + save->next = proc; + } +} + +struct proc *proc_make() +{ + struct proc *proc = malloc(sizeof(*proc)); + proc->pid = pid++; + proc->state = PROC_RUNNING; + proc->next = NULL; + + if (current) + proc_attach(proc); + last = proc; + return proc; +} + +extern void proc_jump_userspace(); + +u32 _esp, _eip; +void proc_init() +{ + cli(); + irq_install_handler(0, scheduler); + + root = proc_make(); + bin_load("/init", root); + strcpy(root->name, "root"); + proc_print(); + + _eip = root->regs.eip; + _esp = root->regs.esp; + proc_jump_userspace(); +} |