Almost finished scheduler, switched to circular linked list

This commit is contained in:
ssimnb 2026-02-09 06:33:12 +01:00
parent edfbfdad14
commit 4c7ecb4012
10 changed files with 124 additions and 89 deletions

View file

@ -1,14 +1,16 @@
#include <kprint.h>
#include <stdint.h>
#include <string.h>
#include <neobbo.h>
#include "../hal/smp.h"
#include <error.h>
#include <string.h>
#include "../mm/kmalloc.h"
#include "../mm/slab.h"
#include "sched.h"
extern void switch_context(context **old, context *new);
extern void switch_context(struct context **old, struct context *new);
struct ma_cache *thread_cache;
#define QUANTUM_US 10000
@ -21,45 +23,66 @@ void idle_task(){
void test_task(){
kprintf("Hello world from scheduled task!\n");
//for(;;);
}
void best_task(){
kprintf("Hello world I am best\n");
//for(;;);
}
void thread_exit(){
struct thread *p = get_cpu_struct()->current_process;
// Remove process from circular linked list
p->prev->next = p->next;
ma_cache_dealloc(p); // KILL the thread
sched();
}
/* Setup a process structure */
proc *alloc_process(void){
proc *proc_list = get_cpu_struct()->process_list;
struct thread *alloc_thread(void){
struct thread *head = get_cpu_struct()->head;
struct thread *base = get_cpu_struct()->base;
for(uint64_t i = 0; i < PROC_MAX; i++){
if(proc_list[i].state == UNUSED){
proc *p = &proc_list[i];
struct thread *t = ma_cache_alloc(thread_cache, 0);
memset(t, 0, sizeof(struct thread));
p->state = READY;
p->kstack = kzalloc(8 * 4096);
p->pid = next_pid++;
uint64_t *sp = (uint64_t*)((uint64_t)p->kstack + 8 * 4096);
// Allocate space for context
sp -= sizeof(context)/sizeof(uint64_t);
p->context = (context*)sp;
p->context->rbp = (uint64_t)p->kstack;
return p;
}
if(base == NULL){
base = t;
head = base;
}else{
head->next = t;
t->prev = head;
t->next = base; // Circular linked list
head = t;
}
klog(__func__, "Couldnt find free process!!!!!!\n");
t->state = READY;
return NULL;
t->kstack = kzalloc(8 * 4096);
t->pid = next_pid++;
uint64_t *sp = (uint64_t*)((uint64_t)t->kstack + 8 * 4096);
// Push the exit function (the thread will return to it when it finishes)
*--sp = (uint64_t)thread_exit;
// Allocate space for context
sp -= sizeof(struct context)/sizeof(uint64_t);
t->context = (struct context*)sp;
t->context->rbp = (uint64_t)sp;
return t;
}
proc *add_process(uint64_t *entry){
proc *proc = alloc_process();
struct thread *add_process(uint64_t *entry){
struct thread *proc = alloc_thread();
if (proc == NULL) {
klog(__func__, "proc == null!");
@ -73,55 +96,59 @@ proc *add_process(uint64_t *entry){
return proc;
}
[[noreturn]] void sched(){
cpu_state *cpu = get_cpu_struct();
asm("cli");
struct thread *prev = cpu->current_process;
prev->state = READY;
cpu->current_process = prev->next;
cpu->current_process->state = RUNNING;
asm("sti");
switch_context(&(get_cpu_struct()->scheduler_context), get_cpu_struct()->current_process->context);
}
void scheduler_init(){
if(!get_cpu_struct_initialized()){
klog(__func__, "CPU struct not initialized!");
kkill();
}
cpu_state *state = get_cpu_struct();
cpu_state *cpu = get_cpu_struct();
if(state->current_process != NULL){
kprintf("scheduler on CPU {d} already initialized!\n", state->lapic_id);
if(cpu->current_process != NULL){
kprintf("scheduler on CPU {d} already initialized!\n", cpu->lapic_id);
return;
}
proc *proc_list = state->process_list;
memset(proc_list, 0, sizeof(proc) * 512);
proc *idle = add_process((uint64_t*)idle_task);
struct thread *idle = add_process((uint64_t*)idle_task);
if(idle == NULL){
klog(__func__, "Failed to allocate idle task");
kkill();
}
state->current_process = idle;
cpu->current_process = idle;
cpu->scheduler_stack = kzalloc(4096);
cpu->scheduler_context = (struct context*)((uint64_t)cpu->scheduler_stack + 4096);
cpu->scheduler_context->rbp = (uint64_t)cpu->scheduler_context;
cpu->scheduler_context->rip = (uint64_t)sched;
add_process((uint64_t*)test_task);
add_process((uint64_t *)best_task);
state->scheduler_initialized = true;
int i = 0;
for(;;){
for(; i < PROC_MAX; i++){
if(proc_list[i].state == READY){
asm("sti");
proc *prev = state->current_process;
prev->state = READY;
state->current_process = &proc_list[i];
state->current_process->state = RUNNING;
switch_context(&(get_cpu_struct()->scheduler_context), get_cpu_struct()->current_process->context);
}
}
i = 0;
}
// Initialize scheduler -> we will now get timer interrupts to switch us into sched()
cpu->scheduler_initialized = true;
}
void enter_scheduler(){
void yield(){
switch_context(&get_cpu_struct()->current_process->context, get_cpu_struct()->scheduler_context);
}