Fixing scheduling bug

This commit is contained in:
ssimnb 2026-02-20 09:45:49 +01:00
parent a7fd9ac224
commit 7706e629c6
2 changed files with 30 additions and 27 deletions

View file

@ -22,6 +22,7 @@ struct thread {
proc_state state; proc_state state;
uint16_t pid; uint16_t pid;
struct context *context; struct context *context;
char name[8];
}; };
void scheduler_init(); void scheduler_init();

View file

@ -11,6 +11,7 @@
#include <scheduler/sched.h> #include <scheduler/sched.h>
extern void switch_context(struct context **old, struct context *new); extern void switch_context(struct context **old, struct context *new);
extern void sched_enter(void *a);
struct ma_cache *thread_cache; struct ma_cache *thread_cache;
struct thread *idle; struct thread *idle;
@ -27,30 +28,27 @@ void idle_task(){
void test_task(){ void test_task(){
kprintf("Hello world from scheduled task!\n"); kprintf("Hello world from scheduled task!\n");
//for(;;); for(;;);
} }
void best_task(){ void best_task(){
kprintf("Hello world I am best\n"); kprintf("Hello world I am best\n");
//for(;;); for(;;);
} }
void thread_exit(){ void thread_exit(){
asm("cli");
cpu_state *cpu = get_cpu_struct(); cpu_state *cpu = get_cpu_struct();
struct thread *p = cpu->current_process; struct thread *p = cpu->current_process;
if(p == p->next){ if(p == p->next || p->prev == p){
// If this is the only thread in the queue then set cpu->head to NULL, so scheduler knows to idle // If this is the only thread in the queue then set cpu->head to NULL, so scheduler knows to idle
cpu->head = NULL; cpu->head = NULL;
}else{ }else{
// Remove process from circular linked list // Remove process from circular linked list
p->next->prev = p->prev; p->next->prev = p->prev;
p->prev->next = p->next; p->prev->next = p->next;
cpu->head = p->next;
if(p == cpu->head){
//cpu->head = p->next;
}
} }
p->state = ZOMBIE; p->state = ZOMBIE;
@ -72,6 +70,7 @@ struct thread *alloc_thread(void){
uint64_t *sp = (uint64_t*)((uint64_t)t->kstack + 8 * 4096); uint64_t *sp = (uint64_t*)((uint64_t)t->kstack + 8 * 4096);
// Push the exit function (the thread will return to it when it finishes) // Push the exit function (the thread will return to it when it finishes)
*--sp = (uint64_t)thread_exit; *--sp = (uint64_t)thread_exit;
@ -115,26 +114,23 @@ struct thread *add_thread(uint64_t *entry){
[[noreturn]] void sched(){ [[noreturn]] void sched(){
cpu_state *cpu = get_cpu_struct();
for(;;){ for(;;){
asm("cli"); // we sti at the end of switch_context asm("cli"); // we sti at the end of switch_context
cpu_state *cpu = get_cpu_struct();
struct thread *prev = cpu->current_process;
if(prev->state == ZOMBIE){ struct thread *prev = cpu->current_process;
kprintf("we are freeing allocated thread 0x{x}\n", prev);
ma_cache_dealloc(prev);
}else{
prev->state = READY;
}
if(cpu->head == NULL){ if(cpu->head == NULL){
cpu->current_process = idle; cpu->current_process = idle;
}else{
if(prev->next){
cpu->current_process = prev->next;
}else{ }else{
cpu->current_process = cpu->head; cpu->current_process = cpu->head;
cpu->head = cpu->head->next;
} }
if(prev->state == ZOMBIE){
ma_cache_dealloc(prev);
}else{
prev->state = READY;
} }
cpu->current_process->state = RUNNING; cpu->current_process->state = RUNNING;
@ -153,26 +149,32 @@ void scheduler_init(){
} }
idle = alloc_thread(); idle = alloc_thread();
idle->context->rip = (uint64_t)idle; idle->context->rip = (uint64_t)idle_task;
assert(idle != NULL && "Failed to allocate idle task!"); assert(idle != NULL && "Failed to allocate idle task!");
cpu->current_process = idle; cpu->current_process = idle;
cpu->scheduler_stack = kzalloc(4096); cpu->scheduler_stack = kzalloc(4096);
cpu->scheduler_context = (struct context*)((uint64_t)cpu->scheduler_stack + 4096); cpu->scheduler_context = (struct context*)((uint64_t)cpu->scheduler_stack + 4096 - sizeof(struct context));
cpu->scheduler_context->rbp = (uint64_t)cpu->scheduler_context; cpu->scheduler_context->rbp = (uint64_t)cpu->scheduler_context;
cpu->scheduler_context->rip = (uint64_t)sched; cpu->scheduler_context->rip = (uint64_t)sched;
add_thread((uint64_t*)test_task); kprintf("og scheduler context: 0x{x}\n", cpu->scheduler_context);
add_thread((uint64_t *)best_task); struct thread *t1 = add_thread((uint64_t*)test_task);
memcpy(t1->name, "testt", 6);
// Initialize scheduler -> we will now get timer interrupts to switch us into sched() struct thread *t2 = add_thread((uint64_t *)best_task);
cpu->scheduler_initialized = true; memcpy(t2->name, "bestt", 6);
cpu->scheduler_initialized = true; // Allow us to get interrupts that schedule us
for(;;);
} }
void yield(){ void yield(){
asm("cli");
switch_context(&get_cpu_struct()->current_process->context, get_cpu_struct()->scheduler_context); switch_context(&get_cpu_struct()->current_process->context, get_cpu_struct()->scheduler_context);
} }