aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/wm/main.c30
-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
-rw-r--r--libs/libc/inc/sys.h1
-rw-r--r--libs/libgui/gui.c71
-rw-r--r--libs/libgui/gui.h2
16 files changed, 200 insertions, 56 deletions
diff --git a/apps/wm/main.c b/apps/wm/main.c
index 8c12b1a..d7bef72 100644
--- a/apps/wm/main.c
+++ b/apps/wm/main.c
@@ -429,24 +429,16 @@ static void window_ping_check(void)
}
}
-// TODO: Run ping in parallel thread/process
static void window_ping_all(void)
{
- static struct timer last = { 0 };
- struct timer timer;
- dev_read(DEV_TIMER, &timer, 0, sizeof(timer));
- if (timer.time - last.time > PING_INTERVAL) {
- window_ping_check();
+ window_ping_check();
- struct node *iterator = windows->head;
- while (iterator) {
- struct window *win = iterator->data;
- if (!(win->flags & WF_NO_WINDOW))
- window_ping(win);
- iterator = iterator->next;
- }
-
- last = timer;
+ struct node *iterator = windows->head;
+ while (iterator) {
+ struct window *win = iterator->data;
+ if (!(win->flags & WF_NO_WINDOW))
+ window_ping(win);
+ iterator = iterator->next;
}
}
@@ -759,7 +751,8 @@ int main(int argc, char **argv)
u8 msg[1024] = { 0 };
struct event_keyboard event_keyboard = { 0 };
struct event_mouse event_mouse = { 0 };
- enum dev_type listeners[] = { DEV_KEYBOARD, DEV_MOUSE, DEV_BUS, 0 };
+ enum dev_type listeners[] = { DEV_KEYBOARD, DEV_MOUSE, DEV_BUS, DEV_TIMER, 0 };
+ dev_control(DEV_TIMER, DEVCTL_TIMER_SLEEP, 0);
while (1) {
res poll_ret = 0;
@@ -775,9 +768,10 @@ int main(int argc, char **argv)
} else if (poll_ret == DEV_BUS) {
if (msg_receive(msg, sizeof(msg)) > 0)
handle_message(msg);
+ } else if (poll_ret == DEV_TIMER) {
+ dev_control(DEV_TIMER, DEVCTL_TIMER_SLEEP, PING_INTERVAL);
+ window_ping_all();
}
-
- window_ping_all();
}
return 1;
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);
diff --git a/libs/libc/inc/sys.h b/libs/libc/inc/sys.h
index 5b2130c..8aae78b 100644
--- a/libs/libc/inc/sys.h
+++ b/libs/libc/inc/sys.h
@@ -48,6 +48,7 @@ enum dev_type {
// Device control declarations
#define DEVCTL_FB_GET 0
+#define DEVCTL_TIMER_SLEEP 0
#define DEVCTL_BUS_CONNECT_BUS 0
#define DEVCTL_BUS_CONNECT_CONN 1
#define DEVCTL_BUS_REGISTER 2
diff --git a/libs/libgui/gui.c b/libs/libgui/gui.c
index 2dae302..f768232 100644
--- a/libs/libgui/gui.c
+++ b/libs/libgui/gui.c
@@ -646,7 +646,6 @@ static void gui_handle_mouse(struct message_mouse *msg)
struct gui_widget widget = { 0 };
gui_widget_at(msg->id, msg->pos, &widget);
- printf("%d\n", widget.id);
struct gui_window *win = gui_window_by_id(msg->id);
vec2 offset = gui_widget_offset(win->main_widget, &widget);
@@ -690,6 +689,25 @@ static void gui_handle_exit(void)
* Main loop
*/
+static void gui_handle_message(void *msg)
+{
+ struct message_header *head = msg;
+ switch (head->type) {
+ case GUI_MOUSE:
+ gui_handle_mouse(msg);
+ break;
+ case GUI_PING_WINDOW:
+ gui_handle_ping_window(msg);
+ break;
+ case GUI_DESTROY_WINDOW:
+ gui_handle_destroy_window(msg);
+ break;
+ default:
+ // TODO: Fix random unknown msg types
+ gui_error(EINVAL);
+ }
+}
+
void gui_loop(void)
{
atexit(gui_handle_exit);
@@ -699,22 +717,43 @@ void gui_loop(void)
u8 msg[4096] = { 0 };
while (gui_connect_wm(), msg_receive(msg, 4096) > 0) {
- struct message_header *head = (void *)msg;
- switch (head->type) {
- case GUI_MOUSE:
- gui_handle_mouse((void *)msg);
- break;
- case GUI_PING_WINDOW:
- gui_handle_ping_window((void *)msg);
- break;
- case GUI_DESTROY_WINDOW:
- gui_handle_destroy_window((void *)msg);
- break;
- default:
- // TODO: Fix random unknown msg types
- gui_error(EINVAL);
- }
+ gui_handle_message(msg);
}
err(1, "Gui loop failed\n");
}
+
+void gui_time_loop(u32 time, void (*callback)(struct timer *time))
+{
+ atexit(gui_handle_exit);
+
+ if (!windows)
+ err(1, "Create some windows first\n");
+
+ u8 msg[4096] = { 0 };
+ struct timer timer = { 0 };
+ enum dev_type listeners[] = { DEV_TIMER, DEV_BUS, 0 };
+ dev_control(DEV_TIMER, DEVCTL_TIMER_SLEEP, 0);
+
+ while (1) {
+ gui_connect_wm();
+ res poll_ret = 0;
+ if ((poll_ret = dev_poll(listeners)) < 0)
+ panic("Poll/read error: %s\n", strerror(errno));
+
+ if (poll_ret == DEV_TIMER) {
+ if (dev_read(DEV_TIMER, &timer, 0, sizeof(timer)) > 0) {
+ callback(&timer);
+ continue;
+ }
+ } else if (poll_ret == DEV_BUS) {
+ if (msg_receive(msg, sizeof(msg)) > 0) {
+ gui_handle_message(msg);
+ dev_control(DEV_TIMER, DEVCTL_TIMER_SLEEP, time);
+ continue;
+ }
+ }
+
+ err(1, "Gui loop failed\n");
+ }
+}
diff --git a/libs/libgui/gui.h b/libs/libgui/gui.h
index 0a4427b..10d44d8 100644
--- a/libs/libgui/gui.h
+++ b/libs/libgui/gui.h
@@ -6,6 +6,7 @@
#include <def.h>
#include <errno.h>
#include <libgui/gfx.h>
+#include <sys.h>
#include <vec.h>
enum gui_listener {
@@ -87,5 +88,6 @@ void gui_widget_margin(u32 win_id, u32 widget_id, vec2 margin);
void gui_widget_layout(u32 win_id, u32 widget_id, enum gui_layout layout);
void gui_loop(void);
+void gui_time_loop(u32 time, void (*callback)(struct timer *time));
#endif