From 28836f3ff593f729a9dc92b67a6f99382bc84c28 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Sat, 7 Dec 2019 02:13:51 +0100 Subject: 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. --- sys/src/9/port/portclock.c | 2 +- sys/src/9/port/proc.c | 29 +++++++++++++++++++++-------- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/sys/src/9/port/portclock.c b/sys/src/9/port/portclock.c index db2420948..6711815ff 100644 --- a/sys/src/9/port/portclock.c +++ b/sys/src/9/port/portclock.c @@ -148,7 +148,7 @@ hzclock(Ureg *ur) m->proc->pc = ur->pc; if(m->flushmmu){ - if(up) + if(up && up->newtlb) flushmmu(); m->flushmmu = 0; } diff --git a/sys/src/9/port/proc.c b/sys/src/9/port/proc.c index f67dc9f3a..8ea620a51 100644 --- a/sys/src/9/port/proc.c +++ b/sys/src/9/port/proc.c @@ -1331,36 +1331,49 @@ procdump(void) static void procflushmmu(int (*match)(Proc*, void*), void *a) { + Proc *await[MAXMACH]; int i, nm, nwait; Proc *p; /* * tell all matching processes to flush their mmu's */ + memset(await, 0, conf.nmach*sizeof(await[0])); nwait = 0; - for(i=0; istate != 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 -- cgit v1.2.3 From 13785bbbef60f5c13aa973c1e7d4277aa55f6a2d Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Sat, 7 Dec 2019 02:19:14 +0100 Subject: pc: replace duplicated and broken mmu flush code in vunmap() comparing m with MACHP() is wrong as m is a constant on 386. add procflushothers(), which flushes all processes except up using common procflushmmu() routine. --- sys/src/9/pc/mmu.c | 22 +--------------------- sys/src/9/port/portfns.h | 1 + sys/src/9/port/proc.c | 11 +++++++++++ 3 files changed, 13 insertions(+), 21 deletions(-) diff --git a/sys/src/9/pc/mmu.c b/sys/src/9/pc/mmu.c index 383ba7d91..c9ff28abb 100644 --- a/sys/src/9/pc/mmu.c +++ b/sys/src/9/pc/mmu.c @@ -643,10 +643,7 @@ vmapalloc(ulong size) void vunmap(void *v, int size) { - int i; ulong va, o; - Mach *nm; - Proc *p; /* * might not be aligned @@ -675,25 +672,8 @@ vunmap(void *v, int size) putcr3(PADDR(MACHP(0)->pdb)); return; } - for(i=0; istate == Dead) - continue; - if(p != up) - p->newtlb = 1; - } - for(i=0; iflushmmu = 1; - } + procflushothers(); flushmmu(); - for(i=0; imachno] && nm->flushmmu) - ; - } } /* diff --git a/sys/src/9/port/portfns.h b/sys/src/9/port/portfns.h index a37777c20..b460ec935 100644 --- a/sys/src/9/port/portfns.h +++ b/sys/src/9/port/portfns.h @@ -229,6 +229,7 @@ void procdump(void); int procfdprint(Chan*, int, char*, int); void procflushseg(Segment*); void procflushpseg(Physseg*); +void procflushothers(void); int procindex(ulong); void procinit0(void); ulong procpagecount(Proc*); diff --git a/sys/src/9/port/proc.c b/sys/src/9/port/proc.c index 8ea620a51..59fe9ecd9 100644 --- a/sys/src/9/port/proc.c +++ b/sys/src/9/port/proc.c @@ -1412,6 +1412,17 @@ procflushpseg(Physseg *ps) procflushmmu(matchpseg, ps); } +static int +matchother(Proc *p, void *a) +{ + return p != a; +} +void +procflushothers(void) +{ + procflushmmu(matchother, up); +} + void scheddump(void) { -- cgit v1.2.3