1*9ef1f84bSDavid du Colombier #include "u.h"
2*9ef1f84bSDavid du Colombier #include "../port/lib.h"
3*9ef1f84bSDavid du Colombier #include "mem.h"
4*9ef1f84bSDavid du Colombier #include "dat.h"
5*9ef1f84bSDavid du Colombier #include "fns.h"
6*9ef1f84bSDavid du Colombier #include "../port/error.h"
7*9ef1f84bSDavid du Colombier
8*9ef1f84bSDavid du Colombier
9*9ef1f84bSDavid du Colombier #define LRES 3 /* log of PC resolution */
10*9ef1f84bSDavid du Colombier #define SZ 4 /* sizeof of count cell; well known as 4 */
11*9ef1f84bSDavid du Colombier
12*9ef1f84bSDavid du Colombier struct
13*9ef1f84bSDavid du Colombier {
14*9ef1f84bSDavid du Colombier uintptr minpc;
15*9ef1f84bSDavid du Colombier uintptr maxpc;
16*9ef1f84bSDavid du Colombier int nbuf;
17*9ef1f84bSDavid du Colombier int time;
18*9ef1f84bSDavid du Colombier ulong *buf;
19*9ef1f84bSDavid du Colombier }kprof;
20*9ef1f84bSDavid du Colombier
21*9ef1f84bSDavid du Colombier enum{
22*9ef1f84bSDavid du Colombier Kprofdirqid,
23*9ef1f84bSDavid du Colombier Kprofdataqid,
24*9ef1f84bSDavid du Colombier Kprofctlqid,
25*9ef1f84bSDavid du Colombier };
26*9ef1f84bSDavid du Colombier Dirtab kproftab[]={
27*9ef1f84bSDavid du Colombier ".", {Kprofdirqid, 0, QTDIR},0, DMDIR|0550,
28*9ef1f84bSDavid du Colombier "kpdata", {Kprofdataqid}, 0, 0600,
29*9ef1f84bSDavid du Colombier "kpctl", {Kprofctlqid}, 0, 0600,
30*9ef1f84bSDavid du Colombier };
31*9ef1f84bSDavid du Colombier
32*9ef1f84bSDavid du Colombier static void
_kproftimer(uintptr pc)33*9ef1f84bSDavid du Colombier _kproftimer(uintptr pc)
34*9ef1f84bSDavid du Colombier {
35*9ef1f84bSDavid du Colombier if(kprof.time == 0)
36*9ef1f84bSDavid du Colombier return;
37*9ef1f84bSDavid du Colombier /*
38*9ef1f84bSDavid du Colombier * if the pc is coming out of spllo or splx,
39*9ef1f84bSDavid du Colombier * use the pc saved when we went splhi.
40*9ef1f84bSDavid du Colombier */
41*9ef1f84bSDavid du Colombier if(pc>=PTR2UINT(spllo) && pc<=PTR2UINT(spldone))
42*9ef1f84bSDavid du Colombier pc = m->splpc;
43*9ef1f84bSDavid du Colombier
44*9ef1f84bSDavid du Colombier kprof.buf[0] += TK2MS(1);
45*9ef1f84bSDavid du Colombier if(kprof.minpc<=pc && pc<kprof.maxpc){
46*9ef1f84bSDavid du Colombier pc -= kprof.minpc;
47*9ef1f84bSDavid du Colombier pc >>= LRES;
48*9ef1f84bSDavid du Colombier kprof.buf[pc] += TK2MS(1);
49*9ef1f84bSDavid du Colombier }else
50*9ef1f84bSDavid du Colombier kprof.buf[1] += TK2MS(1);
51*9ef1f84bSDavid du Colombier }
52*9ef1f84bSDavid du Colombier
53*9ef1f84bSDavid du Colombier static void
kprofinit(void)54*9ef1f84bSDavid du Colombier kprofinit(void)
55*9ef1f84bSDavid du Colombier {
56*9ef1f84bSDavid du Colombier if(SZ != sizeof kprof.buf[0])
57*9ef1f84bSDavid du Colombier panic("kprof size");
58*9ef1f84bSDavid du Colombier kproftimer = _kproftimer;
59*9ef1f84bSDavid du Colombier }
60*9ef1f84bSDavid du Colombier
61*9ef1f84bSDavid du Colombier static Chan*
kprofattach(char * spec)62*9ef1f84bSDavid du Colombier kprofattach(char *spec)
63*9ef1f84bSDavid du Colombier {
64*9ef1f84bSDavid du Colombier ulong n;
65*9ef1f84bSDavid du Colombier
66*9ef1f84bSDavid du Colombier /* allocate when first used */
67*9ef1f84bSDavid du Colombier kprof.minpc = KTZERO;
68*9ef1f84bSDavid du Colombier kprof.maxpc = PTR2UINT(etext);
69*9ef1f84bSDavid du Colombier kprof.nbuf = (kprof.maxpc-kprof.minpc) >> LRES;
70*9ef1f84bSDavid du Colombier n = kprof.nbuf*SZ;
71*9ef1f84bSDavid du Colombier if(kprof.buf == 0) {
72*9ef1f84bSDavid du Colombier kprof.buf = malloc(n);
73*9ef1f84bSDavid du Colombier if(kprof.buf == 0)
74*9ef1f84bSDavid du Colombier error(Enomem);
75*9ef1f84bSDavid du Colombier }
76*9ef1f84bSDavid du Colombier kproftab[1].length = n;
77*9ef1f84bSDavid du Colombier return devattach('K', spec);
78*9ef1f84bSDavid du Colombier }
79*9ef1f84bSDavid du Colombier
80*9ef1f84bSDavid du Colombier static Walkqid*
kprofwalk(Chan * c,Chan * nc,char ** name,int nname)81*9ef1f84bSDavid du Colombier kprofwalk(Chan *c, Chan *nc, char **name, int nname)
82*9ef1f84bSDavid du Colombier {
83*9ef1f84bSDavid du Colombier return devwalk(c, nc, name, nname, kproftab, nelem(kproftab), devgen);
84*9ef1f84bSDavid du Colombier }
85*9ef1f84bSDavid du Colombier
86*9ef1f84bSDavid du Colombier static long
kprofstat(Chan * c,uchar * db,long n)87*9ef1f84bSDavid du Colombier kprofstat(Chan *c, uchar *db, long n)
88*9ef1f84bSDavid du Colombier {
89*9ef1f84bSDavid du Colombier return devstat(c, db, n, kproftab, nelem(kproftab), devgen);
90*9ef1f84bSDavid du Colombier }
91*9ef1f84bSDavid du Colombier
92*9ef1f84bSDavid du Colombier static Chan*
kprofopen(Chan * c,int omode)93*9ef1f84bSDavid du Colombier kprofopen(Chan *c, int omode)
94*9ef1f84bSDavid du Colombier {
95*9ef1f84bSDavid du Colombier if(c->qid.type & QTDIR){
96*9ef1f84bSDavid du Colombier if(omode != OREAD)
97*9ef1f84bSDavid du Colombier error(Eperm);
98*9ef1f84bSDavid du Colombier }
99*9ef1f84bSDavid du Colombier c->mode = openmode(omode);
100*9ef1f84bSDavid du Colombier c->flag |= COPEN;
101*9ef1f84bSDavid du Colombier c->offset = 0;
102*9ef1f84bSDavid du Colombier return c;
103*9ef1f84bSDavid du Colombier }
104*9ef1f84bSDavid du Colombier
105*9ef1f84bSDavid du Colombier static void
kprofclose(Chan *)106*9ef1f84bSDavid du Colombier kprofclose(Chan*)
107*9ef1f84bSDavid du Colombier {
108*9ef1f84bSDavid du Colombier }
109*9ef1f84bSDavid du Colombier
110*9ef1f84bSDavid du Colombier static long
kprofread(Chan * c,void * va,long n,vlong off)111*9ef1f84bSDavid du Colombier kprofread(Chan *c, void *va, long n, vlong off)
112*9ef1f84bSDavid du Colombier {
113*9ef1f84bSDavid du Colombier ulong end;
114*9ef1f84bSDavid du Colombier ulong w, *bp;
115*9ef1f84bSDavid du Colombier uchar *a, *ea;
116*9ef1f84bSDavid du Colombier ulong offset = off;
117*9ef1f84bSDavid du Colombier
118*9ef1f84bSDavid du Colombier switch((int)c->qid.path){
119*9ef1f84bSDavid du Colombier case Kprofdirqid:
120*9ef1f84bSDavid du Colombier return devdirread(c, va, n, kproftab, nelem(kproftab), devgen);
121*9ef1f84bSDavid du Colombier
122*9ef1f84bSDavid du Colombier case Kprofdataqid:
123*9ef1f84bSDavid du Colombier end = kprof.nbuf*SZ;
124*9ef1f84bSDavid du Colombier if(offset & (SZ-1))
125*9ef1f84bSDavid du Colombier error(Ebadarg);
126*9ef1f84bSDavid du Colombier if(offset >= end){
127*9ef1f84bSDavid du Colombier n = 0;
128*9ef1f84bSDavid du Colombier break;
129*9ef1f84bSDavid du Colombier }
130*9ef1f84bSDavid du Colombier if(offset+n > end)
131*9ef1f84bSDavid du Colombier n = end-offset;
132*9ef1f84bSDavid du Colombier n &= ~(SZ-1);
133*9ef1f84bSDavid du Colombier a = va;
134*9ef1f84bSDavid du Colombier ea = a + n;
135*9ef1f84bSDavid du Colombier bp = kprof.buf + offset/SZ;
136*9ef1f84bSDavid du Colombier while(a < ea){
137*9ef1f84bSDavid du Colombier w = *bp++;
138*9ef1f84bSDavid du Colombier *a++ = w>>24;
139*9ef1f84bSDavid du Colombier *a++ = w>>16;
140*9ef1f84bSDavid du Colombier *a++ = w>>8;
141*9ef1f84bSDavid du Colombier *a++ = w>>0;
142*9ef1f84bSDavid du Colombier }
143*9ef1f84bSDavid du Colombier break;
144*9ef1f84bSDavid du Colombier
145*9ef1f84bSDavid du Colombier default:
146*9ef1f84bSDavid du Colombier n = 0;
147*9ef1f84bSDavid du Colombier break;
148*9ef1f84bSDavid du Colombier }
149*9ef1f84bSDavid du Colombier return n;
150*9ef1f84bSDavid du Colombier }
151*9ef1f84bSDavid du Colombier
152*9ef1f84bSDavid du Colombier static long
kprofwrite(Chan * c,void * a,long n,vlong)153*9ef1f84bSDavid du Colombier kprofwrite(Chan *c, void *a, long n, vlong)
154*9ef1f84bSDavid du Colombier {
155*9ef1f84bSDavid du Colombier switch((int)(c->qid.path)){
156*9ef1f84bSDavid du Colombier case Kprofctlqid:
157*9ef1f84bSDavid du Colombier if(strncmp(a, "startclr", 8) == 0){
158*9ef1f84bSDavid du Colombier memset((char *)kprof.buf, 0, kprof.nbuf*SZ);
159*9ef1f84bSDavid du Colombier kprof.time = 1;
160*9ef1f84bSDavid du Colombier }else if(strncmp(a, "start", 5) == 0)
161*9ef1f84bSDavid du Colombier kprof.time = 1;
162*9ef1f84bSDavid du Colombier else if(strncmp(a, "stop", 4) == 0)
163*9ef1f84bSDavid du Colombier kprof.time = 0;
164*9ef1f84bSDavid du Colombier break;
165*9ef1f84bSDavid du Colombier default:
166*9ef1f84bSDavid du Colombier error(Ebadusefd);
167*9ef1f84bSDavid du Colombier }
168*9ef1f84bSDavid du Colombier return n;
169*9ef1f84bSDavid du Colombier }
170*9ef1f84bSDavid du Colombier
171*9ef1f84bSDavid du Colombier Dev kprofdevtab = {
172*9ef1f84bSDavid du Colombier 'K',
173*9ef1f84bSDavid du Colombier "kprof",
174*9ef1f84bSDavid du Colombier
175*9ef1f84bSDavid du Colombier devreset,
176*9ef1f84bSDavid du Colombier kprofinit,
177*9ef1f84bSDavid du Colombier devshutdown,
178*9ef1f84bSDavid du Colombier kprofattach,
179*9ef1f84bSDavid du Colombier kprofwalk,
180*9ef1f84bSDavid du Colombier kprofstat,
181*9ef1f84bSDavid du Colombier kprofopen,
182*9ef1f84bSDavid du Colombier devcreate,
183*9ef1f84bSDavid du Colombier kprofclose,
184*9ef1f84bSDavid du Colombier kprofread,
185*9ef1f84bSDavid du Colombier devbread,
186*9ef1f84bSDavid du Colombier kprofwrite,
187*9ef1f84bSDavid du Colombier devbwrite,
188*9ef1f84bSDavid du Colombier devremove,
189*9ef1f84bSDavid du Colombier devwstat,
190*9ef1f84bSDavid du Colombier };
191