summaryrefslogtreecommitdiff
path: root/src/kernel/task
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/task')
-rw-r--r--src/kernel/task/idt.c25
-rw-r--r--src/kernel/task/idt.h3
-rw-r--r--src/kernel/task/syscall.c2
-rw-r--r--src/kernel/task/task.c18
-rw-r--r--src/kernel/task/task.h5
5 files changed, 42 insertions, 11 deletions
diff --git a/src/kernel/task/idt.c b/src/kernel/task/idt.c
index 72a3d54..cff4ae9 100644
--- a/src/kernel/task/idt.c
+++ b/src/kernel/task/idt.c
@@ -65,6 +65,7 @@ struct idt_entry idt_entries[256];
struct idt_ptr idt_ptr;
static int_callback irq_handlers[16] = {0};
+static struct thread* irq_wakeup[16] = {0};
void idt_isrHandler(struct registers regs) {
if ((regs.int_no == 14 && paging_fault(&regs) != 0) || regs.int_no != 14) {
@@ -80,16 +81,18 @@ void idt_isrHandler(struct registers regs) {
}
void idt_irqHandler(struct registers regs) {
- uint32_t doSwitch = 0;
- doSwitch |= (regs.int_no == 32); //IRQ0 = timer
+ uint32_t doSwitch = (regs.err_code == 0); //IRQ0 = timer
if (regs.err_code > 7) {
outb(0xA0, 0x20);
}
outb(0x20, 0x20);
+ if (irq_wakeup[regs.err_code] != 0) {
+ irq_wakeup[regs.err_code]->state = TS_RUNNING;
+ irq_wakeup[regs.err_code] = 0;
+ doSwitch = 1;
+ }
if (irq_handlers[regs.err_code] != 0) {
irq_handlers[regs.err_code](&regs);
- } else {
- monitor_write("Unhandled IRQ "); monitor_writeHex(regs.int_no - 32); monitor_write("\n");
}
if (doSwitch) tasking_switch();
}
@@ -98,7 +101,7 @@ void idt_syscallHandler(struct registers regs) {
if (syscalls[regs.eax] != 0) {
syscalls[regs.eax](&regs);
} else {
- PANIC("unhandled syscall");
+ monitor_write("Unhandled syscall...\n");
}
}
@@ -187,5 +190,15 @@ void idt_init() {
}
void idt_handleIrq(int number, int_callback func) {
- irq_handlers[number] = func;
+ if (number < 16 && number >= 0) {
+ irq_handlers[number] = func;
+ }
+}
+
+void idt_waitIrq(int number) {
+ if (number < 16 && number >= 0 && proc_priv() <= PL_DRIVER) {
+ irq_wakeup[number] = current_thread;
+ current_thread->state = TS_WAKEWAIT;
+ tasking_schedule();
+ }
}
diff --git a/src/kernel/task/idt.h b/src/kernel/task/idt.h
index bb89013..ed37eb0 100644
--- a/src/kernel/task/idt.h
+++ b/src/kernel/task/idt.h
@@ -27,7 +27,8 @@ struct registers {
typedef void (*int_callback)(struct registers*);
void idt_init();
-void idt_handleIrq(int number, int_callback func);
+void idt_handleIrq(int number, int_callback func); //Set IRQ handler
+void idt_waitIrq(int number); //ask current thread to wait for IRQ
#endif
diff --git a/src/kernel/task/syscall.c b/src/kernel/task/syscall.c
index 8195dd0..752864c 100644
--- a/src/kernel/task/syscall.c
+++ b/src/kernel/task/syscall.c
@@ -14,6 +14,7 @@ CALL0V(tasking_switch, schedule_sc);
CALL1V(thread_sleep, thread_sleep_sc);
CALL1V(process_exit, process_exit_sc);
CALL1(monitor_write, printk_sc);
+CALL1V(idt_waitIrq, irq_wait_sc);
static void thread_new_sc(struct registers* r) {
thread_new(current_thread->process, (thread_entry)r->ebx, (void*)r->ecx);
@@ -26,4 +27,5 @@ int_callback syscalls[] = {
process_exit_sc,
printk_sc,
thread_new_sc,
+ irq_wait_sc,
0 };
diff --git a/src/kernel/task/task.c b/src/kernel/task/task.c
index 8cdf7b3..622eaa1 100644
--- a/src/kernel/task/task.c
+++ b/src/kernel/task/task.c
@@ -88,6 +88,10 @@ void tasking_switch() {
: : "r"(current_thread->ebp), "r"(current_thread->esp), "r"(current_thread->eip));
}
+void tasking_schedule() {
+ asm volatile("int $64" : : "a"(1));
+}
+
void tasking_updateKernelPagetable(uint32_t idx, struct page_table *table, uint32_t tablephysical) {
if (idx < 896) return;
struct process* it = processes;
@@ -121,7 +125,12 @@ void thread_sleep(uint32_t msecs) {
if (current_thread == 0) return;
current_thread->state = TS_SLEEPING;
current_thread->timeWait = timer_time() + msecs;
- asm volatile("int $64" : : "a"(1));
+ tasking_schedule();
+}
+
+int proc_priv() {
+ if (current_thread == 0) return PL_UNKNOWN;
+ return current_thread->process->privilege;
}
void thread_exit2(uint32_t reason) { //See EX_TH_* defines in task.h
@@ -167,7 +176,10 @@ void process_exit(uint32_t retval) {
static uint32_t thread_runnable(struct thread *t) {
if (t->state == TS_RUNNING) return 1;
- if (t->state == TS_SLEEPING && timer_time() >= t->timeWait) return 1;
+ if (t->state == TS_SLEEPING && timer_time() >= t->timeWait) {
+ t->state = TS_RUNNING;
+ return 1;
+ }
return 0;
}
@@ -220,7 +232,7 @@ struct thread *thread_new(struct process *proc, thread_entry entry_point, void *
if (proc->privilege >= PL_SERVICE) { //We are running in user mode
proc->stacksBottom -= USER_STACK_SIZE;
- t->userStack_seg = seg_map(simpleseg_make(proc->stacksBottom, USER_STACK_SIZE, 1), proc->pagedir);
+ t->userStack_seg = seg_map(simpleseg_make(proc->stacksBottom, USER_STACK_SIZE, 1), proc->pagedir, 0);
}
t->kernelStack_addr = kmalloc(KSTACKSIZE);
diff --git a/src/kernel/task/task.h b/src/kernel/task/task.h
index d363333..dd5461e 100644
--- a/src/kernel/task/task.h
+++ b/src/kernel/task/task.h
@@ -7,8 +7,9 @@
#define TS_RUNNING 0
#define TS_SLEEPING 1 //Sleeping for a defined amount of time
-#define TS_WAIKWAIT 2 //Waiting to be waked up by something precise (thread currently blocked)
+#define TS_WAKEWAIT 2 //Waiting to be waked up by something precise (thread currently blocked)
+#define PL_UNKNOWN 4
#define PL_USER 3
#define PL_SERVICE 2
#define PL_DRIVER 1
@@ -47,10 +48,12 @@ extern struct thread *current_thread;
void tasking_init();
void tasking_switch();
+void tasking_schedule();
void tasking_updateKernelPagetable(uint32_t idx, struct page_table *table, uint32_t tablePhysical);
uint32_t tasking_handleException(struct registers *regs);
void thread_sleep(uint32_t msecs);
+int proc_priv(); //Returns current privilege level
void thread_exit();
void process_exit(uint32_t retval);
struct thread * thread_new(struct process *proc, thread_entry entry_point, void *data);