diff options
Diffstat (limited to 'kernel/sched.c')
| -rw-r--r-- | kernel/sched.c | 49 |
1 files changed, 47 insertions, 2 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: |
