/* * @author xamidev * @brief Round-robin scheduler * @license GPL-3.0-only */ #include #include #include #include #include extern struct process_t* processes_list; extern struct process_t* current_process; extern struct process_t* idle_proc; /* * scheduler_init - Choose the first process */ void scheduler_init() { current_process = processes_list; } /* * 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: * - CPU context for next process */ struct cpu_status_t* scheduler_schedule(struct cpu_status_t* context) { if (context == NULL) { panic(NULL, "Scheduler called with NULL context"); } if (current_process == NULL) { // If no more processes, then set IDLE as the current process, that's it. current_process = idle_proc; } if (current_process == idle_proc && current_process->next == NULL) { return idle_proc->context; } current_process->context = context; for (;;) { struct process_t* prev_process = current_process; if (current_process->next != NULL) { current_process = current_process->next; } else { current_process = processes_list; } if (current_process != NULL && current_process->status == DEAD) { process_delete(&prev_process, current_process); current_process = NULL; return idle_proc->context; } else { current_process->status = RUNNING; /* if (prev_process != current_process) { DEBUG("Changed from {pid=%u, name=%s} to {pid=%u, name=%s}", prev_process->pid, prev_process->name, current_process->pid, current_process->name); } */ break; } } //DEBUG("current_process={pid=%u, name='%s', root_page_table[virt]=%p}", current_process->pid, current_process->name, current_process->root_page_table); load_cr3(VIRT_TO_PHYS((uint64_t)current_process->root_page_table)); //DEBUG("Loaded process PML4 into CR3"); return current_process->context; }