13e12c5d1SDavid du Colombier #include "u.h"
23e12c5d1SDavid du Colombier #include "../port/lib.h"
33e12c5d1SDavid du Colombier #include "mem.h"
43e12c5d1SDavid du Colombier #include "dat.h"
53e12c5d1SDavid du Colombier #include "fns.h"
63e12c5d1SDavid du Colombier #include "../port/error.h"
73e12c5d1SDavid du Colombier
83e12c5d1SDavid du Colombier
93e12c5d1SDavid du Colombier #define LRES 3 /* log of PC resolution */
103e12c5d1SDavid du Colombier #define SZ 4 /* sizeof of count cell; well known as 4 */
113e12c5d1SDavid du Colombier
123e12c5d1SDavid du Colombier struct
133e12c5d1SDavid du Colombier {
143e12c5d1SDavid du Colombier int minpc;
153e12c5d1SDavid du Colombier int maxpc;
163e12c5d1SDavid du Colombier int nbuf;
173e12c5d1SDavid du Colombier int time;
183e12c5d1SDavid du Colombier ulong *buf;
193e12c5d1SDavid du Colombier }kprof;
203e12c5d1SDavid du Colombier
213e12c5d1SDavid du Colombier enum{
223e12c5d1SDavid du Colombier Kprofdirqid,
233e12c5d1SDavid du Colombier Kprofdataqid,
243e12c5d1SDavid du Colombier Kprofctlqid,
253e12c5d1SDavid du Colombier };
267dd7cddfSDavid du Colombier Dirtab kproftab[]={
27*9a747e4fSDavid du Colombier ".", {Kprofdirqid, 0, QTDIR}, 0, DMDIR|0550,
283e12c5d1SDavid du Colombier "kpdata", {Kprofdataqid}, 0, 0600,
293e12c5d1SDavid du Colombier "kpctl", {Kprofctlqid}, 0, 0600,
303e12c5d1SDavid du Colombier };
313e12c5d1SDavid du Colombier
327dd7cddfSDavid du Colombier static void
_kproftimer(ulong pc)337dd7cddfSDavid du Colombier _kproftimer(ulong pc)
343e12c5d1SDavid du Colombier {
357dd7cddfSDavid du Colombier extern void spldone(void);
367dd7cddfSDavid du Colombier
377dd7cddfSDavid du Colombier if(kprof.time == 0)
387dd7cddfSDavid du Colombier return;
397dd7cddfSDavid du Colombier /*
407dd7cddfSDavid du Colombier * if the pc is coming out of spllo or splx,
417dd7cddfSDavid du Colombier * use the pc saved when we went splhi.
427dd7cddfSDavid du Colombier */
437dd7cddfSDavid du Colombier if(pc>=(ulong)spllo && pc<=(ulong)spldone)
447dd7cddfSDavid du Colombier pc = m->splpc;
45*9a747e4fSDavid du Colombier
467dd7cddfSDavid du Colombier kprof.buf[0] += TK2MS(1);
477dd7cddfSDavid du Colombier if(kprof.minpc<=pc && pc<kprof.maxpc){
487dd7cddfSDavid du Colombier pc -= kprof.minpc;
497dd7cddfSDavid du Colombier pc >>= LRES;
507dd7cddfSDavid du Colombier kprof.buf[pc] += TK2MS(1);
517dd7cddfSDavid du Colombier }else
527dd7cddfSDavid du Colombier kprof.buf[1] += TK2MS(1);
533e12c5d1SDavid du Colombier }
543e12c5d1SDavid du Colombier
557dd7cddfSDavid du Colombier static void
kprofinit(void)563e12c5d1SDavid du Colombier kprofinit(void)
573e12c5d1SDavid du Colombier {
583e12c5d1SDavid du Colombier if(SZ != sizeof kprof.buf[0])
593e12c5d1SDavid du Colombier panic("kprof size");
607dd7cddfSDavid du Colombier kproftimer = _kproftimer;
613e12c5d1SDavid du Colombier }
623e12c5d1SDavid du Colombier
637dd7cddfSDavid du Colombier static Chan*
kprofattach(char * spec)643e12c5d1SDavid du Colombier kprofattach(char *spec)
653e12c5d1SDavid du Colombier {
663e12c5d1SDavid du Colombier ulong n;
673e12c5d1SDavid du Colombier
683e12c5d1SDavid du Colombier /* allocate when first used */
693e12c5d1SDavid du Colombier kprof.minpc = KTZERO;
703e12c5d1SDavid du Colombier kprof.maxpc = (ulong)etext;
713e12c5d1SDavid du Colombier kprof.nbuf = (kprof.maxpc-kprof.minpc) >> LRES;
723e12c5d1SDavid du Colombier n = kprof.nbuf*SZ;
733e12c5d1SDavid du Colombier if(kprof.buf == 0) {
743e12c5d1SDavid du Colombier kprof.buf = xalloc(n);
753e12c5d1SDavid du Colombier if(kprof.buf == 0)
763e12c5d1SDavid du Colombier error(Enomem);
773e12c5d1SDavid du Colombier }
78*9a747e4fSDavid du Colombier kproftab[1].length = n;
79*9a747e4fSDavid du Colombier return devattach('K', spec);
80*9a747e4fSDavid du Colombier }
81*9a747e4fSDavid du Colombier
82*9a747e4fSDavid du Colombier static Walkqid*
kprofwalk(Chan * c,Chan * nc,char ** name,int nname)83*9a747e4fSDavid du Colombier kprofwalk(Chan *c, Chan *nc, char **name, int nname)
84*9a747e4fSDavid du Colombier {
85*9a747e4fSDavid du Colombier return devwalk(c, nc, name, nname, kproftab, nelem(kproftab), devgen);
863e12c5d1SDavid du Colombier }
873e12c5d1SDavid du Colombier
887dd7cddfSDavid du Colombier static int
kprofstat(Chan * c,uchar * db,int n)89*9a747e4fSDavid du Colombier kprofstat(Chan *c, uchar *db, int n)
903e12c5d1SDavid du Colombier {
91*9a747e4fSDavid du Colombier return devstat(c, db, n, kproftab, nelem(kproftab), devgen);
923e12c5d1SDavid du Colombier }
933e12c5d1SDavid du Colombier
947dd7cddfSDavid du Colombier static Chan*
kprofopen(Chan * c,int omode)953e12c5d1SDavid du Colombier kprofopen(Chan *c, int omode)
963e12c5d1SDavid du Colombier {
97*9a747e4fSDavid du Colombier if(c->qid.type == QTDIR){
983e12c5d1SDavid du Colombier if(omode != OREAD)
993e12c5d1SDavid du Colombier error(Eperm);
1003e12c5d1SDavid du Colombier }
1013e12c5d1SDavid du Colombier c->mode = openmode(omode);
1023e12c5d1SDavid du Colombier c->flag |= COPEN;
1033e12c5d1SDavid du Colombier c->offset = 0;
1043e12c5d1SDavid du Colombier return c;
1053e12c5d1SDavid du Colombier }
1063e12c5d1SDavid du Colombier
1077dd7cddfSDavid du Colombier static void
kprofclose(Chan *)1087dd7cddfSDavid du Colombier kprofclose(Chan*)
1093e12c5d1SDavid du Colombier {
1103e12c5d1SDavid du Colombier }
1113e12c5d1SDavid du Colombier
1127dd7cddfSDavid du Colombier static long
kprofread(Chan * c,void * va,long n,vlong off)1137dd7cddfSDavid du Colombier kprofread(Chan *c, void *va, long n, vlong off)
1143e12c5d1SDavid du Colombier {
1157dd7cddfSDavid du Colombier ulong end;
1163e12c5d1SDavid du Colombier ulong w, *bp;
1173e12c5d1SDavid du Colombier uchar *a, *ea;
1187dd7cddfSDavid du Colombier ulong offset = off;
1193e12c5d1SDavid du Colombier
120*9a747e4fSDavid du Colombier switch((int)c->qid.path){
1213e12c5d1SDavid du Colombier case Kprofdirqid:
1227dd7cddfSDavid du Colombier return devdirread(c, va, n, kproftab, nelem(kproftab), devgen);
1233e12c5d1SDavid du Colombier
1243e12c5d1SDavid du Colombier case Kprofdataqid:
1257dd7cddfSDavid du Colombier end = kprof.nbuf*SZ;
1263e12c5d1SDavid du Colombier if(offset & (SZ-1))
1273e12c5d1SDavid du Colombier error(Ebadarg);
1287dd7cddfSDavid du Colombier if(offset >= end){
1293e12c5d1SDavid du Colombier n = 0;
1303e12c5d1SDavid du Colombier break;
1313e12c5d1SDavid du Colombier }
1327dd7cddfSDavid du Colombier if(offset+n > end)
1337dd7cddfSDavid du Colombier n = end-offset;
1343e12c5d1SDavid du Colombier n &= ~(SZ-1);
1353e12c5d1SDavid du Colombier a = va;
1363e12c5d1SDavid du Colombier ea = a + n;
1373e12c5d1SDavid du Colombier bp = kprof.buf + offset/SZ;
1383e12c5d1SDavid du Colombier while(a < ea){
1393e12c5d1SDavid du Colombier w = *bp++;
1403e12c5d1SDavid du Colombier *a++ = w>>24;
1413e12c5d1SDavid du Colombier *a++ = w>>16;
1423e12c5d1SDavid du Colombier *a++ = w>>8;
1433e12c5d1SDavid du Colombier *a++ = w>>0;
1443e12c5d1SDavid du Colombier }
1453e12c5d1SDavid du Colombier break;
1463e12c5d1SDavid du Colombier
1473e12c5d1SDavid du Colombier default:
1483e12c5d1SDavid du Colombier n = 0;
1493e12c5d1SDavid du Colombier break;
1503e12c5d1SDavid du Colombier }
1513e12c5d1SDavid du Colombier return n;
1523e12c5d1SDavid du Colombier }
1533e12c5d1SDavid du Colombier
1547dd7cddfSDavid du Colombier static long
kprofwrite(Chan * c,void * a,long n,vlong)1557dd7cddfSDavid du Colombier kprofwrite(Chan *c, void *a, long n, vlong)
1563e12c5d1SDavid du Colombier {
157*9a747e4fSDavid du Colombier switch((int)(c->qid.path)){
1583e12c5d1SDavid du Colombier case Kprofctlqid:
1593e12c5d1SDavid du Colombier if(strncmp(a, "startclr", 8) == 0){
1603e12c5d1SDavid du Colombier memset((char *)kprof.buf, 0, kprof.nbuf*SZ);
1613e12c5d1SDavid du Colombier kprof.time = 1;
1623e12c5d1SDavid du Colombier }else if(strncmp(a, "start", 5) == 0)
1633e12c5d1SDavid du Colombier kprof.time = 1;
1643e12c5d1SDavid du Colombier else if(strncmp(a, "stop", 4) == 0)
1653e12c5d1SDavid du Colombier kprof.time = 0;
1663e12c5d1SDavid du Colombier break;
1673e12c5d1SDavid du Colombier default:
1683e12c5d1SDavid du Colombier error(Ebadusefd);
1693e12c5d1SDavid du Colombier }
1703e12c5d1SDavid du Colombier return n;
1713e12c5d1SDavid du Colombier }
1723e12c5d1SDavid du Colombier
1737dd7cddfSDavid du Colombier Dev kprofdevtab = {
174*9a747e4fSDavid du Colombier 'K',
1757dd7cddfSDavid du Colombier "kprof",
1763e12c5d1SDavid du Colombier
1777dd7cddfSDavid du Colombier devreset,
1787dd7cddfSDavid du Colombier kprofinit,
179*9a747e4fSDavid du Colombier devshutdown,
1807dd7cddfSDavid du Colombier kprofattach,
1817dd7cddfSDavid du Colombier kprofwalk,
1827dd7cddfSDavid du Colombier kprofstat,
1837dd7cddfSDavid du Colombier kprofopen,
1847dd7cddfSDavid du Colombier devcreate,
1857dd7cddfSDavid du Colombier kprofclose,
1867dd7cddfSDavid du Colombier kprofread,
1877dd7cddfSDavid du Colombier devbread,
1887dd7cddfSDavid du Colombier kprofwrite,
1897dd7cddfSDavid du Colombier devbwrite,
1907dd7cddfSDavid du Colombier devremove,
1917dd7cddfSDavid du Colombier devwstat,
1927dd7cddfSDavid du Colombier };
193