aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarvin Borner2020-09-07 00:17:04 +0200
committerMarvin Borner2020-09-07 00:17:04 +0200
commit9c2f40441e0cc909ebefe432ddc10e2de29b82ac (patch)
tree2dcdd4ae56faab40f4bbbee27e72023e3b8acdbb
parent97f57cf4da45d268bbea863ae7bf40bb8c749aad (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.c3
-rw-r--r--apps/mandelbrot.c3
-rw-r--r--apps/wm.c4
-rw-r--r--kernel/features/proc.c34
-rw-r--r--kernel/features/syscall.c8
-rw-r--r--kernel/inc/proc.h5
-rw-r--r--libc/inc/sys.h2
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;
diff --git a/apps/wm.c b/apps/wm.c
index 477eb7f..d4db938 100644
--- a/apps/wm.c
+++ b/apps/wm.c
@@ -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))