diff options
author | Freya Murphy <freya@freyacat.org> | 2025-04-27 18:22:39 -0400 |
---|---|---|
committer | Freya Murphy <freya@freyacat.org> | 2025-04-27 18:22:39 -0400 |
commit | 21e2ed43f7d60e11f5b231212e6cada61f6e20c9 (patch) | |
tree | 621302910832df27e43ae1058d3dc3fd431d3643 /kernel | |
parent | fmt (diff) | |
download | comus-21e2ed43f7d60e11f5b231212e6cada61f6e20c9.tar.gz comus-21e2ed43f7d60e11f5b231212e6cada61f6e20c9.tar.bz2 comus-21e2ed43f7d60e11f5b231212e6cada61f6e20c9.zip |
add more syscall impls
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/syscall.c | 192 |
1 files changed, 163 insertions, 29 deletions
diff --git a/kernel/syscall.c b/kernel/syscall.c index 11db5e5..b595b6a 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -5,21 +5,34 @@ #include <comus/drivers/pit.h> #include <comus/memory.h> #include <comus/procs.h> -#include <stdint.h> +#include <comus/time.h> +#include <lib.h> -#define RET(type, name) type *name = (type *)(¤t_pcb->regs->rax) -#define ARG1(type, name) type name = (type)(current_pcb->regs->rdi) -#define ARG2(type, name) type name = (type)(current_pcb->regs->rsi) -#define ARG3(type, name) type name = (type)(current_pcb->regs->rdx) -#define ARG4(type, name) type name = (type)(current_pcb->regs->rcx) +static struct pcb *pcb; + +#define RET(type, name) type *name = (type *)(&pcb->regs->rax) +#define ARG1(type, name) type name = (type)(pcb->regs->rdi) +#define ARG2(type, name) type name = (type)(pcb->regs->rsi) +#define ARG3(type, name) type name = (type)(pcb->regs->rdx) +#define ARG4(type, name) type name = (type)(pcb->regs->rcx) __attribute__((noreturn)) static int sys_exit(void) { ARG1(int, status); - current_pcb->exit_status = status; - pcb_zombify(current_pcb); - current_pcb = NULL; + pcb->exit_status = status; + pcb_zombify(pcb); + + // call next process + dispatch(); +} + +static int sys_waitpid(void) +{ + // arguments are read later + // by procs.c + pcb->state = PROC_STATE_WAITING; + pcb_queue_insert(waiting, pcb); // call next process dispatch(); @@ -31,7 +44,7 @@ static int sys_write(void) ARG2(const void *, buffer); ARG3(size_t, nbytes); - const char *map_buf = kmapuseraddr(current_pcb->memctx, buffer, nbytes); + const char *map_buf = kmapuseraddr(pcb->memctx, buffer, nbytes); if (map_buf == NULL) return 0; @@ -56,6 +69,125 @@ static int sys_write(void) return nbytes; } +static int sys_getpid(void) +{ + return pcb->pid; +} + +static int sys_getppid(void) +{ + // init's parent is itself + if (pcb->parent == NULL) + return init_pcb->pid; + return pcb->parent->pid; +} + +static int sys_gettime(void) +{ + RET(unsigned long, time); + *time = unixtime(); + return 0; +} + +static int sys_getprio(void) +{ + RET(unsigned int, prio); + *prio = pcb->priority; + return 0; +} + +static int sys_setprio(void) +{ + RET(unsigned int, old); + ARG1(unsigned int, new); + + *old = pcb->priority; + pcb->priority = new; + return 0; +} + +static int sys_kill(void) +{ + ARG1(pid_t, pid); + struct pcb *victim, *parent; + + victim = pcb_find_pid(pid); + + // pid does not exist + if (victim == NULL) + return 1; + + parent = victim; + while (parent) { + if (parent->pid == pcb->pid) + break; + parent = parent->parent; + } + + // we do not own this pid + if (parent == NULL) + return 1; + + switch (victim->state) { + case PROC_STATE_KILLED: + case PROC_STATE_ZOMBIE: + // you can't kill it if it's already dead + return 0; + + case PROC_STATE_READY: + case PROC_STATE_SLEEPING: + case PROC_STATE_BLOCKED: + // here, the process is on a queue somewhere; mark + // it as "killed", and let the scheduler deal with it + victim->state = PROC_STATE_KILLED; + return 0; + + case PROC_STATE_RUNNING: + // we have met the enemy, and it is us! + pcb->exit_status = 1; + pcb_zombify(pcb); + // we need a new current process + dispatch(); + break; + + case PROC_STATE_WAITING: + // similar to the 'running' state, but we don't need + // to dispatch a new process + victim->exit_status = 1; + pcb_queue_remove(waiting, pcb); + pcb_zombify(victim); + break; + + default: + // cannot kill a previable process + return 1; + } + + return 0; +} + +static int sys_sleep(void) +{ + RET(int, ret); + ARG1(unsigned long, ms); + + if (ms == 0) { + *ret = 0; + schedule(pcb); + dispatch(); + } + + pcb->wakeup = ticks + ms; + if (pcb_queue_insert(sleeping, pcb)) { + WARN("sleep pcb insert failed"); + return 1; + } + + // calling pcb is in sleeping queue, + // we must call a new one + dispatch(); +} + __attribute__((noreturn)) static int sys_poweroff(void) { // TODO: we should probably @@ -84,7 +216,7 @@ static int sys_drm(void) if (pADDR == NULL) return 1; - vADDR = mem_mapaddr(current_pcb->memctx, pADDR, (void *)0x1000000000, len, + vADDR = mem_mapaddr(pcb->memctx, pADDR, (void *)0x1000000000, len, F_PRESENT | F_WRITEABLE | F_UNPRIVILEGED); if (vADDR == NULL) return 1; @@ -93,7 +225,7 @@ static int sys_drm(void) height = gpu_dev->height; bpp = gpu_dev->bit_depth; - mem_ctx_switch(current_pcb->memctx); + mem_ctx_switch(pcb->memctx); *res_fb = vADDR; *res_width = width; *res_height = height; @@ -111,16 +243,16 @@ static int sys_ticks(void) } static int (*syscall_tbl[N_SYSCALLS])(void) = { - [SYS_exit] = sys_exit, [SYS_waitpid] = NULL, - [SYS_fork] = NULL, [SYS_exec] = NULL, - [SYS_open] = NULL, [SYS_close] = NULL, - [SYS_read] = NULL, [SYS_write] = sys_write, - [SYS_getpid] = NULL, [SYS_getppid] = NULL, - [SYS_gettime] = NULL, [SYS_getprio] = NULL, - [SYS_setprio] = NULL, [SYS_kill] = NULL, - [SYS_sleep] = NULL, [SYS_brk] = NULL, - [SYS_sbrk] = NULL, [SYS_poweroff] = sys_poweroff, - [SYS_drm] = sys_drm, [SYS_ticks] = sys_ticks, + [SYS_exit] = sys_exit, [SYS_waitpid] = sys_waitpid, + [SYS_fork] = NULL, [SYS_exec] = NULL, + [SYS_open] = NULL, [SYS_close] = NULL, + [SYS_read] = NULL, [SYS_write] = sys_write, + [SYS_getpid] = sys_getpid, [SYS_getppid] = sys_getppid, + [SYS_gettime] = sys_gettime, [SYS_getprio] = sys_getprio, + [SYS_setprio] = sys_setprio, [SYS_kill] = sys_kill, + [SYS_sleep] = sys_sleep, [SYS_brk] = NULL, + [SYS_sbrk] = NULL, [SYS_poweroff] = sys_poweroff, + [SYS_drm] = sys_drm, [SYS_ticks] = sys_ticks, }; void syscall_handler(struct cpu_regs *regs) @@ -133,16 +265,17 @@ void syscall_handler(struct cpu_regs *regs) mem_ctx_switch(kernel_mem_ctx); // update data - current_pcb->regs = regs; - num = current_pcb->regs->rax; - current_pcb->regs->rax = 0; + pcb = current_pcb; + pcb->regs = regs; + num = pcb->regs->rax; + pcb->regs->rax = 0; + current_pcb = NULL; // check for invalid syscall if (num >= N_SYSCALLS) { // kill process - current_pcb->exit_status = 1; - pcb_zombify(current_pcb); - current_pcb = NULL; + pcb->exit_status = 1; + pcb_zombify(pcb); // call next process dispatch(); } @@ -154,7 +287,8 @@ void syscall_handler(struct cpu_regs *regs) // on failure, set rax if (ret) - current_pcb->regs->rax = ret; + pcb->regs->rax = ret; // return to current pcb + current_pcb = pcb; } |