Files
pepperOS/src/sched/scheduler.c
T
2026-04-03 19:18:08 +02:00

98 lines
2.7 KiB
C

/*
* @author xamidev <xamidev@riseup.net>
* @brief Round-robin scheduler
* @license GPL-3.0-only
*/
#include <kernel.h>
#include <sched/process.h>
#include <mem/paging.h>
#include <stdint.h>
#include <io/serial/serial.h>
#include <arch/gdt.h>
extern struct process* processes_list;
extern struct process* current_process;
extern struct process* idle_proc;
extern struct tss tss;
/*
* scheduler_init - Choose the first process
*/
void scheduler_init()
{
current_process = processes_list;
DEBUG("scheduler starting with: pid=%u, name='%s', context=%p", current_process->pid, current_process->name, current_process->context);
}
/*
* scheduler_schedule - Main scheduling routine
* @context: CPU context of previous process
*
* Chooses the next process that we should run.
* The routine is executed every SCHEDULER_QUANTUM ticks.
*
* Return:
* <context> - CPU context for next process
*/
struct cpu_status* scheduler_schedule(struct cpu_status* context)
{
if (context == NULL) {
panic(NULL, "Scheduler called with NULL context");
}
if (current_process == NULL) {
panic(NULL, "current_process is NULL");
}
if (current_process->context == NULL) {
panic(NULL, "current_process->context is NULL");
}
current_process->context = context;
if (current_process->status == DEAD) {
struct process* dead_process = current_process;
struct process* next_process = (dead_process->next != NULL) ? dead_process->next : processes_list;
process_delete(&processes_list, dead_process);
if (processes_list == NULL || next_process == dead_process) {
current_process = idle_proc;
return idle_proc->context;
}
current_process = next_process;
} else if (current_process->next != NULL) {
current_process = current_process->next;
} else {
current_process = processes_list;
}
for (;;) {
if (current_process->status == DEAD) {
struct process* dead_process = current_process;
struct process* next_process = (current_process->next != NULL) ? current_process->next : processes_list;
process_delete(&processes_list, dead_process);
if (processes_list == NULL || next_process == dead_process) {
current_process = idle_proc;
return idle_proc->context;
}
current_process = next_process;
continue;
}
current_process->status = RUNNING;
break;
}
// Here, we chose next running process so we load its kernel stack & page tables
tss.rsp0 = (uint64_t)current_process->kernel_stack;
load_cr3(VIRT_TO_PHYS((uint64_t)current_process->root_page_table));
return current_process->context;
}