diff options
| -rw-r--r-- | driver/mouse.c | 2 | ||||
| -rw-r--r-- | kernel/exceptions.c | 3 | ||||
| -rw-r--r-- | kernel/interrupts.c | 88 | ||||
| -rw-r--r-- | kernel/scheduler.c | 75 | ||||
| -rw-r--r-- | kernel/scheduler.h | 5 |
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); |
