diff options
author | Marvin Borner | 2021-07-01 21:13:01 +0200 |
---|---|---|
committer | Marvin Borner | 2021-07-01 22:32:16 +0200 |
commit | f3e85eedc434da973267f360abdbb79cb6f24100 (patch) | |
tree | 9fd71ec70454474a0a2cff479c7d9b949e779c74 /kernel/features | |
parent | 340e841772eb13d9087235b8707c1cfeff8710cb (diff) |
Timing is everything
Diffstat (limited to 'kernel/features')
-rw-r--r-- | kernel/features/dev.c | 2 | ||||
-rw-r--r-- | kernel/features/proc.c | 13 | ||||
-rw-r--r-- | kernel/features/syscall.c | 2 | ||||
-rw-r--r-- | kernel/features/timer.c | 115 |
4 files changed, 129 insertions, 3 deletions
diff --git a/kernel/features/dev.c b/kernel/features/dev.c index 0e082f9..c190a8a 100644 --- a/kernel/features/dev.c +++ b/kernel/features/dev.c @@ -8,7 +8,6 @@ #include <drivers/cpu.h> #include <drivers/int.h> #include <drivers/ps2.h> -#include <drivers/timer.h> #include <drivers/vbe.h> #include <drivers/vmware.h> #include <fb.h> @@ -21,6 +20,7 @@ #include <rand.h> #include <str.h> #include <syscall.h> +#include <timer.h> struct dev_listener { u32 group; diff --git a/kernel/features/proc.c b/kernel/features/proc.c index 03f45c9..9f4b38b 100644 --- a/kernel/features/proc.c +++ b/kernel/features/proc.c @@ -4,7 +4,6 @@ #include <dev.h> #include <drivers/cpu.h> #include <drivers/gdt.h> -#include <drivers/timer.h> #include <errno.h> #include <fs.h> #include <load.h> @@ -14,6 +13,7 @@ #include <proc.h> #include <stack.h> #include <str.h> +#include <timer.h> #define PROC(node) ((struct proc *)node->data) @@ -133,6 +133,17 @@ struct proc *proc_from_pid(u32 pid) return NULL; } +void proc_timer_check(u32 time) +{ + struct node *iterator = proc_list_blocked->head; + while (iterator) { + struct proc *proc = PROC(iterator); + if (proc->timer.mode == TIMER_MODE_SLEEP && time >= proc->timer.data) + dev_unblock_pid(proc->pid); + iterator = iterator->next; + } +} + CLEAR void proc_set_quantum(struct proc *proc, u32 value) { proc->quantum.val = value; diff --git a/kernel/features/syscall.c b/kernel/features/syscall.c index 16a83d6..86b675c 100644 --- a/kernel/features/syscall.c +++ b/kernel/features/syscall.c @@ -3,7 +3,6 @@ #include <dev.h> #include <drivers/cpu.h> #include <drivers/int.h> -#include <drivers/timer.h> #include <errno.h> #include <fs.h> #include <load.h> @@ -14,6 +13,7 @@ #include <str.h> #include <sys.h> #include <syscall.h> +#include <timer.h> static u32 syscall_handler(u32 esp) { diff --git a/kernel/features/timer.c b/kernel/features/timer.c new file mode 100644 index 0000000..674dd1a --- /dev/null +++ b/kernel/features/timer.c @@ -0,0 +1,115 @@ +// MIT License, Copyright (c) 2020 Marvin Borner + +#include <assert.h> +#include <def.h> +#include <dev.h> +#include <drivers/cpu.h> +#include <drivers/int.h> +#include <drivers/pit.h> +#include <drivers/rtc.h> +#include <mem.h> +#include <proc.h> +#include <timer.h> + +static u32 timer_ticks = 0; + +u32 timer_get(void) +{ + return timer_ticks; +} + +static void timer_handler(void) +{ + int_disable(); + if (timer_ticks >= U32_MAX) + timer_ticks = 0; + else + timer_ticks++; + proc_timer_check(timer_ticks); + int_enable(); +} + +CLEAR void timer_install_handler(void) +{ + static u8 check = 0; + assert(check++ == 0); + int_event_handler_add(0, timer_handler); +} + +// "Delay" function with CPU sleep +void timer_wait(u32 ticks) +{ + u32 eticks = timer_ticks + ticks; + while (timer_ticks < eticks) + __asm__ volatile("sti\nhlt\ncli"); +} + +static struct timer timer_struct(void) +{ + struct proc *proc = proc_current(); + struct timer timer = { + .rtc = rtc_stamp(), + .ticks.user = proc->ticks.user, + .ticks.kernel = proc->ticks.kernel, + .time = timer_get(), + }; + return timer; +} + +static res timer_read(void *buf, u32 offset, u32 count) +{ + UNUSED(offset); + + // TODO: Make sleeping more accurate + struct proc *proc = proc_current(); + if (proc->timer.mode == TIMER_MODE_SLEEP) { + dev_block(DEV_TIMER, proc); + proc->timer.mode = TIMER_MODE_DEFAULT; + } + + struct timer timer = timer_struct(); + memcpy_user(buf, &timer, MIN(count, sizeof(timer))); + + return MIN(count, sizeof(timer)); +} + +static res timer_control(u32 request, void *arg1, void *arg2, void *arg3) +{ + UNUSED(arg2); + UNUSED(arg3); + + switch (request) { + case DEVCTL_TIMER_SLEEP: { + struct proc *proc = proc_current(); + proc->timer.mode = TIMER_MODE_SLEEP; + proc->timer.data = timer_ticks + (u32)arg1; + return EOK; + } + default: + return -EINVAL; + } +} + +static res timer_ready(void) +{ + struct proc *proc = proc_current(); + if (proc->timer.mode == TIMER_MODE_SLEEP) { + if (timer_ticks >= proc->timer.data) + return EOK; + return -EAGAIN; + } + return EOK; +} + +// Install timer handler into IRQ0 +CLEAR void timer_install(void) +{ + // hpet_install(10000); // TODO: Reimplement hpet + pit_install(); + + struct dev_dev *dev = zalloc(sizeof(*dev)); + dev->read = timer_read; + dev->control = timer_control; + dev->ready = timer_ready; + dev_add(DEV_TIMER, dev); +} |