From 4dce8a6f8a3588338dbec74b131d5201c52cd8f7 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 22 Aug 2002 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2002-08-22 --- alphapc/clock.c | 10 ++++++++++ alphapc/dat.h | 4 +--- alphapc/trap.c | 1 - bitsy/clock.c | 10 ++++++++++ bitsy/dat.h | 4 +--- mtx/clock.c | 10 ++++++++++ mtx/dat.h | 4 +--- mtx/trap.c | 1 - pc/clock.c | 15 +++++++++++++++ pc/dat.h | 4 +--- pc/i8253.c | 15 +++++++++++++++ pc/main.c | 5 ----- pc/trap.c | 27 ++++++++++++++++----------- port/devcons.c | 31 ++++++++----------------------- port/portdat.h | 15 +++++++++++++++ port/portfns.h | 1 + port/proc.c | 33 ++++++++++++++++++++++----------- 17 files changed, 126 insertions(+), 64 deletions(-) diff --git a/alphapc/clock.c b/alphapc/clock.c index 1f9abf7f1c7c0a5afba6c1d9b341829212244440..f00f87950b0afeee8adc436a982d99c988f1d0b7 100644 --- a/alphapc/clock.c +++ b/alphapc/clock.c @@ -58,6 +58,16 @@ fastticks(uvlong* hz) return ticks; } +/* + * performance measurement ticks. must be low overhead. + * doesn't have to count over a second. + */ +ulong +perfticks(void) +{ + return rpcc(nil); +} + void timerset(uvlong) { diff --git a/alphapc/dat.h b/alphapc/dat.h index 82dc71affdd9e70d7f3d3e075111f82f839da064..637bcc1008c5a523911f917779045f649bc7535a 100644 --- a/alphapc/dat.h +++ b/alphapc/dat.h @@ -146,9 +146,7 @@ struct Mach vlong cpuhz; /* hwrpb->cfreq */ ulong pcclast; uvlong fastclock; - vlong intrts; /* time stamp of last interrupt */ - ulong inidle; /* fastticks in idlehands() since last slowtick */ - ulong avginidle; /* avg fastticks in idlehands() per slowtick */ + Perf perf; /* performance counters */ int tlbfault; /* only used by devproc; no access to tlb */ int tlbpurge; /* ... */ diff --git a/alphapc/trap.c b/alphapc/trap.c index 69593d4b82225db050b2f82d649308c796eb2ada..a066ee5f81d7731a404b184002a1158af7ae1bc9 100644 --- a/alphapc/trap.c +++ b/alphapc/trap.c @@ -291,7 +291,6 @@ trap(Ureg *ur) char buf[ERRMAX]; int user, x; - m->intrts = fastticks(nil); user = ur->status&UMODE; if(user){ diff --git a/bitsy/clock.c b/bitsy/clock.c index aae9169117c76851815ddf6d2cd3452fa021fc6f..54ef093e2e5423b14d13ced6e9edeef9391ee52d 100644 --- a/bitsy/clock.c +++ b/bitsy/clock.c @@ -162,3 +162,13 @@ microdelay(int µs) } } } + +/* + * performance measurement ticks. must be low overhead. + * doesn't have to count over a second. + */ +ulong +perfticks(void) +{ + return timerregs->oscr; +} diff --git a/bitsy/dat.h b/bitsy/dat.h index 75c20e96737902145396fab177d5b6cc931a91b1..ba77b0659f843d7278345b236049c172595f1c2f 100644 --- a/bitsy/dat.h +++ b/bitsy/dat.h @@ -133,13 +133,11 @@ struct Mach int load; int intr; vlong fastclock; /* last sampled value */ - vlong intrts; /* time stamp of last interrupt */ uvlong inidle; /* time spent in idlehands() */ ulong spuriousintr; int lastintr; int ilockdepth; - ulong inidle; /* fastticks in idlehands() since last slowtick */ - ulong avginidle; /* avg fastticks in idlehands() per slowtick */ + Perf perf; /* performance counters */ int flushmmu; /* make current proc flush it's mmu state */ Proc *pid2proc[31]; /* what proc holds what pid */ diff --git a/mtx/clock.c b/mtx/clock.c index 41d2f1f3c4c32d452d3901f95ba33735f61ea08f..61b4c8efe3d325cd29d9984a9bd047e10e99d30b 100644 --- a/mtx/clock.c +++ b/mtx/clock.c @@ -94,3 +94,13 @@ fastticks(uvlong *hz) *hz = HZ; return m->ticks; } + +/* + * performance measurement ticks. must be low overhead. + * doesn't have to count over a second. + */ +ulong +perfticks(void) +{ + return m->ticks; +} diff --git a/mtx/dat.h b/mtx/dat.h index 97277598234550035c94d37ea08e1f955ef95dea..0e2ffc19ab514e3c6b6e077b32d23d76d05c6c40 100644 --- a/mtx/dat.h +++ b/mtx/dat.h @@ -141,9 +141,7 @@ struct Mach ulong pcclast; uvlong fastclock; - vlong intrts; /* time stamp of last interrupt */ - ulong inidle; /* fastticks in idlehands() since last slowtick */ - ulong avginidle; /* avg fastticks in idlehands() per slowtick */ + Perf perf; /* performance counters */ int tlbfault; /* only used by devproc; no access to tlb */ int tlbpurge; /* ... */ diff --git a/mtx/trap.c b/mtx/trap.c index 11ee9eeb91a582034620c66e9dee69132635d25c..36f992b99e37c6de0fc7f06109e3ab56d11b8fc7 100644 --- a/mtx/trap.c +++ b/mtx/trap.c @@ -214,7 +214,6 @@ trap(Ureg *ureg) int ecode, user; char buf[ERRMAX], *s; - m->intrts = fastticks(nil); ecode = (ureg->cause >> 8) & 0xff; user = (ureg->srr1 & MSR_PR) != 0; if(user) diff --git a/pc/clock.c b/pc/clock.c index 0d834f0fcb46562144cc05bcc0866cc298a9d9d2..6b65982a17777dd7c0205983716413a03d8d706e 100644 --- a/pc/clock.c +++ b/pc/clock.c @@ -43,3 +43,18 @@ microdelay(int microsecs) microsecs = 1; aamloop(microsecs); } + +/* + * performance measurement ticks. must be low overhead. + * doesn't have to count over a second. + */ +ulong +perfticks(void) +{ + uvlong x; + + if(!m->havetsc) + return ticks; + rdtsc(&x); + return x; +} diff --git a/pc/dat.h b/pc/dat.h index 427dc57c8abcbd85bbb69d8084828f0c1561683b..7e93d7c14db51b56df65c6b4010385e56e2a870b 100644 --- a/pc/dat.h +++ b/pc/dat.h @@ -175,11 +175,9 @@ struct Mach int syscall; int load; int intr; - uvlong intrts; /* time stamp of last interrupt */ int flushmmu; /* make current proc flush it's mmu state */ int ilockdepth; - ulong inidle; /* fastticks in idlehands() since last slowtick */ - ulong avginidle; /* avg fastticks in idlehands() per slowtick */ + Perf perf; /* performance counters */ ulong spuriousintr; int lastintr; diff --git a/pc/i8253.c b/pc/i8253.c index a4090f61c31288f3799dff1fbf40d25842994db8..c24fd9f3ffd64abf7cce76ecc5eb2e256488201d 100644 --- a/pc/i8253.c +++ b/pc/i8253.c @@ -322,3 +322,18 @@ microdelay(int microsecs) microsecs = 1; aamloop(microsecs); } + +/* + * performance measurement ticks. must be low overhead. + * doesn't have to count over a second. + */ +ulong +perfticks(void) +{ + uvlong x; + + if(!m->havetsc) + return m->ticks; + rdtsc(&x); + return x; +} diff --git a/pc/main.c b/pc/main.c index 0ab5399efdbbbb12f5e63a8067a63b603e061b18..1d9642965a83f8d167af5c401c412163c818fd73 100644 --- a/pc/main.c +++ b/pc/main.c @@ -104,11 +104,6 @@ main(void) initseg(); links(); conf.monitor = 1; -{int x; uvlong start, end; -rdtsc(&start); -for(x = 0; x < 10000; x++) rdtsc(&end); -print("%lld\n", end-start); -} chandevreset(); i8253link(); pageinit(); diff --git a/pc/trap.c b/pc/trap.c index aa586d8e9b980fa657d7307e3fdf4fbc30b065c4..5fde0cd9308d36ec1d74be4f33609eef932b6dd0 100644 --- a/pc/trap.c +++ b/pc/trap.c @@ -249,19 +249,24 @@ static char* excname[32] = { }; /* - * keep histogram of interrupt service times (tops off at 1/100 second) + * keep histogram of interrupt service times */ void -intrtime(Mach *m, int vno) +intrtime(Mach*, int vno) { - uvlong now; ulong diff; + ulong x = perfticks(); + + diff = x - m->perf.intrts; + m->perf.intrts = x; + + m->perf.inintr += diff; + if(up == nil && m->perf.inidle > diff) + m->perf.inidle -= diff; - rdtsc(&now); - diff = now - m->intrts; diff /= m->cpumhz; - if(diff >= 1000) - diff = 999; + if(diff >= Ntimevec) + diff = Ntimevec-1; intrtimes[vno][diff]++; } @@ -280,8 +285,7 @@ trap(Ureg* ureg) Vctl *ctl, *v; Mach *mach; - if(m->havetsc) - rdtsc(&m->intrts); + m->perf.intrts = perfticks(); user = 0; if((ureg->cs & 0xFFFF) == UESEL){ user = 1; @@ -304,8 +308,6 @@ trap(Ureg* ureg) } if(ctl->eoi) ctl->eoi(vno); - if(ctl->isintr && m->havetsc) - intrtime(m, vno); /* * preemptive scheduling. to limit stack depth, @@ -319,11 +321,14 @@ trap(Ureg* ureg) if(up->preempted == 0) if(!active.exiting){ up->preempted = 1; + intrtime(m, vno); sched(); splhi(); up->preempted = 0; return; } + if(ctl->isintr) + intrtime(m, vno); } else if(vno <= nelem(excname) && user){ spllo(); diff --git a/port/devcons.c b/port/devcons.c index fa1015e70480ddc2b5d3f5e86c1315fa5767e03b..af26c2b4a2319c69d02d45786904f1c081489330 100644 --- a/port/devcons.c +++ b/port/devcons.c @@ -641,27 +641,6 @@ consclose(Chan *c) } } -/* - * calculate duty cycle for a processor (100-(%time in idlehands())) - */ -static int -dutycycle(Mach *mp) -{ - static ulong ticks; - uvlong hz; - int x; - - if(ticks == 0){ - fastticks(&hz); - ticks = hz/HZ; - } - x = ticks - mp->avginidle; - if(x < 0) - return 0; - x *= 100; - return x/ticks; -} - static long consread(Chan *c, void *buf, long n, vlong off) { @@ -778,7 +757,7 @@ consread(Chan *c, void *buf, long n, vlong off) return 0; case Qsysstat: - b = smalloc(conf.nmach*(NUMSIZE*9+1) + 1); /* +1 for NUL */ + b = smalloc(conf.nmach*(NUMSIZE*11+1) + 1); /* +1 for NUL */ bp = b; for(id = 0; id < 32; id++) { if(active.machs & (1<load, NUMSIZE); bp += NUMSIZE; - readnum(0, bp, NUMSIZE, dutycycle(mp), NUMSIZE); + readnum(0, bp, NUMSIZE, + (mp->perf.avg_inidle*100)/mp->perf.period, + NUMSIZE); + bp += NUMSIZE; + readnum(0, bp, NUMSIZE, + (mp->perf.avg_inintr*100)/mp->perf.period, + NUMSIZE); bp += NUMSIZE; *bp++ = '\n'; } diff --git a/port/portdat.h b/port/portdat.h index 0b2bf7e4e0bcc793088be8e318f574f0f20b3bae..558fd6662273d284ab40e5622457842ba4fd03ca 100644 --- a/port/portdat.h +++ b/port/portdat.h @@ -24,6 +24,7 @@ typedef struct Mhead Mhead; typedef struct Note Note; typedef struct Page Page; typedef struct Palloc Palloc; +typedef struct Perf Perf; typedef struct Pgrps Pgrps; typedef struct PhysUart PhysUart; typedef struct Pgrp Pgrp; @@ -861,6 +862,20 @@ struct Edfinterface { void (*edfdeadline)(Proc *p); }; +/* + * performance timers, all units in perfticks + */ +struct Perf +{ + ulong intrts; /* time of last interrupt */ + ulong inintr; /* time since last clock tick in interrupt handlers */ + ulong avg_inintr; /* avg time per clock tick in interrupt handlers */ + ulong inidle; /* time since last clock tick in idle loop */ + ulong avg_inidle; /* avg time per clock tick in idle loop */ + ulong last; /* value of perfticks() at last clock tick */ + ulong period; /* perfticks() per clock tick */ +}; + /* queue state bits, Qmsg, Qcoalesce, and Qkick can be set in qopen */ enum { diff --git a/port/portfns.h b/port/portfns.h index bd887814c5fe91ba35973db73eda255137c58186..756640288bc0e524c203c0ec04af419aba7a44cd 100644 --- a/port/portfns.h +++ b/port/portfns.h @@ -202,6 +202,7 @@ void pageinit(void); void pagersummary(void); void panic(char*, ...); Cmdbuf* parsecmd(char *a, int n); +ulong perfticks(void); void pexit(char*, int); void printinit(void); int procindex(ulong); diff --git a/port/proc.c b/port/proc.c index ee1eb1cc140d52afe5ec0c91e2fb5086027c261b..81cd1c86b40bd1258cd810a8bd12edef8ff8a829 100644 --- a/port/proc.c +++ b/port/proc.c @@ -211,9 +211,9 @@ runproc(void) Schedq *rq, *xrq; Proc *p, *l; ulong rt; - uvlong start; + ulong start, now; - start = 0; + start = perfticks(); if ((p = edf->edfrunproc()) != nil) return p; @@ -265,9 +265,12 @@ loop: } } } - if(start == 0) - start = fastticks(nil); + + /* remember how much time we're here */ idlehands(); + now = perfticks(); + m->perf.inidle += now-start; + start = now; } found: @@ -306,8 +309,6 @@ found: p->movetime = MACHP(0)->ticks + HZ/10; p->mp = MACHP(m->machno); - if(start) - m->inidle += fastticks(nil)-start; return p; } @@ -1235,7 +1236,7 @@ void accounttime(void) { Proc *p; - ulong n; + ulong n, per; static ulong nrun; p = m->proc; @@ -1244,6 +1245,20 @@ accounttime(void) p->time[p->insyscall]++; } + /* calculate decaying duty cycles */ + n = perfticks(); + per = n - m->perf.last; + m->perf.last = n; + if(per == 0) + per = 1; + m->perf.period = (m->perf.period*(HZ-1)+per)/HZ; + + m->perf.avg_inidle = (m->perf.avg_inidle*(HZ-1)+m->perf.inidle)/HZ; + m->perf.inidle = 0; + + m->perf.avg_inintr = (m->perf.avg_inintr*(HZ-1)+m->perf.inintr)/HZ; + m->perf.inintr = 0; + /* only one processor gets to compute system load averages */ if(m->machno != 0) return; @@ -1253,10 +1268,6 @@ accounttime(void) nrun = 0; n = (nrdy+n)*1000; m->load = (m->load*19+n)/20; - - /* calculate decaying duty cycle average */ - m->avginidle = (m->avginidle*(HZ-1)+m->inidle)/HZ; - m->inidle = 0; } static void