Almost finished scheduler, switched to circular linked list
This commit is contained in:
parent
edfbfdad14
commit
4c7ecb4012
10 changed files with 124 additions and 89 deletions
|
|
@ -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);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue