mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-28 21:28:21 +00:00
scheduler: a bunch of fixes and a few changes
transferred memory context from proc to thread, fixed bugs relating to blocking, made getnext() wait till something is ready to run
This commit is contained in:
@@ -34,6 +34,7 @@ typedef struct _thread_t{
|
||||
void* kernelstack;
|
||||
void* kernelstackbase;
|
||||
size_t stacksize;
|
||||
vmm_context* ctx;
|
||||
pid_t tid;
|
||||
int priority;
|
||||
} thread_t;
|
||||
@@ -49,7 +50,6 @@ typedef struct _proc_t{
|
||||
int fdlock;
|
||||
size_t fdcount;
|
||||
off_t firstfreefd;
|
||||
vmm_context* context;
|
||||
thread_t** threads;
|
||||
size_t threadcount;
|
||||
dirnode_t* root;
|
||||
@@ -63,6 +63,7 @@ typedef struct{
|
||||
int lock;
|
||||
} sched_queue;
|
||||
|
||||
thread_t* sched_newkthread(void* ip, size_t stacksize, bool run, int prio);
|
||||
void sched_init();
|
||||
void sched_runinit();
|
||||
void sched_eventsignal(event_t* event, thread_t* thread);
|
||||
|
||||
+77
-34
@@ -45,13 +45,7 @@ static proc_t* allocproc(size_t threadcount){
|
||||
proc->fdcount = PROC_START_FD_COUNT;
|
||||
proc->firstfreefd = PROC_START_FD_COUNT;
|
||||
|
||||
proc->context = vmm_newcontext();
|
||||
|
||||
if(!proc->context){
|
||||
free(proc->threads);
|
||||
free(proc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return proc;
|
||||
|
||||
@@ -81,6 +75,16 @@ static thread_t* allocthread(proc_t* proc, state_t state, pid_t tid, size_t ksta
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
thread->ctx = vmm_newcontext();
|
||||
|
||||
if(!thread->ctx){
|
||||
free(thread->kernelstackbase);
|
||||
free(thread->regs);
|
||||
free(thread);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
thread->proc = proc;
|
||||
thread->state = state;
|
||||
thread->tid = tid;
|
||||
@@ -123,32 +127,53 @@ static void queue_remove(sched_queue* queue, thread_t* thread){
|
||||
}
|
||||
|
||||
static thread_t* getnext(){
|
||||
|
||||
|
||||
|
||||
thread_t* thread = NULL;
|
||||
|
||||
for(int i = 0; i < QUEUE_COUNT && thread == NULL; ++i){
|
||||
|
||||
spinlock_acquire(&queues[i].lock);
|
||||
|
||||
if(queues[i].start){
|
||||
thread = queues[i].start;
|
||||
queue_remove(&queues[i], thread);
|
||||
while(thread == NULL){
|
||||
|
||||
for(int i = 0; i < QUEUE_COUNT && thread == NULL; ++i){
|
||||
|
||||
spinlock_acquire(&queues[i].lock);
|
||||
|
||||
if(queues[i].start){
|
||||
thread = queues[i].start;
|
||||
queue_remove(&queues[i], thread);
|
||||
}
|
||||
|
||||
spinlock_release(&queues[i].lock);
|
||||
|
||||
}
|
||||
|
||||
spinlock_release(&queues[i].lock);
|
||||
if(!thread){
|
||||
arch_interrupt_enable();
|
||||
arch_halt();
|
||||
arch_interrupt_disable();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
return thread;
|
||||
|
||||
}
|
||||
|
||||
int aa = 0;
|
||||
|
||||
void sched_timerhook(arch_regs* regs){
|
||||
|
||||
#ifdef __X86_64__
|
||||
|
||||
apic_eoi();
|
||||
|
||||
#endif
|
||||
|
||||
thread_t* current = arch_getcls()->thread;
|
||||
|
||||
sched_queue* currentqueue = &queues[current->priority];
|
||||
|
||||
|
||||
memcpy(current->regs, regs, sizeof(arch_regs));
|
||||
arch_regs_saveextra(¤t->extraregs);
|
||||
|
||||
@@ -157,18 +182,24 @@ void sched_timerhook(arch_regs* regs){
|
||||
queue_add(currentqueue, current);
|
||||
|
||||
spinlock_release(¤tqueue->lock);
|
||||
|
||||
|
||||
thread_t* next = getnext();
|
||||
|
||||
|
||||
if(next)
|
||||
memcpy(regs, next->regs, sizeof(arch_regs));
|
||||
|
||||
|
||||
arch_getcls()->thread = next;
|
||||
|
||||
arch_setkernelstack(next->kernelstack);
|
||||
arch_regs_setupextra(&next->extraregs);
|
||||
|
||||
next->state = THREAD_STATE_RUNNING;
|
||||
|
||||
timer_add(&arch_getcls()->schedreq, THREAD_QUANTUM, false);
|
||||
|
||||
arch_getcls()->thread = next;
|
||||
|
||||
next->state = THREAD_STATE_RUNNING;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -176,15 +207,12 @@ 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);
|
||||
|
||||
}
|
||||
// if we don't have to change address spaces don't waste time
|
||||
|
||||
arch_getcls()->thread = thread;
|
||||
|
||||
if(current->ctx != thread->ctx)
|
||||
vmm_switchcontext(thread->ctx);
|
||||
|
||||
arch_setkernelstack(thread->kernelstack);
|
||||
|
||||
@@ -254,7 +282,7 @@ thread_t* sched_newkthread(void* ip, size_t stacksize, bool run, int prio){
|
||||
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);
|
||||
@@ -262,8 +290,14 @@ void sched_yieldtrampoline(thread_t* thread){
|
||||
thread->state = THREAD_STATE_WAITING;
|
||||
}
|
||||
|
||||
|
||||
thread = getnext();
|
||||
thread->state = THREAD_STATE_RUNNING;
|
||||
|
||||
thread->state = THREAD_STATE_RUNNING;
|
||||
|
||||
timer_resume();
|
||||
|
||||
|
||||
switch_thread(thread);
|
||||
|
||||
}
|
||||
@@ -274,6 +308,8 @@ void arch_sched_yieldtrampoline(thread_t* thread, arch_regs* regs);
|
||||
|
||||
void sched_yield(){
|
||||
|
||||
timer_stop();
|
||||
|
||||
thread_t* thread = arch_getcls()->thread;
|
||||
|
||||
arch_sched_yieldtrampoline(thread, thread->regs);
|
||||
@@ -281,16 +317,19 @@ void sched_yield(){
|
||||
}
|
||||
|
||||
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 && thread->state != THREAD_STATE_BLOCKED_INTR)
|
||||
return;
|
||||
|
||||
|
||||
if(thread->state == THREAD_STATE_BLOCKED_INTR && event == &thread->sigevent)
|
||||
return;
|
||||
|
||||
thread->state = THREAD_STATE_WAITING;
|
||||
thread->awokenby = event;
|
||||
|
||||
spinlock_acquire(&queues[thread->priority].lock);
|
||||
queue_add(&queues[thread->priority], thread);
|
||||
spinlock_release(&queues[thread->priority].lock);
|
||||
|
||||
}
|
||||
|
||||
void sched_block(bool interruptible){
|
||||
@@ -316,11 +355,13 @@ void sched_runinit(){
|
||||
|
||||
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*10, NULL, NULL, false, THREAD_PRIORITY_USER);
|
||||
|
||||
proc_t* proc = thread->proc;
|
||||
|
||||
vmm_switchcontext(proc->context);
|
||||
arch_getcls()->thread = thread;
|
||||
|
||||
vmm_switchcontext(thread->ctx);
|
||||
|
||||
proc->root = vfs_root();
|
||||
proc->cwd = vfs_root();
|
||||
@@ -381,6 +422,8 @@ void sched_runinit(){
|
||||
|
||||
timer_add(&arch_getcls()->schedreq, THREAD_QUANTUM, true);
|
||||
|
||||
thread->extraregs.gsbase = 0xDEAD000C0FFE0000;
|
||||
|
||||
switch_thread(thread);
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user