git: 9front

Download patch

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);
 }
 
 /*
--