summaryrefslogtreecommitdiff
path: root/kernel/sched.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/sched.c')
-rw-r--r--kernel/sched.c49
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: