shithub: riscv

Download patch

ref: 4ac5cfed08bb156dc13fae3ce43c3edab06cf952
parent: d31b10c42e29ba0befe9290164ec587d2a3ebb1e
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Jul 9 11:29:07 EDT 2023

bcm, bcm64, imx8, kw: Fix missing preempted() call on non-clock interrupt (thanks Anthony Martin)

As Anthony Martin noticed, some of the newer ARM and ARM64
kernels missed the preempted() call after handling non-clock
interrupts, which resulteds in a delay of scheduling higher
priority proc that has been woken up by the interrupt handler
(such as a kproc for attending some device or a higher
priority process that waited on some device to complete).

These kernels are all multiprocessors, so the woken process
would most likely be run by any other cpu *eventually*...
... with some delay.

Anyway, this change fixes it.

The change on zynq is cosmetic only. It was not affected
by this problem.

--- a/sys/src/9/bcm/trap.c
+++ b/sys/src/9/bcm/trap.c
@@ -131,7 +131,7 @@
 void
 trap(Ureg *ureg)
 {
-	int clockintr, user, x, rv, rem;
+	int user, x, rv, rem;
 	ulong inst, fsr;
 	uintptr va;
 	char buf[ERRMAX];
@@ -167,7 +167,10 @@
 			ureg->psr & PsrMask);
 		break;
 	case PsrMirq:
-		clockintr = irq(ureg);
+		if(!irq(ureg))
+			preempted();
+		else if(up != nil && up->delaysched)
+			sched();	/* can cause more traps */
 		break;
 	case PsrMabt:			/* prefetch fault */
 		x = ifsrget();
@@ -285,12 +288,6 @@
 		break;
 	}
 	splhi();
-
-	/* delaysched set because we held a lock or because our quantum ended */
-	if(up && up->delaysched && clockintr){
-		sched();		/* can cause more traps */
-		splhi();
-	}
 
 	if(user){
 		if(up->procctl || up->nnote)
--- a/sys/src/9/bcm64/trap.c
+++ b/sys/src/9/bcm64/trap.c
@@ -124,7 +124,9 @@
 	case 0x00:	// unknown
 		if(intr == 1){
 			f = fpukenter(ureg);
-			if(irq(ureg) && up != nil && up->delaysched)
+			if(!irq(ureg))
+				preempted();
+			else if(up != nil && up->delaysched)
 				sched();
 			break;
 		}
--- a/sys/src/9/imx8/trap.c
+++ b/sys/src/9/imx8/trap.c
@@ -124,7 +124,9 @@
 	case 0x00:	// unknown
 		if(intr == 1){
 			f = fpukenter(ureg);
-			if(irq(ureg) && up != nil && up->delaysched)
+			if(!irq(ureg))
+				preempted();
+			else if(up != nil && up->delaysched)
 				sched();
 			break;
 		}
--- a/sys/src/9/kw/dat.h
+++ b/sys/src/9/kw/dat.h
@@ -137,7 +137,6 @@
 	PMach;
 
 	vlong	fastclock;		/* last sampled value */
-	int	inclockintr;
 
 	int	cputype;
 	int	socrev;			/* system-on-chip revision */
--- a/sys/src/9/kw/trap.c
+++ b/sys/src/9/kw/trap.c
@@ -185,14 +185,16 @@
 /*
  *  called by trap to handle interrupts
  */
-static void
+static int
 intrs(Ureg *ur, int sort)
 {
-	int i, s;
+	int i, s, clockintr;
 	ulong ibits;
 	Handler *h;
 	Irq irq;
 
+	clockintr = 0;
+
 	assert(sort >= 0 && sort < nelem(irqs));
 	irq = irqs[sort];
 	ibits = *irq.irq;
@@ -206,7 +208,7 @@
 				splhi();
 				intrtime(m, sort*32 + i);
 				if (sort == Irqbridge && i == IRQcputimer0)
-					m->inclockintr = 1;
+					clockintr = 1;
 				ibits &= ~(1<<i);
 			}
 		}
@@ -217,6 +219,8 @@
 		*irq.irqmask &= ~ibits;
 		splx(s);
 	}
+
+	return clockintr;
 }
 
 void
@@ -382,7 +386,6 @@
 	else
 		ureg->pc -= 4;
 
-	m->inclockintr = 0;
 	switch(ureg->type) {
 	default:
 		panic("unknown trap %ld", ureg->type);
@@ -390,7 +393,12 @@
 	case PsrMirq:
 		ldrexvalid = 0;
 		// splflo();		/* allow fast interrupts */
-		intrs(ureg, Irqlo);
+		if(!intrs(ureg, Irqlo))
+			preempted();
+		else if(up != nil && up->delaysched){
+			ldrexvalid = 0;
+			sched();
+		}
 		m->intr++;
 		break;
 	case PsrMabt:			/* prefetch fault */
@@ -486,13 +494,6 @@
 		break;
 	}
 	splhi();
-
-	/* delaysched set because we held a lock or because our quantum ended */
-	if(up && up->delaysched && m->inclockintr){
-		ldrexvalid = 0;
-		sched();
-		splhi();
-	}
 
 	if(user){
 		if(up->procctl || up->nnote)
--- a/sys/src/9/zynq/fns.h
+++ b/sys/src/9/zynq/fns.h
@@ -49,7 +49,7 @@
 void l1switch(L1 *, int);
 void intrenable(int, void (*)(Ureg *, void *), void *, int, char *);
 void intrinit(void);
-void intr(Ureg *);
+int intr(Ureg *);
 int uartconsole(void);
 long fbctlread(Chan*,void*,long,vlong);
 long fbctlwrite(Chan*,void*,long,vlong);
--- a/sys/src/9/zynq/intr.c
+++ b/sys/src/9/zynq/intr.c
@@ -88,7 +88,7 @@
 	mpcore[ICDABR + (irq >> 5)] |= 1 << (irq & 31);
 }
 
-void
+int
 intr(Ureg *ureg)
 {
 	ulong v;
@@ -109,13 +109,5 @@
 		i->f(ureg, i->arg);
 	mpcore[ICCEOIR] = v;
 
-	if(up != nil){
-		if(irq == TIMERIRQ){
-			if(up->delaysched){
-				splhi();
-				sched();
-			}
-		}else
-			preempted();
-	}
+	return irq == TIMERIRQ;
 }
--- a/sys/src/9/zynq/trap.c
+++ b/sys/src/9/zynq/trap.c
@@ -182,7 +182,10 @@
 		break;
 	case PsrMirq:
 		ureg->pc -= 4;
-		intr(ureg);
+		if(!intr(ureg))
+			preempted();
+		else if(up != nil && up->delaysched)
+			sched();
 		break;
 	default:
 		iprint("cpu%d: unknown trap type %ulx\n", m->machno, ureg->type);