summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--driver/mouse.c2
-rw-r--r--kernel/exceptions.c3
-rw-r--r--kernel/interrupts.c88
-rw-r--r--kernel/scheduler.c75
-rw-r--r--kernel/scheduler.h5
5 files changed, 109 insertions, 64 deletions
diff --git a/driver/mouse.c b/driver/mouse.c
index 2b767b7..7ec5e68 100644
--- a/driver/mouse.c
+++ b/driver/mouse.c
@@ -46,7 +46,7 @@ void mouse_wait(uint8_t a_type) //unsigned char
}
}
-void mouse_write(uint8_t a_write)
+static void mouse_write(uint8_t a_write)
{
//Wait to be able to send a command
mouse_wait(1);
diff --git a/kernel/exceptions.c b/kernel/exceptions.c
index 4ad87e8..a69a49e 100644
--- a/kernel/exceptions.c
+++ b/kernel/exceptions.c
@@ -126,6 +126,7 @@ uint32_t exception_handle(uint32_t esp, uint32_t irq)
klog("killing task in question!");
task_syscall(SYSCALL_EXIT,task_get_current_pid(),0,0);
- return scheduler_run(esp,0);
+ scheduler_wake_all();
+ return scheduler_run(esp);
}
diff --git a/kernel/interrupts.c b/kernel/interrupts.c
index 150a784..9c485cc 100644
--- a/kernel/interrupts.c
+++ b/kernel/interrupts.c
@@ -9,6 +9,10 @@
#include "asm_x86.h"
#include "smp.h"
#include "apic.h"
+#include "ringbuffer.h"
+
+ringbuffer mouse_in;
+ringbuffer kb_in;
/** The size of our interrupts table */
#define INT_MAX 256 // 0-255
@@ -51,57 +55,45 @@ static void int_install_ir(int irq, uint16_t flags, uint16_t sel, void *addr)
*/
uint32_t interrupt_handler(uint32_t esp, uint32_t irq)
{
- // pit timer at 1/25 sec.
- if(irq==INTERRUPT_PIT_TIMER)asm_pit_tick();
+ uint32_t *stack;
- // kb
- if(irq==INTERRUPT_KEYBOARD)
+ // process irq
+ switch(irq)
{
- uint32_t in=x86_inb(0x60);
+ case INTERRUPT_PIT_TIMER:
+ asm_pit_tick();
+ break;
+
+ case INTERRUPT_KEYBOARD:
+ ringbuffer_put(&kb_in,x86_inb(0x60));
+ break;
+
+ case INTERRUPT_MOUSE:
+ ringbuffer_put(&mouse_in,x86_inb(0x60));
+ break;
+
+ case INTERRUPT_SYSCALL:
+ stack=esp;
+ task_syscall(stack[11],stack[8],stack[10],stack[9]); //eax,ebx,ecx,edx
+ break;
+
+ case INTERRUPT_APIC_TIMER:
+ case INTERRUPT_IPI:
+ esp=scheduler_run(esp);
+ break;
+
+ case 255: // default or spurious
+ kpanic("Spurious/Unknown Interrupt!?");
+ break;
}
- // mouse
- if(irq==INTERRUPT_MOUSE)
- {
- uint32_t in=x86_inb(0x60);
-
- /*
- if(irq==INTERRUPT_KEYBOARD){
- keyboard_handle(in); // do this in separate thread via syscalls?
- task_wake_all();
- }
- */
- // TODO: mouse
-
- // test ipi
- //apic_ipi(2,0x81); // force cpu16 to autoschedule? just test
- //klog("0x60 in %d",in);
- }
+ // reschedule to kernel worker on these
+ if(irq==INTERRUPT_SYSCALL||irq==INTERRUPT_KEYBOARD||irq==INTERRUPT_MOUSE)
+ esp=scheduler_wake_worker(esp);
- // 0x80 - a syscall is coming in
- if(irq==INTERRUPT_SYSCALL)
- {
- uint32_t *stack=esp;
- uint32_t eax=stack[11];
- uint32_t ebx=stack[8];
- uint32_t ecx=stack[10];
- uint32_t edx=stack[9];
-
- task_syscall(eax,ebx,ecx,edx);
- esp=scheduler_run(esp,2);
- }
-
- // schedules on APIC timer 0x8C and IPI 0x81
- if(irq==INTERRUPT_APIC_TIMER || irq==INTERRUPT_IPI)
- {
- esp=scheduler_run(esp,-1);
- }
-
- // ack all except software syscalls
- if(irq!=INTERRUPT_SYSCALL)apic_eoi();
-
- // default and spurious
- if(irq==255)kpanic("Spurious/Unknown Interrupt!?");
+ // ack all to LAPIC, except software syscalls
+ if(irq!=INTERRUPT_SYSCALL)
+ apic_eoi();
return esp;
}
@@ -111,6 +103,10 @@ uint32_t interrupt_handler(uint32_t esp, uint32_t irq)
*/
void interrupts_init(uint16_t sel)
{
+ klog("initializing Mouse and Kb input buffers");
+ kb_in=ringbuffer_init(1);// 4096 bytes ringbuffer;
+ mouse_in=ringbuffer_init(1);// 4096 bytes ringbuffer;
+
klog("initializing. IDT: 0x%08x, IDTD: 0x%08X",&idt,&idtd);
// Default interrupt handling
diff --git a/kernel/scheduler.c b/kernel/scheduler.c
index ad6b370..b5d1b34 100644
--- a/kernel/scheduler.c
+++ b/kernel/scheduler.c
@@ -73,25 +73,36 @@ volatile void scheduler_init(uint32_t cpu, void *dir)
task_list[cpu][0].pid=nextPID();
task_list[cpu][0].active=true;
task_list[cpu][0].syscall=false;
- task_list[cpu][0].thread=false;
+ task_list[cpu][1].thread=false;
task_list[cpu][0].vmem=dir;
task_list[cpu][0].esp = VMEM_CPU_STACK_TOP-0x200;
task_list[cpu][0].esp0 = 0; // esp0 not needed by kernel space tasks
- task_pusha(task_list[cpu][0].esp);
-
- // this is our main kernel task at slot 0 (per cpu)
+ // this will go to userspace
task_list[cpu][1].parent=0;
task_list[cpu][1].pid=nextPID();
task_list[cpu][1].active=true;
- task_list[cpu][0].thread=false;
+ task_list[cpu][1].thread=false;
task_list[cpu][1].syscall=false;
task_list[cpu][1].vmem=dir;
task_list[cpu][1].esp = kballoc(4)+4*4096-0x200; // 4 pages stack
task_list[cpu][1].esp0 =kballoc(4)+4*4096; // esp0 not needed by kernel space tasks
+
+ // sleeper
+ task_list[cpu][2].parent=0;
+ task_list[cpu][2].pid=nextPID();
+ task_list[cpu][2].active=true;
+ task_list[cpu][2].thread=false;
+ task_list[cpu][2].syscall=false;
+ task_list[cpu][2].vmem=dir;
+ task_list[cpu][2].esp = kballoc(4)+4*4096-0x200; // 4 pages stack
+ task_list[cpu][2].esp0 =kballoc(4)+4*4096; // esp0 not needed by kernel space tasks
+
+ // stacks
task_pusha(task_list[cpu][0].esp);
task_pusha(task_list[cpu][1].esp);
+ task_pusha(task_list[cpu][2].esp);
}
//
@@ -104,7 +115,7 @@ volatile void scheduler_init(uint32_t cpu, void *dir)
//
// we need to return a NEW stack pointer where popa will get the registers the new task requires
//
-volatile uint32_t scheduler_run(uint32_t oldesp,uint32_t force_pid)
+volatile uint32_t scheduler_run(uint32_t oldesp)
{
uint32_t cpu=smp_get(SMP_APIC_ID);
uint32_t init=smp_get(SMP_SCHEDULER_INIT);
@@ -117,6 +128,7 @@ volatile uint32_t scheduler_run(uint32_t oldesp,uint32_t force_pid)
for(int i=0;i<MAX_TASKS;i++)
{
int idx=(current_task[cpu]+1+i)%MAX_TASKS; // schedule round robin style
+ if(idx==2)continue;// skip sleeper here
if(task_list[cpu][idx].active && !task_list[cpu][idx].syscall) // find active non-blocked task
{
@@ -129,7 +141,13 @@ volatile uint32_t scheduler_run(uint32_t oldesp,uint32_t force_pid)
}
}
- kpanic("nothing to schedule!");
+ // force the sleeper task
+ current_task[cpu]=2;
+ install_tss(cpu,task_list[cpu][2].esp0);
+ x86_set_page_directory(task_list[cpu][2].vmem);
+ return task_list[cpu][2].esp;
+
+// kpanic("nothing to schedule!");
}
@@ -146,8 +164,13 @@ void scheduler_func()
task_syscall_worker();
}
- if(current_task[cpu]==1)
+ if(current_task[cpu]==2)
+ while(1)
+ {
+ while(1)asm("hlt"); // sleeper task
+ }
+ if(current_task[cpu]==1)
while(1)
{
if(cpu==0)
@@ -205,7 +228,15 @@ volatile int add_task(uint32_t parent_pid,uint32_t vmem, bool thread)
kpanic("out of task slots!");
}
-void task_wake_all()
+uint32_t scheduler_wake_worker(uint32_t oldesp)
+{
+ uint32_t cpu=smp_get(SMP_APIC_ID);
+ task_list[cpu][0].syscall=false; // wake (syscall misused)
+ scheduler_wake_all();
+ return scheduler_run(oldesp);
+}
+
+void scheduler_wake_all()
{
uint32_t cpu=smp_get(SMP_APIC_ID);
// simple approach, any syscall might unblock any other syscall // TODO: better! TODO: all cpus!
@@ -215,7 +246,6 @@ void task_wake_all()
}
}
-
/**
* kernel space worker thread
*
@@ -258,7 +288,7 @@ void task_syscall_worker()
task_list[cpu][i].ebx,
task_list[cpu][i].pid);
- task_wake_all();
+ scheduler_wake_all();
uint32_t *stack=task_list[cpu][i].esp;
stack[12]=0x1;
@@ -268,9 +298,26 @@ void task_syscall_worker()
}
}
- //task_list[cpu][0].wait=true;
- //if (nowork)__asm__("hlt");
- __asm__("int $0x81"); // wake scheduler!
+ bool nowork=true;
+
+ x86_cli(); // disable all incoming new work (mouse,kb,timer). software syscalls can not appear since we are here ;)
+ for(int i=0;i<MAX_TASKS;i++) /// ... and check if aaany work is pending.
+ {
+ if(task_list[cpu][i].active,task_list[cpu][i].try&&task_list[cpu][i].syscall)
+ {
+ nowork=false;
+ break;
+ }
+ }
+ if(nowork)
+ {
+ task_list[cpu][0].syscall=true; // sleep (syscall misused)
+ }
+ x86_sti();
+ if(nowork)
+ {
+ __asm__("int $0x81"); // wake scheduler!
+ }
}
}
diff --git a/kernel/scheduler.h b/kernel/scheduler.h
index f77912d..fb1f3c8 100644
--- a/kernel/scheduler.h
+++ b/kernel/scheduler.h
@@ -2,9 +2,10 @@
#include <stdbool.h>
// http://hosted.cjmovie.net/TutMultitask.htm
-volatile uint32_t scheduler_run(uint32_t oldesp,uint32_t force_pid);
+volatile uint32_t scheduler_run(uint32_t oldesp);
+volatile uint32_t scheduler_wake_worker(uint32_t oldesp);
-void task_wake_all();
+void scheduler_wake_all();
volatile uint32_t task_get_current_pid();
volatile uint32_t task_get_parent(uint32_t pid);
volatile void task_set_brk(uint32_t pid,uint32_t brk);