diff options
-rw-r--r-- | apps/wm/main.c | 30 | ||||
-rw-r--r-- | kernel/Makefile | 3 | ||||
-rw-r--r-- | kernel/drivers/int.c | 21 | ||||
-rw-r--r-- | kernel/drivers/pit.c | 20 | ||||
-rw-r--r-- | kernel/drivers/rtc.c | 2 | ||||
-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 (renamed from kernel/drivers/timer.c) | 65 | ||||
-rw-r--r-- | kernel/inc/drivers/int.h | 2 | ||||
-rw-r--r-- | kernel/inc/drivers/pit.h | 8 | ||||
-rw-r--r-- | kernel/inc/proc.h | 7 | ||||
-rw-r--r-- | kernel/inc/timer.h (renamed from kernel/inc/drivers/timer.h) | 7 | ||||
-rw-r--r-- | libs/libc/inc/sys.h | 1 | ||||
-rw-r--r-- | libs/libgui/gui.c | 71 | ||||
-rw-r--r-- | libs/libgui/gui.h | 2 |
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 |