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