shithub: front

Download patch

ref: f1e7d6da67e4eb762fba669a4d324cfdc55ddae1
parent: fc859af624883111ad21311d50dd5ebfaad3b741
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Tue Jul 23 15:50:36 EDT 2024

kernel: sched() should not imply spllo()

The idea is:

When we call sched() with interrupts disabled,
it must not return with them re-enabled.

The code becomes easier to reason about if
we make sched() preserve interrupt status,
which lets us call sched() from an interrupt
handler (with interrupts disabled) without
risking preemption by another interrupt once
sched() returns which can pump-up the stack.

This allows removing Proc.preempted flag as
it is now impossible for interrupts to
preempt each other in preempted().

Extra cleanups:

make interrupted() _Noreturn void
and remove unused Proc.yield flag.

--- a/sys/src/9/arm64/trap.c
+++ b/sys/src/9/arm64/trap.c
@@ -275,10 +275,8 @@
 	if(scallnr != RFORK && (up->procctl || up->nnote))
 		notify(ureg);
 
-	if(up->delaysched){
+	if(up->delaysched)
 		sched();
-		splhi();
-	}
 
 	kexit(ureg);
 	fpukexit(ureg, nil);
--- a/sys/src/9/cycv/trap.c
+++ b/sys/src/9/cycv/trap.c
@@ -273,10 +273,8 @@
 	splhi();
 	if(scallnr != RFORK && (up->procctl || up->nnote))
 		notify(ureg);
-	if(up->delaysched){
+	if(up->delaysched)
 		sched();
-		splhi();
-	}
 	kexit(ureg);
 }
 
--- a/sys/src/9/kw/syscall.c
+++ b/sys/src/9/kw/syscall.c
@@ -237,10 +237,8 @@
 		notify(ureg);
 
 	/* if we delayed sched because we held a lock, sched now */
-	if(up->delaysched){
+	if(up->delaysched)
 		sched();
-		splhi();
-	}
 	kexit(ureg);
 }
 
--- a/sys/src/9/mt7688/syscall.c
+++ b/sys/src/9/mt7688/syscall.c
@@ -108,10 +108,8 @@
 		notify(ureg);
 
 	/* if we delayed sched because we held a lock, sched now */
-	if(up->delaysched){
+	if(up->delaysched)
 		sched();
-		splhi();
-	}
 
 	kexit(ureg);
 
--- a/sys/src/9/omap/syscall.c
+++ b/sys/src/9/omap/syscall.c
@@ -232,10 +232,8 @@
 		notify(ureg);
 
 	/* if we delayed sched because we held a lock, sched now */
-	if(up->delaysched){
+	if(up->delaysched)
 		sched();
-		splhi();
-	}
 	kexit(ureg);
 }
 
--- a/sys/src/9/pc/trap.c
+++ b/sys/src/9/pc/trap.c
@@ -546,10 +546,8 @@
 	if(scallnr!=RFORK && (up->procctl || up->nnote))
 		notify(ureg);
 	/* if we delayed sched because we held a lock, sched now */
-	if(up->delaysched){
+	if(up->delaysched)
 		sched();
-		splhi();
-	}
 	kexit(ureg);
 }
 
--- a/sys/src/9/pc64/trap.c
+++ b/sys/src/9/pc64/trap.c
@@ -537,10 +537,8 @@
 	up->psstate = nil;
 
 	/* if we delayed sched because we held a lock, sched now */
-	if(up->delaysched){
+	if(up->delaysched)
 		sched();
-		splhi();
-	}
 
 	kexit(ureg);
 	fpukexit(ureg, nil);
--- a/sys/src/9/port/portdat.h
+++ b/sys/src/9/port/portdat.h
@@ -769,10 +769,7 @@
 	uchar	fixedpri;	/* priority level doesn't change */
 	ulong	cpu;		/* cpu average */
 	ulong	lastupdate;
-	uchar	yield;		/* non-zero if the process just did a sleep(0) */
-	int	preempted;	/* true if this process hasn't finished the interrupt
-				 *  that last preempted it
-				 */
+
 	Edf	*edf;		/* if non-null, real-time proc, edf contains scheduling params */
 	int	trace;		/* process being traced? */
 
--- a/sys/src/9/port/portfns.h
+++ b/sys/src/9/port/portfns.h
@@ -137,7 +137,7 @@
 Block*		iallocb(int);
 uintptr		ibrk(uintptr, int);
 void		ilock(Lock*);
-void		interrupted(void);
+_Noreturn void	interrupted(void);
 void		iunlock(Lock*);
 ulong		imagecached(void);
 ulong		imagereclaim(int);
--- a/sys/src/9/port/proc.c
+++ b/sys/src/9/port/proc.c
@@ -170,6 +170,8 @@
 void
 sched(void)
 {
+	int s;
+
 	if(m->ilockdepth)
 		panic("cpu%d: ilockdepth %d, last lock %#p at %#p",
 			m->machno,
@@ -199,10 +201,10 @@
  			delayedscheds++;
 			return;
 		}
-		up->delaysched = 0;
-		splhi();
- 		procswitch();
-		spllo();
+		s = splhi();
+ 		up->delaysched = 0;
+		procswitch();
+		splx(s);
 		return;
 	}
 	up = runproc();
@@ -256,12 +258,10 @@
 	if(up == nil || up->state != Running || active.exiting)
 		return;
 	if(!clockintr){
-		if(up->preempted || !anyhigher())
+		if(!anyhigher())
 			return;
 		m->readied = nil;	/* avoid cooperative scheduling */
-		up->preempted = 1;
 		sched();
-		up->preempted = 0;
 	} else if(up->delaysched)
 		sched();		/* quantum ended or we held a lock */
 }
@@ -728,7 +728,6 @@
 	p->lastilock = nil;
 	p->nlocks = 0;
 	p->trace = 0;
-	p->preempted = 0;
 	p->delaysched = 0;
 
 	/* sched params */
@@ -871,7 +870,7 @@
 	splx(s);
 }
 
-void
+_Noreturn void
 interrupted(void)
 {
 	if(up->procctl == Proc_exitme && up->closingfgrp != nil)
@@ -1657,7 +1656,6 @@
 procctl(void)
 {
 	char *state;
-	ulong s;
 
 	switch(up->procctl) {
 	case Proc_exitbig:
@@ -1679,7 +1677,7 @@
 		state = up->psstate;
 		up->psstate = statename[Stopped];
 		/* free a waiting debugger */
-		s = spllo();
+		spllo();
 		qlock(&up->debug);
 		if(up->pdbg != nil) {
 			wakeup(&up->pdbg->sleep);
@@ -1690,7 +1688,6 @@
 		up->state = Stopped;
 		sched();
 		up->psstate = state;
-		splx(s);
 		return;
 	}
 }
--- a/sys/src/9/port/taslock.c
+++ b/sys/src/9/port/taslock.c
@@ -106,7 +106,7 @@
 void
 ilock(Lock *l)
 {
-	ulong x;
+	int x;
 	uintptr pc;
 
 	pc = getcallerpc(&l);
--- a/sys/src/9/ppc/trap.c
+++ b/sys/src/9/ppc/trap.c
@@ -208,10 +208,8 @@
 		if(!user)
 			panic("syscall in kernel: srr1 0x%4.4luX\n", ureg->srr1);
 		syscall(ureg);
-		if (up->delaysched){
+		if (up->delaysched)
 			sched();
-			splhi();
-		}
 		kexit(ureg);
 		return;		/* syscall() calls notify itself, don't do it again */
 
--- a/sys/src/9/sgi/trap.c
+++ b/sys/src/9/sgi/trap.c
@@ -694,10 +694,8 @@
 	if(scallnr!=RFORK && (up->procctl || up->nnote))
 		notify(ur);
 	/* if we delayed sched because we held a lock, sched now */
-	if(up->delaysched){
+	if(up->delaysched)
 		sched();
-		splhi();
-	}
 	/* replicate fpstate to ureg status */
 	if(up->fpstate != FPactive)
 		ur->status &= ~CU1;
--- a/sys/src/9/teg2/syscall.c
+++ b/sys/src/9/teg2/syscall.c
@@ -264,10 +264,8 @@
 	l1cache->wb();			/* system is more stable with this */
 
 	/* if we delayed sched because we held a lock, sched now */
-	if(up->delaysched){
+	if(up->delaysched)
 		sched();
-		splhi();
-	}
 	kexit(ureg);
 }
 
--- a/sys/src/9/xen/trap.c
+++ b/sys/src/9/xen/trap.c
@@ -457,10 +457,8 @@
 	if(scallnr!=RFORK && (up->procctl || up->nnote))
 		notify(ureg);
 	/* if we delayed sched because we held a lock, sched now */
-	if(up->delaysched){
+	if(up->delaysched)
 		sched();
-		splhi();
-	}
 	INTRLOG(dprint("before kexit\n");)
 	kexit(ureg);
 }
--- a/sys/src/9/zynq/trap.c
+++ b/sys/src/9/zynq/trap.c
@@ -272,10 +272,8 @@
 	splhi();
 	if(scallnr != RFORK && (up->procctl || up->nnote))
 		notify(ureg);
-	if(up->delaysched){
+	if(up->delaysched)
 		sched();
-		splhi();
-	}
 	kexit(ureg);
 }
 
--