|
|
1.1 ! root 1: /* Copyright 1985, Massachusetts Institute of Technology */ ! 2: ! 3: /* ! 4: * X Unix performance monitor. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: static char *rcsid_xperfmon_c = "$Header: xperfmon.c,v 10.13 86/11/25 18:31:37 jg Rel $"; ! 9: #endif lint ! 10: ! 11: /* ! 12: * Simple graphical performance monitor for system-wide data. ! 13: */ ! 14: ! 15: #include <stdio.h> ! 16: #include <sys/param.h> ! 17: #include <sys/socket.h> ! 18: #include <sys/vm.h> ! 19: #include <sys/dkstat.h> ! 20: #include <nlist.h> ! 21: #include <sys/buf.h> ! 22: #ifdef vax ! 23: #include <vaxuba/ubavar.h> ! 24: #include <vaxmba/mbavar.h> ! 25: #endif vax ! 26: #ifdef sun ! 27: #include <sundev/mbvar.h> ! 28: #endif sun ! 29: #ifdef ibm032 /* IBM RT/PC */ ! 30: #include <caio/ioccvar.h> ! 31: #endif ibm032 ! 32: #ifdef tahoe ! 33: #include <tahoevba/vbavar.h> ! 34: #endif ! 35: #include <X/Xlib.h> ! 36: #include <net/if.h> ! 37: #include <netinet/in.h> ! 38: #include <sys/file.h> ! 39: #include <sys/time.h> ! 40: ! 41: #include <strings.h> ! 42: ! 43: #define USEC_INC 50000 ! 44: #define SEC_INC 1 ! 45: ! 46: struct packet { ! 47: int input, output, collisions; ! 48: }; ! 49: static struct packet packets, old_packets; ! 50: ! 51: #define NUM_VALS_PER 1000 ! 52: struct statistic { ! 53: int min_val, max_val; ! 54: int value[NUM_VALS_PER]; ! 55: char *label, *label2; ! 56: }; ! 57: ! 58: #define SECS_PER_TIME_TICK 10 ! 59: static char do_time[NUM_VALS_PER]; ! 60: static struct timeval current_time, saved_time; ! 61: static struct timezone dummy_zone; ! 62: ! 63: short gray_bits[16] = { ! 64: 0xaaaa, 0x5555, 0xaaaa, 0x5555, ! 65: 0xaaaa, 0x5555, 0xaaaa, 0x5555, ! 66: 0xaaaa, 0x5555, 0xaaaa, 0x5555, ! 67: 0xaaaa, 0x5555, 0xaaaa, 0x5555}; ! 68: ! 69: /* ! 70: * The array stats always has valid info for stats[i], 0 <= i < num_stats. ! 71: * For each valid stats[i], stats[i].value[j] is valid for 0 <= j < num_of_val. ! 72: * The info for the k-th possible statistic of interest is recorded, if it is ! 73: * recorded at all, in stats[possible_stats[k]]. ! 74: */ ! 75: ! 76: #define NO_STAT -1 ! 77: #define USER_CPU_PERCENTAGE 0 ! 78: #define SYSTEM_CPU_PERCENTAGE 1 ! 79: #define IDLE_CPU_PERCENTAGE 2 ! 80: #define FREE_MEM 3 ! 81: #define DISK_TRANSFERS 4 ! 82: #define INTERRUPTS 5 ! 83: #define INPUT_PACKETS 6 ! 84: #define OUTPUT_PACKETS 7 ! 85: #define COLLISION_PACKETS 8 ! 86: #define NUM_POSSIBLE_STATS 9 ! 87: static int possible_stats[NUM_POSSIBLE_STATS]; ! 88: #define WANT_STAT(x) (possible_stats[(x)] != NO_STAT) ! 89: ! 90: #define MAX_STATS 10 ! 91: ! 92: #define DEFAULT_BORDER_WIDTH 3 ! 93: #define DEFAULT_POSITION "=%dx%d-0+0" ! 94: ! 95: static struct statistic stats[MAX_STATS]; ! 96: ! 97: static struct timeval timeout = { ! 98: SEC_INC,USEC_INC}; ! 99: static int num_stats, num_of_val = 0; ! 100: static int graph_x_offset = 0; ! 101: WindowInfo WInfo; ! 102: ! 103: Window Win; ! 104: char Host[40]; ! 105: char *font_name = "6x10"; ! 106: int background; /* color of background */ ! 107: int foreground; /* color of graph */ ! 108: int highlight; /* color of text, scale */ ! 109: FontInfo *finfo; /* font information needed */ ! 110: int debug = 0; ! 111: #define max(a,b) (a>b ? a:b) ! 112: ! 113: OpaqueFrame win; ! 114: ! 115: #define FORALLPOSSIBLESTATS(stat)\ ! 116: for (stat = 0; stat < NUM_POSSIBLE_STATS; stat++) ! 117: #define FORALLSTATS(stat) for (stat = 0; stat < num_stats; stat++) ! 118: ! 119: struct nlist nl[] = { ! 120: #define X_CPTIME 0 ! 121: { "_cp_time" }, ! 122: #define X_RATE 1 ! 123: { "_rate" }, ! 124: #define X_TOTAL 2 ! 125: { "_total" }, ! 126: #define X_DEFICIT 3 ! 127: { "_deficit" }, ! 128: #define X_FORKSTAT 4 ! 129: { "_forkstat" }, ! 130: #define X_SUM 5 ! 131: { "_sum" }, ! 132: #define X_FIRSTFREE 6 ! 133: { "_firstfree" }, ! 134: #define X_MAXFREE 7 ! 135: { "_maxfree" }, ! 136: #define X_BOOTTIME 8 ! 137: { "_boottime" }, ! 138: #define X_DKXFER 9 ! 139: { "_dk_xfer" }, ! 140: #define X_REC 10 ! 141: { "_rectime" }, ! 142: #define X_PGIN 11 ! 143: { "_pgintime" }, ! 144: #define X_HZ 12 ! 145: { "_hz" }, ! 146: #define X_MBDINIT 13 ! 147: { "_mbdinit" }, ! 148: #define N_IFNET 14 ! 149: { "_ifnet" }, ! 150: #define X_UBDINIT 15 ! 151: { "_ubdinit" }, ! 152: #define X_IOCINIT 16 ! 153: { "_ioccdinit" }, ! 154: #define X_VBDINIT 17 ! 155: { "_vbdinit" }, ! 156: { "" }, ! 157: }; ! 158: ! 159: char dr_name[DK_NDRIVE][10]; ! 160: char dr_unit[DK_NDRIVE]; ! 161: double stat1(); ! 162: int maxfree; ! 163: int hz; ! 164: struct ! 165: { ! 166: int busy; ! 167: long time[CPUSTATES]; ! 168: long xfer[DK_NDRIVE]; ! 169: struct vmmeter Rate; ! 170: struct vmtotal Total; ! 171: struct vmmeter Sum; ! 172: struct forkstat Forkstat; ! 173: unsigned rectime; ! 174: unsigned pgintime; ! 175: } ! 176: s, s1; ! 177: #define rate s.Rate ! 178: #define total s.Total ! 179: #define sum s.Sum ! 180: #define forkstat s.Forkstat ! 181: ! 182: struct vmmeter osum; ! 183: int deficit; ! 184: double etime; ! 185: int mf; ! 186: int swflag; ! 187: ! 188: int nintv; ! 189: long t; ! 190: ! 191: #define steal(where, var) lseek(mf, where, 0); read(mf, &var, sizeof var); ! 192: #define pgtok(a) ((a)*NBPG/1024) ! 193: ! 194: char *options[NUM_POSSIBLE_STATS+1] = { ! 195: "user", "system", "idle", "free", "disk", "interrupts", ! 196: "input", "output", "collision", ! 197: 0 /* Terminator! */ }; ! 198: ! 199: short arrow []= {0x0000, 0x0020, 0x0070, 0x00f8, 0x01fc, 0x03fe, 0x0070, ! 200: 0x0070, 0x0070, 0x0070, 0x0070, 0x0070, 0x0070, 0x0000}; ! 201: short mask []= {0x0020, 0x0070, 0x00f8, 0x01fc, 0x03fe, 0x07ff, 0x07ff, ! 202: 0x00f8, 0x00f8, 0x00f8, 0x00f8, 0x00f8, 0x00f8, 0x00f8}; ! 203: ! 204: ! 205: main(argc, argv) ! 206: int argc; ! 207: char **argv; ! 208: { ! 209: int stat; ! 210: int have_disk; ! 211: struct timeval timeleft; ! 212: char display[40]; ! 213: char *strind; ! 214: int Select_mask, select_mask = 0; ! 215: int maxplus1, n; ! 216: Cursor cursor; ! 217: char *geometry = NULL; /* location of window */ ! 218: char def[32]; ! 219: int reverse = 0; ! 220: double update = -1.; ! 221: double atof(); ! 222: char *border_color; ! 223: char *fore_color; ! 224: char *back_color; ! 225: char *high_color; ! 226: Pixmap border_pixmap; ! 227: char *option; ! 228: int opt; ! 229: int i; ! 230: int minheight, minwidth; ! 231: ! 232: Color cdef; ! 233: int border_width = DEFAULT_BORDER_WIDTH; ! 234: ! 235: display[0] = '\0'; ! 236: ! 237: if ((option = XGetDefault(argv[0],"ReverseVideo")) != NULL ) ! 238: if (strcmp (option, "on") == 0) ! 239: reverse = 1; ! 240: if ((option = XGetDefault(argv[0],"BorderWidth")) != NULL) ! 241: border_width = atoi(option); ! 242: if ((option = XGetDefault(argv[0],"BodyFont")) != NULL) ! 243: font_name = option; ! 244: if ((border_color = XGetDefault(argv[0],"Border")) == NULL) ! 245: border_color = XGetDefault(argv[0],"BorderColor"); ! 246: back_color = XGetDefault(argv[0],"Background"); ! 247: fore_color = XGetDefault(argv[0],"Foreground"); ! 248: high_color = XGetDefault(argv[0],"Highlight"); ! 249: if ((option = XGetDefault(argv[0],"Update")) != NULL) ! 250: update = atof(option); ! 251: ! 252: nintv = get_namelist("/vmunix", "/dev/kmem"); ! 253: collect_stats(); ! 254: etime = 1.0; ! 255: have_disk = (total_disk_transfers() ? 1 : 0); ! 256: ! 257: /* Initialize stats */ ! 258: FORALLPOSSIBLESTATS(stat) ! 259: possible_stats[stat] = NO_STAT; ! 260: num_stats = 0; ! 261: for (i = 1; i < argc; i++) { /* Parse line */ ! 262: if (argv[i][0] == '=') { ! 263: geometry = argv[i]; ! 264: continue; ! 265: } ! 266: if (index(argv[i], ':') != NULL) { /* host:display */ ! 267: strncpy(display, argv[i], sizeof(display)); ! 268: continue; ! 269: } ! 270: if (strcmp(argv[i], "-rv") == 0 || ! 271: strcmp(argv[i], "-reverse") == 0) { /* black on white */ ! 272: reverse = 1; ! 273: continue; ! 274: } ! 275: if (strcmp(argv[i], "-fw") == 0 || ! 276: strcmp(argv[i], "-forward") == 0) { /* white on black */ ! 277: reverse = 0; ! 278: continue; ! 279: } ! 280: if (strcmp(argv[i], "-bw") == 0 || ! 281: strcmp(argv[i], "-border") == 0) { /* border width */ ! 282: if (++i >= argc) usage(); ! 283: border_width = atoi(argv[i]); ! 284: continue; ! 285: } ! 286: if (strcmp(argv[i], "-fn") == 0 || ! 287: strcmp(argv[i], "-font") == 0) { /* host name font */ ! 288: if (++i >= argc) usage(); ! 289: font_name = argv[i]; ! 290: continue; ! 291: } ! 292: if (strcmp(argv[i], "-bd") == 0 || ! 293: strcmp(argv[i], "-color") == 0) { /* border color */ ! 294: if (++i >= argc) usage(); ! 295: border_color = argv[i]; ! 296: continue; ! 297: } ! 298: if (strcmp(argv[i], "-fg") == 0 || ! 299: strcmp(argv[i], "-foreground") == 0) { /* foreground color */ ! 300: if (++i >= argc) usage(); ! 301: fore_color = argv[i]; ! 302: continue; ! 303: } ! 304: if (strcmp(argv[i], "-bg") == 0 || ! 305: strcmp(argv[i], "-background") == 0) { /* background color */ ! 306: if (++i >= argc) usage(); ! 307: back_color = argv[i]; ! 308: continue; ! 309: } ! 310: if (strcmp(argv[i], "-hl") == 0 || ! 311: strcmp(argv[i], "-highlight") == 0) { /* highlight color */ ! 312: if (++i >= argc) usage(); ! 313: high_color = argv[i]; ! 314: continue; ! 315: } ! 316: if (strcmp(argv[i], "-u") == 0 || ! 317: strcmp(argv[i], "-update") == 0) { /* update interval */ ! 318: if (++i >= argc) usage(); ! 319: update = atof(argv[i]); ! 320: continue; ! 321: } ! 322: opt = getcmd(argv[i], options); ! 323: if (opt >= 0 && opt < NUM_POSSIBLE_STATS) { ! 324: if (num_stats == MAX_STATS) { ! 325: fprintf(stderr, ! 326: "MAX_STATS exceeded, please recompile!\n"); ! 327: } ! 328: else possible_stats[opt] = num_stats++; ! 329: continue; ! 330: } ! 331: usage(); ! 332: } ! 333: ! 334: if (num_stats == 0) ! 335: FORALLPOSSIBLESTATS(stat) { ! 336: if ((stat == DISK_TRANSFERS) && (have_disk == 0)) continue; ! 337: possible_stats[stat] = num_stats++; ! 338: if (num_stats == MAX_STATS) break; ! 339: } ! 340: have_disk = 0; /* so max # of packets = 40 */ ! 341: init_stat(USER_CPU_PERCENTAGE, 100, "User", " CPU"); ! 342: init_stat(SYSTEM_CPU_PERCENTAGE, 100, "System", " CPU"); ! 343: init_stat(IDLE_CPU_PERCENTAGE, 100, "Idle", " CPU"); ! 344: init_stat(FREE_MEM, pgtok(maxfree), "Free", " memory"); ! 345: init_stat(DISK_TRANSFERS, 40, "Disk", " transfers"); ! 346: init_stat(INTERRUPTS, 60, "Interrupts", ""); ! 347: init_stat(INPUT_PACKETS, (have_disk ? 20 : 40), "Input", " packets"); ! 348: init_stat(OUTPUT_PACKETS, (have_disk ? 20 : 40), "Output", " packets"); ! 349: init_stat(COLLISION_PACKETS, 10, "Collision", " packets"); ! 350: if (border_width < 0) border_width = DEFAULT_BORDER_WIDTH; ! 351: if (update > .09) { ! 352: timeout.tv_sec = update; ! 353: timeout.tv_usec = (update - (double)((int)update)) * 1000000.; ! 354: } ! 355: if (!XOpenDisplay (display)){ ! 356: fprintf(stderr, "%s: Can't open display '%s'\n", ! 357: argv[0], XDisplayName(display)); ! 358: exit(1); ! 359: } ! 360: if ((finfo = XOpenFont(font_name)) == NULL) { ! 361: fprintf(stderr, "Can't load font %s!\n", font_name); ! 362: exit(1); ! 363: } ! 364: gethostname(Host, sizeof (Host)); ! 365: strcat(Host, ":"); ! 366: FORALLSTATS(stat) { ! 367: int s_width; ! 368: s_width = XStringWidth (stats[stat].label, finfo, 0, 0); ! 369: graph_x_offset = max(graph_x_offset, s_width); ! 370: s_width = XStringWidth (stats[stat].label2, finfo, 0, 0); ! 371: graph_x_offset = max(graph_x_offset, s_width); ! 372: } ! 373: graph_x_offset += 15; ! 374: if(debug) fprintf(stderr, "graph_x_offset=%d\n", graph_x_offset); ! 375: gettimeofday(&saved_time, &dummy_zone); ! 376: ! 377: if (border_color && DisplayCells() > 2 && ! 378: XParseColor(border_color, &cdef) && XGetHardwareColor(&cdef)) ! 379: border_pixmap = XMakeTile(cdef.pixel); ! 380: else if (border_color && strcmp(border_color, "black") == 0) ! 381: border_pixmap = BlackPixmap; ! 382: else if (border_color && strcmp(border_color, "white") == 0) ! 383: border_pixmap = WhitePixmap; ! 384: else ! 385: border_pixmap = XMakePixmap ( ! 386: (Bitmap) XStoreBitmap (16, 16, gray_bits), ! 387: BlackPixel, WhitePixel); ! 388: ! 389: ! 390: ! 391: if (back_color && DisplayCells() > 2 && ! 392: XParseColor(back_color, &cdef) && XGetHardwareColor(&cdef)) { ! 393: background = cdef.pixel; ! 394: } else if (back_color && (strcmp(back_color, "white") == 0)) { ! 395: background = WhitePixel; ! 396: reverse = 0; ! 397: } else if (back_color && (strcmp(back_color, "black") == 0)) { ! 398: background = BlackPixel; ! 399: reverse = 0; ! 400: } else ! 401: background = BlackPixel; ! 402: ! 403: if (fore_color && DisplayCells() > 2 && ! 404: XParseColor(fore_color, &cdef) && XGetHardwareColor(&cdef)) { ! 405: foreground = cdef.pixel; ! 406: } else if (fore_color && (strcmp(fore_color, "black") == 0)) { ! 407: foreground = BlackPixel; ! 408: reverse = 0; ! 409: } else if (fore_color && (strcmp(fore_color, "white") == 0)) { ! 410: foreground = WhitePixel; ! 411: reverse = 0; ! 412: } else ! 413: foreground = WhitePixel; ! 414: ! 415: if (high_color && DisplayCells() > 2 && ! 416: XParseColor(high_color, &cdef) && XGetHardwareColor(&cdef)) { ! 417: highlight = cdef.pixel; ! 418: } else ! 419: highlight = foreground; ! 420: ! 421: if (reverse) { ! 422: highlight = background; ! 423: background = foreground; ! 424: foreground = highlight; ! 425: } ! 426: win.bdrwidth = border_width; ! 427: win.border = border_pixmap; ! 428: win.background = XMakeTile(background); ! 429: ! 430: minheight = (finfo->height * 2 + 2) * num_stats; ! 431: minwidth = graph_x_offset + 100; ! 432: sprintf(def, DEFAULT_POSITION, minwidth+100, ! 433: (finfo->height * 3 + 3) * num_stats); ! 434: ! 435: Win = XCreate ("Performance Monitor", argv[0], geometry, def, &win, ! 436: minwidth, minheight); ! 437: ! 438: win.height -= 10; ! 439: XMapWindow (Win); ! 440: cursor = XCreateCursor (11, 14, arrow, mask, 5, 1, 1, 0, GXcopyInverted); ! 441: XDefineCursor (Win, cursor); ! 442: ! 443: redisplay (Win); ! 444: timeleft = timeout; ! 445: Select_mask = 1<<dpyno(); ! 446: maxplus1 = 1+dpyno(); ! 447: XSelectInput(Win, KeyPressed | ExposeWindow | ExposeCopy); ! 448: while(1) { ! 449: select_mask = Select_mask; ! 450: if(debug) fprintf(stderr, "time=[%d,%d]\n", ! 451: timeleft.tv_sec, timeleft.tv_usec); ! 452: XFlush(); ! 453: if ((n = select(maxplus1, &select_mask, NULL, NULL, &timeleft)) ! 454: < 0) exit(46); ! 455: if(debug) ! 456: fprintf(stderr,"selected n=%d mask=0x%x, time=[%d,%d]\n", ! 457: n, select_mask, timeleft.tv_sec, timeleft.tv_usec); ! 458: if (perf_mon_selected (Win, n, select_mask, &timeleft) ! 459: < 0) break; ! 460: } ! 461: } ! 462: ! 463: getcmd(to_match, table) /* Modified from ucb/lpr/lpc.c */ ! 464: register char *to_match; ! 465: register char **table; ! 466: { ! 467: register char *p, *q; ! 468: int found, index, nmatches, longest; ! 469: ! 470: longest = nmatches = 0; ! 471: found = index = -1; ! 472: for (p = *table; p; p = *(++table)) { ! 473: index++; ! 474: for (q = to_match; *q == *p++; q++) ! 475: if (*q == 0) /* exact match? */ ! 476: return(index); ! 477: if (!*q) { /* the to_match was a prefix */ ! 478: if (q - to_match > longest) { ! 479: longest = q - to_match; ! 480: nmatches = 1; ! 481: found = index; ! 482: } ! 483: else if (q - to_match == longest) ! 484: nmatches++; ! 485: } ! 486: } ! 487: if (nmatches > 1) ! 488: return(-1); ! 489: return(found); ! 490: } ! 491: ! 492: init_stat(index, maxval, label_1, label_2) ! 493: int index, maxval; ! 494: char *label_1, *label_2; ! 495: { ! 496: if WANT_STAT(index) { ! 497: index = possible_stats[index]; ! 498: stats[index].max_val = maxval; ! 499: stats[index].label = label_1; ! 500: stats[index].label2 = label_2; ! 501: } ! 502: } ! 503: ! 504: #define TIMER_EXPIRED(timer) \ ! 505: (*timer && ((*timer)->tv_sec == 0) && ((*timer)->tv_usec == 0)) ! 506: ! 507: int perf_mon_selected(w, number, mask, timer) ! 508: int mask, number; ! 509: Window w; ! 510: struct timeval *timer; ! 511: { ! 512: if(number == 0) { /*timer expired */ ! 513: int *target[CPUSTATES-1], trash; ! 514: collect_stats(); ! 515: for (trash = 0; trash < CPUSTATES-1; trash++) ! 516: target[trash] = &trash; ! 517: if WANT_STAT(USER_CPU_PERCENTAGE) ! 518: target[0] = ! 519: &stats[possible_stats[USER_CPU_PERCENTAGE]].value[num_of_val]; ! 520: if WANT_STAT(SYSTEM_CPU_PERCENTAGE) ! 521: target[1] = ! 522: &stats[possible_stats[SYSTEM_CPU_PERCENTAGE]].value[num_of_val]; ! 523: if WANT_STAT(IDLE_CPU_PERCENTAGE) ! 524: target[2] = ! 525: &stats[possible_stats[IDLE_CPU_PERCENTAGE]].value[num_of_val]; ! 526: copy_cpu_stats(target); ! 527: if WANT_STAT(FREE_MEM) ! 528: stats[possible_stats[FREE_MEM]].value[num_of_val] = ! 529: pgtok(total.t_free); ! 530: if WANT_STAT(DISK_TRANSFERS) ! 531: stats[possible_stats[DISK_TRANSFERS]].value[num_of_val] = ! 532: total_disk_transfers(); ! 533: if WANT_STAT(INTERRUPTS) ! 534: stats[possible_stats[INTERRUPTS]].value[num_of_val] = ! 535: (rate.v_intr/nintv) - hz; ! 536: if WANT_STAT(INPUT_PACKETS) ! 537: stats[possible_stats[INPUT_PACKETS]].value[num_of_val] = ! 538: packets.input - old_packets.input; ! 539: if WANT_STAT(OUTPUT_PACKETS) ! 540: stats[possible_stats[OUTPUT_PACKETS]].value[num_of_val] = ! 541: packets.output - old_packets.output; ! 542: if WANT_STAT(COLLISION_PACKETS) ! 543: stats[possible_stats[COLLISION_PACKETS]].value[num_of_val] = ! 544: packets.collisions - old_packets.collisions; ! 545: gettimeofday(¤t_time, &dummy_zone); ! 546: if (current_time.tv_sec < saved_time.tv_sec) { ! 547: /* Super-user must have set the clock back */ ! 548: saved_time = current_time; ! 549: saved_time.tv_sec -= SECS_PER_TIME_TICK; ! 550: } ! 551: if (saved_time.tv_sec+SECS_PER_TIME_TICK <= current_time.tv_sec) { ! 552: saved_time = current_time; ! 553: do_time[num_of_val] = 1; ! 554: } ! 555: else ! 556: do_time[num_of_val] = 0; ! 557: next_display(w); ! 558: } ! 559: if (mask & (1 << dpyno())){ ! 560: XEvent event; ! 561: XEvent pevent; ! 562: XExposeWindowEvent *exp_event; ! 563: int key; ! 564: if(!XPending()) return (-1); /* end of file on connection */ ! 565: while (XPending()) ! 566: { ! 567: XNextEvent (&event); ! 568: switch (event.type) { ! 569: case KeyPressed: ! 570: if ((key = mapkey(((XKeyPressedEvent *)&event)->detail)) > 0) ! 571: switch(key){ ! 572: case 'f': /* faster usec timeout */ ! 573: if (timeout.tv_usec >= USEC_INC) ! 574: timeout.tv_usec -= USEC_INC; ! 575: else { ! 576: if (timeout.tv_sec >= SEC_INC) { ! 577: timeout.tv_sec -= SEC_INC; ! 578: timeout.tv_usec = 1000000-USEC_INC; ! 579: } ! 580: } ! 581: break; ! 582: case 's': /* slower usec timeout */ ! 583: if (timeout.tv_usec < 1000000-USEC_INC) ! 584: timeout.tv_usec += USEC_INC; ! 585: else { ! 586: timeout.tv_usec = 0; ! 587: timeout.tv_sec += 1; ! 588: } ! 589: break; ! 590: case 'F': /* faster sec timeout */ ! 591: if (timeout.tv_sec >= SEC_INC) ! 592: timeout.tv_sec -= SEC_INC; ! 593: break; ! 594: case 'S': /* slower sec timeout */ ! 595: timeout.tv_sec += SEC_INC; ! 596: break; ! 597: case 'R': /* reset */ ! 598: timeout.tv_sec = SEC_INC; ! 599: timeout.tv_usec = USEC_INC; ! 600: num_of_val = 0; ! 601: redisplay(w); ! 602: break; ! 603: case 'h': ! 604: case 'H': ! 605: case '?': /* Help */ ! 606: printf("%s\n%s\n%s\n%s\n%s\n%s\n", ! 607: "'s' slower usec timeout", ! 608: "'f' faster usec timeout", ! 609: "'S' slower sec timeout", ! 610: "'F' faster sec timeout", ! 611: "'R' reset timeout and display", ! 612: "'q' or 'Q' quit"); ! 613: /* ! 614: * Don't reset timeout ! 615: */ ! 616: return(0); ! 617: case 'q': ! 618: case 'Q': ! 619: return(-1); ! 620: } /* switch(key) */ ! 621: break; ! 622: case ExposeWindow: ! 623: XSync(0); ! 624: while (XPending() != 0) { ! 625: XPeekEvent (&pevent); ! 626: if (pevent.type != ExposeWindow) break; ! 627: XNextEvent(&event); ! 628: } ! 629: ! 630: exp_event = (XExposeWindowEvent *) &event; ! 631: win.x = exp_event->x; ! 632: win.y = exp_event->y; ! 633: win.width = exp_event->width; ! 634: win.height = exp_event->height - 10; ! 635: redisplay(w); ! 636: break; ! 637: default: ! 638: break; ! 639: } ! 640: } ! 641: } ! 642: *timer = timeout; ! 643: return(0); ! 644: } ! 645: ! 646: int total_disk_transfers() ! 647: { ! 648: register int i, total_xfers = 0; ! 649: ! 650: for(i=0; i < DK_NDRIVE; i++) ! 651: total_xfers += s.xfer[i]; ! 652: return(total_xfers/etime); ! 653: } ! 654: ! 655: copy_cpu_stats(stat) ! 656: int *stat[CPUSTATES-1]; ! 657: { ! 658: register int i; ! 659: ! 660: for(i=0; i<CPUSTATES; i++) { ! 661: float f = stat1(i); ! 662: if (i == 0) { /* US+NI */ ! 663: i++; ! 664: f += stat1(i); ! 665: } ! 666: if (stat[i-1] != 0) ! 667: *stat[i-1] = f; ! 668: } ! 669: } ! 670: ! 671: collect_stats() ! 672: { ! 673: ! 674: off_t ifnetaddr = (long)nl[N_IFNET].n_value; ! 675: ! 676: register int i; ! 677: ! 678: lseek(mf, (long)nl[X_CPTIME].n_value, 0); ! 679: read(mf, s.time, sizeof s.time); ! 680: lseek(mf, (long)nl[X_DKXFER].n_value, 0); ! 681: read(mf, s.xfer, sizeof s.xfer); ! 682: if (nintv != 1) { ! 683: steal((long)nl[X_SUM].n_value, rate); ! 684: } ! 685: else { ! 686: steal((long)nl[X_RATE].n_value, rate); ! 687: } ! 688: steal((long)nl[X_TOTAL].n_value, total); ! 689: osum = sum; ! 690: steal((long)nl[X_SUM].n_value, sum); ! 691: steal((long)nl[X_DEFICIT].n_value, deficit); ! 692: etime = 0; ! 693: for (i=0; i < DK_NDRIVE; i++) { ! 694: t = s.xfer[i]; ! 695: s.xfer[i] -= s1.xfer[i]; ! 696: s1.xfer[i] = t; ! 697: } ! 698: for (i=0; i < CPUSTATES; i++) { ! 699: t = s.time[i]; ! 700: s.time[i] -= s1.time[i]; ! 701: s1.time[i] = t; ! 702: etime += s.time[i]; ! 703: } ! 704: if(etime == 0.) ! 705: etime = 1.; ! 706: etime /= 60.; ! 707: nintv = 1; ! 708: ! 709: if (nl[N_IFNET].n_value != 0) { ! 710: struct ifnet ifnet; ! 711: steal((long)nl[N_IFNET].n_value, ifnetaddr); ! 712: old_packets = packets; ! 713: packets.input = packets.output = packets.collisions = 0; ! 714: while (ifnetaddr) { ! 715: steal(ifnetaddr, ifnet); ! 716: packets.input += ifnet.if_ipackets; ! 717: packets.output += ifnet.if_opackets; ! 718: packets.collisions += ifnet.if_collisions; ! 719: ifnetaddr = (off_t) ifnet.if_next; ! 720: } ! 721: } ! 722: ! 723: } ! 724: ! 725: min (a, b) ! 726: int a,b; ! 727: { ! 728: return(a<b ? a:b); ! 729: } ! 730: ! 731: #define YORIGIN_FOR_STAT(num) ((((num)*win.height)/num_stats)+3) ! 732: #define YMIDPOINT_FOR_STAT(num) ((((num)*win.height+win.height/2)/num_stats) + 5) ! 733: #define Y_FOR_STAT_VAL(stat, num_of_val) \ ! 734: y_base - min(height_of_stat, ( \ ! 735: height_of_stat*( \ ! 736: stats[stat].value[num_of_val]-stats[stat].min_val)/( \ ! 737: stats[stat].max_val-stats[stat].min_val))) ! 738: #define First_Point(v, xv, yv) {v->x = xv; v->y = yv;\ ! 739: v++->flags = VertexDontDraw; } ! 740: #define Next_Point(v, xv, yv) {v->x = xv; v->y = yv;\ ! 741: v++->flags = VertexRelative | VertexDrawLastPoint; } ! 742: ! 743: display_dividers(w, clear_first) ! 744: int clear_first; ! 745: Window w; ! 746: { ! 747: register int i, stat; ! 748: register int lwidth = win.width - graph_x_offset; ! 749: Vertex v[NUM_VALS_PER]; ! 750: register Vertex *vp; ! 751: ! 752: if(debug) fprintf(stderr, "num_of_val=%d\n", num_of_val); ! 753: FORALLSTATS(stat) { ! 754: register int y_org = YORIGIN_FOR_STAT(stat+1); ! 755: vp = v; ! 756: if (clear_first) ! 757: XPixSet(w, graph_x_offset, y_org-2, lwidth, 5, background); ! 758: /* Draw the horizontal line and then add the tick marks */ ! 759: XLine(w, graph_x_offset, y_org, win.width, y_org, 1, 1, ! 760: foreground, GXcopy, ~0); ! 761: for (i = 0; i < num_of_val; i++) { ! 762: if (do_time[i]){ ! 763: First_Point(vp, graph_x_offset + i, y_org - 2); ! 764: Next_Point(vp, 0, 4); ! 765: } ! 766: } ! 767: if (vp != v) ! 768: XDraw(w, v, vp-v, 1, 1, foreground, GXcopy, ~0); ! 769: } ! 770: } ! 771: ! 772: redisplay(w) ! 773: Window w; ! 774: { ! 775: register int height_of_stat, stat; ! 776: ! 777: XClear (w); ! 778: display_dividers(w, 0); ! 779: height_of_stat = YORIGIN_FOR_STAT(1) - YORIGIN_FOR_STAT(0) - 10; ! 780: XTextMask (w, 0, 0, Host, strlen (Host), finfo->id, highlight); ! 781: FORALLSTATS(stat) { ! 782: register int y_origin_of_stat = YORIGIN_FOR_STAT(stat); ! 783: int text_size; ! 784: char temp[20]; ! 785: XTextMask (w, 0, YMIDPOINT_FOR_STAT(stat), ! 786: stats[stat].label, strlen (stats[stat].label), finfo->id, ! 787: highlight); ! 788: XTextMask (w, 0, YMIDPOINT_FOR_STAT(stat)+10, ! 789: stats[stat].label2, strlen (stats[stat].label2), finfo->id, ! 790: highlight); ! 791: sprintf(temp, "%d", stats[stat].max_val); ! 792: text_size = XStringWidth (temp, finfo, 0, 0); ! 793: XTextMask (w, graph_x_offset-5-text_size, y_origin_of_stat+5, ! 794: temp, strlen (temp), finfo->id, highlight); ! 795: sprintf(temp, "%d", stats[stat].min_val); ! 796: text_size = XStringWidth (temp, finfo, 0, 0); ! 797: XTextMask (w, graph_x_offset-5-text_size, ! 798: y_origin_of_stat-1+height_of_stat, temp, strlen (temp), ! 799: finfo->id, highlight); ! 800: } ! 801: if (num_of_val > 0) FORALLSTATS(stat) ! 802: redisplay_stat_values(w, height_of_stat, stat, num_of_val); ! 803: ! 804: } ! 805: ! 806: redisplay_stat_values(w, height_of_stat, stat, stop_plus_one) ! 807: Window w; ! 808: int height_of_stat, stat, stop_plus_one; ! 809: { ! 810: register int j, newY; ! 811: Vertex v[NUM_VALS_PER]; ! 812: register Vertex *vp = v; ! 813: int y_base = YORIGIN_FOR_STAT(stat+1)-5; ! 814: newY = Y_FOR_STAT_VAL(stat, 0); ! 815: First_Point(vp, graph_x_offset, newY); ! 816: for (j = 1; j < stop_plus_one; ) { ! 817: register int npts = 0, oldY = newY; ! 818: do { ! 819: newY = Y_FOR_STAT_VAL(stat, j); ! 820: j++; ! 821: npts++; ! 822: } ! 823: while ((oldY == newY) && (j < stop_plus_one)); ! 824: if (--npts) ! 825: Next_Point(vp, npts, 0); ! 826: Next_Point(vp, 1, newY - oldY); ! 827: } ! 828: if (vp != v) ! 829: XDraw(w, v, vp-v, 1, 1, foreground, GXcopy, ~0); ! 830: } ! 831: ! 832: next_display(w) ! 833: Window w; ! 834: { ! 835: int stat, height_of_stat, redisp = 0; ! 836: ! 837: height_of_stat = YORIGIN_FOR_STAT(1) - YORIGIN_FOR_STAT(0) - 10; ! 838: FORALLSTATS(stat) { ! 839: int newY, oldY; ! 840: int y_base = YORIGIN_FOR_STAT(stat+1)-5; ! 841: newY = Y_FOR_STAT_VAL(stat, num_of_val); ! 842: if (num_of_val == 0) ! 843: oldY = newY; ! 844: else ! 845: oldY = Y_FOR_STAT_VAL(stat, num_of_val-1); ! 846: XLine(w, graph_x_offset+num_of_val, oldY, ! 847: graph_x_offset+num_of_val+1, newY, 1, 1, foreground, ! 848: GXcopy, ~0); ! 849: if (do_time[num_of_val]) { ! 850: y_base += 5; ! 851: XLine(w, graph_x_offset+num_of_val, y_base-2, ! 852: graph_x_offset+num_of_val, y_base+2, ! 853: 1, 1, foreground, GXcopy, ~0); ! 854: } ! 855: } ! 856: if (++num_of_val >= NUM_VALS_PER || ! 857: num_of_val >= win.width-graph_x_offset) { ! 858: int num_shift_left = (win.width-graph_x_offset)/2; ! 859: int width = (win.width-graph_x_offset) - num_shift_left; ! 860: register int j; ! 861: for (j = num_shift_left; j < num_of_val; j++) ! 862: do_time[j-num_shift_left] = do_time[j]; ! 863: FORALLSTATS(stat) { ! 864: register int ys = YORIGIN_FOR_STAT(stat)+5, nmax = 1, t; ! 865: for (j = num_shift_left; j < num_of_val; j++) { ! 866: t = stats[stat].value[j-num_shift_left] = ! 867: stats[stat].value[j]; ! 868: nmax = nmax > t ? nmax : t; ! 869: } ! 870: if (stat >= FREE_MEM && stat < COLLISION_PACKETS && nmax != stats[stat].max_val) { ! 871: stats[stat].max_val = nmax; ! 872: redisp = 1; ! 873: } ! 874: if (!redisp) { ! 875: XMoveArea(w, graph_x_offset+num_shift_left, ! 876: ys, graph_x_offset, ys, width, height_of_stat+2); ! 877: XPixSet(w, graph_x_offset+num_shift_left, ! 878: ys, width, height_of_stat+2, background); ! 879: ! 880: } ! 881: } ! 882: num_of_val -= num_shift_left+1; ! 883: if (redisp) ! 884: redisplay(w); ! 885: else ! 886: display_dividers(w, 1); ! 887: } ! 888: } ! 889: ! 890: int get_namelist(kernel_name, memory_name) ! 891: char *kernel_name, *memory_name; ! 892: { ! 893: time_t now; ! 894: time_t boottime; ! 895: register int i; ! 896: int nintv; ! 897: ! 898: nlist(kernel_name, nl); ! 899: if(nl[0].n_type == 0) { ! 900: fprintf(stderr, "no %s namelist\n", kernel_name); ! 901: exit(1); ! 902: } ! 903: mf = open(memory_name, 0); ! 904: if (mf < 0) { ! 905: fprintf(stderr, "cannot open %s\n", memory_name); ! 906: exit(1); ! 907: } ! 908: steal((long)nl[X_MAXFREE].n_value, maxfree); ! 909: steal((long)nl[X_BOOTTIME].n_value, boottime); ! 910: steal((long)nl[X_HZ].n_value, hz); ! 911: for (i = 0; i < DK_NDRIVE; i++) { ! 912: strcpy(dr_name[i], "xx"); ! 913: dr_unit[i] = i; ! 914: } ! 915: read_names(); ! 916: time(&now); ! 917: nintv = now - boottime; ! 918: if (nintv <= 0 || nintv > 60*60*24*365*10) { ! 919: fprintf(stderr, ! 920: "Time makes no sense... namelist must be wrong.\n"); ! 921: exit(1); ! 922: } ! 923: return(nintv); ! 924: } ! 925: ! 926: double ! 927: stat1(row) ! 928: { ! 929: double t; ! 930: register i; ! 931: ! 932: t = 0; ! 933: for(i=0; i<CPUSTATES; i++) ! 934: t += s.time[i]; ! 935: if(t == 0.) ! 936: t = 1.; ! 937: return(s.time[row]*100./t); ! 938: } ! 939: ! 940: #ifdef vax ! 941: read_names() ! 942: { ! 943: struct mba_device mdev; ! 944: register struct mba_device *mp; ! 945: struct mba_driver mdrv; ! 946: short two_char; ! 947: char *cp = (char *) &two_char; ! 948: struct uba_device udev, *up; ! 949: struct uba_driver udrv; ! 950: ! 951: mp = (struct mba_device *) nl[X_MBDINIT].n_value; ! 952: up = (struct uba_device *) nl[X_UBDINIT].n_value; ! 953: if (up == 0) { ! 954: fprintf(stderr, "perfmon: Disk init info not in namelist\n"); ! 955: exit(1); ! 956: } ! 957: if(mp) for (;;) { ! 958: steal(mp++, mdev); ! 959: if (mdev.mi_driver == 0) ! 960: break; ! 961: if (mdev.mi_dk < 0 || mdev.mi_alive == 0) ! 962: continue; ! 963: steal(mdev.mi_driver, mdrv); ! 964: steal(mdrv.md_dname, two_char); ! 965: sprintf(dr_name[mdev.mi_dk], "%c%c", cp[0], cp[1]); ! 966: dr_unit[mdev.mi_dk] = mdev.mi_unit; ! 967: } ! 968: if(up) for (;;) { ! 969: steal(up++, udev); ! 970: if (udev.ui_driver == 0) ! 971: break; ! 972: if (udev.ui_dk < 0 || udev.ui_alive == 0) ! 973: continue; ! 974: steal(udev.ui_driver, udrv); ! 975: steal(udrv.ud_dname, two_char); ! 976: sprintf(dr_name[udev.ui_dk], "%c%c", cp[0], cp[1]); ! 977: dr_unit[udev.ui_dk] = udev.ui_unit; ! 978: } ! 979: } ! 980: #endif vax ! 981: ! 982: #ifdef sun ! 983: read_names() ! 984: { ! 985: struct mb_device mdev; ! 986: register struct mb_device *mp; ! 987: struct mb_driver mdrv; ! 988: short two_char; ! 989: char *cp = (char *) &two_char; ! 990: ! 991: mp = (struct mb_device *) nl[X_MBDINIT].n_value; ! 992: if (mp == 0) { ! 993: fprintf(stderr, "vmstat: Disk init info not in namelist\n"); ! 994: exit(1); ! 995: } ! 996: for (;;) { ! 997: steal(mp++, mdev); ! 998: if (mdev.md_driver == 0) ! 999: break; ! 1000: if (mdev.md_dk < 0 || mdev.md_alive == 0) ! 1001: continue; ! 1002: steal(mdev.md_driver, mdrv); ! 1003: steal(mdrv.mdr_dname, two_char); ! 1004: sprintf(dr_name[mdev.md_dk], "%c%c", cp[0], cp[1]); ! 1005: dr_unit[mdev.md_dk] = mdev.md_unit; ! 1006: } ! 1007: } ! 1008: #endif sun ! 1009: ! 1010: #ifdef ibm032 ! 1011: read_names() ! 1012: { ! 1013: struct iocc_device mdev; ! 1014: register struct iocc_device *mp; ! 1015: struct iocc_driver mdrv; ! 1016: short two_char; ! 1017: char *cp = (char *) &two_char; ! 1018: ! 1019: mp = (struct iocc_device *) nl[X_IOCINIT].n_value; ! 1020: if (mp == 0) { ! 1021: fprintf(stderr, "vmstat: Disk init info not in namelist\n"); ! 1022: exit(1); ! 1023: } ! 1024: for (;;) { ! 1025: steal(mp++, mdev); ! 1026: if (mdev.iod_driver == 0) ! 1027: break; ! 1028: if (mdev.iod_dk < 0 || mdev.iod_alive == 0) ! 1029: continue; ! 1030: steal(mdev.iod_driver, mdrv); ! 1031: steal(mdrv.idr_dname, two_char); ! 1032: sprintf(dr_name[mdev.iod_dk], "%c%c", cp[0], cp[1]); ! 1033: dr_unit[mdev.iod_dk] = mdev.iod_unit; ! 1034: } ! 1035: } ! 1036: #endif ibm032 ! 1037: ! 1038: #ifdef tahoe ! 1039: read_names() ! 1040: { ! 1041: struct vba_device udev, *up; ! 1042: struct vba_driver udrv; ! 1043: short two_char; ! 1044: char *cp = (char *)&two_char; ! 1045: ! 1046: up = (struct vba_device *) nl[X_VBDINIT].n_value; ! 1047: if (up == 0) { ! 1048: fprintf(stderr, "vmstat: Disk init info not in namelist\n"); ! 1049: exit(1); ! 1050: } ! 1051: for (;;) { ! 1052: steal(up++, udev); ! 1053: if (udev.ui_driver == 0) ! 1054: break; ! 1055: if (udev.ui_dk < 0 || udev.ui_alive == 0) ! 1056: continue; ! 1057: steal(udev.ui_driver, udrv); ! 1058: steal(udrv.ud_dname, two_char); ! 1059: sprintf(dr_name[udev.ui_dk], "%c%c%d", ! 1060: cp[0], cp[1], udev.ui_unit); ! 1061: } ! 1062: } ! 1063: #endif ! 1064: ! 1065: usage() ! 1066: { ! 1067: fprintf(stderr, ! 1068: "Usage: xperfmon [host:display] option option .....\n"); ! 1069: exit(1); ! 1070: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.