1: #if !defined(lint) && defined(DOSCCS) 2: static char *sccsid = "@(#)iostat.c 4.16 (2.11BSD) 1996/1/8"; 3: #endif 4: 5: /* 6: * iostat 7: */ 8: #include <stdio.h> 9: #include <ctype.h> 10: #include <nlist.h> 11: #include <signal.h> 12: 13: #include <sys/types.h> 14: #include <sys/file.h> 15: #include <sys/buf.h> 16: #include <sys/dk.h> 17: 18: struct nlist nl[] = { 19: { "_dk_busy" }, 20: #define X_DK_BUSY 0 21: { "_dk_time" }, 22: #define X_DK_TIME 1 23: { "_dk_xfer" }, 24: #define X_DK_XFER 2 25: { "_dk_wds" }, 26: #define X_DK_WDS 3 27: { "_tk_nin" }, 28: #define X_TK_NIN 4 29: { "_tk_nout" }, 30: #define X_TK_NOUT 5 31: { "_dk_seek" }, 32: #define X_DK_SEEK 6 33: { "_cp_time" }, 34: #define X_CP_TIME 7 35: { "_dk_wps" }, 36: #define X_DK_WPS 8 37: { "_hz" }, 38: #define X_HZ 9 39: { "_dk_ndrive" }, 40: #define X_DK_NDRIVE 10 41: { "_dk_name" }, 42: #define X_DK_NAME 11 43: { "_dk_unit" }, 44: #define X_DK_UNIT 12 45: { 0 }, 46: }; 47: 48: char **dr_name; 49: char **dk_name; 50: int *dr_select; 51: int *dk_unit; 52: long *dk_wps; 53: float *dk_mspw; 54: int dk_ndrive; 55: int ndrives = 0; 56: char *defdrives[] = { "rp0", "rp1", "rp2", 0 }; 57: 58: struct { 59: int dk_busy; 60: long cp_time[CPUSTATES]; 61: long *dk_time; 62: long *dk_wds; 63: long *dk_seek; 64: long *dk_xfer; 65: long tk_nin; 66: long tk_nout; 67: } s, s1; 68: 69: int mf; 70: int hz; 71: double etime; 72: int tohdr = 1; 73: int printhdr(); 74: 75: main(argc, argv) 76: char *argv[]; 77: { 78: extern char *ctime(); 79: register i; 80: int iter; 81: double f1, f2; 82: long t; 83: char *arg, **cp, name[6], buf[BUFSIZ]; 84: 85: nlist("/vmunix", nl); 86: if(nl[X_DK_BUSY].n_type == 0) { 87: printf("dk_busy not found in /vmunix namelist\n"); 88: exit(1); 89: } 90: mf = open("/dev/kmem", 0); 91: if(mf < 0) { 92: printf("cannot open /dev/kmem\n"); 93: exit(1); 94: } 95: iter = 0; 96: for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++) 97: ; 98: if (nl[X_DK_NDRIVE].n_value == 0) { 99: printf("dk_ndrive undefined in system\n"); 100: exit(1); 101: } 102: lseek(mf, (long)nl[X_DK_NDRIVE].n_value, L_SET); 103: read(mf, &dk_ndrive, sizeof (dk_ndrive)); 104: if (dk_ndrive <= 0) { 105: printf("dk_ndrive %d\n", dk_ndrive); 106: exit(1); 107: } 108: dr_select = (int *)calloc(dk_ndrive, sizeof (int)); 109: dr_name = (char **)calloc(dk_ndrive, sizeof (char *)); 110: dk_mspw = (float *)calloc(dk_ndrive, sizeof (float)); 111: dk_name = (char **)calloc(dk_ndrive, sizeof (char *)); 112: dk_unit = (int *)calloc(dk_ndrive, sizeof (int)); 113: dk_wps = (long *)calloc(dk_ndrive, sizeof (long)); 114: s.dk_time = (long *)calloc(dk_ndrive, sizeof (long)); 115: s1.dk_time = (long *)calloc(dk_ndrive, sizeof (long)); 116: s.dk_wds = (long *)calloc(dk_ndrive, sizeof (long)); 117: s1.dk_wds = (long *)calloc(dk_ndrive, sizeof (long)); 118: s.dk_seek = (long *)calloc(dk_ndrive, sizeof (long)); 119: s1.dk_seek = (long *)calloc(dk_ndrive, sizeof (long)); 120: s.dk_xfer = (long *)calloc(dk_ndrive, sizeof (long)); 121: s1.dk_xfer = (long *)calloc(dk_ndrive, sizeof (long)); 122: for (arg = buf, i = 0; i < dk_ndrive; i++) { 123: dr_name[i] = arg; 124: sprintf(dr_name[i], "dk%d", i); 125: arg += strlen(dr_name[i]) + 1; 126: } 127: read_names(); 128: lseek(mf, (long)nl[X_HZ].n_value, L_SET); 129: read(mf, &hz, sizeof hz); 130: lseek(mf, (long)nl[X_DK_WPS].n_value, L_SET); 131: read(mf, dk_wps, dk_ndrive * sizeof (long)); 132: for (i = 0; i < dk_ndrive; i++) { 133: if (dk_wps[i] == 0) 134: continue; 135: dk_mspw[i] = 1000.0 / dk_wps[i]; 136: } 137: 138: /* 139: * Choose drives to be displayed. Priority 140: * goes to (in order) drives supplied as arguments, 141: * default drives. If everything isn't filled 142: * in and there are drives not taken care of, 143: * display the first few that fit. 144: */ 145: ndrives = 0; 146: while (argc > 0 && !isdigit(argv[0][0])) { 147: for (i = 0; i < dk_ndrive; i++) { 148: if (strcmp(dr_name[i], argv[0])) 149: continue; 150: dr_select[i] = 1; 151: ndrives++; 152: } 153: argc--, argv++; 154: } 155: for (i = 0; i < dk_ndrive && ndrives < 4; i++) { 156: if (dr_select[i] || dk_mspw[i] == 0.0) 157: continue; 158: for (cp = defdrives; *cp; cp++) 159: if (strcmp(dr_name[i], *cp) == 0) { 160: dr_select[i] = 1; 161: ndrives++; 162: break; 163: } 164: } 165: for (i = 0; i < dk_ndrive && ndrives < 4; i++) { 166: if (dr_select[i]) 167: continue; 168: dr_select[i] = 1; 169: ndrives++; 170: } 171: if (argc > 1) 172: iter = atoi(argv[1]); 173: signal(SIGCONT, printhdr); 174: loop: 175: if (--tohdr == 0) 176: printhdr(); 177: lseek(mf, (long)nl[X_DK_BUSY].n_value, L_SET); 178: read(mf, &s.dk_busy, sizeof s.dk_busy); 179: lseek(mf, (long)nl[X_DK_TIME].n_value, L_SET); 180: read(mf, s.dk_time, dk_ndrive*sizeof (long)); 181: lseek(mf, (long)nl[X_DK_XFER].n_value, L_SET); 182: read(mf, s.dk_xfer, dk_ndrive*sizeof (long)); 183: lseek(mf, (long)nl[X_DK_WDS].n_value, L_SET); 184: read(mf, s.dk_wds, dk_ndrive*sizeof (long)); 185: lseek(mf, (long)nl[X_DK_SEEK].n_value, L_SET); 186: read(mf, s.dk_seek, dk_ndrive*sizeof (long)); 187: lseek(mf, (long)nl[X_TK_NIN].n_value, L_SET); 188: read(mf, &s.tk_nin, sizeof s.tk_nin); 189: lseek(mf, (long)nl[X_TK_NOUT].n_value, L_SET); 190: read(mf, &s.tk_nout, sizeof s.tk_nout); 191: lseek(mf, (long)nl[X_CP_TIME].n_value, L_SET); 192: read(mf, s.cp_time, sizeof s.cp_time); 193: for (i = 0; i < dk_ndrive; i++) { 194: if (!dr_select[i]) 195: continue; 196: #define X(fld) t = s.fld[i]; s.fld[i] -= s1.fld[i]; s1.fld[i] = t 197: X(dk_xfer); X(dk_seek); X(dk_wds); X(dk_time); 198: } 199: t = s.tk_nin; s.tk_nin -= s1.tk_nin; s1.tk_nin = t; 200: t = s.tk_nout; s.tk_nout -= s1.tk_nout; s1.tk_nout = t; 201: etime = 0; 202: for(i=0; i<CPUSTATES; i++) { 203: X(cp_time); 204: etime += s.cp_time[i]; 205: } 206: if (etime == 0.0) 207: etime = 1.0; 208: etime /= (float) hz; 209: printf("%4.0f%5.0f", s.tk_nin/etime, s.tk_nout/etime); 210: for (i=0; i<dk_ndrive; i++) 211: if (dr_select[i]) 212: stats(i); 213: for (i=0; i<CPUSTATES; i++) 214: stat1(i); 215: printf("\n"); 216: fflush(stdout); 217: contin: 218: if (--iter && argc > 0) { 219: sleep(atoi(argv[0])); 220: goto loop; 221: } 222: } 223: 224: printhdr() 225: { 226: register int i; 227: 228: printf(" tty"); 229: for (i = 0; i < dk_ndrive; i++) 230: if (dr_select[i]) 231: printf(" %3.3s ", dr_name[i]); 232: printf(" cpu\n"); 233: printf(" tin tout"); 234: for (i = 0; i < dk_ndrive; i++) 235: if (dr_select[i]) 236: printf(" bps tps msps "); 237: printf(" us ni sy id\n"); 238: tohdr = 19; 239: } 240: 241: stats(dn) 242: { 243: register i; 244: double atime, words, xtime, itime; 245: 246: if (dk_mspw[dn] == 0.0) { 247: printf("%4.0f%4.0f%5.1f ", 0.0, 0.0, 0.0); 248: return; 249: } 250: atime = s.dk_time[dn]; 251: atime /= (float) hz; /* time controller busy, seconds */ 252: words = (double)s.dk_wds[dn]*32.0; /* number of words transferred */ 253: xtime = (double)dk_mspw[dn]*words/1000.;/* transfer time , seconds */ 254: itime = atime - xtime; /* time busy but not transferring , seconds */ 255: if (xtime < 0) 256: itime += xtime, xtime = 0; 257: if (itime < 0) 258: xtime += itime, itime = 0; 259: printf("%4.0f", words/512/etime); 260: printf("%4.0f", (double)s.dk_xfer[dn]/etime); 261: printf("%5.1f ", 262: s.dk_seek[dn] ? itime*1000./(double)s.dk_seek[dn] : 0.0); 263: } 264: 265: stat1(o) 266: { 267: register i; 268: double time; 269: 270: time = 0; 271: for(i=0; i<CPUSTATES; i++) 272: time += s.cp_time[i]; 273: if (time == 0.0) 274: time = 1.0; 275: printf("%3.0f", 100.*s.cp_time[o]/time); 276: } 277: 278: read_names() 279: { 280: char two_char[2]; 281: register int i; 282: 283: lseek(mf, (long)nl[X_DK_NAME].n_value, L_SET); 284: read(mf, dk_name, dk_ndrive * sizeof (char *)); 285: lseek(mf, (long)nl[X_DK_UNIT].n_value, L_SET); 286: read(mf, dk_unit, dk_ndrive * sizeof (int)); 287: 288: for(i = 0; dk_name[i]; i++) { 289: lseek(mf, (long)dk_name[i], L_SET); 290: read(mf, two_char, sizeof two_char); 291: sprintf(dr_name[i], "%c%c%d", two_char[0], two_char[1], 292: dk_unit[i]); 293: } 294: }