aboutsummaryrefslogtreecommitdiff
path: root/src/core/scheduler.c
diff options
context:
space:
mode:
authorLoic Guegan <manzerbredes@mailbox.org>2021-04-16 14:39:24 +0200
committerLoic Guegan <manzerbredes@mailbox.org>2021-04-16 14:39:24 +0200
commit98d524bc8acb7b19afb693afea3ac77629d6f4bf (patch)
tree86a883c01bbf521ef40e914d16939b44c08e7f01 /src/core/scheduler.c
parent58b706d40f8ad0d71b667ca81d91b96ca537cb8e (diff)
Multitasking works!
Diffstat (limited to 'src/core/scheduler.c')
-rw-r--r--src/core/scheduler.c99
1 files changed, 62 insertions, 37 deletions
diff --git a/src/core/scheduler.c b/src/core/scheduler.c
index 0a8c5c7..fffeaf2 100644
--- a/src/core/scheduler.c
+++ b/src/core/scheduler.c
@@ -9,16 +9,14 @@ PROC procs[MAX_PROC];
u16 current_id;
u16 nproc;
-void schedule(){
+void schedule(u32 *stack){
// Note that this function is called by clock
// clock is called by INT_CLOCK (core/int.S)
// which store all the process information on
// the stack. Thus, knowing the C calling conventions
// and that schedule() is call by two functions with no parameters,
// the first process register can be accessed by ebp+2
- u32 *stack;
- asm("mov %%ebp, %0":"=r" (stack));
-
+
// No proc to schedule
if(nproc<2)
return;
@@ -47,7 +45,8 @@ void schedule(){
current_id++;
if(current_id>=nproc)
current_id=0;
-
+ p=&procs[current_id];
+
// Have a clean stack on next interrupt
TSS.esp0=(u32)stack+19;
asm("mov %%ss, %0": "=m" (TSS.ss0));
@@ -58,13 +57,16 @@ void schedule(){
// Perform task switch
asm(
- "mov %0, %%esi \n\t"
+ "push %0 \n\t"
"jmp task_switch \n\t"
:: "a" (p)
);
}
void clock(){
+ u32* stack;
+ asm("mov %%ebp, %0":"=r" (stack));
+
static int tic=0;
static int sec=0;
tic++;
@@ -75,46 +77,69 @@ void clock(){
putchar('.');
}
if(scheduler_on==1)
- schedule();
+ schedule(stack);
}
-void run_task(int *page_dir, void *task, int task_size){
+void task_create(int *page_dir, void *task, int task_size){
+ if(nproc<=MAX_PROC){
// Compute various addresses
- int*pt_addr=(int*)PADDR(page_dir[1]);
- void *entry_point=(void*)(PADDR(pt_addr[3]));
- void *ustack=(void*)((int)entry_point+0xFF);
+ void *entry_point=PAGING_ENTRY_POINT_VIRT;
+ void *ustack=(void*)(PAGING_ENTRY_POINT_VIRT+0xFF);
// Load the task into memory
- memcpy(task,entry_point, task_size);
-
- // Load page directory
- asm(
- "mov %0, %%eax \n\t"
- "mov %%eax,%%cr3 \n\t"
- :: "b"(page_dir)
- );
+ memcpy(task,PAGING_ENTRY_POINT_PHY(page_dir), task_size);
- // Setup users adresses
-
- // Switch to user task
+ // Setup process registers
+ PROC *p=&procs[nproc];
+ p->regs.cs=0x23; // Task cs which is 0x30 along with prlv which is 0x3
+ p->regs.eip=entry_point;
+ p->regs.ss=0x33; // Task ss which is 0x20 along with prlv which is 0x3
+ p->regs.esp=ustack; // Stack is here for now...
+ p->regs.ds=0x2B; // GDT entry 0x28 along with prlv which is 0x3
+ p->regs.eax=0;
+ p->regs.ebx=0;
+ p->regs.ecx=0;
+ p->regs.edx=0;
+
+ // Manage eflags
+ u32 eflags;
asm (
- "cli \n\t" // Ensure we do not get interrupted
- "movl %%ss, %%eax \n\t"
- "movl %%eax, %0 \n\t" // Save kernel ss segment into the TSS
- "movl %%esp, %1 \n\t" // Save kernel esp into the TSS BEFORE setting up the stack
- "pushl $0x33 \n\t" // Push task ss which is 0x30 along with prlv which is 0x3
- "pushl %2 \n\t" // Push task esp
"pushfl \n\t" // Retrieve flags
"popl %%eax \n\t"
"orl $0x200, %%eax \n\t" // Enable interrupt for the user task
"and $0xffffbfff, %%eax \n\t" // Clear the NT flags
- "push %%eax \n\t" // Push task flags
- "push $0x23 \n\t" // Push task cs which is 0x20 along with prlv which is 0x3
- "push %3 \n\t" // Push task entry point
- "mov $0x2B, %%eax \n\t" // GDT entry 0x28 along with prlv which is 0x3
- "mov %%eax, %%ds \n\t" // Setting up user data segment
- "iret \n\t" // Launch user task
- : "=m" (TSS.ss0), "=m" (TSS.esp0)
- : "b" (ustack), "c" (entry_point)
- );
+ "mov %%eax, %0 \n\t" // Get flags into eflag
+ : "=m" (eflags)
+ );
+ p->regs.eflags=eflags;
+
+ // Setup other attributes
+ p->id=nproc;
+ p->pid=nproc;
+ p->page_dir=page_dir;
+ nproc++;
+ }
+}
+
+void scheduler_start(){
+ if(nproc>0){
+ asm("cli");
+ scheduler_on=1; // Enable scheduling
+ u32 *stack;
+ asm("mov %%ebp, %0":"=r" (stack));
+ TSS.esp0=(u32)stack+1; // Remove ebp (c call convention)
+ asm("mov %%ss, %0": "=m" (TSS.ss0));
+
+ current_id=1;
+ PROC *p=&procs[current_id];
+
+ // Ensure interrupts are activated and NT flag is clear
+ p->regs.eflags|=0x200;
+ p->regs.eflags&=0xffffbfff;
+ asm(
+ "push %0 \n\t"
+ "jmp task_switch"
+ :: "a" (p)
+ );
+ }
} \ No newline at end of file