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