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 #ifndef LRES 9 #define LRES 3 /* log of PC resolution */ 10 #endif 11 12 #define SZ 4 /* sizeof of count cell; well known as 4 */ 13 14 enum { 15 SpecialTotalTicks, 16 SpecialOutsideTicks, 17 SpecialMicroSecondsPerTick, 18 SpecialSamples, 19 SpecialSampleSize, 20 SpecialSampleLogBucketSize, 21 SpecialMax 22 }; 23 24 struct 25 { 26 int minpc; 27 int maxpc; 28 int nbuf; 29 int time; 30 ulong *buf; 31 }kprof; 32 33 enum{ 34 Qdir, 35 Qdata, 36 Qctl, 37 Kprofmaxqid, 38 }; 39 40 Dirtab kproftab[]={ 41 ".", {Qdir, 0, QTDIR}, 0, 0500, 42 "kpdata", {Qdata}, 0, 0600, 43 "kpctl", {Qctl}, 0, 0600, 44 }; 45 46 void kproftimer(ulong); 47 void (*kproftick)(ulong); 48 49 static void 50 kprofinit(void) 51 { 52 if(SZ != sizeof kprof.buf[0]) 53 panic("kprof size"); 54 } 55 56 static void 57 kprofbufinit(void) 58 { 59 kprof.buf[SpecialMicroSecondsPerTick] = archkprofmicrosecondspertick(); 60 kprof.buf[SpecialSamples] = kprof.nbuf; 61 kprof.buf[SpecialSampleSize] = SZ; 62 kprof.buf[SpecialSampleLogBucketSize] = LRES; 63 } 64 65 static Chan * 66 kprofattach(char *spec) 67 { 68 ulong n; 69 70 /* allocate when first used */ 71 kproftick = kproftimer; 72 kprof.minpc = KTZERO; 73 kprof.maxpc = (ulong)etext; 74 kprof.nbuf = (kprof.maxpc-kprof.minpc) >> LRES; 75 n = kprof.nbuf*SZ; 76 if(kprof.buf == 0) { 77 kprof.buf = xalloc(n); 78 if(kprof.buf == 0) 79 error(Enomem); 80 } 81 kproftab[0].length = n; 82 kprofbufinit(); 83 return devattach('K', spec); 84 } 85 86 static Walkqid* 87 kprofwalk(Chan *c, Chan *nc, char **name, int nname) 88 { 89 return devwalk(c, nc, name, nname, kproftab, nelem(kproftab), devgen); 90 } 91 92 static int 93 kprofstat(Chan *c, uchar *db, int n) 94 { 95 return devstat(c, db, n, kproftab, nelem(kproftab), devgen); 96 } 97 98 static Chan * 99 kprofopen(Chan *c, int omode) 100 { 101 if(c->qid.type & QTDIR){ 102 if(omode != OREAD) 103 error(Eperm); 104 } 105 c->mode = openmode(omode); 106 c->flag |= COPEN; 107 c->offset = 0; 108 return c; 109 } 110 111 void 112 kprofclose(Chan*) 113 { 114 } 115 116 static long 117 kprofread(Chan *c, void *va, long n, vlong offset) 118 { 119 ulong tabend; 120 ulong w, *bp; 121 uchar *a, *ea; 122 123 switch((ulong)c->qid.path){ 124 case Qdir: 125 return devdirread(c, va, n, kproftab, nelem(kproftab), devgen); 126 127 case Qdata: 128 tabend = kprof.nbuf*SZ; 129 if(offset & (SZ-1)) 130 error(Ebadarg); 131 if(offset >= tabend){ 132 n = 0; 133 break; 134 } 135 if(offset+n > tabend) 136 n = tabend-offset; 137 n &= ~(SZ-1); 138 a = va; 139 ea = a + n; 140 bp = kprof.buf + offset/SZ; 141 while(a < ea){ 142 w = *bp++; 143 *a++ = w>>24; 144 *a++ = w>>16; 145 *a++ = w>>8; 146 *a++ = w>>0; 147 } 148 break; 149 150 default: 151 n = 0; 152 break; 153 } 154 return n; 155 } 156 157 static long 158 kprofwrite(Chan *c, void *vp, long n, vlong offset) 159 { 160 char *a; 161 USED(offset); 162 163 a = vp; 164 switch((ulong)c->qid.path){ 165 case Qctl: 166 if(strncmp(a, "startclr", 8) == 0){ 167 memset((char *)kprof.buf, 0, kprof.nbuf*SZ); 168 kprofbufinit(); 169 archkprofenable(1); 170 kprof.time = 1; 171 }else if(strncmp(a, "start", 5) == 0) { 172 archkprofenable(1); 173 kprof.time = 1; 174 } 175 else if(strncmp(a, "stop", 4) == 0) { 176 archkprofenable(0); 177 kprof.time = 0; 178 } 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[SpecialTotalTicks]++; 203 if(kprof.minpc + (SpecialMax << LRES) <= pc && pc < kprof.maxpc){ 204 pc -= kprof.minpc; 205 pc >>= LRES; 206 kprof.buf[pc]++; 207 }else 208 kprof.buf[SpecialOutsideTicks]++; 209 } 210 211 Dev kprofdevtab = { 212 'K', 213 "kprof", 214 215 devreset, 216 kprofinit, 217 devshutdown, 218 kprofattach, 219 kprofwalk, 220 kprofstat, 221 kprofopen, 222 devcreate, 223 kprofclose, 224 kprofread, 225 devbread, 226 kprofwrite, 227 devbwrite, 228 devremove, 229 devwstat, 230 }; 231