Skip to content

Commit

Permalink
fix(kernel: sched): do not free process on exit
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
d4ilyrun committed Jun 18, 2024
1 parent 45c8b4e commit 7b2d9fc
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 11 deletions.
8 changes: 6 additions & 2 deletions kernel/sys/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
}

Expand Down
20 changes: 11 additions & 9 deletions kernel/sys/sched.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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, &current_process->this);
if (reschedule) {
if (current_process->state == SCHED_RUNNING)
queue_enqueue(&scheduler.ready, &current_process->this);
}

// If some tasks are ready, do not reschedule the idle task
if (next == idle_process && queue_peek(&scheduler.ready)) {
Expand All @@ -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);
}

Expand Down Expand Up @@ -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);
}

Expand All @@ -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);
}

0 comments on commit 7b2d9fc

Please sign in to comment.