/* * @author xamidev * @brief Round-robin scheduler * @license GPL-3.0-only */ #include #include #include #include #include #include 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: * - 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; }