summaryrefslogtreecommitdiff
path: root/kernel/syscall.c
diff options
context:
space:
mode:
authorFreya Murphy <freya@freyacat.org>2025-04-27 18:22:39 -0400
committerFreya Murphy <freya@freyacat.org>2025-04-27 18:22:39 -0400
commit21e2ed43f7d60e11f5b231212e6cada61f6e20c9 (patch)
tree621302910832df27e43ae1058d3dc3fd431d3643 /kernel/syscall.c
parentfmt (diff)
downloadcomus-21e2ed43f7d60e11f5b231212e6cada61f6e20c9.tar.gz
comus-21e2ed43f7d60e11f5b231212e6cada61f6e20c9.tar.bz2
comus-21e2ed43f7d60e11f5b231212e6cada61f6e20c9.zip
add more syscall impls
Diffstat (limited to '')
-rw-r--r--kernel/syscall.c192
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 *)(&current_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;
}