scheduler: yield

This commit is contained in:
Matheus
2022-09-04 17:40:53 -03:00
parent 20249b07b2
commit 4c0ee7179e
3 changed files with 126 additions and 34 deletions
+5 -1
View File
@@ -1,4 +1,4 @@
objects := $(patsubst %.c,%.o,$(wildcard *.c)) israsm.o context.o syscall.o
objects := $(patsubst %.c,%.o,$(wildcard *.c)) israsm.o context.o syscall.o sched.o
subdirs=boot
OBJPATH=$(OBJDIR)/arch/${TARGET}/
export
@@ -23,3 +23,7 @@ syscall.o: syscall.asm
nasm -f elf64 -o $@ $<
mkdir -p $(OBJPATH)
cp $@ $(OBJPATH)/$@
sched.o: sched.asm
nasm -f elf64 -o $@ $<
mkdir -p $(OBJPATH)
cp $@ $(OBJPATH)/$@
+66
View File
@@ -0,0 +1,66 @@
section .text
global arch_sched_yieldtrampoline
; C sysv abi
; rdi -> thread ptr
; rsi -> regs ptr
REGSTRUCTSIZE equ 208
arch_sched_yieldtrampoline:
; save return address to save as rip later
pop r10
; save rsp to reuse later
mov r11, rsp
; temporarily change rsp to set values for the regs structure
mov rsp, rsi
add rsp, REGSTRUCTSIZE
; build the structure
mov r9, ss
push r9
push r11 ; saved rsp
pushfq
mov r9, cs
push r9
push r10 ; rip
push qword 0 ; err
push rbp
push rsi
push rdi
push r15
push r14
push r13
push r12
push r11
push r10
push r9
push r8
push rdx
push rcx
push rbx
push rax
mov r9,ds
push r9
mov r9,es
push r9
push qword 0 ; fs
push qword 0 ; gs
mov r10, cr2
push r10
; restore old stack pointer
mov rsp, r11
extern sched_yieldtrampoline
call sched_yieldtrampoline
; the switch call never returns
+55 -33
View File
@@ -8,6 +8,7 @@
#include <kernel/timer.h>
#include <string.h>
#include <kernel/elf.h>
#include <arch/interrupt.h>
#define PROC_START_FD_COUNT 3
#define THREAD_QUANTUM 10000
@@ -19,8 +20,6 @@
#define QUEUE_COUNT 3
sched_queue queues[QUEUE_COUNT];
sched_queue running;
sched_queue blocked;
static proc_t* allocproc(size_t threadcount){
@@ -140,35 +139,15 @@ static thread_t* getnext(){
}
if(thread){
spinlock_acquire(&running.lock);
queue_add(&running, thread);
spinlock_release(&running.lock);
}
return thread;
}
int a = 0;
void sched_timerhook(arch_regs* regs){
thread_t* current = arch_getcls()->thread;
sched_queue* currentqueue = &queues[current->priority];
spinlock_acquire(&running.lock);
queue_remove(&running, current);
spinlock_release(&running.lock);
memcpy(current->regs, regs, sizeof(arch_regs));
arch_regs_saveextra(&current->extraregs);
@@ -189,14 +168,16 @@ void sched_timerhook(arch_regs* regs){
arch_getcls()->thread = next;
next->state = THREAD_STATE_RUNNING;
}
static void switch_thread(thread_t* thread){
void switch_thread(thread_t* thread){
thread_t* current = arch_getcls()->thread;
// if we don't have to change processes don't waste time
if(current->proc != thread->proc){
vmm_switchcontext(thread->proc->context);
@@ -240,9 +221,13 @@ thread_t* sched_newuthread(void* ip, size_t kstacksize, void* stack, proc_t* pro
thread->proc = proc;
arch_regs_setupuser(thread->regs, ip, stack, true);
if(run)
if(run){
arch_interrupt_disable();
spinlock_acquire(&queues[prio].lock);
queue_add(&queues[prio], thread);
spinlock_release(&queues[prio].lock);
arch_interrupt_enable();
}
return thread;
}
@@ -256,20 +241,55 @@ thread_t* sched_newkthread(void* ip, size_t stacksize, bool run, int prio){
arch_regs_setupkernel(thread->regs, ip, thread->kernelstack, true);
if(run)
if(run){
arch_interrupt_disable();
spinlock_acquire(&queues[prio].lock);
queue_add(&queues[prio], thread);
spinlock_release(&queues[prio].lock);
arch_interrupt_enable();
}
return thread;
}
void sched_yieldtrampoline(thread_t* thread){
arch_regs_saveextra(&thread->extraregs);
if(thread->state == THREAD_STATE_RUNNING){
spinlock_acquire(&queues[thread->priority].lock);
queue_add(&queues[thread->priority], thread);
spinlock_release(&queues[thread->priority].lock);
thread->state = THREAD_STATE_WAITING;
}
thread = getnext();
thread->state = THREAD_STATE_RUNNING;
switch_thread(thread);
}
void arch_sched_yieldtrampoline(thread_t* thread, arch_regs* regs);
// these 3 expect interrupts to be disabled in entry
void sched_yield(){
thread_t* thread = arch_getcls()->thread;
arch_sched_yieldtrampoline(thread, thread->regs);
}
void sched_eventsignal(event_t* event, thread_t* thread){
if((thread->state == THREAD_STATE_BLOCKED_INTR || (thread->state == THREAD_STATE_BLOCKED && event != &thread->sigevent)))
if((thread->state == THREAD_STATE_BLOCKED_INTR || (thread->state == THREAD_STATE_BLOCKED && event == &thread->sigevent)))
return;
thread->state = THREAD_STATE_WAITING;
thread->awokenby = event;
queue_remove(&blocked, thread);
spinlock_acquire(&queues[thread->priority].lock);
queue_add(&queues[thread->priority], thread);
spinlock_release(&queues[thread->priority].lock);
}
@@ -277,10 +297,12 @@ void sched_block(bool interruptible){
thread_t* thread = arch_getcls()->thread;
spinlock_acquire(&queues[thread->priority].lock);
queue_remove(&queues[thread->priority], thread);
queue_add(&blocked, thread);
spinlock_release(&queues[thread->priority].lock);
thread->state = interruptible ? THREAD_STATE_BLOCKED_INTR : THREAD_STATE_BLOCKED;
sched_yield();
}
@@ -300,7 +322,7 @@ void sched_runinit(){
printf("Loading /sbin/init\n");
thread_t* thread = sched_newuthread(NULL, PAGE_SIZE*3, NULL, NULL, true, THREAD_PRIORITY_USER);
proc_t* proc = thread->proc;
vmm_switchcontext(proc->context);