summaryrefslogtreecommitdiffstats
path: root/cddl/contrib/opensolaris/lib
diff options
context:
space:
mode:
authorrpaulo <rpaulo@FreeBSD.org>2014-06-26 07:06:43 +0000
committerrpaulo <rpaulo@FreeBSD.org>2014-06-26 07:06:43 +0000
commitaedbcf436f4de9b9ce6c1f3c8c59c7f227272461 (patch)
tree26c80fb61401f57482f1bd8e72142ee1d1342f9b /cddl/contrib/opensolaris/lib
parentcd5514ba3b318b16aa00b1048bf9160a9f28fb35 (diff)
downloadFreeBSD-src-aedbcf436f4de9b9ce6c1f3c8c59c7f227272461.zip
FreeBSD-src-aedbcf436f4de9b9ce6c1f3c8c59c7f227272461.tar.gz
Bring the following change from the illumos-joyent repository:
commit 78e24ab6803bbe11ba37642624e1498ede5b239d Author: Bryan Cantrill <bryan@joyent.com> Date: Thu Oct 31 01:20:54 2013 OS-1688 DTrace count() with histogram OS-2360 DTrace full width distribution histograms OS-2361 DTrace frequency trails MFC after: 2 weeks
Diffstat (limited to 'cddl/contrib/opensolaris/lib')
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_aggregate.c264
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_consume.c451
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h12
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c17
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_options.c22
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dtrace.h10
6 files changed, 737 insertions, 39 deletions
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_aggregate.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_aggregate.c
index b0f2b4a..6b571fa 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_aggregate.c
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_aggregate.c
@@ -25,7 +25,7 @@
*/
/*
- * Copyright (c) 2011, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
*/
@@ -1301,6 +1301,231 @@ dtrace_aggregate_walk(dtrace_hdl_t *dtp, dtrace_aggregate_f *func, void *arg)
}
static int
+dt_aggregate_total(dtrace_hdl_t *dtp, boolean_t clear)
+{
+ dt_ahashent_t *h;
+ dtrace_aggdata_t **total;
+ dtrace_aggid_t max = DTRACE_AGGVARIDNONE, id;
+ dt_aggregate_t *agp = &dtp->dt_aggregate;
+ dt_ahash_t *hash = &agp->dtat_hash;
+ uint32_t tflags;
+
+ tflags = DTRACE_A_TOTAL | DTRACE_A_HASNEGATIVES | DTRACE_A_HASPOSITIVES;
+
+ /*
+ * If we need to deliver per-aggregation totals, we're going to take
+ * three passes over the aggregate: one to clear everything out and
+ * determine our maximum aggregation ID, one to actually total
+ * everything up, and a final pass to assign the totals to the
+ * individual elements.
+ */
+ for (h = hash->dtah_all; h != NULL; h = h->dtahe_nextall) {
+ dtrace_aggdata_t *aggdata = &h->dtahe_data;
+
+ if ((id = dt_aggregate_aggvarid(h)) > max)
+ max = id;
+
+ aggdata->dtada_total = 0;
+ aggdata->dtada_flags &= ~tflags;
+ }
+
+ if (clear || max == DTRACE_AGGVARIDNONE)
+ return (0);
+
+ total = dt_zalloc(dtp, (max + 1) * sizeof (dtrace_aggdata_t *));
+
+ if (total == NULL)
+ return (-1);
+
+ for (h = hash->dtah_all; h != NULL; h = h->dtahe_nextall) {
+ dtrace_aggdata_t *aggdata = &h->dtahe_data;
+ dtrace_aggdesc_t *agg = aggdata->dtada_desc;
+ dtrace_recdesc_t *rec;
+ caddr_t data;
+ int64_t val, *addr;
+
+ rec = &agg->dtagd_rec[agg->dtagd_nrecs - 1];
+ data = aggdata->dtada_data;
+ addr = (int64_t *)(uintptr_t)(data + rec->dtrd_offset);
+
+ switch (rec->dtrd_action) {
+ case DTRACEAGG_STDDEV:
+ val = dt_stddev((uint64_t *)addr, 1);
+ break;
+
+ case DTRACEAGG_SUM:
+ case DTRACEAGG_COUNT:
+ val = *addr;
+ break;
+
+ case DTRACEAGG_AVG:
+ val = addr[0] ? (addr[1] / addr[0]) : 0;
+ break;
+
+ default:
+ continue;
+ }
+
+ if (total[agg->dtagd_varid] == NULL) {
+ total[agg->dtagd_varid] = aggdata;
+ aggdata->dtada_flags |= DTRACE_A_TOTAL;
+ } else {
+ aggdata = total[agg->dtagd_varid];
+ }
+
+ if (val > 0)
+ aggdata->dtada_flags |= DTRACE_A_HASPOSITIVES;
+
+ if (val < 0) {
+ aggdata->dtada_flags |= DTRACE_A_HASNEGATIVES;
+ val = -val;
+ }
+
+ if (dtp->dt_options[DTRACEOPT_AGGZOOM] != DTRACEOPT_UNSET) {
+ val = (int64_t)((long double)val *
+ (1 / DTRACE_AGGZOOM_MAX));
+
+ if (val > aggdata->dtada_total)
+ aggdata->dtada_total = val;
+ } else {
+ aggdata->dtada_total += val;
+ }
+ }
+
+ /*
+ * And now one final pass to set everyone's total.
+ */
+ for (h = hash->dtah_all; h != NULL; h = h->dtahe_nextall) {
+ dtrace_aggdata_t *aggdata = &h->dtahe_data, *t;
+ dtrace_aggdesc_t *agg = aggdata->dtada_desc;
+
+ if ((t = total[agg->dtagd_varid]) == NULL || aggdata == t)
+ continue;
+
+ aggdata->dtada_total = t->dtada_total;
+ aggdata->dtada_flags |= (t->dtada_flags & tflags);
+ }
+
+ dt_free(dtp, total);
+
+ return (0);
+}
+
+static int
+dt_aggregate_minmaxbin(dtrace_hdl_t *dtp, boolean_t clear)
+{
+ dt_ahashent_t *h;
+ dtrace_aggdata_t **minmax;
+ dtrace_aggid_t max = DTRACE_AGGVARIDNONE, id;
+ dt_aggregate_t *agp = &dtp->dt_aggregate;
+ dt_ahash_t *hash = &agp->dtat_hash;
+
+ for (h = hash->dtah_all; h != NULL; h = h->dtahe_nextall) {
+ dtrace_aggdata_t *aggdata = &h->dtahe_data;
+
+ if ((id = dt_aggregate_aggvarid(h)) > max)
+ max = id;
+
+ aggdata->dtada_minbin = 0;
+ aggdata->dtada_maxbin = 0;
+ aggdata->dtada_flags &= ~DTRACE_A_MINMAXBIN;
+ }
+
+ if (clear || max == DTRACE_AGGVARIDNONE)
+ return (0);
+
+ minmax = dt_zalloc(dtp, (max + 1) * sizeof (dtrace_aggdata_t *));
+
+ if (minmax == NULL)
+ return (-1);
+
+ for (h = hash->dtah_all; h != NULL; h = h->dtahe_nextall) {
+ dtrace_aggdata_t *aggdata = &h->dtahe_data;
+ dtrace_aggdesc_t *agg = aggdata->dtada_desc;
+ dtrace_recdesc_t *rec;
+ caddr_t data;
+ int64_t *addr;
+ int minbin = -1, maxbin = -1, i;
+ int start = 0, size;
+
+ rec = &agg->dtagd_rec[agg->dtagd_nrecs - 1];
+ size = rec->dtrd_size / sizeof (int64_t);
+ data = aggdata->dtada_data;
+ addr = (int64_t *)(uintptr_t)(data + rec->dtrd_offset);
+
+ switch (rec->dtrd_action) {
+ case DTRACEAGG_LQUANTIZE:
+ /*
+ * For lquantize(), we always display the entire range
+ * of the aggregation when aggpack is set.
+ */
+ start = 1;
+ minbin = start;
+ maxbin = size - 1 - start;
+ break;
+
+ case DTRACEAGG_QUANTIZE:
+ for (i = start; i < size; i++) {
+ if (!addr[i])
+ continue;
+
+ if (minbin == -1)
+ minbin = i - start;
+
+ maxbin = i - start;
+ }
+
+ if (minbin == -1) {
+ /*
+ * If we have no data (e.g., due to a clear()
+ * or negative increments), we'll use the
+ * zero bucket as both our min and max.
+ */
+ minbin = maxbin = DTRACE_QUANTIZE_ZEROBUCKET;
+ }
+
+ break;
+
+ default:
+ continue;
+ }
+
+ if (minmax[agg->dtagd_varid] == NULL) {
+ minmax[agg->dtagd_varid] = aggdata;
+ aggdata->dtada_flags |= DTRACE_A_MINMAXBIN;
+ aggdata->dtada_minbin = minbin;
+ aggdata->dtada_maxbin = maxbin;
+ continue;
+ }
+
+ if (minbin < minmax[agg->dtagd_varid]->dtada_minbin)
+ minmax[agg->dtagd_varid]->dtada_minbin = minbin;
+
+ if (maxbin > minmax[agg->dtagd_varid]->dtada_maxbin)
+ minmax[agg->dtagd_varid]->dtada_maxbin = maxbin;
+ }
+
+ /*
+ * And now one final pass to set everyone's minbin and maxbin.
+ */
+ for (h = hash->dtah_all; h != NULL; h = h->dtahe_nextall) {
+ dtrace_aggdata_t *aggdata = &h->dtahe_data, *mm;
+ dtrace_aggdesc_t *agg = aggdata->dtada_desc;
+
+ if ((mm = minmax[agg->dtagd_varid]) == NULL || aggdata == mm)
+ continue;
+
+ aggdata->dtada_minbin = mm->dtada_minbin;
+ aggdata->dtada_maxbin = mm->dtada_maxbin;
+ aggdata->dtada_flags |= DTRACE_A_MINMAXBIN;
+ }
+
+ dt_free(dtp, minmax);
+
+ return (0);
+}
+
+static int
dt_aggregate_walk_sorted(dtrace_hdl_t *dtp,
dtrace_aggregate_f *func, void *arg,
int (*sfunc)(const void *, const void *))
@@ -1309,6 +1534,23 @@ dt_aggregate_walk_sorted(dtrace_hdl_t *dtp,
dt_ahashent_t *h, **sorted;
dt_ahash_t *hash = &agp->dtat_hash;
size_t i, nentries = 0;
+ int rval = -1;
+
+ agp->dtat_flags &= ~(DTRACE_A_TOTAL | DTRACE_A_MINMAXBIN);
+
+ if (dtp->dt_options[DTRACEOPT_AGGHIST] != DTRACEOPT_UNSET) {
+ agp->dtat_flags |= DTRACE_A_TOTAL;
+
+ if (dt_aggregate_total(dtp, B_FALSE) != 0)
+ return (-1);
+ }
+
+ if (dtp->dt_options[DTRACEOPT_AGGPACK] != DTRACEOPT_UNSET) {
+ agp->dtat_flags |= DTRACE_A_MINMAXBIN;
+
+ if (dt_aggregate_minmaxbin(dtp, B_FALSE) != 0)
+ return (-1);
+ }
for (h = hash->dtah_all; h != NULL; h = h->dtahe_nextall)
nentries++;
@@ -1316,7 +1558,7 @@ dt_aggregate_walk_sorted(dtrace_hdl_t *dtp,
sorted = dt_alloc(dtp, nentries * sizeof (dt_ahashent_t *));
if (sorted == NULL)
- return (-1);
+ goto out;
for (h = hash->dtah_all, i = 0; h != NULL; h = h->dtahe_nextall)
sorted[i++] = h;
@@ -1340,14 +1582,20 @@ dt_aggregate_walk_sorted(dtrace_hdl_t *dtp,
for (i = 0; i < nentries; i++) {
h = sorted[i];
- if (dt_aggwalk_rval(dtp, h, func(&h->dtahe_data, arg)) == -1) {
- dt_free(dtp, sorted);
- return (-1);
- }
+ if (dt_aggwalk_rval(dtp, h, func(&h->dtahe_data, arg)) == -1)
+ goto out;
}
+ rval = 0;
+out:
+ if (agp->dtat_flags & DTRACE_A_TOTAL)
+ (void) dt_aggregate_total(dtp, B_TRUE);
+
+ if (agp->dtat_flags & DTRACE_A_MINMAXBIN)
+ (void) dt_aggregate_minmaxbin(dtp, B_TRUE);
+
dt_free(dtp, sorted);
- return (0);
+ return (rval);
}
int
@@ -1870,6 +2118,8 @@ dtrace_aggregate_print(dtrace_hdl_t *dtp, FILE *fp,
{
dt_print_aggdata_t pd;
+ bzero(&pd, sizeof (pd));
+
pd.dtpa_dtp = dtp;
pd.dtpa_fp = fp;
pd.dtpa_allunprint = 1;
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_consume.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_consume.c
index 8d9e494..d255db8 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_consume.c
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_consume.c
@@ -24,7 +24,7 @@
*/
/*
- * Copyright (c) 2011, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
*/
@@ -59,6 +59,25 @@ dt_fabsl(long double x)
return (x);
}
+static int
+dt_ndigits(long long val)
+{
+ int rval = 1;
+ long long cmp = 10;
+
+ if (val < 0) {
+ val = val == INT64_MIN ? INT64_MAX : -val;
+ rval++;
+ }
+
+ while (val > cmp && cmp > 0) {
+ rval++;
+ cmp *= 10;
+ }
+
+ return (rval < 4 ? 4 : rval);
+}
+
/*
* 128-bit arithmetic functions needed to support the stddev() aggregating
* action.
@@ -487,7 +506,125 @@ dt_nullrec()
return (DTRACE_CONSUME_NEXT);
}
-int
+static void
+dt_quantize_total(dtrace_hdl_t *dtp, int64_t datum, long double *total)
+{
+ long double val = dt_fabsl((long double)datum);
+
+ if (dtp->dt_options[DTRACEOPT_AGGZOOM] == DTRACEOPT_UNSET) {
+ *total += val;
+ return;
+ }
+
+ /*
+ * If we're zooming in on an aggregation, we want the height of the
+ * highest value to be approximately 95% of total bar height -- so we
+ * adjust up by the reciprocal of DTRACE_AGGZOOM_MAX when comparing to
+ * our highest value.
+ */
+ val *= 1 / DTRACE_AGGZOOM_MAX;
+
+ if (*total < val)
+ *total = val;
+}
+
+static int
+dt_print_quanthdr(dtrace_hdl_t *dtp, FILE *fp, int width)
+{
+ return (dt_printf(dtp, fp, "\n%*s %41s %-9s\n",
+ width ? width : 16, width ? "key" : "value",
+ "------------- Distribution -------------", "count"));
+}
+
+static int
+dt_print_quanthdr_packed(dtrace_hdl_t *dtp, FILE *fp, int width,
+ const dtrace_aggdata_t *aggdata, dtrace_actkind_t action)
+{
+ int min = aggdata->dtada_minbin, max = aggdata->dtada_maxbin;
+ int minwidth, maxwidth, i;
+
+ assert(action == DTRACEAGG_QUANTIZE || action == DTRACEAGG_LQUANTIZE);
+
+ if (action == DTRACEAGG_QUANTIZE) {
+ if (min != 0 && min != DTRACE_QUANTIZE_ZEROBUCKET)
+ min--;
+
+ if (max < DTRACE_QUANTIZE_NBUCKETS - 1)
+ max++;
+
+ minwidth = dt_ndigits(DTRACE_QUANTIZE_BUCKETVAL(min));
+ maxwidth = dt_ndigits(DTRACE_QUANTIZE_BUCKETVAL(max));
+ } else {
+ maxwidth = 8;
+ minwidth = maxwidth - 1;
+ max++;
+ }
+
+ if (dt_printf(dtp, fp, "\n%*s %*s .",
+ width, width > 0 ? "key" : "", minwidth, "min") < 0)
+ return (-1);
+
+ for (i = min; i <= max; i++) {
+ if (dt_printf(dtp, fp, "-") < 0)
+ return (-1);
+ }
+
+ return (dt_printf(dtp, fp, ". %*s | count\n", -maxwidth, "max"));
+}
+
+/*
+ * We use a subset of the Unicode Block Elements (U+2588 through U+258F,
+ * inclusive) to represent aggregations via UTF-8 -- which are expressed via
+ * 3-byte UTF-8 sequences.
+ */
+#define DTRACE_AGGUTF8_FULL 0x2588
+#define DTRACE_AGGUTF8_BASE 0x258f
+#define DTRACE_AGGUTF8_LEVELS 8
+
+#define DTRACE_AGGUTF8_BYTE0(val) (0xe0 | ((val) >> 12))
+#define DTRACE_AGGUTF8_BYTE1(val) (0x80 | (((val) >> 6) & 0x3f))
+#define DTRACE_AGGUTF8_BYTE2(val) (0x80 | ((val) & 0x3f))
+
+static int
+dt_print_quantline_utf8(dtrace_hdl_t *dtp, FILE *fp, int64_t val,
+ uint64_t normal, long double total)
+{
+ uint_t len = 40, i, whole, partial;
+ long double f = (dt_fabsl((long double)val) * len) / total;
+ const char *spaces = " ";
+
+ whole = (uint_t)f;
+ partial = (uint_t)((f - (long double)(uint_t)f) *
+ (long double)DTRACE_AGGUTF8_LEVELS);
+
+ if (dt_printf(dtp, fp, "|") < 0)
+ return (-1);
+
+ for (i = 0; i < whole; i++) {
+ if (dt_printf(dtp, fp, "%c%c%c",
+ DTRACE_AGGUTF8_BYTE0(DTRACE_AGGUTF8_FULL),
+ DTRACE_AGGUTF8_BYTE1(DTRACE_AGGUTF8_FULL),
+ DTRACE_AGGUTF8_BYTE2(DTRACE_AGGUTF8_FULL)) < 0)
+ return (-1);
+ }
+
+ if (partial != 0) {
+ partial = DTRACE_AGGUTF8_BASE - (partial - 1);
+
+ if (dt_printf(dtp, fp, "%c%c%c",
+ DTRACE_AGGUTF8_BYTE0(partial),
+ DTRACE_AGGUTF8_BYTE1(partial),
+ DTRACE_AGGUTF8_BYTE2(partial)) < 0)
+ return (-1);
+
+ i++;
+ }
+
+ return (dt_printf(dtp, fp, "%s %-9lld\n", spaces + i,
+ (long long)val / normal));
+}
+
+static int
dt_print_quantline(dtrace_hdl_t *dtp, FILE *fp, int64_t val,
uint64_t normal, long double total, char positives, char negatives)
{
@@ -505,6 +642,11 @@ dt_print_quantline(dtrace_hdl_t *dtp, FILE *fp, int64_t val,
if (!negatives) {
if (positives) {
+ if (dtp->dt_encoding == DT_ENCODING_UTF8) {
+ return (dt_print_quantline_utf8(dtp, fp, val,
+ normal, total));
+ }
+
f = (dt_fabsl((long double)val) * len) / total;
depth = (uint_t)(f + 0.5);
} else {
@@ -547,6 +689,77 @@ dt_print_quantline(dtrace_hdl_t *dtp, FILE *fp, int64_t val,
}
}
+/*
+ * As with UTF-8 printing of aggregations, we use a subset of the Unicode
+ * Block Elements (U+2581 through U+2588, inclusive) to represent our packed
+ * aggregation.
+ */
+#define DTRACE_AGGPACK_BASE 0x2581
+#define DTRACE_AGGPACK_LEVELS 8
+
+static int
+dt_print_packed(dtrace_hdl_t *dtp, FILE *fp,
+ long double datum, long double total)
+{
+ static boolean_t utf8_checked = 0;
+ static boolean_t utf8;
+ char *ascii = "__xxxxXX";
+ char *neg = "vvvvVV";
+ unsigned int len;
+ long double val;
+
+ while (!utf8_checked) {
+ char *term;
+
+ /*
+ * We want to determine if we can reasonably emit UTF-8 for our
+ * packed aggregation. To do this, we will check for terminals
+ * that are known to be primitive to emit UTF-8 on these.
+ */
+ utf8_checked = B_TRUE;
+
+ if (dtp->dt_encoding == DT_ENCODING_ASCII)
+ break;
+
+ if (dtp->dt_encoding == DT_ENCODING_UTF8) {
+ utf8 = B_TRUE;
+ break;
+ }
+
+ if ((term = getenv("TERM")) != NULL &&
+ (strcmp(term, "sun") == 0 ||
+ strcmp(term, "sun-color") == 0) ||
+ strcmp(term, "dumb") == 0) {
+ break;
+ }
+
+ utf8 = B_TRUE;
+ }
+
+ if (datum == 0)
+ return (dt_printf(dtp, fp, " "));
+
+ if (datum < 0) {
+ len = strlen(neg);
+ val = dt_fabsl(datum * (len - 1)) / total;
+ return (dt_printf(dtp, fp, "%c", neg[(uint_t)(val + 0.5)]));
+ }
+
+ if (utf8) {
+ int block = DTRACE_AGGPACK_BASE + (unsigned int)(((datum *
+ (DTRACE_AGGPACK_LEVELS - 1)) / total) + 0.5);
+
+ return (dt_printf(dtp, fp, "%c%c%c",
+ DTRACE_AGGUTF8_BYTE0(block),
+ DTRACE_AGGUTF8_BYTE1(block),
+ DTRACE_AGGUTF8_BYTE2(block)));
+ }
+
+ len = strlen(ascii);
+ val = (datum * (len - 1)) / total;
+ return (dt_printf(dtp, fp, "%c", ascii[(uint_t)(val + 0.5)]));
+}
+
int
dt_print_quantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
size_t size, uint64_t normal)
@@ -564,9 +777,9 @@ dt_print_quantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
if (first_bin == DTRACE_QUANTIZE_NBUCKETS - 1) {
/*
- * There isn't any data. This is possible if (and only if)
- * negative increment values have been used. In this case,
- * we'll print the buckets around 0.
+ * There isn't any data. This is possible if the aggregation
+ * has been clear()'d or if negative increment values have been
+ * used. Regardless, we'll print the buckets around 0.
*/
first_bin = DTRACE_QUANTIZE_ZEROBUCKET - 1;
last_bin = DTRACE_QUANTIZE_ZEROBUCKET + 1;
@@ -584,11 +797,10 @@ dt_print_quantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
for (i = first_bin; i <= last_bin; i++) {
positives |= (data[i] > 0);
negatives |= (data[i] < 0);
- total += dt_fabsl((long double)data[i]);
+ dt_quantize_total(dtp, data[i], &total);
}
- if (dt_printf(dtp, fp, "\n%16s %41s %-9s\n", "value",
- "------------- Distribution -------------", "count") < 0)
+ if (dt_print_quanthdr(dtp, fp, 0) < 0)
return (-1);
for (i = first_bin; i <= last_bin; i++) {
@@ -605,6 +817,48 @@ dt_print_quantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
}
int
+dt_print_quantize_packed(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
+ size_t size, const dtrace_aggdata_t *aggdata)
+{
+ const int64_t *data = addr;
+ long double total = 0, count = 0;
+ int min = aggdata->dtada_minbin, max = aggdata->dtada_maxbin, i;
+ int64_t minval, maxval;
+
+ if (size != DTRACE_QUANTIZE_NBUCKETS * sizeof (uint64_t))
+ return (dt_set_errno(dtp, EDT_DMISMATCH));
+
+ if (min != 0 && min != DTRACE_QUANTIZE_ZEROBUCKET)
+ min--;
+
+ if (max < DTRACE_QUANTIZE_NBUCKETS - 1)
+ max++;
+
+ minval = DTRACE_QUANTIZE_BUCKETVAL(min);
+ maxval = DTRACE_QUANTIZE_BUCKETVAL(max);
+
+ if (dt_printf(dtp, fp, " %*lld :", dt_ndigits(minval),
+ (long long)minval) < 0)
+ return (-1);
+
+ for (i = min; i <= max; i++) {
+ dt_quantize_total(dtp, data[i], &total);
+ count += data[i];
+ }
+
+ for (i = min; i <= max; i++) {
+ if (dt_print_packed(dtp, fp, data[i], total) < 0)
+ return (-1);
+ }
+
+ if (dt_printf(dtp, fp, ": %*lld | %lld\n",
+ -dt_ndigits(maxval), (long long)maxval, (long long)count) < 0)
+ return (-1);
+
+ return (0);
+}
+
+int
dt_print_lquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
size_t size, uint64_t normal)
{
@@ -651,7 +905,7 @@ dt_print_lquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
for (i = first_bin; i <= last_bin; i++) {
positives |= (data[i] > 0);
negatives |= (data[i] < 0);
- total += dt_fabsl((long double)data[i]);
+ dt_quantize_total(dtp, data[i], &total);
}
if (dt_printf(dtp, fp, "\n%16s %41s %-9s\n", "value",
@@ -663,8 +917,7 @@ dt_print_lquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
int err;
if (i == 0) {
- (void) snprintf(c, sizeof (c), "< %d",
- base / (uint32_t)normal);
+ (void) snprintf(c, sizeof (c), "< %d", base);
err = dt_printf(dtp, fp, "%16s ", c);
} else if (i == levels + 1) {
(void) snprintf(c, sizeof (c), ">= %d",
@@ -683,6 +936,59 @@ dt_print_lquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
return (0);
}
+/*ARGSUSED*/
+int
+dt_print_lquantize_packed(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
+ size_t size, const dtrace_aggdata_t *aggdata)
+{
+ const int64_t *data = addr;
+ long double total = 0, count = 0;
+ int min, max, base, err;
+ uint64_t arg;
+ uint16_t step, levels;
+ char c[32];
+ unsigned int i;
+
+ if (size < sizeof (uint64_t))
+ return (dt_set_errno(dtp, EDT_DMISMATCH));
+
+ arg = *data++;
+ size -= sizeof (uint64_t);
+
+ base = DTRACE_LQUANTIZE_BASE(arg);
+ step = DTRACE_LQUANTIZE_STEP(arg);
+ levels = DTRACE_LQUANTIZE_LEVELS(arg);
+
+ if (size != sizeof (uint64_t) * (levels + 2))
+ return (dt_set_errno(dtp, EDT_DMISMATCH));
+
+ min = 0;
+ max = levels + 1;
+
+ if (min == 0) {
+ (void) snprintf(c, sizeof (c), "< %d", base);
+ err = dt_printf(dtp, fp, "%8s :", c);
+ } else {
+ err = dt_printf(dtp, fp, "%8d :", base + (min - 1) * step);
+ }
+
+ if (err < 0)
+ return (-1);
+
+ for (i = min; i <= max; i++) {
+ dt_quantize_total(dtp, data[i], &total);
+ count += data[i];
+ }
+
+ for (i = min; i <= max; i++) {
+ if (dt_print_packed(dtp, fp, data[i], total) < 0)
+ return (-1);
+ }
+
+ (void) snprintf(c, sizeof (c), ">= %d", base + (levels * step));
+ return (dt_printf(dtp, fp, ": %-8s | %lld\n", c, (long long)count));
+}
+
int
dt_print_llquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
size_t size, uint64_t normal)
@@ -740,7 +1046,7 @@ dt_print_llquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
for (i = first_bin; i <= last_bin; i++) {
positives |= (data[i] > 0);
negatives |= (data[i] < 0);
- total += dt_fabsl((long double)data[i]);
+ dt_quantize_total(dtp, data[i], &total);
}
if (dt_printf(dtp, fp, "\n%16s %41s %-9s\n", "value",
@@ -823,7 +1129,7 @@ dt_print_stddev(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr,
}
/*ARGSUSED*/
-int
+static int
dt_print_bytes(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr,
size_t nbytes, int width, int quiet, int forceraw)
{
@@ -876,10 +1182,12 @@ dt_print_bytes(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr,
if (j != nbytes)
break;
- if (quiet)
+ if (quiet) {
return (dt_printf(dtp, fp, "%s", c));
- else
- return (dt_printf(dtp, fp, " %-*s", width, c));
+ } else {
+ return (dt_printf(dtp, fp, " %s%*s",
+ width < 0 ? " " : "", width, c));
+ }
}
break;
@@ -1793,10 +2101,83 @@ dt_trunc(dtrace_hdl_t *dtp, caddr_t base, dtrace_recdesc_t *rec)
static int
dt_print_datum(dtrace_hdl_t *dtp, FILE *fp, dtrace_recdesc_t *rec,
- caddr_t addr, size_t size, uint64_t normal)
+ caddr_t addr, size_t size, const dtrace_aggdata_t *aggdata,
+ uint64_t normal, dt_print_aggdata_t *pd)
{
- int err;
+ int err, width;
dtrace_actkind_t act = rec->dtrd_action;
+ boolean_t packed = pd->dtpa_agghist || pd->dtpa_aggpack;
+ dtrace_aggdesc_t *agg = aggdata->dtada_desc;
+
+ static struct {
+ size_t size;
+ int width;
+ int packedwidth;
+ } *fmt, fmttab[] = {
+ { sizeof (uint8_t), 3, 3 },
+ { sizeof (uint16_t), 5, 5 },
+ { sizeof (uint32_t), 8, 8 },
+ { sizeof (uint64_t), 16, 16 },
+ { 0, -50, 16 }
+ };
+
+ if (packed && pd->dtpa_agghisthdr != agg->dtagd_varid) {
+ dtrace_recdesc_t *r;
+
+ width = 0;
+
+ /*
+ * To print our quantization header for either an agghist or
+ * aggpack aggregation, we need to iterate through all of our
+ * of our records to determine their width.
+ */
+ for (r = rec; !DTRACEACT_ISAGG(r->dtrd_action); r++) {
+ for (fmt = fmttab; fmt->size &&
+ fmt->size != r->dtrd_size; fmt++)
+ continue;
+
+ width += fmt->packedwidth + 1;
+ }
+
+ if (pd->dtpa_agghist) {
+ if (dt_print_quanthdr(dtp, fp, width) < 0)
+ return (-1);
+ } else {
+ if (dt_print_quanthdr_packed(dtp, fp,
+ width, aggdata, r->dtrd_action) < 0)
+ return (-1);
+ }
+
+ pd->dtpa_agghisthdr = agg->dtagd_varid;
+ }
+
+ if (pd->dtpa_agghist && DTRACEACT_ISAGG(act)) {
+ char positives = aggdata->dtada_flags & DTRACE_A_HASPOSITIVES;
+ char negatives = aggdata->dtada_flags & DTRACE_A_HASNEGATIVES;
+ int64_t val;
+
+ assert(act == DTRACEAGG_SUM || act == DTRACEAGG_COUNT);
+ val = (long long)*((uint64_t *)addr);
+
+ if (dt_printf(dtp, fp, " ") < 0)
+ return (-1);
+
+ return (dt_print_quantline(dtp, fp, val, normal,
+ aggdata->dtada_total, positives, negatives));
+ }
+
+ if (pd->dtpa_aggpack && DTRACEACT_ISAGG(act)) {
+ switch (act) {
+ case DTRACEAGG_QUANTIZE:
+ return (dt_print_quantize_packed(dtp,
+ fp, addr, size, aggdata));
+ case DTRACEAGG_LQUANTIZE:
+ return (dt_print_lquantize_packed(dtp,
+ fp, addr, size, aggdata));
+ default:
+ break;
+ }
+ }
switch (act) {
case DTRACEACT_STACK:
@@ -1839,28 +2220,33 @@ dt_print_datum(dtrace_hdl_t *dtp, FILE *fp, dtrace_recdesc_t *rec,
break;
}
+ for (fmt = fmttab; fmt->size && fmt->size != size; fmt++)
+ continue;
+
+ width = packed ? fmt->packedwidth : fmt->width;
+
switch (size) {
case sizeof (uint64_t):
- err = dt_printf(dtp, fp, " %16lld",
+ err = dt_printf(dtp, fp, " %*lld", width,
/* LINTED - alignment */
(long long)*((uint64_t *)addr) / normal);
break;
case sizeof (uint32_t):
/* LINTED - alignment */
- err = dt_printf(dtp, fp, " %8d", *((uint32_t *)addr) /
+ err = dt_printf(dtp, fp, " %*d", width, *((uint32_t *)addr) /
(uint32_t)normal);
break;
case sizeof (uint16_t):
/* LINTED - alignment */
- err = dt_printf(dtp, fp, " %5d", *((uint16_t *)addr) /
+ err = dt_printf(dtp, fp, " %*d", width, *((uint16_t *)addr) /
(uint32_t)normal);
break;
case sizeof (uint8_t):
- err = dt_printf(dtp, fp, " %3d", *((uint8_t *)addr) /
+ err = dt_printf(dtp, fp, " %*d", width, *((uint8_t *)addr) /
(uint32_t)normal);
break;
default:
- err = dt_print_bytes(dtp, fp, addr, size, 50, 0, 0);
+ err = dt_print_bytes(dtp, fp, addr, size, width, 0, 0);
break;
}
@@ -1881,6 +2267,9 @@ dt_print_aggs(const dtrace_aggdata_t **aggsdata, int naggvars, void *arg)
caddr_t addr;
size_t size;
+ pd->dtpa_agghist = (aggdata->dtada_flags & DTRACE_A_TOTAL);
+ pd->dtpa_aggpack = (aggdata->dtada_flags & DTRACE_A_MINMAXBIN);
+
/*
* Iterate over each record description in the key, printing the traced
* data, skipping the first datum (the tuple member created by the
@@ -1897,7 +2286,8 @@ dt_print_aggs(const dtrace_aggdata_t **aggsdata, int naggvars, void *arg)
break;
}
- if (dt_print_datum(dtp, fp, rec, addr, size, 1) < 0)
+ if (dt_print_datum(dtp, fp, rec, addr,
+ size, aggdata, 1, pd) < 0)
return (-1);
if (dt_buffered_flush(dtp, NULL, rec, aggdata,
@@ -1920,7 +2310,8 @@ dt_print_aggs(const dtrace_aggdata_t **aggsdata, int naggvars, void *arg)
assert(DTRACEACT_ISAGG(act));
normal = aggdata->dtada_normal;
- if (dt_print_datum(dtp, fp, rec, addr, size, normal) < 0)
+ if (dt_print_datum(dtp, fp, rec, addr,
+ size, aggdata, normal, pd) < 0)
return (-1);
if (dt_buffered_flush(dtp, NULL, rec, aggdata,
@@ -1931,8 +2322,10 @@ dt_print_aggs(const dtrace_aggdata_t **aggsdata, int naggvars, void *arg)
agg->dtagd_flags |= DTRACE_AGD_PRINTED;
}
- if (dt_printf(dtp, fp, "\n") < 0)
- return (-1);
+ if (!pd->dtpa_agghist && !pd->dtpa_aggpack) {
+ if (dt_printf(dtp, fp, "\n") < 0)
+ return (-1);
+ }
if (dt_buffered_flush(dtp, NULL, NULL, aggdata,
DTRACE_BUFDATA_AGGFORMAT | DTRACE_BUFDATA_AGGLAST) < 0)
@@ -2401,7 +2794,7 @@ nofmt:
}
n = dt_print_bytes(dtp, fp, addr,
- tracememsize, 33, quiet, 1);
+ tracememsize, -33, quiet, 1);
tracememsize = 0;
@@ -2434,7 +2827,7 @@ nofmt:
break;
default:
n = dt_print_bytes(dtp, fp, addr,
- rec->dtrd_size, 33, quiet, 0);
+ rec->dtrd_size, -33, quiet, 0);
break;
}
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h
index 2bae220..feea9f7 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h
@@ -189,6 +189,9 @@ typedef struct dt_print_aggdata {
dtrace_aggvarid_t dtpa_id; /* aggregation variable of interest */
FILE *dtpa_fp; /* file pointer */
int dtpa_allunprint; /* print only unprinted aggregations */
+ int dtpa_agghist; /* print aggregation as histogram */
+ int dtpa_agghisthdr; /* aggregation histogram hdr printed */
+ int dtpa_aggpack; /* pack quantized aggregations */
} dt_print_aggdata_t;
typedef struct dt_dirpath {
@@ -283,6 +286,7 @@ struct dtrace_hdl {
uint_t dt_linktype; /* dtrace link output file type (see below) */
uint_t dt_xlatemode; /* dtrace translator linking mode (see below) */
uint_t dt_stdcmode; /* dtrace stdc compatibility mode (see below) */
+ uint_t dt_encoding; /* dtrace output encoding (see below) */
uint_t dt_treedump; /* dtrace tree debug bitmap (see below) */
uint64_t dt_options[DTRACEOPT_MAX]; /* dtrace run-time options */
int dt_version; /* library version requested by client */
@@ -374,6 +378,14 @@ struct dtrace_hdl {
#define DT_STDC_XT 3 /* ISO C + K&R C compat with ISO: __STDC__=0 */
/*
+ * Values for the dt_encoding property, which is used to force a particular
+ * character encoding (overriding default behavior and/or automatic detection).
+ */
+#define DT_ENCODING_UNSET 0
+#define DT_ENCODING_ASCII 1
+#define DT_ENCODING_UTF8 2
+
+/*
* Macro to test whether a given pass bit is set in the dt_treedump bit-vector.
* If the bit for pass 'p' is set, the D compiler displays the parse tree for
* the program by printing it to stderr at the end of compiler pass 'p'.
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c
index 92251d5..192ef0c 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c
@@ -122,9 +122,14 @@
#define DT_VERS_1_8_1 DT_VERSION_NUMBER(1, 8, 1)
#define DT_VERS_1_9 DT_VERSION_NUMBER(1, 9, 0)
#define DT_VERS_1_9_1 DT_VERSION_NUMBER(1, 9, 1)
-#define DT_VERS_LATEST DT_VERS_1_9_1
-#define DT_VERS_STRING "Sun D 1.9.1"
-
+#define DT_VERS_1_9_2 DT_VERSION_NUMBER(1, 9, 2) /* FreeBSD specific */
+#define DT_VERS_1_10 DT_VERSION_NUMBER(1, 10, 0)
+#define DT_VERS_1_11 DT_VERSION_NUMBER(1, 11, 0)
+#define DT_VERS_1_12 DT_VERSION_NUMBER(1, 12, 0)
+#define DT_VERS_1_12_1 DT_VERSION_NUMBER(1, 12, 1)
+#define DT_VERS_LATEST DT_VERS_1_9_2
+#define DT_VERS_STRING "Sun D 1.9.2"
+
const dt_version_t _dtrace_versions[] = {
DT_VERS_1_0, /* D API 1.0.0 (PSARC 2001/466) Solaris 10 FCS */
DT_VERS_1_1, /* D API 1.1.0 Solaris Express 6/05 */
@@ -145,6 +150,11 @@ const dt_version_t _dtrace_versions[] = {
DT_VERS_1_8_1, /* D API 1.8.1 */
DT_VERS_1_9, /* D API 1.9 */
DT_VERS_1_9_1, /* D API 1.9.1 */
+ DT_VERS_1_9_2, /* D API 1.9.1 */
+ DT_VERS_1_10, /* D API 1.10 */
+ DT_VERS_1_11, /* D API 1.11 */
+ DT_VERS_1_12, /* D API 1.12 */
+ DT_VERS_1_12_1, /* D API 1.12.1 */
0
};
@@ -1144,6 +1154,7 @@ alloc:
dtp->dt_linktype = DT_LTYP_ELF;
dtp->dt_xlatemode = DT_XL_STATIC;
dtp->dt_stdcmode = DT_STDC_XA;
+ dtp->dt_encoding = DT_ENCODING_UNSET;
dtp->dt_version = version;
dtp->dt_fd = dtfd;
dtp->dt_ftfd = ftfd;
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_options.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_options.c
index c20d250..832af88 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_options.c
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_options.c
@@ -25,6 +25,7 @@
*/
/*
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
*/
@@ -338,6 +339,23 @@ dt_opt_linktype(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
/*ARGSUSED*/
static int
+dt_opt_encoding(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
+{
+ if (arg == NULL)
+ return (dt_set_errno(dtp, EDT_BADOPTVAL));
+
+ if (strcmp(arg, "ascii") == 0)
+ dtp->dt_encoding = DT_ENCODING_ASCII;
+ else if (strcmp(arg, "utf8") == 0)
+ dtp->dt_encoding = DT_ENCODING_UTF8;
+ else
+ return (dt_set_errno(dtp, EDT_BADOPTVAL));
+
+ return (0);
+}
+
+/*ARGSUSED*/
+static int
dt_opt_evaltime(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
{
if (arg == NULL)
@@ -928,6 +946,7 @@ static const dt_option_t _dtrace_ctoptions[] = {
{ "define", dt_opt_cpp_opts, (uintptr_t)"-D" },
{ "droptags", dt_opt_droptags },
{ "empty", dt_opt_cflags, DTRACE_C_EMPTY },
+ { "encoding", dt_opt_encoding },
{ "errtags", dt_opt_cflags, DTRACE_C_ETAGS },
{ "evaltime", dt_opt_evaltime },
{ "incdir", dt_opt_cpp_opts, (uintptr_t)"-I" },
@@ -988,11 +1007,14 @@ static const dt_option_t _dtrace_rtoptions[] = {
* Dynamic run-time options.
*/
static const dt_option_t _dtrace_drtoptions[] = {
+ { "agghist", dt_opt_runtime, DTRACEOPT_AGGHIST },
+ { "aggpack", dt_opt_runtime, DTRACEOPT_AGGPACK },
{ "aggrate", dt_opt_rate, DTRACEOPT_AGGRATE },
{ "aggsortkey", dt_opt_runtime, DTRACEOPT_AGGSORTKEY },
{ "aggsortkeypos", dt_opt_runtime, DTRACEOPT_AGGSORTKEYPOS },
{ "aggsortpos", dt_opt_runtime, DTRACEOPT_AGGSORTPOS },
{ "aggsortrev", dt_opt_runtime, DTRACEOPT_AGGSORTREV },
+ { "aggzoom", dt_opt_runtime, DTRACEOPT_AGGZOOM },
{ "flowindent", dt_opt_runtime, DTRACEOPT_FLOWINDENT },
{ "quiet", dt_opt_runtime, DTRACEOPT_QUIET },
{ "rawbytes", dt_opt_runtime, DTRACEOPT_RAWBYTES },
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dtrace.h b/cddl/contrib/opensolaris/lib/libdtrace/common/dtrace.h
index b2e3108..cbaa03f 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dtrace.h
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dtrace.h
@@ -356,6 +356,12 @@ extern int dtrace_handle_setopt(dtrace_hdl_t *,
#define DTRACE_A_PERCPU 0x0001
#define DTRACE_A_KEEPDELTA 0x0002
#define DTRACE_A_ANONYMOUS 0x0004
+#define DTRACE_A_TOTAL 0x0008
+#define DTRACE_A_MINMAXBIN 0x0010
+#define DTRACE_A_HASNEGATIVES 0x0020
+#define DTRACE_A_HASPOSITIVES 0x0040
+
+#define DTRACE_AGGZOOM_MAX 0.95 /* height of max bar */
#define DTRACE_AGGWALK_ERROR -1 /* error while processing */
#define DTRACE_AGGWALK_NEXT 0 /* proceed to next element */
@@ -376,6 +382,10 @@ struct dtrace_aggdata {
caddr_t dtada_delta; /* delta data, if available */
caddr_t *dtada_percpu; /* per CPU data, if avail */
caddr_t *dtada_percpu_delta; /* per CPU delta, if avail */
+ int64_t dtada_total; /* per agg total, if avail */
+ uint16_t dtada_minbin; /* minimum bin, if avail */
+ uint16_t dtada_maxbin; /* maximum bin, if avail */
+ uint32_t dtada_flags; /* flags */
};
typedef int dtrace_aggregate_f(const dtrace_aggdata_t *, void *);
OpenPOWER on IntegriCloud