summaryrefslogtreecommitdiff
path: root/kernel/scheduler.c
diff options
context:
space:
mode:
authorMiguel <m.i@gmx.at>2018-09-02 00:08:42 +0200
committerMiguel <m.i@gmx.at>2018-09-02 00:08:42 +0200
commit8e3411139b27a3421e9ac75c13f14f99f6dd3137 (patch)
treecf8b53ab02863117c310bde11ee4683e134cf1b2 /kernel/scheduler.c
parent0fff2e6dc6fae82da1c7978918a490c25cc36f04 (diff)
syscalls
Diffstat (limited to 'kernel/scheduler.c')
-rw-r--r--kernel/scheduler.c196
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)