diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/sched.c | 49 | ||||
| -rw-r--r-- | kernel/serial.c | 15 |
2 files changed, 55 insertions, 9 deletions
diff --git a/kernel/sched.c b/kernel/sched.c index c502024..da55fa3 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -1,3 +1,4 @@ +#include <asm/interrupt.h> #include <asm/system.h> #include <errno.h> #include <kernel/con.h> @@ -241,8 +242,13 @@ void reschedule(void) { } } - /* if not, then halt the machine */ - __asm__ ("hlt"); + /* if not, then halt the machine (temporarily re-enabling interrupts) */ + __asm__ volatile ( + "pushf\n" + "sti\n" + "hlt\n" + "popf\n" + ); } } @@ -258,6 +264,45 @@ void wake_up(struct task_struct **task) { *task = NULL; } +void sleep_on(struct task_struct **waiting) { + struct task_struct *t; + + if(waiting == NULL) + return; + + t = *waiting; + *waiting = ctask; + ctask->state = TSTATE_UNINTERRUPTIBLE; + reschedule(); + + *waiting = t; + if(t) + t->state = TSTATE_RUNNING; +} + +void interruptible_sleep_on(struct task_struct **waiting) { + struct task_struct *t; + + if(waiting == NULL) + return; + + t = *waiting; + *waiting = ctask; + while(1) { + ctask->state = TSTATE_INTERRUPTIBLE; + reschedule(); + + if(*waiting == NULL || *waiting == ctask) + break; + + (*waiting)->state = TSTATE_RUNNING; + } + + *waiting = NULL; + if(t) + t->state = TSTATE_RUNNING; +} + void sighandler_default(uint32_t sig) { switch(sig) { case SIGKILL: diff --git a/kernel/serial.c b/kernel/serial.c index 911f02c..f5610f5 100644 --- a/kernel/serial.c +++ b/kernel/serial.c @@ -97,18 +97,19 @@ ssize_t rsread(void *buf, size_t len) { return 0; while(n--) { - if(rxread == rxwrite) { - /* put the current task to sleep */ - waiting_task = ctask; - ctask->state = TSTATE_INTERRUPTIBLE; - reschedule(); - } + /* check if the buffer's empty and if so, go to sleep */ + cli(); + if(rxread == rxwrite) + interruptible_sleep_on(&waiting_task); + /* check again to see if anything was read, or we were interrupted */ if(rxread == rxwrite) { - waiting_task = NULL; + sti(); return -EINTR; } + sti(); + *b++ = rxbuf[rxread]; rxread = rxread + 1 % sizeof(rxbuf); } |
