mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-11-01 15:08:21 +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
|
subdirs=boot
|
||||||
OBJPATH=$(OBJDIR)/arch/${TARGET}/
|
OBJPATH=$(OBJDIR)/arch/${TARGET}/
|
||||||
export
|
export
|
||||||
@@ -23,3 +23,7 @@ syscall.o: syscall.asm
|
|||||||
nasm -f elf64 -o $@ $<
|
nasm -f elf64 -o $@ $<
|
||||||
mkdir -p $(OBJPATH)
|
mkdir -p $(OBJPATH)
|
||||||
cp $@ $(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 <kernel/timer.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <kernel/elf.h>
|
#include <kernel/elf.h>
|
||||||
|
#include <arch/interrupt.h>
|
||||||
|
|
||||||
#define PROC_START_FD_COUNT 3
|
#define PROC_START_FD_COUNT 3
|
||||||
#define THREAD_QUANTUM 10000
|
#define THREAD_QUANTUM 10000
|
||||||
@@ -19,8 +20,6 @@
|
|||||||
#define QUEUE_COUNT 3
|
#define QUEUE_COUNT 3
|
||||||
|
|
||||||
sched_queue queues[QUEUE_COUNT];
|
sched_queue queues[QUEUE_COUNT];
|
||||||
sched_queue running;
|
|
||||||
sched_queue blocked;
|
|
||||||
|
|
||||||
static proc_t* allocproc(size_t threadcount){
|
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;
|
return thread;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int a = 0;
|
|
||||||
|
|
||||||
void sched_timerhook(arch_regs* regs){
|
void sched_timerhook(arch_regs* regs){
|
||||||
|
|
||||||
thread_t* current = arch_getcls()->thread;
|
thread_t* current = arch_getcls()->thread;
|
||||||
|
|
||||||
sched_queue* currentqueue = &queues[current->priority];
|
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));
|
memcpy(current->regs, regs, sizeof(arch_regs));
|
||||||
arch_regs_saveextra(¤t->extraregs);
|
arch_regs_saveextra(¤t->extraregs);
|
||||||
@@ -189,14 +168,16 @@ void sched_timerhook(arch_regs* regs){
|
|||||||
|
|
||||||
arch_getcls()->thread = next;
|
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;
|
thread_t* current = arch_getcls()->thread;
|
||||||
|
|
||||||
// if we don't have to change processes don't waste time
|
// if we don't have to change processes don't waste time
|
||||||
|
|
||||||
if(current->proc != thread->proc){
|
if(current->proc != thread->proc){
|
||||||
|
|
||||||
vmm_switchcontext(thread->proc->context);
|
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;
|
thread->proc = proc;
|
||||||
arch_regs_setupuser(thread->regs, ip, stack, true);
|
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);
|
queue_add(&queues[prio], thread);
|
||||||
|
spinlock_release(&queues[prio].lock);
|
||||||
|
arch_interrupt_enable();
|
||||||
|
}
|
||||||
return thread;
|
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);
|
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);
|
queue_add(&queues[prio], thread);
|
||||||
|
spinlock_release(&queues[prio].lock);
|
||||||
|
arch_interrupt_enable();
|
||||||
|
}
|
||||||
return thread;
|
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){
|
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;
|
return;
|
||||||
|
|
||||||
thread->state = THREAD_STATE_WAITING;
|
thread->state = THREAD_STATE_WAITING;
|
||||||
thread->awokenby = event;
|
thread->awokenby = event;
|
||||||
queue_remove(&blocked, thread);
|
|
||||||
|
spinlock_acquire(&queues[thread->priority].lock);
|
||||||
queue_add(&queues[thread->priority], thread);
|
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;
|
thread_t* thread = arch_getcls()->thread;
|
||||||
|
|
||||||
|
spinlock_acquire(&queues[thread->priority].lock);
|
||||||
queue_remove(&queues[thread->priority], thread);
|
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;
|
thread->state = interruptible ? THREAD_STATE_BLOCKED_INTR : THREAD_STATE_BLOCKED;
|
||||||
|
|
||||||
sched_yield();
|
sched_yield();
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -300,7 +322,7 @@ void sched_runinit(){
|
|||||||
printf("Loading /sbin/init\n");
|
printf("Loading /sbin/init\n");
|
||||||
|
|
||||||
thread_t* thread = sched_newuthread(NULL, PAGE_SIZE*3, NULL, NULL, true, THREAD_PRIORITY_USER);
|
thread_t* thread = sched_newuthread(NULL, PAGE_SIZE*3, NULL, NULL, true, THREAD_PRIORITY_USER);
|
||||||
|
|
||||||
proc_t* proc = thread->proc;
|
proc_t* proc = thread->proc;
|
||||||
|
|
||||||
vmm_switchcontext(proc->context);
|
vmm_switchcontext(proc->context);
|
||||||
|
|||||||
Reference in New Issue
Block a user