1 #include <u.h> 2 #include <libc.h> 3 #include <libg.h> 4 5 #define Min(a, b) ((a) < (b) ? (a) : (b)) 6 int *vector; 7 int nvec; 8 int cmax = 1; 9 Rectangle scroll; 10 int height; 11 int lasttype = -1; 12 int type; 13 char *mon; 14 Point pbot, ptop; 15 int ys[4]; 16 17 char *getstr(int); 18 void reshape(Rectangle); 19 int getstat(void); 20 int inittype(int); 21 void ignore(void*, char*); 22 void mousepkt(int, char*); 23 int sysfield(int, int); 24 25 enum 26 { 27 Memory=0, 28 Ether, 29 Swap, 30 Contxt, /* Code relies on the order of these up to load - Dont move! */ 31 Intr, 32 Syscall, 33 Fault, 34 Tlbfault, 35 Tlbpurge, 36 Load, 37 Ntype 38 }; 39 40 void 41 main(int argc, char **argv) 42 { 43 int l, t, n, ms, scaled, i; 44 char buf[128]; 45 Point p1; 46 47 ARGBEGIN{ 48 case 'm': 49 type = Memory; 50 break; 51 case 'w': 52 type = Swap; 53 break; 54 case 'e': 55 type = Ether; 56 break; 57 case 'c': 58 type = Contxt; 59 break; 60 case 'i': 61 type = Intr; 62 break; 63 case 's': 64 type = Syscall; 65 break; 66 case 'f': 67 type = Fault; 68 break; 69 case 't': 70 type = Tlbfault; 71 break; 72 case 'p': 73 type = Tlbpurge; 74 break; 75 case 'l': 76 type = Load; 77 break; 78 default: 79 fprint(2, "usage: stats [-mwecisftpl]\n"); 80 exits("usage"); 81 }ARGEND 82 83 binit(0, 0, "stats"); 84 85 ms = open("/dev/mouse", OREAD); 86 if(ms < 0) { 87 perror("open mouse"); 88 exits("mouse"); 89 } 90 91 reshape(screen.r); 92 93 notify(ignore); 94 95 for(;;) { 96 if(vector[nvec-1] == cmax) { 97 cmax = 0; 98 for(i = 0; i < nvec-1; i++) 99 if(vector[i] > cmax) 100 cmax = vector[i]; 101 reshape(screen.r); 102 } 103 104 l = vector[0]; 105 memmove(vector+1, vector, sizeof(int) * (nvec-1)); 106 vector[0] = getstat(); 107 vector[0] = l+(vector[0]-l)/2; 108 109 if(vector[0] > cmax) { 110 cmax = vector[0]; 111 reshape(screen.r); 112 } 113 segment(&screen, ptop, pbot, 1, Zero); 114 scaled = (vector[0]*height)/cmax; 115 segment(&screen, pbot, sub(pbot, Pt(0, scaled)), 1, F); 116 for(i = 0; i < 4; i++) 117 point(&screen, Pt(ptop.x, ys[i]), 0xff, F); 118 p1 = scroll.min; 119 p1.x--; 120 bitblt(&screen, p1, &screen, scroll, S); 121 122 sprint(buf, "%d %s", cmax, mon); 123 string(&screen, scroll.min, font, buf, S); 124 bflush(); 125 do { 126 alarm(1000); 127 n = read(ms, buf, sizeof(buf)); 128 if(n >= 14) { 129 t = alarm(0); 130 if(t == 0) 131 t = 1000; 132 mousepkt(ms, buf); 133 alarm(t); 134 } 135 }while(n > 0); 136 } 137 } 138 139 void 140 mousepkt(int ms, char *buf) 141 { 142 if(buf[0] != 'm') 143 return; 144 if(buf[1] & 0x80) { /* Reshaped */ 145 reshape(bscreenrect(0)); 146 return; 147 } 148 if(buf[1] & 0x07) { /* Button */ 149 type++; 150 if(type == Ntype) 151 type = 0; 152 /* wait for button up */ 153 while(read(ms, buf, 14) == 14 && (buf[1] & 0x07)) 154 ; 155 } 156 } 157 158 void 159 reshape(Rectangle r) 160 { 161 int *newvector; 162 Point p1, p2; 163 int q, i, width, scaled; 164 165 if(cmax == 0) 166 cmax = 1; 167 168 screen.r = r; 169 scroll = inset(r, 4); 170 height = scroll.max.y - scroll.min.y; 171 width = scroll.max.x - scroll.min.x; 172 173 newvector = malloc(width*sizeof(int)); 174 memset(newvector, 0, width*sizeof(int)); 175 if(vector) { 176 memmove(newvector, vector, Min(width, nvec)*sizeof(int)); 177 free(vector); 178 } 179 nvec = width; 180 vector = newvector; 181 182 bitblt(&screen, screen.r.min, &screen, screen.r, Zero); 183 border(&screen, screen.r, 1, F); 184 185 p1 = scroll.min; 186 p2 = Pt(scroll.max.x, scroll.min.y); 187 q = height/4; 188 for(i = 0; i < 4; i++) { 189 segment(&screen, p1, p2, 0xff, F); 190 ys[i] = p1.y; 191 p1.y += q; 192 p2.y += q; 193 } 194 195 ptop.x = scroll.max.x-1; 196 pbot.x = ptop.x; 197 ptop.y = scroll.min.y; 198 pbot.y = scroll.max.y; 199 200 p1 = pbot; 201 for(i = 0; i < nvec; i++) { 202 scaled = (vector[i]*height)/cmax; 203 segment(&screen, p1, sub(p1, Pt(0, scaled)), 1, F); 204 p1.x -= 1; 205 } 206 } 207 208 int 209 getstat(void) 210 { 211 static int fd, nfd; 212 static int lastval; 213 int newval, val; 214 char *s; 215 216 if(type != lasttype) { 217 for(;;) { 218 close(fd); 219 fd = inittype(type); 220 if(fd >= 0) 221 break; 222 type++; 223 if(type == Ntype) 224 type = Memory; 225 } 226 lasttype = type; 227 lastval = 0; 228 } 229 230 switch(type) { 231 case Memory: 232 s = getstr(fd); 233 return atoi(s); 234 case Swap: 235 s = getstr(fd); 236 s = strchr(s, 'y'); 237 s++; 238 return atoi(s); 239 case Ether: 240 s = getstr(fd); 241 s = strchr(s, ':'); /* In */ 242 val = atoi(s+1); 243 s = strchr(s, ':'); /* Out */ 244 val += atoi(s+1); 245 if(lastval == 0) 246 lastval = val; 247 newval = val-lastval; 248 lastval = val; 249 return newval; 250 case Contxt: 251 case Intr: 252 case Syscall: 253 case Fault: 254 case Tlbfault: 255 case Tlbpurge: 256 val = sysfield(fd, type-Contxt+1); 257 if(lastval == 0) 258 lastval = val; 259 newval = val-lastval; 260 lastval = val; 261 return newval; 262 case Load: 263 return sysfield(fd, 7); 264 } 265 } 266 267 int 268 inittype(int type) 269 { 270 char *s; 271 int f; 272 273 f = -1; 274 memset(vector, 0, nvec*sizeof(int)); 275 switch(type) { 276 case Memory: 277 mon = "mem"; 278 f = open("/dev/swap", OREAD); 279 s = getstr(f); 280 s = strchr(s, '/'); 281 s++; 282 cmax = atoi(s); 283 reshape(screen.r); 284 break; 285 case Swap: 286 mon = "swap"; 287 f = open("/dev/swap", OREAD); 288 s = getstr(f); 289 s = strchr(s, 'y'); 290 s = strchr(s, '/'); 291 s++; 292 cmax = atoi(s); 293 reshape (screen.r); 294 break; 295 case Ether: 296 mon = "ether"; 297 f = open("#l/ether/0/stats", OREAD); 298 cmax = 1; 299 reshape (screen.r); 300 break; 301 case Contxt: 302 mon = "contxt"; 303 f = open("/dev/sysstat", OREAD); 304 cmax = 1; 305 reshape (screen.r); 306 break; 307 case Intr: 308 mon = "intr"; 309 f = open("/dev/sysstat", OREAD); 310 cmax = 1; 311 reshape (screen.r); 312 break; 313 case Syscall: 314 mon = "syscall"; 315 f = open("/dev/sysstat", OREAD); 316 cmax = 1; 317 reshape (screen.r); 318 break; 319 case Fault: 320 mon = "fault"; 321 f = open("/dev/sysstat", OREAD); 322 cmax = 1; 323 reshape (screen.r); 324 break; 325 case Tlbfault: 326 mon = "tlbmiss"; 327 f = open("/dev/sysstat", OREAD); 328 cmax = 1; 329 reshape (screen.r); 330 break; 331 case Tlbpurge: 332 mon = "tlbpurge"; 333 f = open("/dev/sysstat", OREAD); 334 cmax = 1; 335 reshape (screen.r); 336 break; 337 case Load: 338 mon = "load"; 339 f = open("/dev/sysstat", OREAD); 340 cmax = 1; 341 reshape (screen.r); 342 break; 343 } 344 if(f < 0) { 345 fprint(2, "stats: %s: %r", mon); 346 sleep(500); 347 } 348 349 return f; 350 } 351 352 int 353 sysfield(int fd, int nr) 354 { 355 int val = 0; 356 char *s; 357 358 s = getstr(fd); 359 for(;;) { 360 val += atoi(s+(nr*12)); 361 s = strchr(s, '\n'); 362 if(s == 0 || *++s == '\0') 363 break; 364 s++; 365 }; 366 return val; 367 } 368 369 char * 370 getstr(int fd) 371 { 372 static char buf[1000]; 373 int n; 374 375 if(seek(fd, 0, 0) < 0) 376 exits("getstr: seek"); 377 n = read(fd, buf, sizeof(buf)); 378 if(n < 0) 379 exits("getstr: read"); 380 buf[n] = 0; 381 return buf; 382 } 383 384 void 385 ignore(void *a, char *c) 386 { 387 USED(a); 388 if(strcmp(c, "alarm") == 0) 389 noted(NCONT); 390 391 noted(NDFLT); 392 } 393