CeDOS - Commit 6604191e

sched: Improved scheduling algorithm This new scheduling algorithm keeps track of process starvation. The ready process with the most time passed since last execution is chosen; If no ready processes are available, the idle process is chosen. This algorithm handles blocked processes gracefully. Instead of expecting at least one ready process to exist, it will schedule the idle process if there are no other ready processes. This new scheduling algorithm obsoleted some old code which unblocked blocked processes, so that the algorithm would always have ready processes.
Celina Sophie Kalus
Thu, 07 Dec 2023 16:08:01 +0100
3 files changed, 29 insertions(+), 21 deletions(-)
M kernel/sched/process.hkernel/sched/process.h

@@ -86,6 +86,9 @@

//! Process priority. PROCESS_PRIO priority; + //! Process starvation counter + int starvation; + //! Stack checksum STACK_CHECKSUM checksum;
M kernel/sched/sched.ckernel/sched/sched.c

@@ -118,6 +118,7 @@ /* TODO: check if code exists at entry point */

// start the process p->state = PSTATE_READY; + p->starvation = 0; crit_exit();

@@ -126,7 +127,6 @@ }

void sched_interrupt_c(SCHED_FRAME * volatile frame, uint32_t volatile ebp) { - //kpanic("SCHEDULER STACK INFO"); PROCESS* current = get_process(current_pid); if (current_pid != 0) {

@@ -135,8 +135,6 @@ current->ebp = (VIRT_ADDR)(ebp);

current->eip = (VIRT_ADDR)frame->eip; current->eflags = frame->eflags; - - // save stack checksum stack_compute_checksum(&(current->checksum), current->esp, current->ebp); }

@@ -151,13 +149,6 @@ PRINT_DBG("exiting %i, ", current_pid);

current_pid = next_schedule(current_pid); PRINT_DBG("entering %i\n", current_pid); - // unblock all blocked processes - for (PROCESS *p = get_first_process(); p != NULL; p = p->next) { - if (p->state == PSTATE_BLOCKED) { - p->state = PSTATE_READY; - } - } - // prepare to return to process PROCESS* next = get_process(current_pid); switch_page_dir(next->page_dir);

@@ -208,19 +199,14 @@ current_pid = 0;

// create idle process PROCESS_ID idle = sched_spawn(NULL, NULL, 0); - assert(idle != -1); + assert(idle == 0); return 1; } void sched_yield(void) { crit_enter(); - //PRINT_DBG("yield.\n"); PROCESS *current = get_process(current_pid); - if (current != NULL && current->state != PSTATE_TERMINATED) { - current->state = PSTATE_READY; - //current->state = PSTATE_RUNNING; - } uint32_t csc = crit_stash(); sti();
M kernel/sched/sched_strats.ckernel/sched/sched_strats.c

@@ -3,12 +3,31 @@

#define NULL ((void*)0) PROCESS_ID next_schedule(PROCESS_ID current) { - PROCESS* process = get_process(current); + PROCESS* next = get_first_process(); + + PROCESS* choice = NULL; + + while (next) { + // skip idle process + if (next->id == 0) { + next = next->next; + continue; + } + + next->starvation++; + + // choose ready process with highest starvation value + if (next->state == PSTATE_READY && next->starvation > choice->starvation) { + choice = next; + } - if (process != NULL && process->next != NULL && process->next->state != PSTATE_TERMINATED) { - return process->next->id; + next = next->next; + } + + if (choice) { + choice->starvation = 0; + return choice->id; } else { - PROCESS *first = get_first_process(); - return first->id; + return 0; } }