diff options
author | Marvin Borner | 2020-09-07 00:17:04 +0200 |
---|---|---|
committer | Marvin Borner | 2020-09-07 00:17:04 +0200 |
commit | 9c2f40441e0cc909ebefe432ddc10e2de29b82ac (patch) | |
tree | 2dcdd4ae56faab40f4bbbee27e72023e3b8acdbb | |
parent | 97f57cf4da45d268bbea863ae7bf40bb8c749aad (diff) |
Added wait syscall.
This makes a process sleep until it receives a new message (no polling!).
I thought that this will result in performance improvements but I haven't
noticed any, yet. Maybe I'll remove this again in the future..
-rw-r--r-- | apps/init.c | 3 | ||||
-rw-r--r-- | apps/mandelbrot.c | 3 | ||||
-rw-r--r-- | apps/wm.c | 4 | ||||
-rw-r--r-- | kernel/features/proc.c | 34 | ||||
-rw-r--r-- | kernel/features/syscall.c | 8 | ||||
-rw-r--r-- | kernel/inc/proc.h | 5 | ||||
-rw-r--r-- | libc/inc/sys.h | 2 |
7 files changed, 52 insertions, 7 deletions
diff --git a/apps/init.c b/apps/init.c index ba6f93e..ccf88dd 100644 --- a/apps/init.c +++ b/apps/init.c @@ -13,5 +13,8 @@ int main(int argc, char **argv) /* int test = exec("/window", "test", NULL); */ int mandelbrot = exec("/mandelbrot", "mandelbrot", NULL); + while (1) { + yield(); + }; return wm + mandelbrot; } diff --git a/apps/mandelbrot.c b/apps/mandelbrot.c index d5b8ae0..9f73501 100644 --- a/apps/mandelbrot.c +++ b/apps/mandelbrot.c @@ -49,7 +49,6 @@ void draw_mandelbrot(struct window *win, int resolution) } gui_redraw(); print("Rendered mandelbrot successfully\n"); - yield(); } int main() @@ -62,7 +61,7 @@ int main() draw_mandelbrot(win, 50); while (1) { - yield(); + wait(); }; return 0; @@ -12,7 +12,7 @@ #include <sys.h> #include <vesa.h> -#define MOUSE_SKIP 4 // => Every nth move gets skipped +#define MOUSE_SKIP 5 // => Every move % n != 0 gets skipped static struct vbe *vbe; static struct window *direct; // Direct video memory window @@ -84,7 +84,7 @@ int main(int argc, char **argv) int mouse_skip = 0; while (1) { if (!(msg = msg_receive())) { - yield(); + wait(); continue; } diff --git a/kernel/features/proc.c b/kernel/features/proc.c index a5df875..19845d4 100644 --- a/kernel/features/proc.c +++ b/kernel/features/proc.c @@ -40,6 +40,15 @@ void scheduler(struct regs *regs) else current = proc_list->head; + while (((struct proc *)current->data)->state == PROC_WAITING) { + /* assert(proc_awake() > 0); */ + if (current && current->next && current->next->data) { + current = current->next; + } else { + current = proc_list->head; + } + } + memcpy(regs, &((struct proc *)current->data)->regs, sizeof(struct regs)); if (regs->cs != GDT_USER_CODE_OFFSET) { @@ -55,6 +64,16 @@ void scheduler(struct regs *regs) /* printf("{%d}", ((struct proc *)current->data)->pid); */ } +void scheduler_enable() +{ + irq_install_handler(0, scheduler); +} + +void scheduler_disable() +{ + irq_install_handler(0, timer_handler); +} + void proc_print() { struct node *node = proc_list->head; @@ -73,6 +92,17 @@ struct proc *proc_current() return current && current->data ? current->data : NULL; } +int proc_awake() +{ + int ret = 0; + struct node *iterator = proc_list->head; + do { + if (((struct proc *)iterator->data)->state != PROC_WAITING) + ret++; + } while ((iterator = iterator->next) != NULL); + return ret; +} + void proc_send(struct proc *src, struct proc *dest, enum message_type type, void *data) { // TODO: Use unique key instead of pid for IPC messaging @@ -85,6 +115,8 @@ void proc_send(struct proc *src, struct proc *dest, enum message_type type, void msg->msg->type = type; msg->msg->data = data; list_add(dest->messages, msg); + if (dest->state == PROC_WAITING) + dest->state = PROC_DEFAULT; } struct proc_message *proc_receive(struct proc *proc) @@ -159,7 +191,7 @@ void proc_init() return; cli(); - irq_install_handler(0, scheduler); + scheduler_enable(); proc_list = list_new(); kernel_proc = proc_make(); diff --git a/kernel/features/syscall.c b/kernel/features/syscall.c index 25770a4..b3af455 100644 --- a/kernel/features/syscall.c +++ b/kernel/features/syscall.c @@ -17,7 +17,7 @@ void syscall_handler(struct regs *r) enum sys num = r->eax; r->eax = 0; - if (num != SYS_RECEIVE && num != SYS_YIELD && num != SYS_TIME) + if (num != SYS_RECEIVE && num != SYS_YIELD && num != SYS_WAIT && num != SYS_TIME) printf("[SYSCALL] %d from %s: ", num, proc_current()->name); switch (num) { @@ -74,6 +74,12 @@ void syscall_handler(struct regs *r) proc_yield(r); break; } + case SYS_WAIT: { + /* printf("wait\n"); */ + proc_current()->state = PROC_WAITING; + proc_yield(r); + break; + } case SYS_TIME: { /* printf("time\n"); */ r->eax = timer_get(); diff --git a/kernel/inc/proc.h b/kernel/inc/proc.h index 2335d5d..9d4906d 100644 --- a/kernel/inc/proc.h +++ b/kernel/inc/proc.h @@ -17,7 +17,7 @@ #define GDT_USER_CODE_OFFSET 0x1b // User code segment offset in GDT (with ring3 mask) #define GDT_USER_DATA_OFFSET 0x23 // User data segment offset in GDT (with ring3 mask) -enum proc_state { PROC_DEFAULT }; +enum proc_state { PROC_DEFAULT, PROC_WAITING }; struct proc { u32 pid; @@ -36,9 +36,12 @@ struct proc_message { struct proc *kernel_proc; +void scheduler_enable(); +void scheduler_disable(); void proc_init(); void proc_print(); struct proc *proc_current(); +int proc_awake(); void proc_send(struct proc *src, struct proc *dest, enum message_type type, void *data); struct proc_message *proc_receive(struct proc *proc); struct proc *proc_from_pid(u32 pid); diff --git a/libc/inc/sys.h b/libc/inc/sys.h index 073ccd2..1b01127 100644 --- a/libc/inc/sys.h +++ b/libc/inc/sys.h @@ -16,6 +16,7 @@ enum sys { SYS_EXEC, // Execute path SYS_EXIT, // Exit current process SYS_YIELD, // Switch to next process + SYS_WAIT, // Sleep until new message arrives SYS_TIME, // Get kernel time SYS_REGISTER, // Register for event SYS_UNREGISTER, // Unregister event @@ -71,6 +72,7 @@ int sysv(enum sys num, ...); } \ } #define yield() (int)sys0(SYS_YIELD) +#define wait() (int)sys0(SYS_WAIT) #define time() (int)sys0(SYS_TIME) #define event_register(id) sys1(SYS_REGISTER, (int)(id)) |