| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: vmstat.c,v 1.187 2012/03/20 20:34:59 matt Exp $ */ | | 1 | /* $NetBSD: vmstat.c,v 1.188 2012/04/29 16:23:56 para Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 1998, 2000, 2001, 2007 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 1998, 2000, 2001, 2007 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation by: | | 7 | * This code is derived from software contributed to The NetBSD Foundation by: |
8 | * - Jason R. Thorpe of the Numerical Aerospace Simulation Facility, | | 8 | * - Jason R. Thorpe of the Numerical Aerospace Simulation Facility, |
9 | * NASA Ames Research Center. | | 9 | * NASA Ames Research Center. |
10 | * - Simon Burge and Luke Mewburn of Wasabi Systems, Inc. | | 10 | * - Simon Burge and Luke Mewburn of Wasabi Systems, Inc. |
11 | * | | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | | 12 | * Redistribution and use in source and binary forms, with or without |
13 | * modification, are permitted provided that the following conditions | | 13 | * modification, are permitted provided that the following conditions |
14 | * are met: | | 14 | * are met: |
| @@ -60,27 +60,27 @@ | | | @@ -60,27 +60,27 @@ |
60 | * SUCH DAMAGE. | | 60 | * SUCH DAMAGE. |
61 | */ | | 61 | */ |
62 | | | 62 | |
63 | #include <sys/cdefs.h> | | 63 | #include <sys/cdefs.h> |
64 | #ifndef lint | | 64 | #ifndef lint |
65 | __COPYRIGHT("@(#) Copyright (c) 1980, 1986, 1991, 1993\ | | 65 | __COPYRIGHT("@(#) Copyright (c) 1980, 1986, 1991, 1993\ |
66 | The Regents of the University of California. All rights reserved."); | | 66 | The Regents of the University of California. All rights reserved."); |
67 | #endif /* not lint */ | | 67 | #endif /* not lint */ |
68 | | | 68 | |
69 | #ifndef lint | | 69 | #ifndef lint |
70 | #if 0 | | 70 | #if 0 |
71 | static char sccsid[] = "@(#)vmstat.c 8.2 (Berkeley) 3/1/95"; | | 71 | static char sccsid[] = "@(#)vmstat.c 8.2 (Berkeley) 3/1/95"; |
72 | #else | | 72 | #else |
73 | __RCSID("$NetBSD: vmstat.c,v 1.187 2012/03/20 20:34:59 matt Exp $"); | | 73 | __RCSID("$NetBSD: vmstat.c,v 1.188 2012/04/29 16:23:56 para Exp $"); |
74 | #endif | | 74 | #endif |
75 | #endif /* not lint */ | | 75 | #endif /* not lint */ |
76 | | | 76 | |
77 | #define __POOL_EXPOSE | | 77 | #define __POOL_EXPOSE |
78 | | | 78 | |
79 | #include <sys/param.h> | | 79 | #include <sys/param.h> |
80 | #include <sys/types.h> | | 80 | #include <sys/types.h> |
81 | #include <sys/mount.h> | | 81 | #include <sys/mount.h> |
82 | #include <sys/uio.h> | | 82 | #include <sys/uio.h> |
83 | | | 83 | |
84 | #include <sys/buf.h> | | 84 | #include <sys/buf.h> |
85 | #include <sys/evcnt.h> | | 85 | #include <sys/evcnt.h> |
86 | #include <sys/ioctl.h> | | 86 | #include <sys/ioctl.h> |
| @@ -151,43 +151,39 @@ struct cpuqueue cpu_queue; | | | @@ -151,43 +151,39 @@ struct cpuqueue cpu_queue; |
151 | /* | | 151 | /* |
152 | * General namelist | | 152 | * General namelist |
153 | */ | | 153 | */ |
154 | struct nlist namelist[] = | | 154 | struct nlist namelist[] = |
155 | { | | 155 | { |
156 | #define X_BOOTTIME 0 | | 156 | #define X_BOOTTIME 0 |
157 | { .n_name = "_boottime" }, | | 157 | { .n_name = "_boottime" }, |
158 | #define X_HZ 1 | | 158 | #define X_HZ 1 |
159 | { .n_name = "_hz" }, | | 159 | { .n_name = "_hz" }, |
160 | #define X_STATHZ 2 | | 160 | #define X_STATHZ 2 |
161 | { .n_name = "_stathz" }, | | 161 | { .n_name = "_stathz" }, |
162 | #define X_NCHSTATS 3 | | 162 | #define X_NCHSTATS 3 |
163 | { .n_name = "_nchstats" }, | | 163 | { .n_name = "_nchstats" }, |
164 | #define X_KMEMSTAT 4 | | 164 | #define X_ALLEVENTS 4 |
165 | { .n_name = "_kmemstatistics" }, | | | |
166 | #define X_KMEMBUCKETS 5 | | | |
167 | { .n_name = "_kmembuckets" }, | | | |
168 | #define X_ALLEVENTS 6 | | | |
169 | { .n_name = "_allevents" }, | | 165 | { .n_name = "_allevents" }, |
170 | #define X_POOLHEAD 7 | | 166 | #define X_POOLHEAD 5 |
171 | { .n_name = "_pool_head" }, | | 167 | { .n_name = "_pool_head" }, |
172 | #define X_UVMEXP 8 | | 168 | #define X_UVMEXP 6 |
173 | { .n_name = "_uvmexp" }, | | 169 | { .n_name = "_uvmexp" }, |
174 | #define X_TIME_SECOND 9 | | 170 | #define X_TIME_SECOND 7 |
175 | { .n_name = "_time_second" }, | | 171 | { .n_name = "_time_second" }, |
176 | #define X_TIME 10 | | 172 | #define X_TIME 8 |
177 | { .n_name = "_time" }, | | 173 | { .n_name = "_time" }, |
178 | #define X_CPU_QUEUE 11 | | 174 | #define X_CPU_QUEUE 9 |
179 | { .n_name = "_cpu_queue" }, | | 175 | { .n_name = "_cpu_queue" }, |
180 | #define X_NL_SIZE 12 | | 176 | #define X_NL_SIZE 10 |
181 | { .n_name = NULL }, | | 177 | { .n_name = NULL }, |
182 | }; | | 178 | }; |
183 | | | 179 | |
184 | /* | | 180 | /* |
185 | * Namelist for pre-evcnt interrupt counters. | | 181 | * Namelist for pre-evcnt interrupt counters. |
186 | */ | | 182 | */ |
187 | struct nlist intrnl[] = | | 183 | struct nlist intrnl[] = |
188 | { | | 184 | { |
189 | #define X_INTRNAMES 0 | | 185 | #define X_INTRNAMES 0 |
190 | { .n_name = "_intrnames" }, | | 186 | { .n_name = "_intrnames" }, |
191 | #define X_EINTRNAMES 1 | | 187 | #define X_EINTRNAMES 1 |
192 | { .n_name = "_eintrnames" }, | | 188 | { .n_name = "_eintrnames" }, |
193 | #define X_INTRCNT 2 | | 189 | #define X_INTRCNT 2 |
| @@ -292,27 +288,26 @@ kvm_t *kd; | | | @@ -292,27 +288,26 @@ kvm_t *kd; |
292 | (width) - (fixed) - (ovflw) : 0, \ | | 288 | (width) - (fixed) - (ovflw) : 0, \ |
293 | (val)) - (width); \ | | 289 | (val)) - (width); \ |
294 | if ((ovflw) < 0) \ | | 290 | if ((ovflw) < 0) \ |
295 | (ovflw) = 0; \ | | 291 | (ovflw) = 0; \ |
296 | } while (/* CONSTCOND */0) | | 292 | } while (/* CONSTCOND */0) |
297 | | | 293 | |
298 | void cpustats(int *); | | 294 | void cpustats(int *); |
299 | void cpucounters(struct cpu_counter *); | | 295 | void cpucounters(struct cpu_counter *); |
300 | void deref_kptr(const void *, void *, size_t, const char *); | | 296 | void deref_kptr(const void *, void *, size_t, const char *); |
301 | void drvstats(int *); | | 297 | void drvstats(int *); |
302 | void doevcnt(int verbose, int type); | | 298 | void doevcnt(int verbose, int type); |
303 | void dohashstat(int, int, const char *); | | 299 | void dohashstat(int, int, const char *); |
304 | void dointr(int verbose); | | 300 | void dointr(int verbose); |
305 | void domem(void); | | | |
306 | void dopool(int, int); | | 301 | void dopool(int, int); |
307 | void dopoolcache(int); | | 302 | void dopoolcache(int); |
308 | void dosum(void); | | 303 | void dosum(void); |
309 | void dovmstat(struct timespec *, int); | | 304 | void dovmstat(struct timespec *, int); |
310 | void print_total_hdr(void); | | 305 | void print_total_hdr(void); |
311 | void dovmtotal(struct timespec *, int); | | 306 | void dovmtotal(struct timespec *, int); |
312 | void kread(struct nlist *, int, void *, size_t); | | 307 | void kread(struct nlist *, int, void *, size_t); |
313 | int kreadc(struct nlist *, int, void *, size_t); | | 308 | int kreadc(struct nlist *, int, void *, size_t); |
314 | void needhdr(int); | | 309 | void needhdr(int); |
315 | void getnlist(int); | | 310 | void getnlist(int); |
316 | long getuptime(void); | | 311 | long getuptime(void); |
317 | void printhdr(void); | | 312 | void printhdr(void); |
318 | long pct(long, long); | | 313 | long pct(long, long); |
| @@ -484,27 +479,26 @@ main(int argc, char *argv[]) | | | @@ -484,27 +479,26 @@ main(int argc, char *argv[]) |
484 | if (todo & (HISTLIST|HISTDUMP)) { | | 479 | if (todo & (HISTLIST|HISTDUMP)) { |
485 | if ((todo & (HISTLIST|HISTDUMP)) == | | 480 | if ((todo & (HISTLIST|HISTDUMP)) == |
486 | (HISTLIST|HISTDUMP)) | | 481 | (HISTLIST|HISTDUMP)) |
487 | errx(1, "you may list or dump," | | 482 | errx(1, "you may list or dump," |
488 | " but not both!"); | | 483 | " but not both!"); |
489 | hist_traverse(todo, histname); | | 484 | hist_traverse(todo, histname); |
490 | (void)putchar('\n'); | | 485 | (void)putchar('\n'); |
491 | } | | 486 | } |
492 | if (todo & FORKSTAT) { | | 487 | if (todo & FORKSTAT) { |
493 | doforkst(); | | 488 | doforkst(); |
494 | (void)putchar('\n'); | | 489 | (void)putchar('\n'); |
495 | } | | 490 | } |
496 | if (todo & MEMSTAT) { | | 491 | if (todo & MEMSTAT) { |
497 | domem(); | | | |
498 | dopool(verbose, wide); | | 492 | dopool(verbose, wide); |
499 | (void)putchar('\n'); | | 493 | (void)putchar('\n'); |
500 | } | | 494 | } |
501 | if (todo & POOLCACHESTAT) { | | 495 | if (todo & POOLCACHESTAT) { |
502 | dopoolcache(verbose); | | 496 | dopoolcache(verbose); |
503 | (void)putchar('\n'); | | 497 | (void)putchar('\n'); |
504 | } | | 498 | } |
505 | if (todo & SUMSTAT) { | | 499 | if (todo & SUMSTAT) { |
506 | dosum(); | | 500 | dosum(); |
507 | (void)putchar('\n'); | | 501 | (void)putchar('\n'); |
508 | } | | 502 | } |
509 | if (todo & INTRSTAT) { | | 503 | if (todo & INTRSTAT) { |
510 | dointr(verbose); | | 504 | dointr(verbose); |
| @@ -1216,139 +1210,26 @@ doevcnt(int verbose, int type) | | | @@ -1216,139 +1210,26 @@ doevcnt(int verbose, int type) |
1216 | 34 - (evcnt.ev_grouplen + 1 + evcnt.ev_namelen), "", | | 1210 | 34 - (evcnt.ev_grouplen + 1 + evcnt.ev_namelen), "", |
1217 | evcnt.ev_count, | | 1211 | evcnt.ev_count, |
1218 | (evcnt.ev_count / uptime), | | 1212 | (evcnt.ev_count / uptime), |
1219 | (evcnt.ev_type < __arraycount(evtypes) ? | | 1213 | (evcnt.ev_type < __arraycount(evtypes) ? |
1220 | evtypes[evcnt.ev_type] : "?")); | | 1214 | evtypes[evcnt.ev_type] : "?")); |
1221 | | | 1215 | |
1222 | counttotal += evcnt.ev_count; | | 1216 | counttotal += evcnt.ev_count; |
1223 | } | | 1217 | } |
1224 | if (type != EVCNT_TYPE_ANY) | | 1218 | if (type != EVCNT_TYPE_ANY) |
1225 | (void)printf("%-34s %16"PRIu64" %8"PRIu64"\n", | | 1219 | (void)printf("%-34s %16"PRIu64" %8"PRIu64"\n", |
1226 | "Total", counttotal, counttotal / uptime); | | 1220 | "Total", counttotal, counttotal / uptime); |
1227 | } | | 1221 | } |
1228 | | | 1222 | |
1229 | static char memname[64]; | | | |
1230 | | | | |
1231 | void | | | |
1232 | domem(void) | | | |
1233 | { | | | |
1234 | struct kmembuckets *kp; | | | |
1235 | struct malloc_type ks, *ksp; | | | |
1236 | int i, j; | | | |
1237 | int len, size, first; | | | |
1238 | long totuse = 0, totfree = 0, totreq = 0; | | | |
1239 | struct kmembuckets buckets[MINBUCKET + 16]; | | | |
1240 | | | | |
1241 | kread(namelist, X_KMEMBUCKETS, buckets, sizeof(buckets)); | | | |
1242 | for (first = 1, i = MINBUCKET, kp = &buckets[i]; i < MINBUCKET + 16; | | | |
1243 | i++, kp++) { | | | |
1244 | if (kp->kb_calls == 0) | | | |
1245 | continue; | | | |
1246 | if (first) { | | | |
1247 | (void)printf("Memory statistics by bucket size\n"); | | | |
1248 | (void)printf( | | | |
1249 | " Size In Use Free Requests HighWater Couldfree\n"); | | | |
1250 | first = 0; | | | |
1251 | } | | | |
1252 | size = 1 << i; | | | |
1253 | (void)printf("%8d %8ld %6ld %10ld %7ld %10ld\n", size, | | | |
1254 | kp->kb_total - kp->kb_totalfree, | | | |
1255 | kp->kb_totalfree, kp->kb_calls, | | | |
1256 | kp->kb_highwat, kp->kb_couldfree); | | | |
1257 | totfree += size * kp->kb_totalfree; | | | |
1258 | } | | | |
1259 | | | | |
1260 | /* | | | |
1261 | * If kmem statistics are not being gathered by the kernel, | | | |
1262 | * first will still be 1. | | | |
1263 | */ | | | |
1264 | if (first) { | | | |
1265 | warnx("Kmem statistics are not being gathered by the kernel."); | | | |
1266 | return; | | | |
1267 | } | | | |
1268 | | | | |
1269 | (void)printf("\nMemory usage type by bucket size\n"); | | | |
1270 | (void)printf(" Size Type(s)\n"); | | | |
1271 | kp = &buckets[MINBUCKET]; | | | |
1272 | for (j = 1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1, kp++) { | | | |
1273 | if (kp->kb_calls == 0) | | | |
1274 | continue; | | | |
1275 | first = 1; | | | |
1276 | len = 8; | | | |
1277 | for (kread(namelist, X_KMEMSTAT, &ksp, sizeof(ksp)); | | | |
1278 | ksp != NULL; ksp = ks.ks_next) { | | | |
1279 | deref_kptr(ksp, &ks, sizeof(ks), "malloc type"); | | | |
1280 | if (ks.ks_calls == 0) | | | |
1281 | continue; | | | |
1282 | if ((ks.ks_size & j) == 0) | | | |
1283 | continue; | | | |
1284 | deref_kptr(ks.ks_shortdesc, memname, | | | |
1285 | sizeof(memname), "malloc type name"); | | | |
1286 | len += 2 + strlen(memname); | | | |
1287 | if (first) | | | |
1288 | (void)printf("%8d %s", j, memname); | | | |
1289 | else | | | |
1290 | (void)printf(","); | | | |
1291 | if (len >= 80) { | | | |
1292 | (void)printf("\n\t "); | | | |
1293 | len = 10 + strlen(memname); | | | |
1294 | } | | | |
1295 | if (!first) | | | |
1296 | (void)printf(" %s", memname); | | | |
1297 | first = 0; | | | |
1298 | } | | | |
1299 | (void)putchar('\n'); | | | |
1300 | } | | | |
1301 | | | | |
1302 | (void)printf( | | | |
1303 | "\nMemory statistics by type Type Kern\n"); | | | |
1304 | (void)printf( | | | |
1305 | " Type InUse MemUse HighUse Limit Requests Limit Limit Size(s)\n"); | | | |
1306 | for (kread(namelist, X_KMEMSTAT, &ksp, sizeof(ksp)); | | | |
1307 | ksp != NULL; ksp = ks.ks_next) { | | | |
1308 | deref_kptr(ksp, &ks, sizeof(ks), "malloc type"); | | | |
1309 | if (ks.ks_calls == 0) | | | |
1310 | continue; | | | |
1311 | deref_kptr(ks.ks_shortdesc, memname, | | | |
1312 | sizeof(memname), "malloc type name"); | | | |
1313 | (void)printf("%15s %5ld %6ldK %6ldK %6ldK %10ld %5u %5u", | | | |
1314 | memname, | | | |
1315 | ks.ks_inuse, howmany(ks.ks_memuse, KILO), | | | |
1316 | howmany(ks.ks_maxused, KILO), | | | |
1317 | howmany(ks.ks_limit, KILO), ks.ks_calls, | | | |
1318 | ks.ks_limblocks, ks.ks_mapblocks); | | | |
1319 | first = 1; | | | |
1320 | for (j = 1 << MINBUCKET, i = MINBUCKET; | | | |
1321 | j < 1 << (MINBUCKET + 16); | | | |
1322 | j <<= 1, i++) | | | |
1323 | { | | | |
1324 | if ((ks.ks_size & j) == 0) | | | |
1325 | continue; | | | |
1326 | if (first) | | | |
1327 | (void)printf(" %d", j); | | | |
1328 | else | | | |
1329 | (void)printf(",%d", j); | | | |
1330 | first = 0; | | | |
1331 | (void)printf(":%u", ks.ks_active[i - MINBUCKET]); | | | |
1332 | } | | | |
1333 | (void)printf("\n"); | | | |
1334 | totuse += ks.ks_memuse; | | | |
1335 | totreq += ks.ks_calls; | | | |
1336 | } | | | |
1337 | (void)printf("\nMemory totals: In Use Free Requests\n"); | | | |
1338 | (void)printf(" %7ldK %6ldK %8ld\n\n", | | | |
1339 | howmany(totuse, KILO), howmany(totfree, KILO), totreq); | | | |
1340 | } | | | |
1341 | | | | |
1342 | void | | 1223 | void |
1343 | dopool(int verbose, int wide) | | 1224 | dopool(int verbose, int wide) |
1344 | { | | 1225 | { |
1345 | int first, ovflw; | | 1226 | int first, ovflw; |
1346 | void *addr; | | 1227 | void *addr; |
1347 | long total, inuse, this_total, this_inuse; | | 1228 | long total, inuse, this_total, this_inuse; |
1348 | TAILQ_HEAD(,pool) pool_head; | | 1229 | TAILQ_HEAD(,pool) pool_head; |
1349 | struct pool pool, *pp = &pool; | | 1230 | struct pool pool, *pp = &pool; |
1350 | struct pool_allocator pa; | | 1231 | struct pool_allocator pa; |
1351 | char name[32], maxp[32]; | | 1232 | char name[32], maxp[32]; |
1352 | | | 1233 | |
1353 | kread(namelist, X_POOLHEAD, &pool_head, sizeof(pool_head)); | | 1234 | kread(namelist, X_POOLHEAD, &pool_head, sizeof(pool_head)); |
1354 | addr = TAILQ_FIRST(&pool_head); | | 1235 | addr = TAILQ_FIRST(&pool_head); |