diff options
Diffstat (limited to 'kernel/scheduler.c')
| -rw-r--r-- | kernel/scheduler.c | 196 |
1 files changed, 107 insertions, 89 deletions
diff --git a/kernel/scheduler.c b/kernel/scheduler.c index b367825..ee1cea2 100644 --- a/kernel/scheduler.c +++ b/kernel/scheduler.c @@ -1,7 +1,3 @@ -// http://hosted.cjmovie.net/TutMultitask.htm -// -// - #include "kernel.h" #include "mem.h" #include "asm/x86.h" @@ -11,53 +7,70 @@ #include "fs/fs.h" #include "fs/ext2.h" -static volatile int volatile current_task=-1; +#define NO_TASK 0xffffffff + +static volatile uint32_t current_task=NO_TASK; static volatile struct task_list_struct { - volatile int parent; - volatile bool active; - volatile uint32_t esp; // stack pointer of the task; - volatile pdirectory *vmem; // number of virtual memory table to switch to - volatile bool waiting; - volatile bool skipwait; - volatile uint32_t brk; - volatile uint32_t esp0; - - volatile bool syscall; // waiting for syscall to be processed. + volatile bool active; // is this slot used (Y/N) + volatile uint32_t pid; // process id (TODO) + + volatile uint32_t parent; // parent process id + volatile uint32_t esp; // stack pointer of the task + volatile uint32_t esp0; // tss.esp0 + volatile pdirectory *vmem; // number of virtual memory table + + volatile uint32_t brk; // memory brk pos + + volatile bool wait; // waiting for syscall to be processed. volatile uint32_t eax; volatile uint32_t ebx; volatile uint32_t ecx; volatile uint32_t edx; - }volatile task_list[MAX_TASKS]; -volatile int add_task(uint32_t esp, uint32_t vmem) +volatile int task_reset(uint32_t pid, uint32_t entry, uint32_t stack) +{ + uint32_t *stk=task_list[pid].esp; + stk[14]=entry; + stk[17]=stack; +} + +volatile int add_task(uint32_t parent) { for(int i=0;i<MAX_TASKS;i++) { if(task_list[i].active!=true) { - task_list[i].parent=current_task; - task_list[i].vmem=vmem; - task_list[i].esp = kballoc(4)+4*4096; + task_list[i].parent=parent; + + // TODO: do this without paging please! + task_list[i].vmem=vmem_new_space_dir(task_list[parent].vmem); //TODO: what will happen if we get rescheduled!?!?! + task_list[i].esp = kballoc(4)+2*4096; // center + + // TODO: use own page here and copy it instead of this! task_list[i].esp0 = kballoc(4)+4*4096; - task_list[i].active=true; - task_list[i].waiting=false; - task_list[i].skipwait=false; + + task_list[i].wait=false; task_list[i].brk=task_list[current_task].brk; - uint32_t *addi2=(uint32_t *)esp; - addi2+=14; + uint32_t *source=(uint32_t *)task_list[parent].esp; + uint32_t *dst=(uint32_t *)task_list[i].esp; - for(int x=0;x<15;x++) + for(int x=0;x<100;x++) //TODO: better copy this page too instead of stack { - task_list[i].esp-=4; - uint32_t *addi1=(uint32_t *)task_list[i].esp; - *addi1=*addi2; - addi2--; + *dst=*source; + dst++; + source++; } + + uint32_t *stack=task_list[i].esp; + stack[12]=0x1; + stack[13]=0; // this task returns pid=0 to the caller + + task_list[i].active=true; //TODO: LOCK! (also other similar) return i; } } @@ -65,34 +78,44 @@ volatile int add_task(uint32_t esp, uint32_t vmem) kpanic("out of task slots!"); } -void task_wake_syscall_worker() -{ - task_list[2].waiting=false; // todo: context switch immiditly? -} + +/** + * kernel space worker thread + * + * we can get interrupted by an interrupt ANYTIME! + * + */ void task_syscall_worker() { - klog("checking if any pending syscalls."); - - for(int i=0;i<MAX_TASKS;i++) + while(1) { - if(task_list[i].syscall) - { - klog("task %d waiting on syscall %d. processing...",i,task_list[i].eax); + //klog("checking if any pending syscalls."); - task_list[2].vmem=task_list[i].vmem; // switch syscall worker to pagedir of calling userprog - x86_set_page_directory(task_list[2].vmem); - syscall_generic(task_list[i].eax, - task_list[i].ebx, - task_list[i].ecx, - task_list[i].edx); - - task_list[i].syscall=false; + for(int i=0;i<MAX_TASKS;i++) + { + if(task_list[i].wait) + { + // klog("task %d waiting on syscall %d. processing...",i,task_list[i].eax); + task_list[2].vmem=task_list[i].vmem; // switch syscall worker to pagedir of calling userprog + x86_set_page_directory(task_list[2].vmem); + uint32_t ret= syscall_generic(task_list[i].eax, + task_list[i].edx, + task_list[i].ecx, + task_list[i].ebx, + i); + + uint32_t *stack=task_list[i].esp; + stack[12]=0x1; + stack[13]=ret; + + task_list[i].wait=false; + } } - } - task_list[current_task].waiting=true; - __asm__("hlt"); //TODO: force task switch here... via syscall? + task_list[2].wait=true; + __asm__("int $0x81"); // wake scheduler! + } } // @@ -105,24 +128,22 @@ void task_syscall_worker() // // we need to return a NEW stack pointer where popa will get the registers the new task requires // -static int first=1; volatile uint32_t my_scheduler(uint32_t oldesp) { - - if(!first) - { - task_list[current_task].esp=oldesp; - } - first=0; + // + static bool first=true; + if(current_task==NO_TASK)return oldesp; + if(!first) task_list[current_task].esp=oldesp; + first=false; + // for(int i=0;i<MAX_TASKS;i++) { int pid=(current_task+1+i)%MAX_TASKS; // schedule round robin style - if(task_list[pid].active && !task_list[pid].waiting && !task_list[pid].syscall) + if(task_list[pid].active && !task_list[pid].wait) // find active non-blocked task { - if(current_task!=pid) - klog("switch from %d to %d", current_task, pid); + //if(current_task!=pid)klog("switch from %d to %d", current_task, pid); current_task=pid; install_tss(task_list[pid].esp0); @@ -136,28 +157,22 @@ volatile uint32_t my_scheduler(uint32_t oldesp) kpanic("nothing to schedule!"); } -// this gets called by our clock interrupt regularly! -volatile uint32_t task_switch_next(uint32_t oldesp) +volatile uint32_t task_syscall(uint32_t eax,uint32_t ebx, uint32_t ecx, uint32_t edx) { - // check if multitasking has been started - if(current_task<0)return oldesp; - return my_scheduler(oldesp); -} - -volatile uint32_t task_syscall(uint32_t eax,uint32_t ebx, uint32_t ecx, uint32_t edx,uint32_t oldesp) -{ - task_list[current_task].syscall=true; + task_list[current_task].wait=true; task_list[current_task].eax=eax; task_list[current_task].ebx=ebx; task_list[current_task].ecx=ecx; task_list[current_task].edx=edx; - return my_scheduler(oldesp); + + task_list[2].wait=false; } //TODO: free vmem too! //TODO: notify waiting parent when child finished; volatile uint32_t task_exit(uint32_t oldesp) { + /* task_list[current_task].active=false; int parent_pid=task_list[current_task].parent; @@ -174,8 +189,8 @@ volatile uint32_t task_exit(uint32_t oldesp) } else { - klog("[%d] skipwait", parent_pid); - task_list[parent_pid].skipwait=true; +// klog("[%d] skipwait", parent_pid); +// task_list[parent_pid].skipwait=true; } } @@ -183,11 +198,12 @@ volatile uint32_t task_exit(uint32_t oldesp) vmem_free_dir(task_list[current_task].vmem); return my_scheduler(oldesp); + */ } volatile uint32_t task_wait(uint32_t oldesp) -{ +{ /* klog("[%d] wait", current_task); if(task_list[current_task].skipwait) { @@ -198,13 +214,14 @@ volatile uint32_t task_wait(uint32_t oldesp) task_list[current_task].waiting=true; } return my_scheduler(oldesp); + */ } -volatile uint32_t task_fork(uint32_t oldesp) +volatile uint32_t task_fork(uint32_t pid) { - int pid=add_task(oldesp,vmem_new_space_dir(task_list[current_task].vmem)); + int ret=add_task(pid); klog("[%d] forked -> [%d] (free blocks remaining: %d )", current_task, pid,mem_get_free_blocks_count()); - return pid; + return ret; } // init task (root of all other tasks / processes) // @@ -220,27 +237,28 @@ volatile void scheduler_init(pdirectory *dir) // this is our main user task on slot 0 task_list[0].parent=0; task_list[0].active=true; - task_list[0].waiting=false; + task_list[0].wait=false; task_list[0].vmem=dir; - task_list[0].esp = kballoc(4)+4*4096; + task_list[0].esp = kballoc(4)+3*4096; task_list[0].esp0 = kballoc(4)+4*4096; - task_list[1].parent=0; - task_list[1].active=true; - task_list[1].waiting=false; - task_list[1].vmem=dir; - task_list[1].esp = kballoc(4)+4*4096; - task_list[1].esp0 = 0; // not needed by kernel space tasks +// task_list[1].parent=0; +// task_list[1].active=true; +// task_list[1].waiting=false; +// task_list[1].syscall=false; +// task_list[1].vmem=dir; +// task_list[1].esp = kballoc(4)+3*4096; +// task_list[1].esp0 = 0; // not needed by kernel space tasks task_list[2].parent=0; task_list[2].active=true; - task_list[2].waiting=false; + task_list[2].wait=false; task_list[2].vmem=dir; - task_list[2].esp = kballoc(4)+4*4096; + task_list[2].esp = kballoc(4)+3*4096; task_list[2].esp0 = 0; // not needed by kernel space tasks task_pusha(task_list[2].esp); - task_pusha(task_list[1].esp); +// task_pusha(task_list[1].esp); task_pusha(task_list[0].esp); // finally enable interrrupts so the scheduler is called (by timer) |
