/* @(#)sysmeter.c 1.1 88/02/26 3.2 NFSSRC */ #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef FSCALE #define FSCALE (1<<8) #endif #define MAXSTEP 5 /* five step function in slide */ #define CHAR_SIZE 9 /* width per char. */ #define SLIDER_SIZE 8 /* half of slider height */ #define H_GAP1 2 /* gap between lower horizontal line and lower chars. */ #define H_GAP2 4 /* gap between top h. line and top chars. */ #define V_GAP 2 /* gap between right vertical line and next char. */ #define PER_INT 1 /* pixls per interval */ #define MIN_PIC 1 /* min. appearance on each view */ #define MIN_INT_WID (40/PER_INT) #define S1X1 (CHAR_SIZE) #define S1Y1 (2*SLIDER_SIZE) #define S1X2 (S1X1+2*SLIDER_SIZE) #define S1Y2 (S1Y1+2*SLIDER_SIZE) #define S2X1 (S1X2+CHAR_SIZE*5) #define S2Y1 (S1Y1+SLIDER_SIZE-CHAR_SIZE/2) #define S2X2 (S2X1+CHAR_SIZE) #define S2Y2 (S1Y2-SLIDER_SIZE+CHAR_SIZE/2) #define S3X1 (S1X1) #define S3Y1 (0) #define S3X2 (CHAR_SIZE*14) #define S3Y2 (2*SLIDER_SIZE-CHAR_SIZE-2) #define SLDXL S3X1 #define SLDXH S3X2 #define M_ALLOC 100 /* num. of structure once allocated */ #define ADJMAX(val, max, indx)\ while (max <= val) max *= 2; \ if ( val > items[indx].cmax ) { \ val = items[indx].cmax; \ } char hostnm[MAXHOSTNAMELEN]; int g_size = 40; int tot_elapse; Colorindex backgnd_color = 15, chartback_color = 12, avg_color = 1, text_color = 4, changeback_color = 10; #define P_CPU 0 #define P_PAGE 1 #define P_SWAP 2 #define P_INTR 3 #define P_DISK 4 #define P_CNTXT 5 #define P_LOAD 6 #define P_PKTS 7 #define P_IPKTS 8 #define P_OPKTS 9 #define P_COLLS 10 #define P_ERRS 11 #define MAXITEMS 12 #define P_DISP_AVG 50 #define P_PARAM 51 #define P_STYLE 52 #define P_EXIT 53 /* the latter 4 items must be number n+1 */ const char menu[] = "Sysmeter %t|cpu|page|swap|intr|disk|contxt|load|pkts|inpkts|outpkts|colls|errs %l|Display average %x51|Change params %x52|Change style %x53|Exit %x54"; struct disp_fac { short onoff; short cmax; short minmax; short maxmax; char *name; int adj; int x1; int y1; int x2; int y2; } items[MAXITEMS] = { {0, 100, 100, 100, "cpu", 0}, {0, 16, 4, 8192, "page", 0}, {0, 4, 4, 8192, "swap", 0}, {0, 64, 4, 8192, "intr", 0}, {0, 32, 4, 8192, "disk", 0}, {0, 64, 4, 8192, "cntxt", 0}, {0, 4, 4, 8192, "load", 0}, {0, 32, 4, 8192, "pkts", 0}, {0, 32, 4, 8192, "inpkts", 0}, {0, 32, 4, 8192, "outpkts", 0}, {0, 4, 4, 8192, "colls", 0}, {0, 4, 4, 8192, "errs", 0}, }; enum { SAMPLE, AVERAGE, WINDOW } chg_state = SAMPLE; struct entry *avail_h, *used_h, *used_t; struct entry { struct entry *f_link; struct entry *b_link; int data[MAXITEMS]; int avg[MAXITEMS]; int intv; }; int total_item; int smp_intv = 2, avg_intv = 20; int meter = 0, f_row, row, x_coord = -1, y_coord = -1; int f_duration = 120, duration; char v_chg = 0, vflag; int vers, Debug = 0; int wid; int item_len, item_high; int in_interrupt, need_avg, fancy_title =1; int x_size, y_size; int rx_size, ry_size; int menu1, accum; int acc_s, acc_a, acc_w; int step_val[MAXSTEP] = { 1, 5, 30, 60, 300 }; int step_rng[MAXSTEP] = { 20, 8, 8, 10, 21}; int sld_max, sld_maxp; char buf[80]; char buf2[80]; int sig_timer; void get_perfdata(); int set_unit(); CLIENT *Client; struct hostent *hp; struct timeval retry_timeout, total_timeout; struct sockaddr_in server_addr; int sock = RPC_ANYSOCK; struct statstime stats_info; main(argc, argv) char **argv; { short val; int tval, dev, x1, y1; (void) gethostname(hostnm, sizeof(hostnm)); while (argc > 1) { if (argv[1][0] != '-') { if ( vflag ) { seton(argv[1]); } else usage(); } else { vflag = 0; switch(argv[1][1]) { case 's': if ( argc < 3 || argv[2][0] == '-' ) usage(); smp_intv = atoi(argv[2]); if ( smp_intv < 1) smp_intv = 2; argc--; argv++; break; case 'a': if ( argc < 3 || argv[2][0] == '-' ) usage(); avg_intv = atoi(argv[2]); need_avg = 1; argc--; argv++; break; case 'r': if ( argc < 3 || argv[2][0] == '-' ) usage(); f_row = atoi(argv[2]); argc--; argv++; break; case 'g': if ( argc < 3 || argv[2][0] == '-' ) usage(); g_size = atoi(argv[2]); argc--; argv++; break; case 'h': if ( argc < 3 || argv[2][0] == '-' ) usage(); strcpy(hostnm, argv[2]); argc--; argv++; break; case 'v': vflag++; break; case 'x': if ( argc < 3 || argv[2][0] == '-' ) usage(); x_coord = atoi(argv[2]); argc--; argv++; break; case 'y': if ( argc < 3 || argv[2][0] == '-' ) usage(); y_coord = atoi(argv[2]); argc--; argv++; break; case 'd': if ( argc < 3 || argv[2][0] == '-' ) usage(); f_duration = atoi(argv[2]); argc--; argv++; break; case 'm': meter = 1; break; case 'D': Debug = 1; break; case 'i': if ( argc < 3 || argv[2][0] == '-' ) usage(); (void) sscanf(argv[2], "%hu,%hu,%hu,%hu,%hu", &backgnd_color, &chartback_color, &avg_color, &text_color, &changeback_color); argc--; argv++; break; default: usage(); } } argv++; argc--; } if ( !total_item ) { items[0].onoff = 1; total_item++; } row = f_row; if ( row == 0 ) row = (total_item + 1)/2; rndup_dur(); perf_setup(); qdevice(RIGHTMOUSE); qdevice(LEFTMOUSE); qdevice(REDRAW); menu1 = defpup((char *)menu); for (tval = 0; tval < MAXITEMS; tval++) { setpup(menu1, tval+1, items[tval].onoff ? PUP_CHECK: PUP_BOX); } for ( ; ; ) { errno = 0; dev = qread(&val); if ( dev != REDRAW && val != 1 ) continue; in_interrupt = 1; switch(dev) { case RIGHTMOUSE: tval = dopup(menu1); menu_op(tval); break; case LEFTMOUSE: if ( v_chg ) { x1 = getvaluator(MOUSEX) - x_coord; y1 = getvaluator(MOUSEY) - y_coord; left_func(x1, y1); } break; case REDRAW: re_start(); break; default: break; } in_interrupt = 0; } } left_func(x, y) int x, y; { int i; int t_x, t_y; getsize((long *)&t_x, (long *)&t_y); x = x*x_size/t_x; y = y*y_size/t_y; if ( x >= S1X1 && x <= S1X2 && y <= S1Y2 && y >= S1Y1 ) { switch (chg_state) { case SAMPLE: if (accum >= 1) acc_s = accum; chg_state = AVERAGE; accum = acc_a; break; case AVERAGE: if (accum > smp_intv) acc_a = accum; chg_state = WINDOW; accum = acc_w; break; case WINDOW: if (accum > smp_intv) acc_w = accum; chg_state = SAMPLE; accum = acc_s; break; } draw_chg(); draw_chg(); return; } else if ( x >= S2X1 && x <= S2X2 && y <= S2Y2 && y >= S2Y1 ) { if (acc_s < 1) { #ifdef DEBUG abort(); #endif acc_s = 1; } smp_intv = acc_s; avg_intv = acc_a; f_duration = acc_w; acc_s = acc_a = acc_w = 0; switch (chg_state) { case SAMPLE: if (accum >= 1) smp_intv = accum; break; case AVERAGE: if (accum > smp_intv) avg_intv = accum; break; case WINDOW: if (accum > smp_intv) f_duration = accum; else return; break; } v_chg = 0; accum = 0; re_start(); } else { for ( ; getbutton(LEFTMOUSE); ) { x = getvaluator(MOUSEX) - x_coord; y = getvaluator(MOUSEY) - y_coord; x = x*x_size/t_x; y = y*y_size/t_y; if (x >= S3X1 && x <= S3X2 && y <= S3Y2 && y >= S3Y1 ) { x = (x-SLDXL)*sld_maxp/(SLDXH - SLDXL); accum = 0; for ( i = 0; i < MAXSTEP; i++ ) { if ( x > step_rng[i] ) { accum += step_val[i]*step_rng[i]; x -= step_rng[i]; continue; } accum += step_val[i]*x; break; } draw_slide(accum); } } } } menu_op(val) int val; { val--; if (v_chg && val != P_EXIT && val != P_PARAM) return; switch(val) { case P_CPU: case P_PAGE: case P_SWAP: case P_INTR: case P_DISK: case P_CNTXT: case P_LOAD: case P_PKTS: case P_IPKTS: case P_OPKTS: case P_COLLS: case P_ERRS: if ( items[val].onoff ) { items[val].onoff = 0; total_item--; setpup(menu1, val+1, PUP_BOX); } else { items[val].onoff = 1; total_item++; setpup(menu1, val+1, PUP_CHECK); } if ( total_item == 0 ) { items[P_CPU].onoff = 1; total_item = 1; setpup(menu1, P_CPU+1, PUP_CHECK); } re_start(); break; case P_DISP_AVG: need_avg = !need_avg; re_start(); break; case P_PARAM: if (v_chg) { v_chg = 0; re_start(); } else { v_chg = 1; acc_s = smp_intv; acc_a = avg_intv; acc_w = duration; switch (chg_state) { case SAMPLE: accum = smp_intv; break; case AVERAGE: accum = avg_intv; break; case WINDOW: accum = duration; break; default: #ifdef DEBUG abort(); #endif break; } if (acc_s < 1) { #ifdef DEBUG abort(); #endif accum = 1; } re_draw(1); re_draw(1); draw_chg(); draw_chg(); } break; case P_STYLE: meter = !meter; re_start(); break; case P_EXIT: winclose(wid); exit(1); default: break; } } static void retitle(void) { char title[MAXHOSTNAMELEN + 50]; if (fancy_title) { if ( meter ) { if ( need_avg ) sprintf(title, "%s (samp=%ds,avg=%ds)", hostnm, smp_intv, avg_intv); else sprintf(title, "%s (samp=%ds)", hostnm, smp_intv); } else if ( need_avg ) sprintf(title, "%s (samp=%ds,avg=%ds,win=%ds)", hostnm, smp_intv, avg_intv, duration); else sprintf(title, "%s (samp=%ds,win=%ds)", hostnm, smp_intv, duration); } else sprintf(title, "%s", hostnm); wintitle(title); } re_start() { rndup_dur(); item_high = g_size + CHAR_SIZE + H_GAP1 + H_GAP2 + MIN_PIC; if ( meter ) { item_len = g_size + CHAR_SIZE*4+V_GAP; } else { item_len = (duration/smp_intv) * PER_INT+PER_INT-1+4*CHAR_SIZE+V_GAP; } row = howmanyrow(); x_size = item_len*((total_item+row-1)/row)+CHAR_SIZE; y_size = row*item_high + CHAR_SIZE; getorigin((long *)&x_coord, (long *)&y_coord); resize(); getsize((long *)&rx_size,(long *)&ry_size); retitle (); draw_backg(); draw_backg(); re_draw(1); re_draw(1); if ( v_chg ) { draw_chg(); draw_chg(); } (void) signal(SIGALRM, get_perfdata); alarm(smp_intv); } seton(item) char *item; { int i; if (!strcmp(item, "all")) { for ( i = 0; i < MAXITEMS; i++ ) { items[i].onoff = 1; total_item++; } return; } else for ( i = 0; i < MAXITEMS; i++ ) if ( !strcmp(item, items[i].name) ) { items[i].onoff = 1; total_item++; return; } usage(); } usage() { fprintf(stderr, "Usage: sysmeter [-s sample-interval]\n"); fprintf(stderr, " [-a averaging-interval]\n"); fprintf(stderr, " [-h hostname]\n"); fprintf(stderr, " [-r row]\n"); fprintf(stderr, " [-d duration-in-seconds]\n"); fprintf(stderr, " [-D debugging-version]\n"); fprintf(stderr, " [-x xcoord] [-y ycoord]\n"); fprintf(stderr, " [-g height]\n"); fprintf(stderr, " [-m]\n"); fprintf(stderr, " [-i 1stof5colorindex]\n"); fprintf(stderr, " [-v value value ...]\n"); fprintf(stderr, "value can be: cpu page swap intr disk cntxt load pkts inpkts outpkts colls errs\n"); exit(1); } perf_setup() { int i; vers = RSTATVERS_TIME; if ((hp = gethostbyname(hostnm)) == NULL) { fprintf(stderr, "sysmeter: unknown host %s\n", hostnm); exit(1); } bcopy(hp->h_addr, (caddr_t)&server_addr.sin_addr, hp->h_length); server_addr.sin_family = AF_INET; server_addr.sin_port = 0; /* use pmapper */ if (Debug) printf("Got the host named %s (%s)\n", hostnm, inet_ntoa(server_addr.sin_addr)); retry_timeout.tv_sec = 5; retry_timeout.tv_usec = 0; if ((Client = clntudp_create(&server_addr, RSTATPROG, vers, retry_timeout, &sock)) == NULL) { fprintf(stderr, "sysmeter: cannot contact %s%s\n", hostnm, clnt_spcreateerror("")); exit(1); } if (Debug) printf("UDP RPC connection created\n"); Client->cl_auth = authunix_create_default(); total_timeout.tv_sec = 20; total_timeout.tv_usec = 0; for ( i = 0; i < MAXSTEP; i++ ) { sld_maxp += step_rng[i]; sld_max += step_val[i]*step_rng[i]; } /* open window, get window size and allocate memory */ create_window(); get_perfdata(); } /* all coordination supposed to aligned with pixels, otherwise, you can't determine the window size */ create_window() { item_high = g_size+CHAR_SIZE+H_GAP1+H_GAP2 + MIN_PIC; if ( meter ) { item_len = g_size + CHAR_SIZE*4+V_GAP; } else { item_len = (duration/smp_intv)*PER_INT+PER_INT-1+4*CHAR_SIZE+V_GAP; } #ifdef DEBUG foreground(); #endif if ( x_coord >= 0 && y_coord >= 0 ) { if ( row > total_item ) row = total_item; x_size = item_len*((total_item+row-1)/row) + CHAR_SIZE; y_size = row*item_high + CHAR_SIZE; if ( x_coord + x_size > XMAXSCREEN ) x_coord = XMAXSCREEN - x_size; if ( y_coord + y_size + 2*CHAR_SIZE > YMAXSCREEN ) y_coord = YMAXSCREEN - y_size - 2*CHAR_SIZE; prefposition(x_coord, x_coord + x_size, y_coord, y_coord + y_size); wid = winopen("sysmeter"); winconstraints();; } else { wid = winopen("sysmeter"); getorigin((long *)&x_coord, (long *)&y_coord); f_row = row = howmanyrow(); x_size = item_len*((total_item+row-1)/row) + CHAR_SIZE; y_size = row*item_high + CHAR_SIZE; resize(); } doublebuffer(); gconfig(); getsize((long *)&rx_size, (long *)&ry_size); retitle (); draw_backg(); draw_backg(); } resize() { register float t_x, t_y; if ( x_size >= rx_size ) { t_x = x_size/rx_size; } else { t_x = rx_size/x_size; } if ( y_size >= ry_size ) { t_y = y_size/ry_size; } else { t_y = ry_size/y_size; } if ( t_x >= t_y ) { if ( ry_size < y_size ) ry_size = y_size; if ( ry_size*x_size/y_size - 1 > XMAXSCREEN ) return; if ( rx_size != ry_size*x_size/y_size ) winposition(x_coord, x_coord+ry_size*x_size/y_size-1, y_coord, y_coord+ry_size-1); } else { if ( rx_size < x_size ) rx_size = x_size; if ( rx_size*y_size/x_size -1 > YMAXSCREEN ) return; if ( ry_size != rx_size*y_size/x_size ) winposition(x_coord, x_coord+rx_size-1, y_coord, y_coord+rx_size*y_size/x_size-1); } } /* given an arbitrary shape of window, figure out best arrangement */ int howmanyrow() { register int i, j, col; float prev_ratio, r_ratio, tmp_ratio; float f1, f2; getsize((long *)&rx_size, (long *)&ry_size); prev_ratio = -1; f1 = rx_size; f2 = ry_size; r_ratio = f2/f1; for ( i = 1; i <= total_item; i++ ) { col = (total_item + i - 1)/i; if ( (i*col - total_item) > (col-1) ) continue; x_size = item_len*col + CHAR_SIZE; y_size = i*item_high + CHAR_SIZE; f1 = x_size; f2 = y_size; tmp_ratio = f2/f1; if ( tmp_ratio >= r_ratio ) { if ( prev_ratio < 0 ) return(i); if ( tmp_ratio - r_ratio > r_ratio - prev_ratio ) return (j); else return (i); } prev_ratio = tmp_ratio; j = i; } return (total_item); } draw_backg() { int x1, x2, y1, y2; int i, j, c_row, row_item; float xx, yy; reshapeviewport(); xx = x_size; yy = y_size; ortho2(0.0, xx, 0.0, yy); color(backgnd_color); clear(); getsize((long *)&rx_size, (long *)&ry_size); row_item = 0; c_row = 0; for ( j = i = 0; i < total_item; i++) { for ( ; !(items[j].onoff); j++); x1 = item_len*row_item + 4*CHAR_SIZE + V_GAP; y1 = (row-c_row-1)*item_high + CHAR_SIZE + H_GAP1 + H_GAP2; y2 = y1 + g_size + MIN_PIC; if ( meter ) { x2 = x1 + g_size; color(text_color); move2i(x1, y2); draw2i(x1, y1); draw2i(x2, y1); move2i(x1, y2); draw2i(x1 + g_size/8, y2); move2i(x1, y1 + g_size*3/4 + MIN_PIC); draw2i(x1 + g_size/8, y1 + g_size*3/4 + MIN_PIC); move2i(x1, y1 + g_size/2 + MIN_PIC); draw2i(x1 + g_size/8, y1 + g_size/2 + MIN_PIC); move2i(x1, y1 + g_size/4 + MIN_PIC); draw2i(x1 + g_size/8, y1 + g_size/4 + MIN_PIC); } else { x2 = (row_item + 1)*item_len; color(chartback_color); rectfi(x1, y1, x2, y2); } items[j].x1 = x1; items[j].x2 = x2; items[j].y1 = y1; items[j].y2 = y2; strcpy(buf, items[j].name); color(text_color); cmov2i(x1 + V_GAP, y1 - H_GAP1 - CHAR_SIZE*x_size/rx_size); charstr(buf); cmov2i(x1 - V_GAP - 4*CHAR_SIZE*x_size/rx_size, y2 - CHAR_SIZE*x_size/rx_size); sprintf(buf, "%4d", items[j].cmax); charstr(buf); cmov2i(x1 - V_GAP - CHAR_SIZE*x_size/rx_size, y1); charstr("0"); row_item++; if ( row_item >= (total_item+row-1)/row ) { row_item = 0; c_row++; } j++; } swapbuffers(); getorigin((long *)&x_coord, (long *)&y_coord); } void get_perfdata() { enum clnt_stat err; sig_timer++; err = clnt_call(Client, RSTATPROC_STATS, xdr_void, 0, xdr_statstime, &stats_info, total_timeout); if ( err != RPC_SUCCESS ) { fprintf(stderr, "sysmeter: can't get stats: %s\n", clnt_sperrno(err)); winclose(wid); exit(1); } insert_new(); (void) signal(SIGALRM, get_perfdata); alarm(smp_intv); } insert_new() { static struct statstime prev_v; static int first = 1; register int i; register struct entry *mem; int temp, totcpu; if ( in_interrupt ) return; if ( avail_h == 0 ) release_used(); if ( avail_h == 0 ) { mem = (struct entry *)malloc(M_ALLOC*sizeof(struct entry)); if ( mem == NULL ) { fprintf(stderr, "Out of memory\n"); winclose(wid); exit(1); } for ( i = 0; i < M_ALLOC; i++, mem++) insert_avail(mem); } if (first) { prev_v = stats_info; first = 0; return; } mem = avail_h; if ( avail_h->f_link ) avail_h->f_link->b_link = 0; avail_h = avail_h->f_link; mem->intv = smp_intv; temp = stats_info.cp_time[CP_USER] - prev_v.cp_time[CP_USER] + stats_info.cp_time[CP_NICE] - prev_v.cp_time[CP_NICE] + stats_info.cp_time[CP_SYS] - prev_v.cp_time[CP_SYS]; totcpu = temp + stats_info.cp_time[CP_IDLE] - prev_v.cp_time[CP_IDLE]; if (totcpu) mem->data[P_CPU] = temp*100/totcpu; else mem->data[P_CPU] = 0; mem->data[P_PAGE] = (stats_info.v_pgpgin - prev_v.v_pgpgin + stats_info.v_pgpgout - prev_v.v_pgpgout + smp_intv/2) / smp_intv; mem->data[P_SWAP] = (stats_info.v_pswpin - prev_v.v_pswpin + stats_info.v_pswpout - prev_v.v_pswpout + smp_intv/2) / smp_intv; mem->data[P_INTR] = (stats_info.v_intr - prev_v.v_intr + smp_intv/2) / smp_intv; mem->data[P_DISK] = (stats_info.dk_xfer[0] - prev_v.dk_xfer[0] + stats_info.dk_xfer[1] - prev_v.dk_xfer[1] + stats_info.dk_xfer[2] - prev_v.dk_xfer[2] + stats_info.dk_xfer[3] - prev_v.dk_xfer[3] + smp_intv/2) / smp_intv; mem->data[P_CNTXT] = (stats_info.v_swtch - prev_v.v_swtch + smp_intv/2) / smp_intv; mem->data[P_LOAD] = stats_info.avenrun[0]/FSCALE; mem->data[P_PKTS] = (stats_info.if_ipackets - prev_v.if_ipackets + stats_info.if_opackets - prev_v.if_opackets + smp_intv/2) / smp_intv; mem->data[P_IPKTS] = (stats_info.if_ipackets - prev_v.if_ipackets + smp_intv/2) / smp_intv; mem->data[P_OPKTS] = (stats_info.if_opackets - prev_v.if_opackets + smp_intv/2) / smp_intv; mem->data[P_COLLS] = (stats_info.if_collisions - prev_v.if_collisions + smp_intv/2) / smp_intv; mem->data[P_ERRS] = (stats_info.if_ierrors - prev_v.if_ierrors + stats_info.if_oerrors - prev_v.if_oerrors + smp_intv/2) / smp_intv; for ( i = 0; i < MAXITEMS; i++ ) if ( mem->data[i] < 0 ) mem->data[i] = 0; if ( used_h ) { used_h->b_link = mem; mem->f_link = used_h; mem->b_link = 0; used_h = mem; } else { used_t = used_h = mem; mem->f_link = mem->b_link = 0; } set_avgval(); tot_elapse += smp_intv; prev_v = stats_info; re_draw(0); } re_draw(force) int force; { register struct entry *ent; int new_max, c_col, i, j; int c_val, ini_draw; int x_pos, y_pos; long draw[4][2]; if ( used_h == 0 ) return; if ( !force && v_chg ) return; c_col = 0; for ( i = 0; i < MAXITEMS; i++) { if ( !items[i].onoff ) continue; ini_draw = c_val = 0; new_max = items[i].cmax/2; x_pos = items[i].x1; y_pos = items[i].y1; if ( meter ) { color(backgnd_color); rectfi(x_pos+g_size/3, y_pos, x_pos+g_size-g_size/3+g_size/8, y_pos+g_size+MIN_PIC); } else { color(chartback_color); rectfi(x_pos, y_pos, items[i].x2, items[i].y2); } if ( meter ) { if ( need_avg ) { c_val = used_h->avg[i]; ADJMAX(c_val, new_max, i); color(avg_color); rectfi(x_pos+g_size/3+g_size/8, y_pos, x_pos+g_size-g_size/3+g_size/8, y_pos+MIN_PIC+g_size*c_val/items[i].cmax); } c_val = used_h->data[i]; ADJMAX(c_val, new_max, i); color(chartback_color); rectfi(x_pos+g_size/3, y_pos, x_pos+g_size-g_size/3, y_pos+MIN_PIC+g_size*c_val/items[i].cmax); move2i(x_pos+g_size/3, y_pos); color(text_color); draw2i(x_pos+g_size-g_size/3+g_size/8, y_pos); goto adjust_max; } if ( need_avg && used_h->f_link) { color(avg_color); j = duration/smp_intv; c_val = used_h->avg[i]; ADJMAX(c_val, new_max, i); draw[0][0] = x_pos + j*PER_INT; draw[0][1] = y_pos + MIN_PIC + g_size*c_val/items[i].cmax; draw[3][0] = draw[0][0]; draw[2][1] = draw[3][1] = y_pos; ent = used_h->f_link; j--; for ( ; j >= 0; j-- ) { c_val = ent->avg[i]; ADJMAX(c_val, new_max, i); draw[2][0] = draw[1][0] = x_pos + j*PER_INT; draw[1][1] = y_pos+MIN_PIC+g_size*c_val/items[i].cmax; polf2i(4, draw); draw[0][0] = draw[1][0]; draw[0][1] = draw[1][1]; draw[3][0] = draw[2][0]; if ( !(ent = ent->f_link ) ) break; } } color(BLACK); ent = used_h; ini_draw = c_val = 0; for ( j = duration/smp_intv; j; j-- ) { if ( !ent ) break; c_val = ent->data[i]; ent = ent->f_link; /* now draw one sample */ ADJMAX(c_val, new_max, i); if ( ini_draw ) draw2i(x_pos + j*PER_INT, y_pos + MIN_PIC + g_size*c_val/items[i].cmax); else { ini_draw = 1; move2i(x_pos + j*PER_INT, y_pos + MIN_PIC + g_size*c_val/items[i].cmax); } } adjust_max: if ( new_max > items[i].maxmax ) new_max = items[i].maxmax; if ( new_max < items[i].minmax ) new_max = items[i].minmax; if ( i != P_CPU && ((new_max != items[i].cmax) || items[i].adj) ) { if ( items[i].cmax == new_max ) items[i].adj = 0; else items[i].adj = 1; items[i].cmax = new_max; x_pos = items[i].x1 - V_GAP - 4*CHAR_SIZE*x_size/rx_size; y_pos = items[i].y2 - CHAR_SIZE*x_size/rx_size; color(backgnd_color); rectfi(x_pos, y_pos, x_pos + 4*CHAR_SIZE*x_size/rx_size, y_pos + CHAR_SIZE*x_size/rx_size + H_GAP2); color(text_color); sprintf(buf, "%4d", items[i].cmax); cmov2i(x_pos, y_pos); charstr(buf); } if ( ++c_col >= (total_item+row-1)/row ) { c_col = 0; } } swapbuffers(); } draw_chg() { long i, arrow[3][2]; float xx, yy; color(changeback_color); rectfi(0, 0, 15*CHAR_SIZE, 4*SLIDER_SIZE); color(text_color); arcfi(CHAR_SIZE+SLIDER_SIZE, 3*SLIDER_SIZE, SLIDER_SIZE-1, 450, 1350); arcfi(CHAR_SIZE+SLIDER_SIZE, 3*SLIDER_SIZE, SLIDER_SIZE-1, 1650, 2550); arcfi(CHAR_SIZE+SLIDER_SIZE, 3*SLIDER_SIZE, SLIDER_SIZE-1, 2850, 3750); color(changeback_color); circfi(CHAR_SIZE+SLIDER_SIZE, 3*SLIDER_SIZE, SLIDER_SIZE-3); color(text_color); for ( i = 0; i < 3; i++ ) { pushmatrix(); xx = CHAR_SIZE+SLIDER_SIZE; yy = 3*SLIDER_SIZE; translate(xx, yy, 0.0); arrow[0][0] = 0; arrow[0][1] = -2; arrow[1][0] = 2; arrow[1][1] = 0; arrow[2][0] = -2; arrow[2][1] = 0; rotate(i*1200+450, 'Z'); xx = SLIDER_SIZE-2; translate(xx, 0.0, 0.0); polf2i(3, arrow); popmatrix(); } cmov2i(S1X2+CHAR_SIZE, 3*SLIDER_SIZE-CHAR_SIZE/2); switch (chg_state) { case SAMPLE: strcpy(buf, "Sample"); break; case AVERAGE: strcpy(buf, "Average"); break; case WINDOW: strcpy(buf, "Window"); break; } charstr(buf); recti(S2X1, S2Y1, S2X2, S2Y2); cmov2i(S2X1+2, S2Y1+1); charstr("ok"); cmov2i(CHAR_SIZE, 2*SLIDER_SIZE-CHAR_SIZE+1); charstr("0"); sprintf(buf, "%d", sld_max); cmov2i(14*CHAR_SIZE-strlen(buf)*CHAR_SIZE*x_size/rx_size, 2*SLIDER_SIZE-CHAR_SIZE+1); charstr(buf); rectfi(SLDXL, 2*SLIDER_SIZE-CHAR_SIZE-2, SLDXH, 2*SLIDER_SIZE-CHAR_SIZE); draw_slide(accum); } draw_slide(val) int val; { register int i, cur_val, tot_p; long trian[3][2]; float x_lo, y_lo; color(changeback_color); rectfi(0, 0, 15*CHAR_SIZE, 2*SLIDER_SIZE-CHAR_SIZE-2); color(chartback_color); rectfi(3*CHAR_SIZE, 2*SLIDER_SIZE-CHAR_SIZE+1, CHAR_SIZE*10, 2*SLIDER_SIZE); color(text_color); cur_val = val/60; sprintf(buf, "%3d", cur_val); strcat(buf, "m"); cur_val = val - cur_val*60; sprintf(buf2, "%2d", cur_val); strcat(buf, buf2); strcat(buf, "s"); cmov2i(3*CHAR_SIZE, 2*SLIDER_SIZE-CHAR_SIZE+1); charstr(buf); cur_val = tot_p = 0; for ( i = 0; i < MAXSTEP; i++ ) { if ( val > cur_val + step_val[i]*step_rng[i] ) { cur_val += step_val[i]*step_rng[i]; tot_p += step_rng[i]; continue; } tot_p += ((val - cur_val + step_val[i] - 1)/step_val[i]); break; } x_lo = (SLDXH-SLDXL)*tot_p; x_lo = x_lo/sld_maxp + SLDXL; y_lo = 2*SLIDER_SIZE-CHAR_SIZE-2; pushmatrix(); translate(x_lo, y_lo, 0.0); trian[0][0] = 0; trian[0][1] = 0; trian[1][0] = -2; trian[1][1] = -5; trian[2][0] = 2; trian[2][1] = -5; polf2i(3, trian); popmatrix(); swapbuffers(); } /* * Compute averag value from '*used_h', averaging over 'avg_intv'. */ int set_avgval() { int i; register tot_s; register float c_val; register struct entry *ent; for ( i = 0; i < MAXITEMS; i++ ) { ent = used_h; c_val = 0; tot_s = 0; for ( ; ; ) { if ( tot_s + ent->intv > avg_intv ) c_val = (c_val*tot_s+ent->data[i]*(avg_intv-tot_s))/avg_intv; else c_val = (c_val*tot_s+ent->data[i]*ent->intv)/(tot_s+ent->intv); tot_s += ent->intv; if ( tot_s >= avg_intv || !(ent = ent->f_link) ) { used_h->avg[i] = c_val; break; } } } } insert_avail(m) struct entry *m; { if ( avail_h ) { m->f_link = avail_h; avail_h->b_link = m; m->b_link = 0; avail_h = m; } else { avail_h = m; avail_h->f_link = avail_h->b_link = 0; } } release_used() { register int tm; register struct entry *i, *next; tm = duration + avg_intv; if ( used_h == 0 || tot_elapse < tm ) return; for ( i = used_t; tot_elapse > tm; i = next ) { next = i->b_link; tot_elapse -= i->intv; i->b_link->f_link = 0; used_t = i->b_link; insert_avail(i); } } rndup_dur() { duration = (f_duration + smp_intv - 1) / smp_intv * smp_intv; if (duration/smp_intv < MIN_INT_WID) duration = MIN_INT_WID * smp_intv; }