ref: 71c1961cceb6e9fc886398278c8191b85b2eb952
parent: 48d57b7af201fe15103c779bab72b6968def780f
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Tue Jan 6 21:37:13 EST 2026
kernel: debounce killbig() Skip killbig() while there are still processes in Proc_exitbig state, to avoid overshooting. Free segments in pexit() *before* freeing the pid. Replace pprint() with print() to avoid deadlocking when trying to print to rio window where rio might itself getting swapped out. Do a final needpages() check before comitting to killing the process.
--- a/sys/src/9/port/devswap.c
+++ b/sys/src/9/port/devswap.c
@@ -129,6 +129,56 @@
wakeup(&swapalloc.r);
}
+static void
+killbig(void)
+{+ int i;
+ Segment *s;
+ ulong l, max;
+ Proc *p, *kp;
+
+ max = 0;
+ kp = nil;
+ for(i = 0; (p = proctab(i)) != nil; i++) {+ if(p->state <= New || p->kp || p->parentpid == 0)
+ continue;
+ if(p->procctl == Proc_exitbig)
+ return; /* try later when done exiting */
+ if((p->noswap || (p->procmode & 0222) == 0) && strcmp(eve, p->user) == 0)
+ continue;
+ l = procpagecount(p);
+ if(l > max){+ kp = p;
+ max = l;
+ }
+ }
+ if(kp == nil)
+ return;
+ if(!canqlock(&kp->debug))
+ return;
+ if(!canqlock(&kp->seglock)){+ qunlock(&kp->debug);
+ return;
+ }
+ if(!needpages(nil)){+ qunlock(&kp->seglock);
+ qunlock(&kp->debug);
+ return;
+ }
+ s = kp->seg[BSEG];
+ killproc(kp, Proc_exitbig);
+ qunlock(&kp->debug);
+ if(s != nil && s->ref > 1){+ for(i = 0; (p = proctab(i)) != nil; i++) {+ if(p == kp || !matchseg(p, s) || !canqlock(&p->debug))
+ continue;
+ killproc(p, Proc_exitbig);
+ qunlock(&p->debug);
+ }
+ }
+ qunlock(&kp->seglock);
+}
+
static int
reclaim(void)
{--- a/sys/src/9/port/portfns.h
+++ b/sys/src/9/port/portfns.h
@@ -170,7 +170,6 @@
int kenter(Ureg*);
void kexit(Ureg*);
void kickpager(void);
-void killbig(void);
void killproc(Proc*,int);
void kproc(char*, void(*)(void*), void*);
void kprocchild(Proc*, void (*)(void));
--- a/sys/src/9/port/proc.c
+++ b/sys/src/9/port/proc.c
@@ -1343,6 +1343,16 @@
addbroken();
}
+ qlock(&up->seglock);
+ for(i = 0; i < NSEG; i++){+ s = up->seg[i];
+ if(s != nil){+ up->seg[i] = nil;
+ putseg(s);
+ }
+ }
+ qunlock(&up->seglock);
+
qlock(&up->debug);
lock(&up->exl); /* Prevent my children from leaving waits */
@@ -1380,16 +1390,6 @@
up->nwatchpt = 0;
qunlock(&up->debug);
- qlock(&up->seglock);
- for(i = 0; i < NSEG; i++){- s = up->seg[i];
- if(s != nil){- up->seg[i] = nil;
- putseg(s);
- }
- }
- qunlock(&up->seglock);
-
edfstop(up);
if(up->edf != nil){free(up->edf);
@@ -1655,7 +1655,7 @@
switch(up->procctl) {case Proc_exitbig:
spllo();
- pprint("Killed: Insufficient physical memory\n");+ print("%s %lud: Killed: Insufficient physical memory\n", up->text, up->pid); pexit("Killed: Insufficient physical memory", 1);case Proc_exitme:
@@ -1730,51 +1730,6 @@
pages += s->used;
}
return pages;
-}
-
-void
-killbig(void)
-{- int i;
- Segment *s;
- ulong l, max;
- Proc *p, *kp;
-
- max = 0;
- kp = nil;
- for(i = 0; (p = proctab(i)) != nil; i++) {- if(p->state <= New || p->kp || p->parentpid == 0)
- continue;
- if((p->noswap || (p->procmode & 0222) == 0) && strcmp(eve, p->user) == 0)
- continue;
- l = procpagecount(p);
- if(l > max){- kp = p;
- max = l;
- }
- }
- if(kp == nil)
- return;
- if(!canqlock(&kp->debug))
- return;
- if(!canqlock(&kp->seglock)){- qunlock(&kp->debug);
- return;
- }
- s = kp->seg[BSEG];
- if(kp->procctl != Proc_exitbig)
- killproc(kp, Proc_exitbig);
- qunlock(&kp->debug);
- if(s != nil && s->ref > 1){- for(i = 0; (p = proctab(i)) != nil; i++) {- if(p == kp || !matchseg(p, s) || !canqlock(&p->debug))
- continue;
- if(p->procctl != Proc_exitbig)
- killproc(p, Proc_exitbig);
- qunlock(&p->debug);
- }
- }
- qunlock(&kp->seglock);
}
/*
--
⑨