From 3bcbdb5ec45b7cb524cfbd10c8297c695f095ed9 Mon Sep 17 00:00:00 2001 From: kamkow1 Date: Thu, 1 Jan 2026 16:59:04 +0100 Subject: [PATCH] Fix proc_kill () race, improve scheduler locking --- kernel/proc/proc.c | 59 +++++++++++++++++++++++++++------------------- kernel/proc/proc.h | 7 ++++++ 2 files changed, 42 insertions(+), 24 deletions(-) diff --git a/kernel/proc/proc.c b/kernel/proc/proc.c index f66bf5b..14c8514 100644 --- a/kernel/proc/proc.c +++ b/kernel/proc/proc.c @@ -153,6 +153,7 @@ static struct proc* proc_spawn_rd (char* name) { proc->pdata.regs.cs = 0x18 | 0x03; proc->pdata.regs.rip = aux.entry; proc->lock = SPIN_LOCK_INIT; + atomic_store (&proc->state, PROC_READY); #endif return proc; @@ -181,26 +182,51 @@ static void proc_register (struct proc* proc) { spin_unlock (&procs_lock); } +static struct proc *proc_find_sched (void) { + struct proc *start = thiscpu->proc_current; + struct proc *proc = start->next; + + for (;;) { + if (proc == NULL) { + proc = thiscpu->proc_run_q; + } + + if (atomic_load (&proc->state) == PROC_READY) { + return proc; + } + + /* No runnable processes found. */ + if (proc == start) { + return NULL; + } + + proc = proc->next; + } +} + void proc_sched (void) { + struct proc *next = NULL; + spin_lock (&thiscpu->lock); if (thiscpu->proc_run_q == NULL || thiscpu->proc_current == NULL) { - goto done; + spin_unlock (&thiscpu->lock); + goto idle; } - thiscpu->proc_current = thiscpu->proc_current->next; + next = proc_find_sched (); - if (thiscpu->proc_current == NULL) { - thiscpu->proc_current = thiscpu->proc_run_q; + if (next != NULL) { + thiscpu->proc_current = next; } -done: spin_unlock (&thiscpu->lock); - if (thiscpu->proc_current != NULL) { - do_sched (&thiscpu->proc_current->pdata.regs, &thiscpu->proc_current->pd); + if (next != NULL && atomic_load (&next->state) == PROC_READY) { + do_sched (&next->pdata.regs, &next->pd); } +idle: #if defined(__x86_64__) extern void amd64_spin (void); @@ -209,23 +235,8 @@ done: } void proc_kill (struct proc* proc) { - spin_lock (&procs_lock); - - spin_lock (&thiscpu->lock); - - linklist_remove (struct procw*, procs, proc->procw); - linklist_remove (struct proc*, thiscpu->proc_run_q, proc); - - if (thiscpu->proc_current == proc) - thiscpu->proc_current = NULL; - - spin_unlock (&thiscpu->lock); - - spin_unlock (&procs_lock); - - /* clean up */ - free (proc->procw); - free (proc); + /* mark for garbage collection */ + atomic_store (&proc->state, PROC_DEAD); } static void proc_irq_sched (void* arg, void* regs) { diff --git a/kernel/proc/proc.h b/kernel/proc/proc.h index 353e76c..2a8f370 100644 --- a/kernel/proc/proc.h +++ b/kernel/proc/proc.h @@ -11,6 +11,12 @@ #include /* USTACK_SIZE */ #endif +/// Process is ready to run +#define PROC_READY 0 +/// Process marked garbage collection +#define PROC_DEAD 1 + + struct cpu; struct proc_mapping { @@ -30,6 +36,7 @@ struct proc { spin_lock_t lock; struct cpu* cpu; struct procw* procw; /* link to it's global struct */ + atomic_int state; }; /*