diff options
| author | Loic Guegan <manzerbredes@mailbox.org> | 2021-04-16 14:39:24 +0200 |
|---|---|---|
| committer | Loic Guegan <manzerbredes@mailbox.org> | 2021-04-16 14:39:24 +0200 |
| commit | 98d524bc8acb7b19afb693afea3ac77629d6f4bf (patch) | |
| tree | 86a883c01bbf521ef40e914d16939b44c08e7f01 /src/core/scheduler.c | |
| parent | 58b706d40f8ad0d71b667ca81d91b96ca537cb8e (diff) | |
Multitasking works!
Diffstat (limited to 'src/core/scheduler.c')
| -rw-r--r-- | src/core/scheduler.c | 99 |
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 |
