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.cs = 0x18 | 0x03;
proc->pdata.regs.rip = aux.entry; proc->pdata.regs.rip = aux.entry;
proc->lock = SPIN_LOCK_INIT; proc->lock = SPIN_LOCK_INIT;
atomic_store (&proc->state, PROC_READY);
#endif #endif
return proc; return proc;
@@ -181,26 +182,51 @@ static void proc_register (struct proc* proc) {
spin_unlock (&procs_lock); 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) { void proc_sched (void) {
struct proc *next = NULL;
spin_lock (&thiscpu->lock); spin_lock (&thiscpu->lock);
if (thiscpu->proc_run_q == NULL || thiscpu->proc_current == NULL) { 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) { if (next != NULL) {
thiscpu->proc_current = thiscpu->proc_run_q; thiscpu->proc_current = next;
} }
done:
spin_unlock (&thiscpu->lock); spin_unlock (&thiscpu->lock);
if (thiscpu->proc_current != NULL) { if (next != NULL && atomic_load (&next->state) == PROC_READY) {
do_sched (&thiscpu->proc_current->pdata.regs, &thiscpu->proc_current->pd); do_sched (&next->pdata.regs, &next->pd);
} }
idle:
#if defined(__x86_64__) #if defined(__x86_64__)
extern void amd64_spin (void); extern void amd64_spin (void);
@@ -209,23 +235,8 @@ done:
} }
void proc_kill (struct proc* proc) { void proc_kill (struct proc* proc) {
spin_lock (&procs_lock); /* mark for garbage collection */
atomic_store (&proc->state, PROC_DEAD);
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);
} }
static void proc_irq_sched (void* arg, void* regs) { static void proc_irq_sched (void* arg, void* regs) {

View File

@@ -11,6 +11,12 @@
#include <amd64/proc.h> /* USTACK_SIZE */ #include <amd64/proc.h> /* USTACK_SIZE */
#endif #endif
/// Process is ready to run
#define PROC_READY 0
/// Process marked garbage collection
#define PROC_DEAD 1
struct cpu; struct cpu;
struct proc_mapping { struct proc_mapping {
@@ -30,6 +36,7 @@ struct proc {
spin_lock_t lock; spin_lock_t lock;
struct cpu* cpu; struct cpu* cpu;
struct procw* procw; /* link to it's global struct */ struct procw* procw; /* link to it's global struct */
atomic_int state;
}; };
/* /*