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);
}
--
⑨