ref: 4ac5cfed08bb156dc13fae3ce43c3edab06cf952
parent: d31b10c42e29ba0befe9290164ec587d2a3ebb1e
author: cinap_lenrek <[email protected]>
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);