diff options
Diffstat (limited to 'usr/src/cmd/mdb/common')
| -rw-r--r-- | usr/src/cmd/mdb/common/mdb/mdb_modapi.c | 199 | ||||
| -rw-r--r-- | usr/src/cmd/mdb/common/mdb/mdb_modapi.h | 5 | ||||
| -rw-r--r-- | usr/src/cmd/mdb/common/modules/genunix/Makefile.files | 1 | ||||
| -rw-r--r-- | usr/src/cmd/mdb/common/modules/genunix/dist.c | 226 | ||||
| -rw-r--r-- | usr/src/cmd/mdb/common/modules/genunix/dist.h | 44 | ||||
| -rw-r--r-- | usr/src/cmd/mdb/common/modules/genunix/kmem.c | 10 | ||||
| -rw-r--r-- | usr/src/cmd/mdb/common/modules/libumem/umem.c | 10 |
7 files changed, 281 insertions, 214 deletions
diff --git a/usr/src/cmd/mdb/common/mdb/mdb_modapi.c b/usr/src/cmd/mdb/common/mdb/mdb_modapi.c index 2f30802dfc..670df6a2e2 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_modapi.c +++ b/usr/src/cmd/mdb/common/mdb/mdb_modapi.c @@ -36,9 +36,6 @@ #include <mdb/mdb_lex.h> #include <mdb/mdb_frame.h> #include <mdb/mdb.h> -#ifndef _KMDB -#include <math.h> -#endif /* * Private callback structure for implementing mdb_walk_dcmd, below. @@ -855,199 +852,3 @@ mdb_callback_remove(void *hdl) { mdb_callb_remove(hdl); } - -/* - * Divides the given range (inclusive at both endpoints) evenly into the given - * number of buckets, adding one bucket at the end that is one past the end of - * the range. The returned buckets will be automatically freed when the dcmd - * completes or is forcibly aborted. - */ -const int * -mdb_dist_linear(int buckets, int beg, int end) -{ - int *out = mdb_alloc((buckets + 1) * sizeof (*out), UM_SLEEP | UM_GC); - int pos; - int dist = end - beg + 1; - - for (pos = 0; pos < buckets; pos++) - out[pos] = beg + (pos * dist)/buckets; - out[buckets] = end + 1; - - return (out); -} - -/* - * We want the bins to be a constant ratio: - * - * b_0 = beg; - * b_idx = b_{idx-1} * r; - * b_buckets = end + 1; - * - * That is: - * - * buckets - * beg * r = end - * - * Which reduces to: - * - * buckets ___________________ - * r = -------/ ((end + 1) / beg) - * - * log ((end + 1) / beg) - * log r = --------------------- - * buckets - * - * (log ((end + 1) / beg)) / buckets - * r = e - */ -/* ARGSUSED */ -const int * -mdb_dist_geometric(int buckets, int beg, int end, int minbucketsize) -{ -#ifdef _KMDB - return (mdb_dist_linear(buckets, beg, end)); -#else - int *out = mdb_alloc((buckets + 1) * sizeof (*out), UM_SLEEP | UM_GC); - - extern double log(double); - extern double exp(double); - - double r; - double b; - int idx = 0; - int last; - int begzero; - - if (minbucketsize == 0) - minbucketsize = 1; - - if (buckets == 1) { - out[0] = beg; - out[1] = end + 1; - return (out); - } - - begzero = (beg == 0); - if (begzero) - beg = 1; - - r = exp(log((double)(end + 1) / beg) / buckets); - - /* - * We've now computed r, using the previously derived formula. We - * now need to generate the array of bucket bounds. There are - * two major variables: - * - * b holds b_idx, the current index, as a double. - * last holds the integer which goes into out[idx] - * - * Our job is to transform the smooth function b_idx, defined - * above, into integer-sized buckets, with a specified minimum - * bucket size. Since b_idx is an exponentially growing function, - * any inadequate buckets must be at the beginning. To deal - * with this, we make buckets of minimum size until b catches up - * with last. - * - * A final wrinkle is that beg *can* be zero. We compute r and b - * as if beg was 1, then start last as 0. This can lead to a bit - * of oddness around the 0 bucket, but it's mostly reasonable. - */ - - b = last = beg; - if (begzero) - last = 0; - - for (idx = 0; idx < buckets; idx++) { - int next; - - out[idx] = last; - - b *= r; - next = (int)b; - - if (next > last + minbucketsize - 1) - last = next; - else - last += minbucketsize; - } - out[buckets] = end + 1; - - return (out); -#endif -} - -#define NCHARS 50 -/* - * Print the distribution header with the given bucket label. The header is - * printed on a single line, and the label is assumed to fit within the given - * width (number of characters). The default label width when unspecified (0) - * is eleven characters. Optionally, a label other than "count" may be specified - * for the bucket counts. - */ -void -mdb_dist_print_header(const char *label, int width, const char *count) -{ - int n; - const char *dist = " Distribution "; - char dashes[NCHARS + 1]; - - if (width == 0) - width = 11; - - if (count == NULL) - count = "count"; - - n = (NCHARS - strlen(dist)) / 2; - (void) memset(dashes, '-', n); - dashes[n] = '\0'; - - mdb_printf("%*s %s%s%s %s\n", width, label, dashes, dist, dashes, - count); -} - -/* - * Print one distribution bucket whose range is from distarray[i] inclusive to - * distarray[i + 1] exclusive by totalling counts in that index range. The - * given total is assumed to be the sum of all elements in the counts array. - * Each bucket is labeled by its range in the form "first-last" (omit "-last" if - * the range is a single value) where first and last are integers, and last is - * one less than the first value of the next bucket range. The bucket label is - * assumed to fit within the given width (number of characters), which should - * match the width value passed to mdb_dist_print_header(). The default width - * when unspecified (0) is eleven characters. - */ -void -mdb_dist_print_bucket(const int *distarray, int i, uint_t counts[], - uint64_t total, int width) -{ - int b; /* bucket range index */ - int bb = distarray[i]; /* bucket begin */ - int be = distarray[i + 1] - 1; /* bucket end */ - uint64_t count = 0; /* bucket value */ - - int nats; - char ats[NCHARS + 1], spaces[NCHARS + 1]; - char range[40]; - - if (width == 0) - width = 11; - - if (total == 0) - total = 1; /* avoid divide-by-zero */ - - for (b = bb; b <= be; b++) - count += counts[b]; - - nats = (NCHARS * count) / total; - (void) memset(ats, '@', nats); - ats[nats] = 0; - (void) memset(spaces, ' ', NCHARS - nats); - spaces[NCHARS - nats] = 0; - - if (bb == be) - (void) mdb_snprintf(range, sizeof (range), "%d", bb); - else - (void) mdb_snprintf(range, sizeof (range), "%d-%d", bb, be); - mdb_printf("%*s |%s%s %lld\n", width, range, ats, spaces, count); -} -#undef NCHARS diff --git a/usr/src/cmd/mdb/common/mdb/mdb_modapi.h b/usr/src/cmd/mdb/common/mdb/mdb_modapi.h index 15eb7828f4..338c56c55f 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_modapi.h +++ b/usr/src/cmd/mdb/common/mdb/mdb_modapi.h @@ -289,11 +289,6 @@ typedef void (*mdb_callback_f)(void *); extern void *mdb_callback_add(int, mdb_callback_f, void *); extern void mdb_callback_remove(void *); -extern const int *mdb_dist_linear(int, int, int); -extern const int *mdb_dist_geometric(int, int, int, int); -extern void mdb_dist_print_header(const char *, int, const char *); -extern void mdb_dist_print_bucket(const int *, int, uint_t[], uint64_t, int); - extern size_t strlcat(char *, const char *, size_t); extern char *strcat(char *, const char *); extern char *strcpy(char *, const char *); diff --git a/usr/src/cmd/mdb/common/modules/genunix/Makefile.files b/usr/src/cmd/mdb/common/modules/genunix/Makefile.files index c4fa4477b6..8bf1c1b520 100644 --- a/usr/src/cmd/mdb/common/modules/genunix/Makefile.files +++ b/usr/src/cmd/mdb/common/modules/genunix/Makefile.files @@ -37,6 +37,7 @@ GENUNIX_SRCS = \ ctxop.c \ cyclic.c \ devinfo.c \ + dist.c \ findstack.c \ fm.c \ genunix.c \ diff --git a/usr/src/cmd/mdb/common/modules/genunix/dist.c b/usr/src/cmd/mdb/common/modules/genunix/dist.c new file mode 100644 index 0000000000..37b6ad553f --- /dev/null +++ b/usr/src/cmd/mdb/common/modules/genunix/dist.c @@ -0,0 +1,226 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <mdb/mdb_modapi.h> +#ifndef _KMDB +#include <math.h> +#endif + +#include "dist.h" + +/* + * Divides the given range (inclusive at both endpoints) evenly into the given + * number of buckets, adding one bucket at the end that is one past the end of + * the range. The returned buckets will be automatically freed when the dcmd + * completes or is forcibly aborted. + */ +const int * +dist_linear(int buckets, int beg, int end) +{ + int *out = mdb_alloc((buckets + 1) * sizeof (*out), UM_SLEEP | UM_GC); + int pos; + int dist = end - beg + 1; + + for (pos = 0; pos < buckets; pos++) + out[pos] = beg + (pos * dist)/buckets; + out[buckets] = end + 1; + + return (out); +} + +/* + * We want the bins to be a constant ratio: + * + * b_0 = beg; + * b_idx = b_{idx-1} * r; + * b_buckets = end + 1; + * + * That is: + * + * buckets + * beg * r = end + * + * Which reduces to: + * + * buckets ___________________ + * r = -------/ ((end + 1) / beg) + * + * log ((end + 1) / beg) + * log r = --------------------- + * buckets + * + * (log ((end + 1) / beg)) / buckets + * r = e + */ +/* ARGSUSED */ +const int * +dist_geometric(int buckets, int beg, int end, int minbucketsize) +{ +#ifdef _KMDB + return (dist_linear(buckets, beg, end)); +#else + int *out = mdb_alloc((buckets + 1) * sizeof (*out), UM_SLEEP | UM_GC); + + double r; + double b; + int idx = 0; + int last; + int begzero; + + if (minbucketsize == 0) + minbucketsize = 1; + + if (buckets == 1) { + out[0] = beg; + out[1] = end + 1; + return (out); + } + + begzero = (beg == 0); + if (begzero) + beg = 1; + + r = exp(log((double)(end + 1) / beg) / buckets); + + /* + * We've now computed r, using the previously derived formula. We + * now need to generate the array of bucket bounds. There are + * two major variables: + * + * b holds b_idx, the current index, as a double. + * last holds the integer which goes into out[idx] + * + * Our job is to transform the smooth function b_idx, defined + * above, into integer-sized buckets, with a specified minimum + * bucket size. Since b_idx is an exponentially growing function, + * any inadequate buckets must be at the beginning. To deal + * with this, we make buckets of minimum size until b catches up + * with last. + * + * A final wrinkle is that beg *can* be zero. We compute r and b + * as if beg was 1, then start last as 0. This can lead to a bit + * of oddness around the 0 bucket, but it's mostly reasonable. + */ + + b = last = beg; + if (begzero) + last = 0; + + for (idx = 0; idx < buckets; idx++) { + int next; + + out[idx] = last; + + b *= r; + next = (int)b; + + if (next > last + minbucketsize - 1) + last = next; + else + last += minbucketsize; + } + out[buckets] = end + 1; + + return (out); +#endif +} + +#define NCHARS 50 +/* + * Print the distribution header with the given bucket label. The header is + * printed on a single line, and the label is assumed to fit within the given + * width (number of characters). The default label width when unspecified (0) + * is eleven characters. Optionally, a label other than "count" may be specified + * for the bucket counts. + */ +void +dist_print_header(const char *label, int width, const char *count) +{ + int n; + const char *dist = " Distribution "; + char dashes[NCHARS + 1]; + + if (width == 0) + width = 11; + + if (count == NULL) + count = "count"; + + n = (NCHARS - strlen(dist)) / 2; + (void) memset(dashes, '-', n); + dashes[n] = '\0'; + + mdb_printf("%*s %s%s%s %s\n", width, label, dashes, dist, dashes, + count); +} + +/* + * Print one distribution bucket whose range is from distarray[i] inclusive to + * distarray[i + 1] exclusive by totalling counts in that index range. The + * given total is assumed to be the sum of all elements in the counts array. + * Each bucket is labeled by its range in the form "first-last" (omit "-last" if + * the range is a single value) where first and last are integers, and last is + * one less than the first value of the next bucket range. The bucket label is + * assumed to fit within the given width (number of characters), which should + * match the width value passed to dist_print_header(). The default width when + * unspecified (0) is eleven characters. + */ +void +dist_print_bucket(const int *distarray, int i, const uint_t *counts, + uint64_t total, int width) +{ + int b; /* bucket range index */ + int bb = distarray[i]; /* bucket begin */ + int be = distarray[i + 1] - 1; /* bucket end */ + uint64_t count = 0; /* bucket value */ + + int nats; + char ats[NCHARS + 1], spaces[NCHARS + 1]; + char range[40]; + + if (width == 0) + width = 11; + + if (total == 0) + total = 1; /* avoid divide-by-zero */ + + for (b = bb; b <= be; b++) + count += counts[b]; + + nats = (NCHARS * count) / total; + (void) memset(ats, '@', nats); + ats[nats] = 0; + (void) memset(spaces, ' ', NCHARS - nats); + spaces[NCHARS - nats] = 0; + + if (bb == be) + (void) mdb_snprintf(range, sizeof (range), "%d", bb); + else + (void) mdb_snprintf(range, sizeof (range), "%d-%d", bb, be); + mdb_printf("%*s |%s%s %lld\n", width, range, ats, spaces, count); +} +#undef NCHARS diff --git a/usr/src/cmd/mdb/common/modules/genunix/dist.h b/usr/src/cmd/mdb/common/modules/genunix/dist.h new file mode 100644 index 0000000000..f3c581fdc6 --- /dev/null +++ b/usr/src/cmd/mdb/common/modules/genunix/dist.h @@ -0,0 +1,44 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _DIST_H +#define _DIST_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const int *dist_linear(int, int, int); +extern const int *dist_geometric(int, int, int, int); +extern void dist_print_header(const char *, int, const char *); +extern void dist_print_bucket(const int *, int, const uint_t *, uint64_t, int); + +#ifdef __cplusplus +} +#endif + +#endif /* _DIST_H */ diff --git a/usr/src/cmd/mdb/common/modules/genunix/kmem.c b/usr/src/cmd/mdb/common/modules/genunix/kmem.c index 4511438b6a..47ad09126f 100644 --- a/usr/src/cmd/mdb/common/modules/genunix/kmem.c +++ b/usr/src/cmd/mdb/common/modules/genunix/kmem.c @@ -39,6 +39,7 @@ #include <sys/sysmacros.h> #include <vm/page.h> +#include "dist.h" #include "kmem.h" #include "leaky.h" @@ -353,12 +354,12 @@ kmem_slabs_print_dist(uint_t *ks_bucket, size_t buffers_per_slab, */ complete[0] = buffers_per_slab; complete[1] = buffers_per_slab + 1; - distarray = mdb_dist_linear(buckets - 1, 1, buffers_per_slab - 1); + distarray = dist_linear(buckets - 1, 1, buffers_per_slab - 1); mdb_printf("%*s\n", LABEL_WIDTH, "Allocated"); - mdb_dist_print_header("Buffers", LABEL_WIDTH, "Slabs"); + dist_print_header("Buffers", LABEL_WIDTH, "Slabs"); - mdb_dist_print_bucket(complete, 0, ks_bucket, total, LABEL_WIDTH); + dist_print_bucket(complete, 0, ks_bucket, total, LABEL_WIDTH); /* * Print bucket ranges in descending order after the first bucket for * completely allocated slabs, so a person can see immediately whether @@ -367,8 +368,7 @@ kmem_slabs_print_dist(uint_t *ks_bucket, size_t buffers_per_slab, * extra terminating bucket. */ for (i = buckets - 2; i >= 0; i--) { - mdb_dist_print_bucket(distarray, i, ks_bucket, total, - LABEL_WIDTH); + dist_print_bucket(distarray, i, ks_bucket, total, LABEL_WIDTH); } mdb_printf("\n"); } diff --git a/usr/src/cmd/mdb/common/modules/libumem/umem.c b/usr/src/cmd/mdb/common/modules/libumem/umem.c index ee0b5d5ef1..bd6c41b889 100644 --- a/usr/src/cmd/mdb/common/modules/libumem/umem.c +++ b/usr/src/cmd/mdb/common/modules/libumem/umem.c @@ -35,6 +35,7 @@ #include "misc.h" #include "leaky.h" +#include "dist.h" #include "umem_pagesize.h" @@ -3669,14 +3670,13 @@ umem_malloc_print_dist(uint_t *um_bucket, size_t minmalloc, size_t maxmalloc, } if (geometric) - distarray = mdb_dist_geometric(buckets, minb, maxb, - minbucketsize); + distarray = dist_geometric(buckets, minb, maxb, minbucketsize); else - distarray = mdb_dist_linear(buckets, minb, maxb); + distarray = dist_linear(buckets, minb, maxb); - mdb_dist_print_header("malloc size", 11, "count"); + dist_print_header("malloc size", 11, "count"); for (i = 0; i < buckets; i++) { - mdb_dist_print_bucket(distarray, i, um_bucket, um_malloc, 11); + dist_print_bucket(distarray, i, um_bucket, um_malloc, 11); } mdb_printf("\n"); } |
