From 7b2d9fc728735bc49c86288e8ab5acead03f046c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20DUBOIN?= Date: Tue, 18 Jun 2024 19:51:35 +0200 Subject: [PATCH] fix(kernel: sched): do not free process on exit WARNING: This is only temporary and we should find a proper alternative The way we were freeing the process caused multiple issues: * #PF by referencing the freed processs when rescheduling the next one * The previous process being present twice inside the runqueue These made debugging other issues more complicated since these problems do not arise each time we run, bu they sure make it impossible to debug appropriately when they do. --- kernel/sys/process.c | 8 ++++++-- kernel/sys/sched.c | 20 +++++++++++--------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/kernel/sys/process.c b/kernel/sys/process.c index fd4ef57..d0f77b8 100644 --- a/kernel/sys/process.c +++ b/kernel/sys/process.c @@ -61,7 +61,7 @@ process_t *process_create(char *name, process_entry_t entrypoint, void *data) void arch_process_free(process_t *process); -static void process_free(process_t *process) +MAYBE_UNUSED static void process_free(process_t *process) { log_info("process", "terminating '%s'", process->name); vmm_destroy(process->vmm); @@ -72,7 +72,11 @@ static void process_free(process_t *process) bool process_switch(process_t *process) { if (process->state == SCHED_KILLED) { - process_free(process); + // FIXME: Find a way to free the process on exit + // By doing it this way, referencing the freed process + // causes a #PF when rescheduling the next process. + // + // process_free(process); return false; } diff --git a/kernel/sys/sched.c b/kernel/sys/sched.c index 8027bd0..f44b7c3 100644 --- a/kernel/sys/sched.c +++ b/kernel/sys/sched.c @@ -42,7 +42,7 @@ static process_t *idle_process; * * @see scheduler_lock scheduler_unlock */ -static void do_schedule(void) +static void do_schedule(bool reschedule) { node_t *next_node = queue_dequeue(&scheduler.ready); @@ -51,9 +51,10 @@ static void do_schedule(void) process_t *next = container_of(next_node, process_t, this); - if (current_process->state == SCHED_RUNNING || - current_process->state == SCHED_KILLED) - queue_enqueue(&scheduler.ready, ¤t_process->this); + if (reschedule) { + if (current_process->state == SCHED_RUNNING) + queue_enqueue(&scheduler.ready, ¤t_process->this); + } // If some tasks are ready, do not reschedule the idle task if (next == idle_process && queue_peek(&scheduler.ready)) { @@ -64,14 +65,15 @@ static void do_schedule(void) next->running.preempt = timer_gettick() + SCHED_TIMESLICE; - if (!process_switch(next)) - do_schedule(); + if (!process_switch(next)) { + do_schedule(false); + } } void schedule(void) { const bool old_if = scheduler_lock(); - do_schedule(); + do_schedule(true); scheduler_unlock(old_if); } @@ -123,7 +125,7 @@ void sched_block_current_process(void) { const bool old_if = scheduler_lock(); current_process->state = SCHED_WAITING; - do_schedule(); + do_schedule(true); scheduler_unlock(old_if); } @@ -139,7 +141,7 @@ void sched_unblock_process(process_t *process) // give the least time possible to the IDLE task if (current_process == idle_process) - do_schedule(); + do_schedule(true); scheduler_unlock(old_if); }