aboutsummaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/Makefile3
-rw-r--r--kernel/drivers/int.c21
-rw-r--r--kernel/drivers/pit.c20
-rw-r--r--kernel/drivers/rtc.c2
-rw-r--r--kernel/features/dev.c2
-rw-r--r--kernel/features/proc.c13
-rw-r--r--kernel/features/syscall.c2
-rw-r--r--kernel/features/timer.c (renamed from kernel/drivers/timer.c)65
-rw-r--r--kernel/inc/drivers/int.h2
-rw-r--r--kernel/inc/drivers/pit.h8
-rw-r--r--kernel/inc/proc.h7
-rw-r--r--kernel/inc/timer.h (renamed from kernel/inc/drivers/timer.h)7
12 files changed, 130 insertions, 22 deletions
diff --git a/kernel/Makefile b/kernel/Makefile
index 9fed3f1..85ff419 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -15,7 +15,7 @@ COBJS = entry_asm.o \
drivers/ide.o \
drivers/vbe.o \
drivers/bga.o \
- drivers/timer.o \
+ drivers/pit.o \
drivers/vmware.o \
drivers/ps2/ps2.o \
drivers/ps2/mouse.o \
@@ -27,6 +27,7 @@ COBJS = entry_asm.o \
features/fb.o \
features/logger.o \
features/load.o \
+ features/timer.o \
features/proc.o \
features/proc_asm.o \
features/syscall.o
diff --git a/kernel/drivers/int.c b/kernel/drivers/int.c
index f6a5134..d5f0a67 100644
--- a/kernel/drivers/int.c
+++ b/kernel/drivers/int.c
@@ -172,19 +172,32 @@ static u32 int_special_handler(struct int_frame *frame)
* Universal handler
*/
+static u8 int_enabled = 1;
+
u32 int_handler(u32 esp);
u32 int_handler(u32 esp)
{
struct int_frame *frame = (struct int_frame *)esp;
- if (frame->int_no < 32)
+ if (frame->int_no < 32) {
int_trap_handler(frame);
- else if (frame->int_no < 48)
+ } else if (int_enabled && frame->int_no < 48) {
esp = int_event_handler(frame);
- else if (frame->int_no >= 128 && frame->int_no < 144)
+ } else if (frame->int_no >= 128 && frame->int_no < 144) {
esp = int_special_handler(frame);
- else
+ } else if (frame->int_no >= 48) {
panic("Unknown interrupt: %d\n", frame->int_no);
+ }
pic_ack(frame->int_no);
return esp;
}
+
+void int_disable(void)
+{
+ int_enabled = 0;
+}
+
+void int_enable(void)
+{
+ int_enabled = 1;
+}
diff --git a/kernel/drivers/pit.c b/kernel/drivers/pit.c
new file mode 100644
index 0000000..abba5e8
--- /dev/null
+++ b/kernel/drivers/pit.c
@@ -0,0 +1,20 @@
+// MIT License, Copyright (c) 2021 Marvin Borner
+
+#include <def.h>
+#include <drivers/cpu.h>
+#include <drivers/pit.h>
+#include <timer.h>
+
+CLEAR static void pit_phase(u32 hz)
+{
+ u32 divisor = 3579545 / 3 / hz;
+ outb(0x43, 0x36); // 01 10 11 0b // CTR, RW, MODE, BCD
+ outb(0x40, (u8)(divisor & 0xFF));
+ outb(0x40, (u8)(divisor >> 8));
+}
+
+CLEAR void pit_install(void)
+{
+ pit_phase(1000);
+ timer_install_handler();
+}
diff --git a/kernel/drivers/rtc.c b/kernel/drivers/rtc.c
index b67829e..0a9a3fd 100644
--- a/kernel/drivers/rtc.c
+++ b/kernel/drivers/rtc.c
@@ -3,10 +3,10 @@
#include <def.h>
#include <drivers/cpu.h>
#include <drivers/rtc.h>
-#include <drivers/timer.h>
#include <fs.h>
#include <mem.h>
#include <str.h>
+#include <timer.h>
static u8 rtc_busy(void)
{
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/drivers/timer.c b/kernel/features/timer.c
index 977647c..674dd1a 100644
--- a/kernel/drivers/timer.c
+++ b/kernel/features/timer.c
@@ -1,24 +1,18 @@
// 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 <drivers/timer.h>
#include <mem.h>
#include <proc.h>
+#include <timer.h>
static u32 timer_ticks = 0;
-CLEAR static void timer_phase(int hz)
-{
- int divisor = 3579545 / 3 / hz;
- outb(0x43, 0x36); // 01 10 11 0b // CTR, RW, MODE, BCD
- outb(0x40, (u8)(divisor & 0xFF));
- outb(0x40, (u8)(divisor >> 8));
-}
-
u32 timer_get(void)
{
return timer_ticks;
@@ -26,10 +20,20 @@ u32 timer_get(void)
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
@@ -56,21 +60,56 @@ 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: Find optimal femtosecond period */
- /* if (!hpet) */
- timer_phase(1000);
- int_event_handler_add(0, timer_handler);
+ // 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);
}
diff --git a/kernel/inc/drivers/int.h b/kernel/inc/drivers/int.h
index 8146898..9dd4a6f 100644
--- a/kernel/inc/drivers/int.h
+++ b/kernel/inc/drivers/int.h
@@ -44,6 +44,8 @@ struct idt_ptr {
} PACKED;
void idt_install(void);
+void int_enable(void);
+void int_disable(void);
void int_trap_handler_add(u32 int_no, void (*handler)(u32 esp));
void int_event_handler_add(u32 int_no, void (*handler)(void));
diff --git a/kernel/inc/drivers/pit.h b/kernel/inc/drivers/pit.h
new file mode 100644
index 0000000..b3cd507
--- /dev/null
+++ b/kernel/inc/drivers/pit.h
@@ -0,0 +1,8 @@
+// MIT License, Copyright (c) 2021 Marvin Borner
+
+#ifndef PIT_H
+#define PIT_H
+
+void pit_install(void);
+
+#endif
diff --git a/kernel/inc/proc.h b/kernel/inc/proc.h
index 42ff75d..5cc1fef 100644
--- a/kernel/inc/proc.h
+++ b/kernel/inc/proc.h
@@ -8,6 +8,7 @@
#include <list.h>
#include <stack.h>
#include <sys.h>
+#include <timer.h>
#define PROC_QUANTUM 15 // Milliseconds or something // TODO
#define PROC_STACK_SIZE 0x4000 // 16KiB
@@ -51,6 +52,11 @@ struct proc {
u8 val;
u8 cnt;
} quantum;
+
+ struct {
+ enum timer_mode mode;
+ u32 data;
+ } timer;
};
u32 scheduler(u32 esp);
@@ -62,6 +68,7 @@ u8 proc_idle(void);
struct proc *proc_from_pid(u32 pid);
void proc_exit(s32 status);
void proc_yield(void);
+void proc_timer_check(u32 time);
void proc_set_quantum(struct proc *proc, u32 value) NONNULL;
void proc_reset_quantum(struct proc *proc) NONNULL;
void proc_state(struct proc *proc, enum proc_state state) NONNULL;
diff --git a/kernel/inc/drivers/timer.h b/kernel/inc/timer.h
index ea1643b..1233f6e 100644
--- a/kernel/inc/drivers/timer.h
+++ b/kernel/inc/timer.h
@@ -5,6 +5,13 @@
#include <def.h>
+enum timer_mode {
+ TIMER_MODE_DEFAULT,
+ TIMER_MODE_SLEEP,
+};
+
+void timer_install_handler(void);
+
u32 timer_get(void);
void timer_wait(u32 ticks);
void timer_install(void);