mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 20:58:22 +00:00
scheduler: yield
This commit is contained in:
@@ -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)/$@
|
||||
|
||||
@@ -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
@@ -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(¤t->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);
|
||||
|
||||
Reference in New Issue
Block a user