M alphapc/clock.c => alphapc/clock.c +10 -0
@@ 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)
{
M alphapc/dat.h => alphapc/dat.h +1 -3
@@ 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; /* ... */
M alphapc/trap.c => alphapc/trap.c +0 -1
@@ 291,7 291,6 @@ trap(Ureg *ur)
char buf[ERRMAX];
int user, x;
- m->intrts = fastticks(nil);
user = ur->status&UMODE;
if(user){
M bitsy/clock.c => bitsy/clock.c +10 -0
@@ 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;
+}
M bitsy/dat.h => bitsy/dat.h +1 -3
@@ 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 */
M mtx/clock.c => mtx/clock.c +10 -0
@@ 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;
+}
M mtx/dat.h => mtx/dat.h +1 -3
@@ 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; /* ... */
M mtx/trap.c => mtx/trap.c +0 -1
@@ 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)
M pc/clock.c => pc/clock.c +15 -0
@@ 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;
+}
M pc/dat.h => pc/dat.h +1 -3
@@ 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;
M pc/i8253.c => pc/i8253.c +15 -0
@@ 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;
+}
M pc/main.c => pc/main.c +0 -5
@@ 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();
M pc/trap.c => pc/trap.c +16 -11
@@ 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();
M port/devcons.c => port/devcons.c +8 -23
@@ 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<<id)) {
@@ 799,7 778,13 @@ consread(Chan *c, void *buf, long n, vlong off)
bp += NUMSIZE;
readnum(0, bp, NUMSIZE, mp->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';
}
M port/portdat.h => port/portdat.h +15 -0
@@ 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
{
M port/portfns.h => port/portfns.h +1 -0
@@ 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);
M port/proc.c => port/proc.c +22 -11
@@ 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