ref: 28836f3ff593f729a9dc92b67a6f99382bc84c28
parent: 480d7b8f5f0ccb52391c41ffa58c196618827346
author: cinap_lenrek <[email protected]>
date: Fri Dec 6 21:13:51 EST 2019
kernel: avoid useless mmu flushes, implement better wait condition for procflushmmu() procflushmmu() returns once all *OTHER* processors that had matching processes running on them flushed ther tlb/mmu state. the caller of procflush...() takes care of flushing "up" by calling flushmmu() later. if the current process matched, then that means m->flushmmu would be set, and hzclock() would call flushmmu() again. to avoid this, we now check up->newtlb in addition to m->flushmmu in hzclock() before calling flushmmu(). we also maintain information on which process on what processor to wait for locally, which helps making progress when multiple procflushmmu()'s are running concurrently. in addition, this makes the wait condition for procflushmmu() more sophisticated, by validating if the processor still runs the selected process and only if it matchatches, considers the MACHP(nm)->flushmmu flag.
--- a/sys/src/9/port/portclock.c
+++ b/sys/src/9/port/portclock.c
@@ -148,7 +148,7 @@
m->proc->pc = ur->pc;
if(m->flushmmu){
- if(up)
+ if(up && up->newtlb)
flushmmu();
m->flushmmu = 0;
}
--- a/sys/src/9/port/proc.c
+++ b/sys/src/9/port/proc.c
@@ -1331,6 +1331,7 @@
static void
procflushmmu(int (*match)(Proc*, void*), void *a)
{
+ Proc *await[MAXMACH];
int i, nm, nwait;
Proc *p;
@@ -1337,30 +1338,42 @@
/*
* tell all matching processes to flush their mmu's
*/
+ memset(await, 0, conf.nmach*sizeof(await[0]));
nwait = 0;
- for(i=0; i<conf.nproc; i++) {
+ for(i = 0; i < conf.nproc; i++){
p = &procalloc.arena[i];
if(p->state != Dead && (*match)(p, a)){
p->newtlb = 1;
for(nm = 0; nm < conf.nmach; nm++){
if(MACHP(nm)->proc == p){
+ coherence();
MACHP(nm)->flushmmu = 1;
- nwait++;
+ if(await[nm] == nil)
+ nwait++;
+ await[nm] = p;
}
}
}
}
- if(nwait == 0)
- return;
-
/*
* wait for all other processors to take a clock interrupt
* and flush their mmu's
*/
- for(nm = 0; nm < conf.nmach; nm++)
- while(m->machno != nm && MACHP(nm)->flushmmu)
- sched();
+ for(;;){
+ if(nwait == 0 || nwait == 1 && await[m->machno] != nil)
+ break;
+
+ sched();
+
+ for(nm = 0; nm < conf.nmach; nm++){
+ p = await[nm];
+ if(p != nil && (MACHP(nm)->proc != p || MACHP(nm)->flushmmu == 0)){
+ await[nm] = nil;
+ nwait--;
+ }
+ }
+ }
}
static int