From: CSRG Date: Sun, 24 Apr 1988 10:45:18 +0000 (-0800) Subject: BSD 4_3_Tahoe development X-Git-Tag: BSD-4_3_Net_1^2~134 X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/commitdiff_plain/da47b949c5df9d82629ccc4771667849805ba1f0 BSD 4_3_Tahoe development Work on file usr/src/new/X/xperfmon/xperfmon.c Synthesized-from: CSRG/cd2/4.3tahoe --- diff --git a/usr/src/new/X/xperfmon/xperfmon.c b/usr/src/new/X/xperfmon/xperfmon.c new file mode 100644 index 0000000000..b664726ba3 --- /dev/null +++ b/usr/src/new/X/xperfmon/xperfmon.c @@ -0,0 +1,1070 @@ +/* Copyright 1985, Massachusetts Institute of Technology */ + +/* + * X Unix performance monitor. + */ + +#ifndef lint +static char *rcsid_xperfmon_c = "$Header: xperfmon.c,v 10.13 86/11/25 18:31:37 jg Rel $"; +#endif lint + +/* + * Simple graphical performance monitor for system-wide data. + */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef vax +#include +#include +#endif vax +#ifdef sun +#include +#endif sun +#ifdef ibm032 /* IBM RT/PC */ +#include +#endif ibm032 +#ifdef tahoe +#include +#endif +#include +#include +#include +#include +#include + +#include + +#define USEC_INC 50000 +#define SEC_INC 1 + +struct packet { + int input, output, collisions; +}; +static struct packet packets, old_packets; + +#define NUM_VALS_PER 1000 +struct statistic { + int min_val, max_val; + int value[NUM_VALS_PER]; + char *label, *label2; +}; + +#define SECS_PER_TIME_TICK 10 +static char do_time[NUM_VALS_PER]; +static struct timeval current_time, saved_time; +static struct timezone dummy_zone; + +short gray_bits[16] = { + 0xaaaa, 0x5555, 0xaaaa, 0x5555, + 0xaaaa, 0x5555, 0xaaaa, 0x5555, + 0xaaaa, 0x5555, 0xaaaa, 0x5555, + 0xaaaa, 0x5555, 0xaaaa, 0x5555}; + +/* + * The array stats always has valid info for stats[i], 0 <= i < num_stats. + * For each valid stats[i], stats[i].value[j] is valid for 0 <= j < num_of_val. + * The info for the k-th possible statistic of interest is recorded, if it is + * recorded at all, in stats[possible_stats[k]]. + */ + +#define NO_STAT -1 +#define USER_CPU_PERCENTAGE 0 +#define SYSTEM_CPU_PERCENTAGE 1 +#define IDLE_CPU_PERCENTAGE 2 +#define FREE_MEM 3 +#define DISK_TRANSFERS 4 +#define INTERRUPTS 5 +#define INPUT_PACKETS 6 +#define OUTPUT_PACKETS 7 +#define COLLISION_PACKETS 8 +#define NUM_POSSIBLE_STATS 9 +static int possible_stats[NUM_POSSIBLE_STATS]; +#define WANT_STAT(x) (possible_stats[(x)] != NO_STAT) + +#define MAX_STATS 10 + +#define DEFAULT_BORDER_WIDTH 3 +#define DEFAULT_POSITION "=%dx%d-0+0" + +static struct statistic stats[MAX_STATS]; + +static struct timeval timeout = { + SEC_INC,USEC_INC}; +static int num_stats, num_of_val = 0; +static int graph_x_offset = 0; +WindowInfo WInfo; + +Window Win; +char Host[40]; +char *font_name = "6x10"; +int background; /* color of background */ +int foreground; /* color of graph */ +int highlight; /* color of text, scale */ +FontInfo *finfo; /* font information needed */ +int debug = 0; +#define max(a,b) (a>b ? a:b) + +OpaqueFrame win; + +#define FORALLPOSSIBLESTATS(stat)\ + for (stat = 0; stat < NUM_POSSIBLE_STATS; stat++) +#define FORALLSTATS(stat) for (stat = 0; stat < num_stats; stat++) + +struct nlist nl[] = { +#define X_CPTIME 0 + { "_cp_time" }, +#define X_RATE 1 + { "_rate" }, +#define X_TOTAL 2 + { "_total" }, +#define X_DEFICIT 3 + { "_deficit" }, +#define X_FORKSTAT 4 + { "_forkstat" }, +#define X_SUM 5 + { "_sum" }, +#define X_FIRSTFREE 6 + { "_firstfree" }, +#define X_MAXFREE 7 + { "_maxfree" }, +#define X_BOOTTIME 8 + { "_boottime" }, +#define X_DKXFER 9 + { "_dk_xfer" }, +#define X_REC 10 + { "_rectime" }, +#define X_PGIN 11 + { "_pgintime" }, +#define X_HZ 12 + { "_hz" }, +#define X_MBDINIT 13 + { "_mbdinit" }, +#define N_IFNET 14 + { "_ifnet" }, +#define X_UBDINIT 15 + { "_ubdinit" }, +#define X_IOCINIT 16 + { "_ioccdinit" }, +#define X_VBDINIT 17 + { "_vbdinit" }, + { "" }, +}; + +char dr_name[DK_NDRIVE][10]; +char dr_unit[DK_NDRIVE]; +double stat1(); +int maxfree; +int hz; +struct +{ + int busy; + long time[CPUSTATES]; + long xfer[DK_NDRIVE]; + struct vmmeter Rate; + struct vmtotal Total; + struct vmmeter Sum; + struct forkstat Forkstat; + unsigned rectime; + unsigned pgintime; +} +s, s1; +#define rate s.Rate +#define total s.Total +#define sum s.Sum +#define forkstat s.Forkstat + +struct vmmeter osum; +int deficit; +double etime; +int mf; +int swflag; + +int nintv; +long t; + +#define steal(where, var) lseek(mf, where, 0); read(mf, &var, sizeof var); +#define pgtok(a) ((a)*NBPG/1024) + +char *options[NUM_POSSIBLE_STATS+1] = { + "user", "system", "idle", "free", "disk", "interrupts", + "input", "output", "collision", + 0 /* Terminator! */ }; + +short arrow []= {0x0000, 0x0020, 0x0070, 0x00f8, 0x01fc, 0x03fe, 0x0070, + 0x0070, 0x0070, 0x0070, 0x0070, 0x0070, 0x0070, 0x0000}; +short mask []= {0x0020, 0x0070, 0x00f8, 0x01fc, 0x03fe, 0x07ff, 0x07ff, + 0x00f8, 0x00f8, 0x00f8, 0x00f8, 0x00f8, 0x00f8, 0x00f8}; + + +main(argc, argv) +int argc; +char **argv; +{ + int stat; + int have_disk; + struct timeval timeleft; + char display[40]; + char *strind; + int Select_mask, select_mask = 0; + int maxplus1, n; + Cursor cursor; + char *geometry = NULL; /* location of window */ + char def[32]; + int reverse = 0; + double update = -1.; + double atof(); + char *border_color; + char *fore_color; + char *back_color; + char *high_color; + Pixmap border_pixmap; + char *option; + int opt; + int i; + int minheight, minwidth; + + Color cdef; + int border_width = DEFAULT_BORDER_WIDTH; + + display[0] = '\0'; + + if ((option = XGetDefault(argv[0],"ReverseVideo")) != NULL ) + if (strcmp (option, "on") == 0) + reverse = 1; + if ((option = XGetDefault(argv[0],"BorderWidth")) != NULL) + border_width = atoi(option); + if ((option = XGetDefault(argv[0],"BodyFont")) != NULL) + font_name = option; + if ((border_color = XGetDefault(argv[0],"Border")) == NULL) + border_color = XGetDefault(argv[0],"BorderColor"); + back_color = XGetDefault(argv[0],"Background"); + fore_color = XGetDefault(argv[0],"Foreground"); + high_color = XGetDefault(argv[0],"Highlight"); + if ((option = XGetDefault(argv[0],"Update")) != NULL) + update = atof(option); + + nintv = get_namelist("/vmunix", "/dev/kmem"); + collect_stats(); + etime = 1.0; + have_disk = (total_disk_transfers() ? 1 : 0); + + /* Initialize stats */ + FORALLPOSSIBLESTATS(stat) + possible_stats[stat] = NO_STAT; + num_stats = 0; + for (i = 1; i < argc; i++) { /* Parse line */ + if (argv[i][0] == '=') { + geometry = argv[i]; + continue; + } + if (index(argv[i], ':') != NULL) { /* host:display */ + strncpy(display, argv[i], sizeof(display)); + continue; + } + if (strcmp(argv[i], "-rv") == 0 || + strcmp(argv[i], "-reverse") == 0) { /* black on white */ + reverse = 1; + continue; + } + if (strcmp(argv[i], "-fw") == 0 || + strcmp(argv[i], "-forward") == 0) { /* white on black */ + reverse = 0; + continue; + } + if (strcmp(argv[i], "-bw") == 0 || + strcmp(argv[i], "-border") == 0) { /* border width */ + if (++i >= argc) usage(); + border_width = atoi(argv[i]); + continue; + } + if (strcmp(argv[i], "-fn") == 0 || + strcmp(argv[i], "-font") == 0) { /* host name font */ + if (++i >= argc) usage(); + font_name = argv[i]; + continue; + } + if (strcmp(argv[i], "-bd") == 0 || + strcmp(argv[i], "-color") == 0) { /* border color */ + if (++i >= argc) usage(); + border_color = argv[i]; + continue; + } + if (strcmp(argv[i], "-fg") == 0 || + strcmp(argv[i], "-foreground") == 0) { /* foreground color */ + if (++i >= argc) usage(); + fore_color = argv[i]; + continue; + } + if (strcmp(argv[i], "-bg") == 0 || + strcmp(argv[i], "-background") == 0) { /* background color */ + if (++i >= argc) usage(); + back_color = argv[i]; + continue; + } + if (strcmp(argv[i], "-hl") == 0 || + strcmp(argv[i], "-highlight") == 0) { /* highlight color */ + if (++i >= argc) usage(); + high_color = argv[i]; + continue; + } + if (strcmp(argv[i], "-u") == 0 || + strcmp(argv[i], "-update") == 0) { /* update interval */ + if (++i >= argc) usage(); + update = atof(argv[i]); + continue; + } + opt = getcmd(argv[i], options); + if (opt >= 0 && opt < NUM_POSSIBLE_STATS) { + if (num_stats == MAX_STATS) { + fprintf(stderr, + "MAX_STATS exceeded, please recompile!\n"); + } + else possible_stats[opt] = num_stats++; + continue; + } + usage(); + } + + if (num_stats == 0) + FORALLPOSSIBLESTATS(stat) { + if ((stat == DISK_TRANSFERS) && (have_disk == 0)) continue; + possible_stats[stat] = num_stats++; + if (num_stats == MAX_STATS) break; + } + have_disk = 0; /* so max # of packets = 40 */ + init_stat(USER_CPU_PERCENTAGE, 100, "User", " CPU"); + init_stat(SYSTEM_CPU_PERCENTAGE, 100, "System", " CPU"); + init_stat(IDLE_CPU_PERCENTAGE, 100, "Idle", " CPU"); + init_stat(FREE_MEM, pgtok(maxfree), "Free", " memory"); + init_stat(DISK_TRANSFERS, 40, "Disk", " transfers"); + init_stat(INTERRUPTS, 60, "Interrupts", ""); + init_stat(INPUT_PACKETS, (have_disk ? 20 : 40), "Input", " packets"); + init_stat(OUTPUT_PACKETS, (have_disk ? 20 : 40), "Output", " packets"); + init_stat(COLLISION_PACKETS, 10, "Collision", " packets"); + if (border_width < 0) border_width = DEFAULT_BORDER_WIDTH; + if (update > .09) { + timeout.tv_sec = update; + timeout.tv_usec = (update - (double)((int)update)) * 1000000.; + } + if (!XOpenDisplay (display)){ + fprintf(stderr, "%s: Can't open display '%s'\n", + argv[0], XDisplayName(display)); + exit(1); + } + if ((finfo = XOpenFont(font_name)) == NULL) { + fprintf(stderr, "Can't load font %s!\n", font_name); + exit(1); + } + gethostname(Host, sizeof (Host)); + strcat(Host, ":"); + FORALLSTATS(stat) { + int s_width; + s_width = XStringWidth (stats[stat].label, finfo, 0, 0); + graph_x_offset = max(graph_x_offset, s_width); + s_width = XStringWidth (stats[stat].label2, finfo, 0, 0); + graph_x_offset = max(graph_x_offset, s_width); + } + graph_x_offset += 15; + if(debug) fprintf(stderr, "graph_x_offset=%d\n", graph_x_offset); + gettimeofday(&saved_time, &dummy_zone); + + if (border_color && DisplayCells() > 2 && + XParseColor(border_color, &cdef) && XGetHardwareColor(&cdef)) + border_pixmap = XMakeTile(cdef.pixel); + else if (border_color && strcmp(border_color, "black") == 0) + border_pixmap = BlackPixmap; + else if (border_color && strcmp(border_color, "white") == 0) + border_pixmap = WhitePixmap; + else + border_pixmap = XMakePixmap ( + (Bitmap) XStoreBitmap (16, 16, gray_bits), + BlackPixel, WhitePixel); + + + + if (back_color && DisplayCells() > 2 && + XParseColor(back_color, &cdef) && XGetHardwareColor(&cdef)) { + background = cdef.pixel; + } else if (back_color && (strcmp(back_color, "white") == 0)) { + background = WhitePixel; + reverse = 0; + } else if (back_color && (strcmp(back_color, "black") == 0)) { + background = BlackPixel; + reverse = 0; + } else + background = BlackPixel; + + if (fore_color && DisplayCells() > 2 && + XParseColor(fore_color, &cdef) && XGetHardwareColor(&cdef)) { + foreground = cdef.pixel; + } else if (fore_color && (strcmp(fore_color, "black") == 0)) { + foreground = BlackPixel; + reverse = 0; + } else if (fore_color && (strcmp(fore_color, "white") == 0)) { + foreground = WhitePixel; + reverse = 0; + } else + foreground = WhitePixel; + + if (high_color && DisplayCells() > 2 && + XParseColor(high_color, &cdef) && XGetHardwareColor(&cdef)) { + highlight = cdef.pixel; + } else + highlight = foreground; + + if (reverse) { + highlight = background; + background = foreground; + foreground = highlight; + } + win.bdrwidth = border_width; + win.border = border_pixmap; + win.background = XMakeTile(background); + + minheight = (finfo->height * 2 + 2) * num_stats; + minwidth = graph_x_offset + 100; + sprintf(def, DEFAULT_POSITION, minwidth+100, + (finfo->height * 3 + 3) * num_stats); + + Win = XCreate ("Performance Monitor", argv[0], geometry, def, &win, + minwidth, minheight); + + win.height -= 10; + XMapWindow (Win); + cursor = XCreateCursor (11, 14, arrow, mask, 5, 1, 1, 0, GXcopyInverted); + XDefineCursor (Win, cursor); + + redisplay (Win); + timeleft = timeout; + Select_mask = 1< longest) { + longest = q - to_match; + nmatches = 1; + found = index; + } + else if (q - to_match == longest) + nmatches++; + } + } + if (nmatches > 1) + return(-1); + return(found); +} + +init_stat(index, maxval, label_1, label_2) +int index, maxval; +char *label_1, *label_2; +{ + if WANT_STAT(index) { + index = possible_stats[index]; + stats[index].max_val = maxval; + stats[index].label = label_1; + stats[index].label2 = label_2; + } +} + +#define TIMER_EXPIRED(timer) \ +(*timer && ((*timer)->tv_sec == 0) && ((*timer)->tv_usec == 0)) + +int perf_mon_selected(w, number, mask, timer) +int mask, number; +Window w; +struct timeval *timer; +{ + if(number == 0) { /*timer expired */ + int *target[CPUSTATES-1], trash; + collect_stats(); + for (trash = 0; trash < CPUSTATES-1; trash++) + target[trash] = &trash; + if WANT_STAT(USER_CPU_PERCENTAGE) + target[0] = + &stats[possible_stats[USER_CPU_PERCENTAGE]].value[num_of_val]; + if WANT_STAT(SYSTEM_CPU_PERCENTAGE) + target[1] = + &stats[possible_stats[SYSTEM_CPU_PERCENTAGE]].value[num_of_val]; + if WANT_STAT(IDLE_CPU_PERCENTAGE) + target[2] = + &stats[possible_stats[IDLE_CPU_PERCENTAGE]].value[num_of_val]; + copy_cpu_stats(target); + if WANT_STAT(FREE_MEM) + stats[possible_stats[FREE_MEM]].value[num_of_val] = + pgtok(total.t_free); + if WANT_STAT(DISK_TRANSFERS) + stats[possible_stats[DISK_TRANSFERS]].value[num_of_val] = + total_disk_transfers(); + if WANT_STAT(INTERRUPTS) + stats[possible_stats[INTERRUPTS]].value[num_of_val] = + (rate.v_intr/nintv) - hz; + if WANT_STAT(INPUT_PACKETS) + stats[possible_stats[INPUT_PACKETS]].value[num_of_val] = + packets.input - old_packets.input; + if WANT_STAT(OUTPUT_PACKETS) + stats[possible_stats[OUTPUT_PACKETS]].value[num_of_val] = + packets.output - old_packets.output; + if WANT_STAT(COLLISION_PACKETS) + stats[possible_stats[COLLISION_PACKETS]].value[num_of_val] = + packets.collisions - old_packets.collisions; + gettimeofday(¤t_time, &dummy_zone); + if (current_time.tv_sec < saved_time.tv_sec) { + /* Super-user must have set the clock back */ + saved_time = current_time; + saved_time.tv_sec -= SECS_PER_TIME_TICK; + } + if (saved_time.tv_sec+SECS_PER_TIME_TICK <= current_time.tv_sec) { + saved_time = current_time; + do_time[num_of_val] = 1; + } + else + do_time[num_of_val] = 0; + next_display(w); + } + if (mask & (1 << dpyno())){ + XEvent event; + XEvent pevent; + XExposeWindowEvent *exp_event; + int key; + if(!XPending()) return (-1); /* end of file on connection */ + while (XPending()) + { + XNextEvent (&event); + switch (event.type) { + case KeyPressed: + if ((key = mapkey(((XKeyPressedEvent *)&event)->detail)) > 0) + switch(key){ + case 'f': /* faster usec timeout */ + if (timeout.tv_usec >= USEC_INC) + timeout.tv_usec -= USEC_INC; + else { + if (timeout.tv_sec >= SEC_INC) { + timeout.tv_sec -= SEC_INC; + timeout.tv_usec = 1000000-USEC_INC; + } + } + break; + case 's': /* slower usec timeout */ + if (timeout.tv_usec < 1000000-USEC_INC) + timeout.tv_usec += USEC_INC; + else { + timeout.tv_usec = 0; + timeout.tv_sec += 1; + } + break; + case 'F': /* faster sec timeout */ + if (timeout.tv_sec >= SEC_INC) + timeout.tv_sec -= SEC_INC; + break; + case 'S': /* slower sec timeout */ + timeout.tv_sec += SEC_INC; + break; + case 'R': /* reset */ + timeout.tv_sec = SEC_INC; + timeout.tv_usec = USEC_INC; + num_of_val = 0; + redisplay(w); + break; + case 'h': + case 'H': + case '?': /* Help */ + printf("%s\n%s\n%s\n%s\n%s\n%s\n", + "'s' slower usec timeout", + "'f' faster usec timeout", + "'S' slower sec timeout", + "'F' faster sec timeout", + "'R' reset timeout and display", + "'q' or 'Q' quit"); + /* + * Don't reset timeout + */ + return(0); + case 'q': + case 'Q': + return(-1); + } /* switch(key) */ + break; + case ExposeWindow: + XSync(0); + while (XPending() != 0) { + XPeekEvent (&pevent); + if (pevent.type != ExposeWindow) break; + XNextEvent(&event); + } + + exp_event = (XExposeWindowEvent *) &event; + win.x = exp_event->x; + win.y = exp_event->y; + win.width = exp_event->width; + win.height = exp_event->height - 10; + redisplay(w); + break; + default: + break; + } + } + } + *timer = timeout; + return(0); +} + +int total_disk_transfers() +{ + register int i, total_xfers = 0; + + for(i=0; i < DK_NDRIVE; i++) + total_xfers += s.xfer[i]; + return(total_xfers/etime); +} + +copy_cpu_stats(stat) +int *stat[CPUSTATES-1]; +{ + register int i; + + for(i=0; ix = xv; v->y = yv;\ + v++->flags = VertexDontDraw; } +#define Next_Point(v, xv, yv) {v->x = xv; v->y = yv;\ + v++->flags = VertexRelative | VertexDrawLastPoint; } + +display_dividers(w, clear_first) +int clear_first; +Window w; +{ + register int i, stat; + register int lwidth = win.width - graph_x_offset; + Vertex v[NUM_VALS_PER]; + register Vertex *vp; + + if(debug) fprintf(stderr, "num_of_val=%d\n", num_of_val); + FORALLSTATS(stat) { + register int y_org = YORIGIN_FOR_STAT(stat+1); + vp = v; + if (clear_first) + XPixSet(w, graph_x_offset, y_org-2, lwidth, 5, background); + /* Draw the horizontal line and then add the tick marks */ + XLine(w, graph_x_offset, y_org, win.width, y_org, 1, 1, + foreground, GXcopy, ~0); + for (i = 0; i < num_of_val; i++) { + if (do_time[i]){ + First_Point(vp, graph_x_offset + i, y_org - 2); + Next_Point(vp, 0, 4); + } + } + if (vp != v) + XDraw(w, v, vp-v, 1, 1, foreground, GXcopy, ~0); + } +} + +redisplay(w) +Window w; +{ + register int height_of_stat, stat; + + XClear (w); + display_dividers(w, 0); + height_of_stat = YORIGIN_FOR_STAT(1) - YORIGIN_FOR_STAT(0) - 10; + XTextMask (w, 0, 0, Host, strlen (Host), finfo->id, highlight); + FORALLSTATS(stat) { + register int y_origin_of_stat = YORIGIN_FOR_STAT(stat); + int text_size; + char temp[20]; + XTextMask (w, 0, YMIDPOINT_FOR_STAT(stat), + stats[stat].label, strlen (stats[stat].label), finfo->id, + highlight); + XTextMask (w, 0, YMIDPOINT_FOR_STAT(stat)+10, + stats[stat].label2, strlen (stats[stat].label2), finfo->id, + highlight); + sprintf(temp, "%d", stats[stat].max_val); + text_size = XStringWidth (temp, finfo, 0, 0); + XTextMask (w, graph_x_offset-5-text_size, y_origin_of_stat+5, + temp, strlen (temp), finfo->id, highlight); + sprintf(temp, "%d", stats[stat].min_val); + text_size = XStringWidth (temp, finfo, 0, 0); + XTextMask (w, graph_x_offset-5-text_size, + y_origin_of_stat-1+height_of_stat, temp, strlen (temp), + finfo->id, highlight); + } + if (num_of_val > 0) FORALLSTATS(stat) + redisplay_stat_values(w, height_of_stat, stat, num_of_val); + +} + +redisplay_stat_values(w, height_of_stat, stat, stop_plus_one) +Window w; +int height_of_stat, stat, stop_plus_one; +{ + register int j, newY; + Vertex v[NUM_VALS_PER]; + register Vertex *vp = v; + int y_base = YORIGIN_FOR_STAT(stat+1)-5; + newY = Y_FOR_STAT_VAL(stat, 0); + First_Point(vp, graph_x_offset, newY); + for (j = 1; j < stop_plus_one; ) { + register int npts = 0, oldY = newY; + do { + newY = Y_FOR_STAT_VAL(stat, j); + j++; + npts++; + } + while ((oldY == newY) && (j < stop_plus_one)); + if (--npts) + Next_Point(vp, npts, 0); + Next_Point(vp, 1, newY - oldY); + } + if (vp != v) + XDraw(w, v, vp-v, 1, 1, foreground, GXcopy, ~0); +} + +next_display(w) +Window w; +{ + int stat, height_of_stat, redisp = 0; + + height_of_stat = YORIGIN_FOR_STAT(1) - YORIGIN_FOR_STAT(0) - 10; + FORALLSTATS(stat) { + int newY, oldY; + int y_base = YORIGIN_FOR_STAT(stat+1)-5; + newY = Y_FOR_STAT_VAL(stat, num_of_val); + if (num_of_val == 0) + oldY = newY; + else + oldY = Y_FOR_STAT_VAL(stat, num_of_val-1); + XLine(w, graph_x_offset+num_of_val, oldY, + graph_x_offset+num_of_val+1, newY, 1, 1, foreground, + GXcopy, ~0); + if (do_time[num_of_val]) { + y_base += 5; + XLine(w, graph_x_offset+num_of_val, y_base-2, + graph_x_offset+num_of_val, y_base+2, + 1, 1, foreground, GXcopy, ~0); + } + } + if (++num_of_val >= NUM_VALS_PER || + num_of_val >= win.width-graph_x_offset) { + int num_shift_left = (win.width-graph_x_offset)/2; + int width = (win.width-graph_x_offset) - num_shift_left; + register int j; + for (j = num_shift_left; j < num_of_val; j++) + do_time[j-num_shift_left] = do_time[j]; + FORALLSTATS(stat) { + register int ys = YORIGIN_FOR_STAT(stat)+5, nmax = 1, t; + for (j = num_shift_left; j < num_of_val; j++) { + t = stats[stat].value[j-num_shift_left] = + stats[stat].value[j]; + nmax = nmax > t ? nmax : t; + } + if (stat >= FREE_MEM && stat < COLLISION_PACKETS && nmax != stats[stat].max_val) { + stats[stat].max_val = nmax; + redisp = 1; + } + if (!redisp) { + XMoveArea(w, graph_x_offset+num_shift_left, + ys, graph_x_offset, ys, width, height_of_stat+2); + XPixSet(w, graph_x_offset+num_shift_left, + ys, width, height_of_stat+2, background); + + } + } + num_of_val -= num_shift_left+1; + if (redisp) + redisplay(w); + else + display_dividers(w, 1); + } +} + +int get_namelist(kernel_name, memory_name) +char *kernel_name, *memory_name; +{ + time_t now; + time_t boottime; + register int i; + int nintv; + + nlist(kernel_name, nl); + if(nl[0].n_type == 0) { + fprintf(stderr, "no %s namelist\n", kernel_name); + exit(1); + } + mf = open(memory_name, 0); + if (mf < 0) { + fprintf(stderr, "cannot open %s\n", memory_name); + exit(1); + } + steal((long)nl[X_MAXFREE].n_value, maxfree); + steal((long)nl[X_BOOTTIME].n_value, boottime); + steal((long)nl[X_HZ].n_value, hz); + for (i = 0; i < DK_NDRIVE; i++) { + strcpy(dr_name[i], "xx"); + dr_unit[i] = i; + } + read_names(); + time(&now); + nintv = now - boottime; + if (nintv <= 0 || nintv > 60*60*24*365*10) { + fprintf(stderr, + "Time makes no sense... namelist must be wrong.\n"); + exit(1); + } + return(nintv); +} + +double +stat1(row) +{ + double t; + register i; + + t = 0; + for(i=0; i