123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- #include "u.h"
- #include "../port/lib.h"
- #include "mem.h"
- #include "dat.h"
- #include "fns.h"
- #include "../port/error.h"
- #define LRES 3 /* log of PC resolution */
- #define SZ 4 /* sizeof of count cell; well known as 4 */
- struct
- {
- int minpc;
- int maxpc;
- int nbuf;
- int time;
- ulong *buf;
- }kprof;
- enum{
- Kprofdirqid,
- Kprofdataqid,
- Kprofctlqid,
- };
- Dirtab kproftab[]={
- ".", {Kprofdirqid, 0, QTDIR}, 0, DMDIR|0550,
- "kpdata", {Kprofdataqid}, 0, 0600,
- "kpctl", {Kprofctlqid}, 0, 0600,
- };
- static void
- _kproftimer(ulong pc)
- {
- extern void spldone(void);
- if(kprof.time == 0)
- return;
- /*
- * if the pc is coming out of spllo or splx,
- * use the pc saved when we went splhi.
- */
- if(pc>=(ulong)spllo && pc<=(ulong)spldone)
- pc = m->splpc;
- kprof.buf[0] += TK2MS(1);
- if(kprof.minpc<=pc && pc<kprof.maxpc){
- pc -= kprof.minpc;
- pc >>= LRES;
- kprof.buf[pc] += TK2MS(1);
- }else
- kprof.buf[1] += TK2MS(1);
- }
- static void
- kprofinit(void)
- {
- if(SZ != sizeof kprof.buf[0])
- panic("kprof size");
- kproftimer = _kproftimer;
- }
- static Chan*
- kprofattach(char *spec)
- {
- ulong n;
- /* allocate when first used */
- kprof.minpc = KTZERO;
- kprof.maxpc = (ulong)etext;
- kprof.nbuf = (kprof.maxpc-kprof.minpc) >> LRES;
- n = kprof.nbuf*SZ;
- if(kprof.buf == 0) {
- kprof.buf = xalloc(n);
- if(kprof.buf == 0)
- error(Enomem);
- }
- kproftab[1].length = n;
- return devattach('K', spec);
- }
- static Walkqid*
- kprofwalk(Chan *c, Chan *nc, char **name, int nname)
- {
- return devwalk(c, nc, name, nname, kproftab, nelem(kproftab), devgen);
- }
- static int
- kprofstat(Chan *c, uchar *db, int n)
- {
- return devstat(c, db, n, kproftab, nelem(kproftab), devgen);
- }
- static Chan*
- kprofopen(Chan *c, int omode)
- {
- if(c->qid.type == QTDIR){
- if(omode != OREAD)
- error(Eperm);
- }
- c->mode = openmode(omode);
- c->flag |= COPEN;
- c->offset = 0;
- return c;
- }
- static void
- kprofclose(Chan*)
- {
- }
- static long
- kprofread(Chan *c, void *va, long n, vlong off)
- {
- ulong end;
- ulong w, *bp;
- uchar *a, *ea;
- ulong offset = off;
- switch((int)c->qid.path){
- case Kprofdirqid:
- return devdirread(c, va, n, kproftab, nelem(kproftab), devgen);
- case Kprofdataqid:
- end = kprof.nbuf*SZ;
- if(offset & (SZ-1))
- error(Ebadarg);
- if(offset >= end){
- n = 0;
- break;
- }
- if(offset+n > end)
- n = end-offset;
- n &= ~(SZ-1);
- a = va;
- ea = a + n;
- bp = kprof.buf + offset/SZ;
- while(a < ea){
- w = *bp++;
- *a++ = w>>24;
- *a++ = w>>16;
- *a++ = w>>8;
- *a++ = w>>0;
- }
- break;
- default:
- n = 0;
- break;
- }
- return n;
- }
- static long
- kprofwrite(Chan *c, void *a, long n, vlong)
- {
- switch((int)(c->qid.path)){
- case Kprofctlqid:
- if(strncmp(a, "startclr", 8) == 0){
- memset((char *)kprof.buf, 0, kprof.nbuf*SZ);
- kprof.time = 1;
- }else if(strncmp(a, "start", 5) == 0)
- kprof.time = 1;
- else if(strncmp(a, "stop", 4) == 0)
- kprof.time = 0;
- break;
- default:
- error(Ebadusefd);
- }
- return n;
- }
- Dev kprofdevtab = {
- 'K',
- "kprof",
- devreset,
- kprofinit,
- devshutdown,
- kprofattach,
- kprofwalk,
- kprofstat,
- kprofopen,
- devcreate,
- kprofclose,
- kprofread,
- devbread,
- kprofwrite,
- devbwrite,
- devremove,
- devwstat,
- };
|