Fix proc_kill () race, improve scheduler locking
All checks were successful
Build documentation / build-and-deploy (push) Successful in 1m45s

This commit is contained in:
2026-01-01 16:59:04 +01:00
parent 7f53ede2ab
commit 3bcbdb5ec4
2 changed files with 42 additions and 24 deletions

View File

@@ -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) {