1 static char *sccsid = "@(#)vmstat.c 4.8 (Berkeley) 11/15/82"; 2 #include <stdio.h> 3 #include <sys/param.h> 4 #include <sys/vm.h> 5 #include <sys/dk.h> 6 #include <nlist.h> 7 #include <sys/buf.h> 8 #include <vaxuba/ubavar.h> 9 #include <vaxmba/mbavar.h> 10 11 struct nlist nl[] = { 12 #define X_CPTIME 0 13 { "_cp_time" }, 14 #define X_RATE 1 15 { "_rate" }, 16 #define X_TOTAL 2 17 { "_total" }, 18 #define X_DEFICIT 3 19 { "_deficit" }, 20 #define X_FORKSTAT 4 21 { "_forkstat" }, 22 #define X_SUM 5 23 { "_sum" }, 24 #define X_FIRSTFREE 6 25 { "_firstfree" }, 26 #define X_MAXFREE 7 27 { "_maxfree" }, 28 #define X_BOOTTIME 8 29 { "_boottime" }, 30 #define X_DKXFER 9 31 { "_dk_xfer" }, 32 #define X_MBDINIT 10 33 { "_mbdinit" }, 34 #define X_UBDINIT 11 35 { "_ubdinit" }, 36 #define X_REC 12 37 { "_rectime" }, 38 #define X_PGIN 13 39 { "_pgintime" }, 40 #define X_HZ 14 41 { "_hz" }, 42 { 0 }, 43 }; 44 45 char dr_name[DK_NDRIVE][10]; 46 char dr_unit[DK_NDRIVE]; 47 double stat1(); 48 int firstfree, maxfree; 49 int hz; 50 struct 51 { 52 int busy; 53 long time[CPUSTATES]; 54 long xfer[DK_NDRIVE]; 55 struct vmmeter Rate; 56 struct vmtotal Total; 57 struct vmmeter Sum; 58 struct forkstat Forkstat; 59 unsigned rectime; 60 unsigned pgintime; 61 } s, s1, z; 62 #define rate s.Rate 63 #define total s.Total 64 #define sum s.Sum 65 #define forkstat s.Forkstat 66 67 int zero; 68 int deficit; 69 double etime; 70 int mf; 71 72 main(argc, argv) 73 char **argv; 74 { 75 time_t now; 76 int lines; 77 extern char *ctime(); 78 register i,j; 79 int iter, nintv; 80 time_t boottime; 81 double f1, f2; 82 long t; 83 extern char _sobuf[]; 84 85 setbuf(stdout, _sobuf); 86 nlist("/vmunix", nl); 87 if(nl[0].n_type == 0) { 88 printf("no /vmunix namelist\n"); 89 exit(1); 90 } 91 mf = open("/dev/kmem", 0); 92 if(mf < 0) { 93 printf("cannot open /dev/kmem\n"); 94 exit(1); 95 } 96 iter = 0; 97 argc--, argv++; 98 while (argc>0 && argv[0][0]=='-') { 99 char *cp = *argv++; 100 argc--; 101 while (*++cp) switch (*cp) { 102 103 case 't': 104 dotimes(); 105 exit(0); 106 case 'z': 107 close(mf); 108 mf = open("/dev/kmem", 2); 109 lseek(mf, (long)nl[X_SUM].n_value, 0); 110 write(mf, &z.Sum, sizeof z.Sum); 111 exit(0); 112 113 case 'f': 114 doforkst(); 115 exit(0); 116 117 case 's': 118 dosum(); 119 exit(0); 120 121 default: 122 fprintf(stderr, "usage: vmstat [ -fs ] [ interval ] [ count]\n"); 123 exit(1); 124 } 125 } 126 if(argc > 1) 127 iter = atoi(argv[1]); 128 lseek(mf, (long)nl[X_FIRSTFREE].n_value, 0); 129 read(mf, &firstfree, sizeof firstfree); 130 lseek(mf, (long)nl[X_MAXFREE].n_value, 0); 131 read(mf, &maxfree, sizeof maxfree); 132 lseek(mf, (long)nl[X_BOOTTIME].n_value, 0); 133 read(mf, &boottime, sizeof boottime); 134 lseek(mf, (long)nl[X_HZ].n_value, 0); 135 read(mf, &hz, sizeof hz); 136 for (i = 0; i < DK_NDRIVE; i++) { 137 strcpy(dr_name[i], "xx"); 138 dr_unit[i] = i; 139 } 140 read_names(); 141 time(&now); 142 nintv = now - boottime; 143 if (nintv <= 0 || nintv > 60*60*24*365*10) { 144 printf("Time makes no sense... namelist must be wrong.\n"); 145 exit(1); 146 } 147 reprint: 148 lines = 20; 149 /* s1 = z; */ 150 printf("\ 151 procs memory page disk faults cpu\n\ 152 r b w avm fre re at pi po fr de sr %c%d %c%d %c%d %c%d in sy cs us sy id\n\ 153 ", dr_name[0][0], dr_unit[0], dr_name[1][0], dr_unit[1], dr_name[2][0], dr_unit[2], dr_name[3][0], dr_unit[3]); 154 loop: 155 lseek(mf, (long)nl[X_CPTIME].n_value, 0); 156 read(mf, s.time, sizeof s.time); 157 lseek(mf, (long)nl[X_DKXFER].n_value, 0); 158 read(mf, s.xfer, sizeof s.xfer); 159 if (nintv != 1) { 160 lseek(mf, (long)nl[X_SUM].n_value, 0); 161 read(mf, &rate, sizeof rate); 162 } else { 163 lseek(mf, (long)nl[X_RATE].n_value, 0); 164 read(mf, &rate, sizeof rate); 165 } 166 lseek(mf, (long)nl[X_TOTAL].n_value, 0); 167 read(mf, &total, sizeof total); 168 lseek(mf, (long)nl[X_DEFICIT].n_value, 0); 169 read(mf, &deficit, sizeof deficit); 170 etime = 0; 171 for (i=0; i < DK_NDRIVE; i++) { 172 t = s.xfer[i]; 173 s.xfer[i] -= s1.xfer[i]; 174 s1.xfer[i] = t; 175 } 176 for (i=0; i < CPUSTATES; i++) { 177 t = s.time[i]; 178 s.time[i] -= s1.time[i]; 179 s1.time[i] = t; 180 etime += s.time[i]; 181 } 182 if(etime == 0.) 183 etime = 1.; 184 printf("%2d%2d%2d", total.t_rq, total.t_dw+total.t_pw, total.t_sw); 185 printf("%6d%5d", total.t_avm/2, total.t_free/2); 186 printf("%4d%3d%4d", 187 (rate.v_pgrec - (rate.v_xsfrec+rate.v_xifrec))/nintv, 188 (rate.v_xsfrec+rate.v_xifrec)/nintv, rate.v_pgpgin/2/nintv); 189 printf("%4d%4d%4d%4d", rate.v_pgpgout/2/nintv, 190 rate.v_dfree/2/nintv, deficit/2, rate.v_scan/nintv); 191 etime /= 60.; 192 for(i=0; i<4; i++) 193 stats(i); 194 printf("%4d%4d", (rate.v_intr/nintv) - hz, rate.v_syscall/nintv); 195 printf("%4d", rate.v_swtch/nintv); 196 for(i=0; i<CPUSTATES; i++) { 197 float f = stat1(i); 198 if (i == 0) { /* US+NI */ 199 i++; 200 f += stat1(i); 201 } 202 printf("%3.0f", f); 203 } 204 printf("\n"); 205 fflush(stdout); 206 contin: 207 nintv = 1; 208 --iter; 209 if(iter) 210 if(argc > 0) { 211 sleep(atoi(argv[0])); 212 if (--lines <= 0) 213 goto reprint; 214 goto loop; 215 } 216 } 217 218 dotimes() 219 { 220 221 lseek(mf, (long)nl[X_REC].n_value, 0); 222 read(mf, &s.rectime, sizeof s.rectime); 223 lseek(mf, (long)nl[X_PGIN].n_value, 0); 224 read(mf, &s.pgintime, sizeof s.pgintime); 225 lseek(mf, (long)nl[X_SUM].n_value, 0); 226 read(mf, &sum, sizeof sum); 227 printf("%d reclaims, %d total time (usec)\n", sum.v_pgrec, s.rectime); 228 printf("average: %d usec / reclaim\n", s.rectime/sum.v_pgrec); 229 printf("\n"); 230 printf("%d page ins, %d total time (msec)\n",sum.v_pgin, s.pgintime/10); 231 printf("average: %8.1f msec / page in\n", s.pgintime/(sum.v_pgin*10.0)); 232 } 233 234 dosum() 235 { 236 237 lseek(mf, (long)nl[X_SUM].n_value, 0); 238 read(mf, &sum, sizeof sum); 239 printf("%9d swap ins\n", sum.v_swpin); 240 printf("%9d swap outs\n", sum.v_swpout); 241 printf("%9d pages swapped in\n", sum.v_pswpin / CLSIZE); 242 printf("%9d pages swapped out\n", sum.v_pswpout / CLSIZE); 243 printf("%9d total address trans. faults taken\n", sum.v_faults); 244 printf("%9d page ins\n", sum.v_pgin); 245 printf("%9d page outs\n", sum.v_pgout); 246 printf("%9d pages paged in\n", sum.v_pgpgin); 247 printf("%9d pages paged out\n", sum.v_pgpgout); 248 printf("%9d sequential process pages freed\n", sum.v_seqfree); 249 printf("%9d total reclaims\n", sum.v_pgrec); 250 printf("%9d reclaims from free list\n", sum.v_pgfrec); 251 printf("%9d intransit blocking page faults\n", sum.v_intrans); 252 printf("%9d zero fill pages created\n", sum.v_nzfod / CLSIZE); 253 printf("%9d zero fill page faults\n", sum.v_zfod / CLSIZE); 254 printf("%9d executable fill pages created\n", sum.v_nexfod / CLSIZE); 255 printf("%9d executable fill page faults\n", sum.v_exfod / CLSIZE); 256 printf("%9d swap text pages found in free list\n", sum.v_xsfrec); 257 printf("%9d inode text pages found in free list\n", sum.v_xifrec); 258 printf("%9d file fill pages created\n", sum.v_nvrfod / CLSIZE); 259 printf("%9d file fill page faults\n", sum.v_vrfod / CLSIZE); 260 printf("%9d pages examined by the clock daemon\n", sum.v_scan); 261 printf("%9d revolutions of the clock hand\n", sum.v_rev); 262 printf("%9d pages freed by the clock daemon\n", sum.v_dfree / CLSIZE); 263 printf("%9d cpu context switches\n", sum.v_swtch); 264 printf("%9d device interrupts\n", sum.v_intr); 265 printf("%9d pseduo-dma dz interrupts\n", sum.v_pdma); 266 printf("%9d traps\n", sum.v_trap); 267 printf("%9d system calls\n", sum.v_syscall); 268 } 269 270 271 doforkst() 272 { 273 274 lseek(mf, (long)nl[X_FORKSTAT].n_value, 0); 275 read(mf, &forkstat, sizeof forkstat); 276 printf("%d forks, %d pages, average=%.2f\n", 277 forkstat.cntfork, forkstat.sizfork, 278 (float) forkstat.sizfork / forkstat.cntfork); 279 printf("%d vforks, %d pages, average=%.2f\n", 280 forkstat.cntvfork, forkstat.sizvfork, 281 (float)forkstat.sizvfork / forkstat.cntvfork); 282 } 283 284 stats(dn) 285 { 286 287 if (dn >= DK_NDRIVE) { 288 printf(" 0"); 289 return; 290 } 291 printf("%3.0f", s.xfer[dn]/etime); 292 } 293 294 double 295 stat1(row) 296 { 297 double t; 298 register i; 299 300 t = 0; 301 for(i=0; i<CPUSTATES; i++) 302 t += s.time[i]; 303 if(t == 0.) 304 t = 1.; 305 return(s.time[row]*100./t); 306 } 307 308 pct(top, bot) 309 { 310 311 if (bot == 0) 312 return (0); 313 return ((top * 100) / bot); 314 } 315 316 /* 317 * Read the drive names out of kmem. 318 * ARGH ARGH ARGH ARGH !!!!!!!!!!!! 319 */ 320 321 #define steal(where, var) lseek(mf, where, 0); read(mf, &var, sizeof var); 322 read_names() 323 { 324 struct mba_device mdev; 325 register struct mba_device *mp; 326 struct mba_driver mdrv; 327 short two_char; 328 char *cp = (char *) &two_char; 329 struct uba_device udev, *up; 330 struct uba_driver udrv; 331 332 mp = (struct mba_device *) nl[X_MBDINIT].n_value; 333 up = (struct uba_device *) nl[X_UBDINIT].n_value; 334 if (up == 0) { 335 fprintf(stderr, "iostat: Disk init info not in namelist\n"); 336 exit(1); 337 } 338 if (mp) for (;;) { 339 steal(mp++, mdev); 340 if (mdev.mi_driver == 0) 341 break; 342 if (mdev.mi_dk < 0 || mdev.mi_alive == 0) 343 continue; 344 steal(mdev.mi_driver, mdrv); 345 steal(mdrv.md_dname, two_char); 346 sprintf(dr_name[mdev.mi_dk], "%c%c", cp[0], cp[1]); 347 dr_unit[mdev.mi_dk] = mdev.mi_unit; 348 } 349 for (;;) { 350 steal(up++, udev); 351 if (udev.ui_driver == 0) 352 break; 353 if (udev.ui_dk < 0 || udev.ui_alive == 0) 354 continue; 355 steal(udev.ui_driver, udrv); 356 steal(udrv.ud_dname, two_char); 357 sprintf(dr_name[udev.ui_dk], "%c%c", cp[0], cp[1]); 358 dr_unit[udev.ui_dk] = udev.ui_unit; 359 } 360 } 361