Print this page
4471 DTrace count() with histogram
4472 DTrace full width distribution histograms
4473 DTrace frequency trails


   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 /*
  27  * Copyright (c) 2011, Joyent, Inc. All rights reserved.
  28  * Copyright (c) 2012 by Delphix. All rights reserved.
  29  */
  30 
  31 #include <stdlib.h>
  32 #include <strings.h>
  33 #include <errno.h>
  34 #include <unistd.h>
  35 #include <limits.h>
  36 #include <assert.h>
  37 #include <ctype.h>
  38 #include <alloca.h>
  39 #include <dt_impl.h>
  40 #include <dt_pq.h>
  41 
  42 #define DT_MASK_LO 0x00000000FFFFFFFFULL
  43 
  44 /*
  45  * We declare this here because (1) we need it and (2) we want to avoid a
  46  * dependency on libm in libdtrace.
  47  */
  48 static long double
  49 dt_fabsl(long double x)
  50 {
  51         if (x < 0)
  52                 return (-x);
  53 
  54         return (x);
  55 }
  56 



















  57 /*
  58  * 128-bit arithmetic functions needed to support the stddev() aggregating
  59  * action.
  60  */
  61 static int
  62 dt_gt_128(uint64_t *a, uint64_t *b)
  63 {
  64         return (a[1] > b[1] || (a[1] == b[1] && a[0] > b[0]));
  65 }
  66 
  67 static int
  68 dt_ge_128(uint64_t *a, uint64_t *b)
  69 {
  70         return (a[1] > b[1] || (a[1] == b[1] && a[0] >= b[0]));
  71 }
  72 
  73 static int
  74 dt_le_128(uint64_t *a, uint64_t *b)
  75 {
  76         return (a[1] < b[1] || (a[1] == b[1] && a[0] <= b[0]));


 465         if (flow == DTRACEFLOW_RETURN && data->dtpda_indent > 0)
 466                 data->dtpda_indent -= 2;
 467 
 468         data->dtpda_flow = flow;
 469 
 470         return (0);
 471 }
 472 
 473 static int
 474 dt_nullprobe()
 475 {
 476         return (DTRACE_CONSUME_THIS);
 477 }
 478 
 479 static int
 480 dt_nullrec()
 481 {
 482         return (DTRACE_CONSUME_NEXT);
 483 }
 484 
 485 int






















































































































 486 dt_print_quantline(dtrace_hdl_t *dtp, FILE *fp, int64_t val,
 487     uint64_t normal, long double total, char positives, char negatives)
 488 {
 489         long double f;
 490         uint_t depth, len = 40;
 491 
 492         const char *ats = "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@";
 493         const char *spaces = "                                        ";
 494 
 495         assert(strlen(ats) == len && strlen(spaces) == len);
 496         assert(!(total == 0 && (positives || negatives)));
 497         assert(!(val < 0 && !negatives));
 498         assert(!(val > 0 && !positives));
 499         assert(!(val != 0 && total == 0));
 500 
 501         if (!negatives) {
 502                 if (positives) {





 503                         f = (dt_fabsl((long double)val) * len) / total;
 504                         depth = (uint_t)(f + 0.5);
 505                 } else {
 506                         depth = 0;
 507                 }
 508 
 509                 return (dt_printf(dtp, fp, "|%s%s %-9lld\n", ats + len - depth,
 510                     spaces + depth, (long long)val / normal));
 511         }
 512 
 513         if (!positives) {
 514                 f = (dt_fabsl((long double)val) * len) / total;
 515                 depth = (uint_t)(f + 0.5);
 516 
 517                 return (dt_printf(dtp, fp, "%s%s| %-9lld\n", spaces + depth,
 518                     ats + len - depth, (long long)val / normal));
 519         }
 520 
 521         /*
 522          * If we're here, we have both positive and negative bucket values.


 525          * the size of normal quantize()/lquantize() bars, so we divide the
 526          * length in half before calculating the bar length.
 527          */
 528         len /= 2;
 529         ats = &ats[len];
 530         spaces = &spaces[len];
 531 
 532         f = (dt_fabsl((long double)val) * len) / total;
 533         depth = (uint_t)(f + 0.5);
 534 
 535         if (val <= 0) {
 536                 return (dt_printf(dtp, fp, "%s%s|%*s %-9lld\n", spaces + depth,
 537                     ats + len - depth, len, "", (long long)val / normal));
 538         } else {
 539                 return (dt_printf(dtp, fp, "%20s|%s%s %-9lld\n", "",
 540                     ats + len - depth, spaces + depth,
 541                     (long long)val / normal));
 542         }
 543 }
 544 


































































 545 int
 546 dt_print_quantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
 547     size_t size, uint64_t normal)
 548 {
 549         const int64_t *data = addr;
 550         int i, first_bin = 0, last_bin = DTRACE_QUANTIZE_NBUCKETS - 1;
 551         long double total = 0;
 552         char positives = 0, negatives = 0;
 553 
 554         if (size != DTRACE_QUANTIZE_NBUCKETS * sizeof (uint64_t))
 555                 return (dt_set_errno(dtp, EDT_DMISMATCH));
 556 
 557         while (first_bin < DTRACE_QUANTIZE_NBUCKETS - 1 && data[first_bin] == 0)
 558                 first_bin++;
 559 
 560         if (first_bin == DTRACE_QUANTIZE_NBUCKETS - 1) {
 561                 /*
 562                  * There isn't any data.  This is possible if (and only if)
 563                  * negative increment values have been used.  In this case,
 564                  * we'll print the buckets around 0.
 565                  */
 566                 first_bin = DTRACE_QUANTIZE_ZEROBUCKET - 1;
 567                 last_bin = DTRACE_QUANTIZE_ZEROBUCKET + 1;
 568         } else {
 569                 if (first_bin > 0)
 570                         first_bin--;
 571 
 572                 while (last_bin > 0 && data[last_bin] == 0)
 573                         last_bin--;
 574 
 575                 if (last_bin < DTRACE_QUANTIZE_NBUCKETS - 1)
 576                         last_bin++;
 577         }
 578 
 579         for (i = first_bin; i <= last_bin; i++) {
 580                 positives |= (data[i] > 0);
 581                 negatives |= (data[i] < 0);
 582                 total += dt_fabsl((long double)data[i]);
 583         }
 584 
 585         if (dt_printf(dtp, fp, "\n%16s %41s %-9s\n", "value",
 586             "------------- Distribution -------------", "count") < 0)
 587                 return (-1);
 588 
 589         for (i = first_bin; i <= last_bin; i++) {
 590                 if (dt_printf(dtp, fp, "%16lld ",
 591                     (long long)DTRACE_QUANTIZE_BUCKETVAL(i)) < 0)
 592                         return (-1);
 593 
 594                 if (dt_print_quantline(dtp, fp, data[i], normal, total,
 595                     positives, negatives) < 0)
 596                         return (-1);
 597         }
 598 
 599         return (0);
 600 }
 601 
 602 int










































 603 dt_print_lquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
 604     size_t size, uint64_t normal)
 605 {
 606         const int64_t *data = addr;
 607         int i, first_bin, last_bin, base;
 608         uint64_t arg;
 609         long double total = 0;
 610         uint16_t step, levels;
 611         char positives = 0, negatives = 0;
 612 
 613         if (size < sizeof (uint64_t))
 614                 return (dt_set_errno(dtp, EDT_DMISMATCH));
 615 
 616         arg = *data++;
 617         size -= sizeof (uint64_t);
 618 
 619         base = DTRACE_LQUANTIZE_BASE(arg);
 620         step = DTRACE_LQUANTIZE_STEP(arg);
 621         levels = DTRACE_LQUANTIZE_LEVELS(arg);
 622 


 629         while (first_bin <= levels + 1 && data[first_bin] == 0)
 630                 first_bin++;
 631 
 632         if (first_bin > levels + 1) {
 633                 first_bin = 0;
 634                 last_bin = 2;
 635         } else {
 636                 if (first_bin > 0)
 637                         first_bin--;
 638 
 639                 while (last_bin > 0 && data[last_bin] == 0)
 640                         last_bin--;
 641 
 642                 if (last_bin < levels + 1)
 643                         last_bin++;
 644         }
 645 
 646         for (i = first_bin; i <= last_bin; i++) {
 647                 positives |= (data[i] > 0);
 648                 negatives |= (data[i] < 0);
 649                 total += dt_fabsl((long double)data[i]);
 650         }
 651 
 652         if (dt_printf(dtp, fp, "\n%16s %41s %-9s\n", "value",
 653             "------------- Distribution -------------", "count") < 0)
 654                 return (-1);
 655 
 656         for (i = first_bin; i <= last_bin; i++) {
 657                 char c[32];
 658                 int err;
 659 
 660                 if (i == 0) {
 661                         (void) snprintf(c, sizeof (c), "< %d",
 662                             base / (uint32_t)normal);
 663                         err = dt_printf(dtp, fp, "%16s ", c);
 664                 } else if (i == levels + 1) {
 665                         (void) snprintf(c, sizeof (c), ">= %d",
 666                             base + (levels * step));
 667                         err = dt_printf(dtp, fp, "%16s ", c);
 668                 } else {
 669                         err = dt_printf(dtp, fp, "%16d ",
 670                             base + (i - 1) * step);
 671                 }
 672 
 673                 if (err < 0 || dt_print_quantline(dtp, fp, data[i], normal,
 674                     total, positives, negatives) < 0)
 675                         return (-1);
 676         }
 677 
 678         return (0);
 679 }
 680 





















































 681 int
 682 dt_print_llquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
 683     size_t size, uint64_t normal)
 684 {
 685         int i, first_bin, last_bin, bin = 1, order, levels;
 686         uint16_t factor, low, high, nsteps;
 687         const int64_t *data = addr;
 688         int64_t value = 1, next, step;
 689         char positives = 0, negatives = 0;
 690         long double total = 0;
 691         uint64_t arg;
 692         char c[32];
 693 
 694         if (size < sizeof (uint64_t))
 695                 return (dt_set_errno(dtp, EDT_DMISMATCH));
 696 
 697         arg = *data++;
 698         size -= sizeof (uint64_t);
 699 
 700         factor = DTRACE_LLQUANTIZE_FACTOR(arg);


 718         while (first_bin < levels && data[first_bin] == 0)
 719                 first_bin++;
 720 
 721         if (first_bin == levels) {
 722                 first_bin = 0;
 723                 last_bin = 1;
 724         } else {
 725                 if (first_bin > 0)
 726                         first_bin--;
 727 
 728                 while (last_bin > 0 && data[last_bin] == 0)
 729                         last_bin--;
 730 
 731                 if (last_bin < levels - 1)
 732                         last_bin++;
 733         }
 734 
 735         for (i = first_bin; i <= last_bin; i++) {
 736                 positives |= (data[i] > 0);
 737                 negatives |= (data[i] < 0);
 738                 total += dt_fabsl((long double)data[i]);
 739         }
 740 
 741         if (dt_printf(dtp, fp, "\n%16s %41s %-9s\n", "value",
 742             "------------- Distribution -------------", "count") < 0)
 743                 return (-1);
 744 
 745         for (order = 0; order < low; order++)
 746                 value *= factor;
 747 
 748         next = value * factor;
 749         step = next > nsteps ? next / nsteps : 1;
 750 
 751         if (first_bin == 0) {
 752                 (void) snprintf(c, sizeof (c), "< %lld", value);
 753 
 754                 if (dt_printf(dtp, fp, "%16s ", c) < 0)
 755                         return (-1);
 756 
 757                 if (dt_print_quantline(dtp, fp, data[0], normal,
 758                     total, positives, negatives) < 0)


 801         /* LINTED - alignment */
 802         int64_t *data = (int64_t *)addr;
 803 
 804         return (dt_printf(dtp, fp, " %16lld", data[0] ?
 805             (long long)(data[1] / (int64_t)normal / data[0]) : 0));
 806 }
 807 
 808 /*ARGSUSED*/
 809 static int
 810 dt_print_stddev(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr,
 811     size_t size, uint64_t normal)
 812 {
 813         /* LINTED - alignment */
 814         uint64_t *data = (uint64_t *)addr;
 815 
 816         return (dt_printf(dtp, fp, " %16llu", data[0] ?
 817             (unsigned long long) dt_stddev(data, normal) : 0));
 818 }
 819 
 820 /*ARGSUSED*/
 821 int
 822 dt_print_bytes(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr,
 823     size_t nbytes, int width, int quiet, int forceraw)
 824 {
 825         /*
 826          * If the byte stream is a series of printable characters, followed by
 827          * a terminating byte, we print it out as a string.  Otherwise, we
 828          * assume that it's something else and just print the bytes.
 829          */
 830         int i, j, margin = 5;
 831         char *c = (char *)addr;
 832 
 833         if (nbytes == 0)
 834                 return (0);
 835 
 836         if (forceraw)
 837                 goto raw;
 838 
 839         if (dtp->dt_options[DTRACEOPT_RAWBYTES] != DTRACEOPT_UNSET)
 840                 goto raw;
 841 


 854                     c[i] == '\b' || c[i] == '\a')
 855                         continue;
 856 
 857                 if (c[i] == '\0' && i > 0) {
 858                         /*
 859                          * This looks like it might be a string.  Before we
 860                          * assume that it is indeed a string, check the
 861                          * remainder of the byte range; if it contains
 862                          * additional non-nul characters, we'll assume that
 863                          * it's a binary stream that just happens to look like
 864                          * a string, and we'll print out the individual bytes.
 865                          */
 866                         for (j = i + 1; j < nbytes; j++) {
 867                                 if (c[j] != '\0')
 868                                         break;
 869                         }
 870 
 871                         if (j != nbytes)
 872                                 break;
 873 
 874                         if (quiet)
 875                                 return (dt_printf(dtp, fp, "%s", c));
 876                         else
 877                                 return (dt_printf(dtp, fp, "  %-*s", width, c));


 878                 }
 879 
 880                 break;
 881         }
 882 
 883         if (i == nbytes) {
 884                 /*
 885                  * The byte range is all printable characters, but there is
 886                  * no trailing nul byte.  We'll assume that it's a string and
 887                  * print it as such.
 888                  */
 889                 char *s = alloca(nbytes + 1);
 890                 bcopy(c, s, nbytes);
 891                 s[nbytes] = '\0';
 892                 return (dt_printf(dtp, fp, "  %-*s", width, s));
 893         }
 894 
 895 raw:
 896         if (dt_printf(dtp, fp, "\n%*s      ", margin, "") < 0)
 897                 return (-1);


1462                 return (dt_set_errno(dtp, EDT_BADNORMAL));
1463         }
1464 
1465         if (remaining < 0) {
1466                 func = dtrace_aggregate_walk_valsorted;
1467                 remaining = -remaining;
1468         } else {
1469                 func = dtrace_aggregate_walk_valrevsorted;
1470         }
1471 
1472         assert(remaining >= 0);
1473         trunc.dttd_remaining = remaining;
1474 
1475         (void) func(dtp, dt_trunc_agg, &trunc);
1476 
1477         return (0);
1478 }
1479 
1480 static int
1481 dt_print_datum(dtrace_hdl_t *dtp, FILE *fp, dtrace_recdesc_t *rec,
1482     caddr_t addr, size_t size, uint64_t normal)

1483 {
1484         int err;
1485         dtrace_actkind_t act = rec->dtrd_action;








































































1486 
1487         switch (act) {
1488         case DTRACEACT_STACK:
1489                 return (dt_print_stack(dtp, fp, NULL, addr,
1490                     rec->dtrd_arg, rec->dtrd_size / rec->dtrd_arg));
1491 
1492         case DTRACEACT_USTACK:
1493         case DTRACEACT_JSTACK:
1494                 return (dt_print_ustack(dtp, fp, NULL, addr, rec->dtrd_arg));
1495 
1496         case DTRACEACT_USYM:
1497         case DTRACEACT_UADDR:
1498                 return (dt_print_usym(dtp, fp, addr, act));
1499 
1500         case DTRACEACT_UMOD:
1501                 return (dt_print_umod(dtp, fp, NULL, addr));
1502 
1503         case DTRACEACT_SYM:
1504                 return (dt_print_sym(dtp, fp, NULL, addr));
1505 


1508 
1509         case DTRACEAGG_QUANTIZE:
1510                 return (dt_print_quantize(dtp, fp, addr, size, normal));
1511 
1512         case DTRACEAGG_LQUANTIZE:
1513                 return (dt_print_lquantize(dtp, fp, addr, size, normal));
1514 
1515         case DTRACEAGG_LLQUANTIZE:
1516                 return (dt_print_llquantize(dtp, fp, addr, size, normal));
1517 
1518         case DTRACEAGG_AVG:
1519                 return (dt_print_average(dtp, fp, addr, size, normal));
1520 
1521         case DTRACEAGG_STDDEV:
1522                 return (dt_print_stddev(dtp, fp, addr, size, normal));
1523 
1524         default:
1525                 break;
1526         }
1527 





1528         switch (size) {
1529         case sizeof (uint64_t):
1530                 err = dt_printf(dtp, fp, " %16lld",
1531                     /* LINTED - alignment */
1532                     (long long)*((uint64_t *)addr) / normal);
1533                 break;
1534         case sizeof (uint32_t):
1535                 /* LINTED - alignment */
1536                 err = dt_printf(dtp, fp, " %8d", *((uint32_t *)addr) /
1537                     (uint32_t)normal);
1538                 break;
1539         case sizeof (uint16_t):
1540                 /* LINTED - alignment */
1541                 err = dt_printf(dtp, fp, " %5d", *((uint16_t *)addr) /
1542                     (uint32_t)normal);
1543                 break;
1544         case sizeof (uint8_t):
1545                 err = dt_printf(dtp, fp, " %3d", *((uint8_t *)addr) /
1546                     (uint32_t)normal);
1547                 break;
1548         default:
1549                 err = dt_print_bytes(dtp, fp, addr, size, 50, 0, 0);
1550                 break;
1551         }
1552 
1553         return (err);
1554 }
1555 
1556 int
1557 dt_print_aggs(const dtrace_aggdata_t **aggsdata, int naggvars, void *arg)
1558 {
1559         int i, aggact = 0;
1560         dt_print_aggdata_t *pd = arg;
1561         const dtrace_aggdata_t *aggdata = aggsdata[0];
1562         dtrace_aggdesc_t *agg = aggdata->dtada_desc;
1563         FILE *fp = pd->dtpa_fp;
1564         dtrace_hdl_t *dtp = pd->dtpa_dtp;
1565         dtrace_recdesc_t *rec;
1566         dtrace_actkind_t act;
1567         caddr_t addr;
1568         size_t size;
1569 



1570         /*
1571          * Iterate over each record description in the key, printing the traced
1572          * data, skipping the first datum (the tuple member created by the
1573          * compiler).
1574          */
1575         for (i = 1; i < agg->dtagd_nrecs; i++) {
1576                 rec = &agg->dtagd_rec[i];
1577                 act = rec->dtrd_action;
1578                 addr = aggdata->dtada_data + rec->dtrd_offset;
1579                 size = rec->dtrd_size;
1580 
1581                 if (DTRACEACT_ISAGG(act)) {
1582                         aggact = i;
1583                         break;
1584                 }
1585 
1586                 if (dt_print_datum(dtp, fp, rec, addr, size, 1) < 0)

1587                         return (-1);
1588 
1589                 if (dt_buffered_flush(dtp, NULL, rec, aggdata,
1590                     DTRACE_BUFDATA_AGGKEY) < 0)
1591                         return (-1);
1592         }
1593 
1594         assert(aggact != 0);
1595 
1596         for (i = (naggvars == 1 ? 0 : 1); i < naggvars; i++) {
1597                 uint64_t normal;
1598 
1599                 aggdata = aggsdata[i];
1600                 agg = aggdata->dtada_desc;
1601                 rec = &agg->dtagd_rec[aggact];
1602                 act = rec->dtrd_action;
1603                 addr = aggdata->dtada_data + rec->dtrd_offset;
1604                 size = rec->dtrd_size;
1605 
1606                 assert(DTRACEACT_ISAGG(act));
1607                 normal = aggdata->dtada_normal;
1608 
1609                 if (dt_print_datum(dtp, fp, rec, addr, size, normal) < 0)

1610                         return (-1);
1611 
1612                 if (dt_buffered_flush(dtp, NULL, rec, aggdata,
1613                     DTRACE_BUFDATA_AGGVAL) < 0)
1614                         return (-1);
1615 
1616                 if (!pd->dtpa_allunprint)
1617                         agg->dtagd_flags |= DTRACE_AGD_PRINTED;
1618         }
1619 

1620         if (dt_printf(dtp, fp, "\n") < 0)
1621                 return (-1);

1622 
1623         if (dt_buffered_flush(dtp, NULL, NULL, aggdata,
1624             DTRACE_BUFDATA_AGGFORMAT | DTRACE_BUFDATA_AGGLAST) < 0)
1625                 return (-1);
1626 
1627         return (0);
1628 }
1629 
1630 int
1631 dt_print_agg(const dtrace_aggdata_t *aggdata, void *arg)
1632 {
1633         dt_print_aggdata_t *pd = arg;
1634         dtrace_aggdesc_t *agg = aggdata->dtada_desc;
1635         dtrace_aggvarid_t aggvarid = pd->dtpa_id;
1636 
1637         if (pd->dtpa_allunprint) {
1638                 if (agg->dtagd_flags & DTRACE_AGD_PRINTED)
1639                         return (0);
1640         } else {
1641                 /*


2058                                 }
2059 
2060                                 if (dt_printf(dtp, fp, "\n") < 0 ||
2061                                     dtrace_aggregate_walk_joined(dtp, aggvars,
2062                                     naggvars, dt_print_aggs, &pd) < 0) {
2063                                         dt_free(dtp, aggvars);
2064                                         return (-1);
2065                                 }
2066 
2067                                 dt_free(dtp, aggvars);
2068                                 goto nextrec;
2069                         }
2070 
2071                         if (act == DTRACEACT_TRACEMEM) {
2072                                 if (tracememsize == 0 ||
2073                                     tracememsize > rec->dtrd_size) {
2074                                         tracememsize = rec->dtrd_size;
2075                                 }
2076 
2077                                 n = dt_print_bytes(dtp, fp, addr,
2078                                     tracememsize, 33, quiet, 1);
2079 
2080                                 tracememsize = 0;
2081 
2082                                 if (n < 0)
2083                                         return (-1);
2084 
2085                                 goto nextrec;
2086                         }
2087 
2088                         switch (rec->dtrd_size) {
2089                         case sizeof (uint64_t):
2090                                 n = dt_printf(dtp, fp,
2091                                     quiet ? "%lld" : " %16lld",
2092                                     /* LINTED - alignment */
2093                                     *((unsigned long long *)addr));
2094                                 break;
2095                         case sizeof (uint32_t):
2096                                 n = dt_printf(dtp, fp, quiet ? "%d" : " %8d",
2097                                     /* LINTED - alignment */
2098                                     *((uint32_t *)addr));
2099                                 break;
2100                         case sizeof (uint16_t):
2101                                 n = dt_printf(dtp, fp, quiet ? "%d" : " %5d",
2102                                     /* LINTED - alignment */
2103                                     *((uint16_t *)addr));
2104                                 break;
2105                         case sizeof (uint8_t):
2106                                 n = dt_printf(dtp, fp, quiet ? "%d" : " %3d",
2107                                     *((uint8_t *)addr));
2108                                 break;
2109                         default:
2110                                 n = dt_print_bytes(dtp, fp, addr,
2111                                     rec->dtrd_size, 33, quiet, 0);
2112                                 break;
2113                         }
2114 
2115                         if (n < 0)
2116                                 return (-1); /* errno is set for us */
2117 
2118 nextrec:
2119                         if (dt_buffered_flush(dtp, &data, rec, NULL, 0) < 0)
2120                                 return (-1); /* errno is set for us */
2121                 }
2122 
2123                 /*
2124                  * Call the record callback with a NULL record to indicate
2125                  * that we're done processing this EPID.
2126                  */
2127                 rval = (*rfunc)(&data, NULL, arg);
2128 nextepid:
2129                 offs += epd->dtepd_size;
2130                 dtp->dt_last_epid = id;
2131                 if (just_one) {




   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 /*
  27  * Copyright (c) 2013, Joyent, Inc. All rights reserved.
  28  * Copyright (c) 2012 by Delphix. All rights reserved.
  29  */
  30 
  31 #include <stdlib.h>
  32 #include <strings.h>
  33 #include <errno.h>
  34 #include <unistd.h>
  35 #include <limits.h>
  36 #include <assert.h>
  37 #include <ctype.h>
  38 #include <alloca.h>
  39 #include <dt_impl.h>
  40 #include <dt_pq.h>
  41 
  42 #define DT_MASK_LO 0x00000000FFFFFFFFULL
  43 
  44 /*
  45  * We declare this here because (1) we need it and (2) we want to avoid a
  46  * dependency on libm in libdtrace.
  47  */
  48 static long double
  49 dt_fabsl(long double x)
  50 {
  51         if (x < 0)
  52                 return (-x);
  53 
  54         return (x);
  55 }
  56 
  57 static int
  58 dt_ndigits(long long val)
  59 {
  60         int rval = 1;
  61         long long cmp = 10;
  62 
  63         if (val < 0) {
  64                 val = val == INT64_MIN ? INT64_MAX : -val;
  65                 rval++;
  66         }
  67 
  68         while (val > cmp && cmp > 0) {
  69                 rval++;
  70                 cmp *= 10;
  71         }
  72 
  73         return (rval < 4 ? 4 : rval);
  74 }
  75 
  76 /*
  77  * 128-bit arithmetic functions needed to support the stddev() aggregating
  78  * action.
  79  */
  80 static int
  81 dt_gt_128(uint64_t *a, uint64_t *b)
  82 {
  83         return (a[1] > b[1] || (a[1] == b[1] && a[0] > b[0]));
  84 }
  85 
  86 static int
  87 dt_ge_128(uint64_t *a, uint64_t *b)
  88 {
  89         return (a[1] > b[1] || (a[1] == b[1] && a[0] >= b[0]));
  90 }
  91 
  92 static int
  93 dt_le_128(uint64_t *a, uint64_t *b)
  94 {
  95         return (a[1] < b[1] || (a[1] == b[1] && a[0] <= b[0]));


 484         if (flow == DTRACEFLOW_RETURN && data->dtpda_indent > 0)
 485                 data->dtpda_indent -= 2;
 486 
 487         data->dtpda_flow = flow;
 488 
 489         return (0);
 490 }
 491 
 492 static int
 493 dt_nullprobe()
 494 {
 495         return (DTRACE_CONSUME_THIS);
 496 }
 497 
 498 static int
 499 dt_nullrec()
 500 {
 501         return (DTRACE_CONSUME_NEXT);
 502 }
 503 
 504 static void
 505 dt_quantize_total(dtrace_hdl_t *dtp, int64_t datum, long double *total)
 506 {
 507         long double val = dt_fabsl((long double)datum);
 508 
 509         if (dtp->dt_options[DTRACEOPT_AGGZOOM] == DTRACEOPT_UNSET) {
 510                 *total += val;
 511                 return;
 512         }
 513 
 514         /*
 515          * If we're zooming in on an aggregation, we want the height of the
 516          * highest value to be approximately 95% of total bar height -- so we
 517          * adjust up by the reciprocal of DTRACE_AGGZOOM_MAX when comparing to
 518          * our highest value.
 519          */
 520         val *= 1 / DTRACE_AGGZOOM_MAX;
 521 
 522         if (*total < val)
 523                 *total = val;
 524 }
 525 
 526 static int
 527 dt_print_quanthdr(dtrace_hdl_t *dtp, FILE *fp, int width)
 528 {
 529         return (dt_printf(dtp, fp, "\n%*s %41s %-9s\n",
 530             width ? width : 16, width ? "key" : "value",
 531             "------------- Distribution -------------", "count"));
 532 }
 533 
 534 static int
 535 dt_print_quanthdr_packed(dtrace_hdl_t *dtp, FILE *fp, int width,
 536     const dtrace_aggdata_t *aggdata, dtrace_actkind_t action)
 537 {
 538         int min = aggdata->dtada_minbin, max = aggdata->dtada_maxbin;
 539         int minwidth, maxwidth, i;
 540 
 541         assert(action == DTRACEAGG_QUANTIZE || action == DTRACEAGG_LQUANTIZE);
 542 
 543         if (action == DTRACEAGG_QUANTIZE) {
 544                 if (min != 0 && min != DTRACE_QUANTIZE_ZEROBUCKET)
 545                         min--;
 546 
 547                 if (max < DTRACE_QUANTIZE_NBUCKETS - 1)
 548                         max++;
 549 
 550                 minwidth = dt_ndigits(DTRACE_QUANTIZE_BUCKETVAL(min));
 551                 maxwidth = dt_ndigits(DTRACE_QUANTIZE_BUCKETVAL(max));
 552         } else {
 553                 maxwidth = 8;
 554                 minwidth = maxwidth - 1;
 555                 max++;
 556         }
 557 
 558         if (dt_printf(dtp, fp, "\n%*s %*s .",
 559             width, width > 0 ? "key" : "", minwidth, "min") < 0)
 560                 return (-1);
 561 
 562         for (i = min; i <= max; i++) {
 563                 if (dt_printf(dtp, fp, "-") < 0)
 564                         return (-1);
 565         }
 566 
 567         return (dt_printf(dtp, fp, ". %*s | count\n", -maxwidth, "max"));
 568 }
 569 
 570 /*
 571  * We use a subset of the Unicode Block Elements (U+2588 through U+258F,
 572  * inclusive) to represent aggregations via UTF-8 -- which are expressed via
 573  * 3-byte UTF-8 sequences.
 574  */
 575 #define DTRACE_AGGUTF8_FULL     0x2588
 576 #define DTRACE_AGGUTF8_BASE     0x258f
 577 #define DTRACE_AGGUTF8_LEVELS   8
 578 
 579 #define DTRACE_AGGUTF8_BYTE0(val)       (0xe0 | ((val) >> 12))
 580 #define DTRACE_AGGUTF8_BYTE1(val)       (0x80 | (((val) >> 6) & 0x3f))
 581 #define DTRACE_AGGUTF8_BYTE2(val)       (0x80 | ((val) & 0x3f))
 582 
 583 static int
 584 dt_print_quantline_utf8(dtrace_hdl_t *dtp, FILE *fp, int64_t val,
 585     uint64_t normal, long double total)
 586 {
 587         uint_t len = 40, i, whole, partial;
 588         long double f = (dt_fabsl((long double)val) * len) / total;
 589         const char *spaces = "                                        ";
 590 
 591         whole = (uint_t)f;
 592         partial = (uint_t)((f - (long double)(uint_t)f) *
 593             (long double)DTRACE_AGGUTF8_LEVELS);
 594 
 595         if (dt_printf(dtp, fp, "|") < 0)
 596                 return (-1);
 597 
 598         for (i = 0; i < whole; i++) {
 599                 if (dt_printf(dtp, fp, "%c%c%c",
 600                     DTRACE_AGGUTF8_BYTE0(DTRACE_AGGUTF8_FULL),
 601                     DTRACE_AGGUTF8_BYTE1(DTRACE_AGGUTF8_FULL),
 602                     DTRACE_AGGUTF8_BYTE2(DTRACE_AGGUTF8_FULL)) < 0)
 603                         return (-1);
 604         }
 605 
 606         if (partial != 0) {
 607                 partial = DTRACE_AGGUTF8_BASE - (partial - 1);
 608 
 609                 if (dt_printf(dtp, fp, "%c%c%c",
 610                     DTRACE_AGGUTF8_BYTE0(partial),
 611                     DTRACE_AGGUTF8_BYTE1(partial),
 612                     DTRACE_AGGUTF8_BYTE2(partial)) < 0)
 613                         return (-1);
 614 
 615                 i++;
 616         }
 617 
 618         return (dt_printf(dtp, fp, "%s %-9lld\n", spaces + i,
 619             (long long)val / normal));
 620 }
 621 
 622 static int
 623 dt_print_quantline(dtrace_hdl_t *dtp, FILE *fp, int64_t val,
 624     uint64_t normal, long double total, char positives, char negatives)
 625 {
 626         long double f;
 627         uint_t depth, len = 40;
 628 
 629         const char *ats = "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@";
 630         const char *spaces = "                                        ";
 631 
 632         assert(strlen(ats) == len && strlen(spaces) == len);
 633         assert(!(total == 0 && (positives || negatives)));
 634         assert(!(val < 0 && !negatives));
 635         assert(!(val > 0 && !positives));
 636         assert(!(val != 0 && total == 0));
 637 
 638         if (!negatives) {
 639                 if (positives) {
 640                         if (dtp->dt_encoding == DT_ENCODING_UTF8) {
 641                                 return (dt_print_quantline_utf8(dtp, fp, val,
 642                                     normal, total));
 643                         }
 644 
 645                         f = (dt_fabsl((long double)val) * len) / total;
 646                         depth = (uint_t)(f + 0.5);
 647                 } else {
 648                         depth = 0;
 649                 }
 650 
 651                 return (dt_printf(dtp, fp, "|%s%s %-9lld\n", ats + len - depth,
 652                     spaces + depth, (long long)val / normal));
 653         }
 654 
 655         if (!positives) {
 656                 f = (dt_fabsl((long double)val) * len) / total;
 657                 depth = (uint_t)(f + 0.5);
 658 
 659                 return (dt_printf(dtp, fp, "%s%s| %-9lld\n", spaces + depth,
 660                     ats + len - depth, (long long)val / normal));
 661         }
 662 
 663         /*
 664          * If we're here, we have both positive and negative bucket values.


 667          * the size of normal quantize()/lquantize() bars, so we divide the
 668          * length in half before calculating the bar length.
 669          */
 670         len /= 2;
 671         ats = &ats[len];
 672         spaces = &spaces[len];
 673 
 674         f = (dt_fabsl((long double)val) * len) / total;
 675         depth = (uint_t)(f + 0.5);
 676 
 677         if (val <= 0) {
 678                 return (dt_printf(dtp, fp, "%s%s|%*s %-9lld\n", spaces + depth,
 679                     ats + len - depth, len, "", (long long)val / normal));
 680         } else {
 681                 return (dt_printf(dtp, fp, "%20s|%s%s %-9lld\n", "",
 682                     ats + len - depth, spaces + depth,
 683                     (long long)val / normal));
 684         }
 685 }
 686 
 687 /*
 688  * As with UTF-8 printing of aggregations, we use a subset of the Unicode
 689  * Block Elements (U+2581 through U+2588, inclusive) to represent our packed
 690  * aggregation.
 691  */
 692 #define DTRACE_AGGPACK_BASE     0x2581
 693 #define DTRACE_AGGPACK_LEVELS   8
 694 
 695 static int
 696 dt_print_packed(dtrace_hdl_t *dtp, FILE *fp,
 697     long double datum, long double total)
 698 {
 699         static boolean_t utf8_checked = B_FALSE;
 700         static boolean_t utf8;
 701         char *ascii = "__xxxxXX";
 702         char *neg = "vvvvVV";
 703         unsigned int len;
 704         long double val;
 705 
 706         if (!utf8_checked) {
 707                 char *term;
 708 
 709                 /*
 710                  * We want to determine if we can reasonably emit UTF-8 for our
 711                  * packed aggregation.  To do this, we will check for terminals
 712                  * that are known to be primitive to emit UTF-8 on these.
 713                  */
 714                 utf8_checked = B_TRUE;
 715 
 716                 if (dtp->dt_encoding == DT_ENCODING_ASCII)
 717                         utf8 = B_FALSE;
 718                 else if (dtp->dt_encoding == DT_ENCODING_UTF8)
 719                         utf8 = B_TRUE;
 720                 else if ((term = getenv("TERM")) != NULL &&
 721                     (strcmp(term, "sun") == 0 ||
 722                     strcmp(term, "sun-color") == 0) ||
 723                     strcmp(term, "dumb") == 0)
 724                         utf8 = B_FALSE;
 725                 else
 726                         utf8 = B_TRUE;
 727         }
 728 
 729         if (datum == 0)
 730                 return (dt_printf(dtp, fp, " "));
 731 
 732         if (datum < 0) {
 733                 len = strlen(neg);
 734                 val = dt_fabsl(datum * (len - 1)) / total;
 735                 return (dt_printf(dtp, fp, "%c", neg[(uint_t)(val + 0.5)]));
 736         }
 737 
 738         if (utf8) {
 739                 int block = DTRACE_AGGPACK_BASE + (unsigned int)(((datum *
 740                     (DTRACE_AGGPACK_LEVELS - 1)) / total) + 0.5);
 741 
 742                 return (dt_printf(dtp, fp, "%c%c%c",
 743                     DTRACE_AGGUTF8_BYTE0(block),
 744                     DTRACE_AGGUTF8_BYTE1(block),
 745                     DTRACE_AGGUTF8_BYTE2(block)));
 746         }
 747 
 748         len = strlen(ascii);
 749         val = (datum * (len - 1)) / total;
 750         return (dt_printf(dtp, fp, "%c", ascii[(uint_t)(val + 0.5)]));
 751 }
 752 
 753 int
 754 dt_print_quantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
 755     size_t size, uint64_t normal)
 756 {
 757         const int64_t *data = addr;
 758         int i, first_bin = 0, last_bin = DTRACE_QUANTIZE_NBUCKETS - 1;
 759         long double total = 0;
 760         char positives = 0, negatives = 0;
 761 
 762         if (size != DTRACE_QUANTIZE_NBUCKETS * sizeof (uint64_t))
 763                 return (dt_set_errno(dtp, EDT_DMISMATCH));
 764 
 765         while (first_bin < DTRACE_QUANTIZE_NBUCKETS - 1 && data[first_bin] == 0)
 766                 first_bin++;
 767 
 768         if (first_bin == DTRACE_QUANTIZE_NBUCKETS - 1) {
 769                 /*
 770                  * There isn't any data.  This is possible if the aggregation
 771                  * has been clear()'d or if negative increment values have been
 772                  * used.  Regardless, we'll print the buckets around 0.
 773                  */
 774                 first_bin = DTRACE_QUANTIZE_ZEROBUCKET - 1;
 775                 last_bin = DTRACE_QUANTIZE_ZEROBUCKET + 1;
 776         } else {
 777                 if (first_bin > 0)
 778                         first_bin--;
 779 
 780                 while (last_bin > 0 && data[last_bin] == 0)
 781                         last_bin--;
 782 
 783                 if (last_bin < DTRACE_QUANTIZE_NBUCKETS - 1)
 784                         last_bin++;
 785         }
 786 
 787         for (i = first_bin; i <= last_bin; i++) {
 788                 positives |= (data[i] > 0);
 789                 negatives |= (data[i] < 0);
 790                 dt_quantize_total(dtp, data[i], &total);
 791         }
 792 
 793         if (dt_print_quanthdr(dtp, fp, 0) < 0)

 794                 return (-1);
 795 
 796         for (i = first_bin; i <= last_bin; i++) {
 797                 if (dt_printf(dtp, fp, "%16lld ",
 798                     (long long)DTRACE_QUANTIZE_BUCKETVAL(i)) < 0)
 799                         return (-1);
 800 
 801                 if (dt_print_quantline(dtp, fp, data[i], normal, total,
 802                     positives, negatives) < 0)
 803                         return (-1);
 804         }
 805 
 806         return (0);
 807 }
 808 
 809 int
 810 dt_print_quantize_packed(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
 811     size_t size, const dtrace_aggdata_t *aggdata)
 812 {
 813         const int64_t *data = addr;
 814         long double total = 0, count = 0;
 815         int min = aggdata->dtada_minbin, max = aggdata->dtada_maxbin, i;
 816         int64_t minval, maxval;
 817 
 818         if (size != DTRACE_QUANTIZE_NBUCKETS * sizeof (uint64_t))
 819                 return (dt_set_errno(dtp, EDT_DMISMATCH));
 820 
 821         if (min != 0 && min != DTRACE_QUANTIZE_ZEROBUCKET)
 822                 min--;
 823 
 824         if (max < DTRACE_QUANTIZE_NBUCKETS - 1)
 825                 max++;
 826 
 827         minval = DTRACE_QUANTIZE_BUCKETVAL(min);
 828         maxval = DTRACE_QUANTIZE_BUCKETVAL(max);
 829 
 830         if (dt_printf(dtp, fp, " %*lld :", dt_ndigits(minval),
 831             (long long)minval) < 0)
 832                 return (-1);
 833 
 834         for (i = min; i <= max; i++) {
 835                 dt_quantize_total(dtp, data[i], &total);
 836                 count += data[i];
 837         }
 838 
 839         for (i = min; i <= max; i++) {
 840                 if (dt_print_packed(dtp, fp, data[i], total) < 0)
 841                         return (-1);
 842         }
 843 
 844         if (dt_printf(dtp, fp, ": %*lld | %lld\n",
 845             -dt_ndigits(maxval), (long long)maxval, (long long)count) < 0)
 846                 return (-1);
 847 
 848         return (0);
 849 }
 850 
 851 int
 852 dt_print_lquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
 853     size_t size, uint64_t normal)
 854 {
 855         const int64_t *data = addr;
 856         int i, first_bin, last_bin, base;
 857         uint64_t arg;
 858         long double total = 0;
 859         uint16_t step, levels;
 860         char positives = 0, negatives = 0;
 861 
 862         if (size < sizeof (uint64_t))
 863                 return (dt_set_errno(dtp, EDT_DMISMATCH));
 864 
 865         arg = *data++;
 866         size -= sizeof (uint64_t);
 867 
 868         base = DTRACE_LQUANTIZE_BASE(arg);
 869         step = DTRACE_LQUANTIZE_STEP(arg);
 870         levels = DTRACE_LQUANTIZE_LEVELS(arg);
 871 


 878         while (first_bin <= levels + 1 && data[first_bin] == 0)
 879                 first_bin++;
 880 
 881         if (first_bin > levels + 1) {
 882                 first_bin = 0;
 883                 last_bin = 2;
 884         } else {
 885                 if (first_bin > 0)
 886                         first_bin--;
 887 
 888                 while (last_bin > 0 && data[last_bin] == 0)
 889                         last_bin--;
 890 
 891                 if (last_bin < levels + 1)
 892                         last_bin++;
 893         }
 894 
 895         for (i = first_bin; i <= last_bin; i++) {
 896                 positives |= (data[i] > 0);
 897                 negatives |= (data[i] < 0);
 898                 dt_quantize_total(dtp, data[i], &total);
 899         }
 900 
 901         if (dt_printf(dtp, fp, "\n%16s %41s %-9s\n", "value",
 902             "------------- Distribution -------------", "count") < 0)
 903                 return (-1);
 904 
 905         for (i = first_bin; i <= last_bin; i++) {
 906                 char c[32];
 907                 int err;
 908 
 909                 if (i == 0) {
 910                         (void) snprintf(c, sizeof (c), "< %d", base);

 911                         err = dt_printf(dtp, fp, "%16s ", c);
 912                 } else if (i == levels + 1) {
 913                         (void) snprintf(c, sizeof (c), ">= %d",
 914                             base + (levels * step));
 915                         err = dt_printf(dtp, fp, "%16s ", c);
 916                 } else {
 917                         err = dt_printf(dtp, fp, "%16d ",
 918                             base + (i - 1) * step);
 919                 }
 920 
 921                 if (err < 0 || dt_print_quantline(dtp, fp, data[i], normal,
 922                     total, positives, negatives) < 0)
 923                         return (-1);
 924         }
 925 
 926         return (0);
 927 }
 928 
 929 /*ARGSUSED*/
 930 int
 931 dt_print_lquantize_packed(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
 932     size_t size, const dtrace_aggdata_t *aggdata)
 933 {
 934         const int64_t *data = addr;
 935         long double total = 0, count = 0;
 936         int min, max, base, err;
 937         uint64_t arg;
 938         uint16_t step, levels;
 939         char c[32];
 940         unsigned int i;
 941 
 942         if (size < sizeof (uint64_t))
 943                 return (dt_set_errno(dtp, EDT_DMISMATCH));
 944 
 945         arg = *data++;
 946         size -= sizeof (uint64_t);
 947 
 948         base = DTRACE_LQUANTIZE_BASE(arg);
 949         step = DTRACE_LQUANTIZE_STEP(arg);
 950         levels = DTRACE_LQUANTIZE_LEVELS(arg);
 951 
 952         if (size != sizeof (uint64_t) * (levels + 2))
 953                 return (dt_set_errno(dtp, EDT_DMISMATCH));
 954 
 955         min = 0;
 956         max = levels + 1;
 957 
 958         if (min == 0) {
 959                 (void) snprintf(c, sizeof (c), "< %d", base);
 960                 err = dt_printf(dtp, fp, "%8s :", c);
 961         } else {
 962                 err = dt_printf(dtp, fp, "%8d :", base + (min - 1) * step);
 963         }
 964 
 965         if (err < 0)
 966                 return (-1);
 967 
 968         for (i = min; i <= max; i++) {
 969                 dt_quantize_total(dtp, data[i], &total);
 970                 count += data[i];
 971         }
 972 
 973         for (i = min; i <= max; i++) {
 974                 if (dt_print_packed(dtp, fp, data[i], total) < 0)
 975                         return (-1);
 976         }
 977 
 978         (void) snprintf(c, sizeof (c), ">= %d", base + (levels * step));
 979         return (dt_printf(dtp, fp, ": %-8s | %lld\n", c, (long long)count));
 980 }
 981 
 982 int
 983 dt_print_llquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
 984     size_t size, uint64_t normal)
 985 {
 986         int i, first_bin, last_bin, bin = 1, order, levels;
 987         uint16_t factor, low, high, nsteps;
 988         const int64_t *data = addr;
 989         int64_t value = 1, next, step;
 990         char positives = 0, negatives = 0;
 991         long double total = 0;
 992         uint64_t arg;
 993         char c[32];
 994 
 995         if (size < sizeof (uint64_t))
 996                 return (dt_set_errno(dtp, EDT_DMISMATCH));
 997 
 998         arg = *data++;
 999         size -= sizeof (uint64_t);
1000 
1001         factor = DTRACE_LLQUANTIZE_FACTOR(arg);


1019         while (first_bin < levels && data[first_bin] == 0)
1020                 first_bin++;
1021 
1022         if (first_bin == levels) {
1023                 first_bin = 0;
1024                 last_bin = 1;
1025         } else {
1026                 if (first_bin > 0)
1027                         first_bin--;
1028 
1029                 while (last_bin > 0 && data[last_bin] == 0)
1030                         last_bin--;
1031 
1032                 if (last_bin < levels - 1)
1033                         last_bin++;
1034         }
1035 
1036         for (i = first_bin; i <= last_bin; i++) {
1037                 positives |= (data[i] > 0);
1038                 negatives |= (data[i] < 0);
1039                 dt_quantize_total(dtp, data[i], &total);
1040         }
1041 
1042         if (dt_printf(dtp, fp, "\n%16s %41s %-9s\n", "value",
1043             "------------- Distribution -------------", "count") < 0)
1044                 return (-1);
1045 
1046         for (order = 0; order < low; order++)
1047                 value *= factor;
1048 
1049         next = value * factor;
1050         step = next > nsteps ? next / nsteps : 1;
1051 
1052         if (first_bin == 0) {
1053                 (void) snprintf(c, sizeof (c), "< %lld", value);
1054 
1055                 if (dt_printf(dtp, fp, "%16s ", c) < 0)
1056                         return (-1);
1057 
1058                 if (dt_print_quantline(dtp, fp, data[0], normal,
1059                     total, positives, negatives) < 0)


1102         /* LINTED - alignment */
1103         int64_t *data = (int64_t *)addr;
1104 
1105         return (dt_printf(dtp, fp, " %16lld", data[0] ?
1106             (long long)(data[1] / (int64_t)normal / data[0]) : 0));
1107 }
1108 
1109 /*ARGSUSED*/
1110 static int
1111 dt_print_stddev(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr,
1112     size_t size, uint64_t normal)
1113 {
1114         /* LINTED - alignment */
1115         uint64_t *data = (uint64_t *)addr;
1116 
1117         return (dt_printf(dtp, fp, " %16llu", data[0] ?
1118             (unsigned long long) dt_stddev(data, normal) : 0));
1119 }
1120 
1121 /*ARGSUSED*/
1122 static int
1123 dt_print_bytes(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr,
1124     size_t nbytes, int width, int quiet, int forceraw)
1125 {
1126         /*
1127          * If the byte stream is a series of printable characters, followed by
1128          * a terminating byte, we print it out as a string.  Otherwise, we
1129          * assume that it's something else and just print the bytes.
1130          */
1131         int i, j, margin = 5;
1132         char *c = (char *)addr;
1133 
1134         if (nbytes == 0)
1135                 return (0);
1136 
1137         if (forceraw)
1138                 goto raw;
1139 
1140         if (dtp->dt_options[DTRACEOPT_RAWBYTES] != DTRACEOPT_UNSET)
1141                 goto raw;
1142 


1155                     c[i] == '\b' || c[i] == '\a')
1156                         continue;
1157 
1158                 if (c[i] == '\0' && i > 0) {
1159                         /*
1160                          * This looks like it might be a string.  Before we
1161                          * assume that it is indeed a string, check the
1162                          * remainder of the byte range; if it contains
1163                          * additional non-nul characters, we'll assume that
1164                          * it's a binary stream that just happens to look like
1165                          * a string, and we'll print out the individual bytes.
1166                          */
1167                         for (j = i + 1; j < nbytes; j++) {
1168                                 if (c[j] != '\0')
1169                                         break;
1170                         }
1171 
1172                         if (j != nbytes)
1173                                 break;
1174 
1175                         if (quiet) {
1176                                 return (dt_printf(dtp, fp, "%s", c));
1177                         } else {
1178                                 return (dt_printf(dtp, fp, " %s%*s",
1179                                     width < 0 ? " " : "", width, c));
1180                         }
1181                 }
1182 
1183                 break;
1184         }
1185 
1186         if (i == nbytes) {
1187                 /*
1188                  * The byte range is all printable characters, but there is
1189                  * no trailing nul byte.  We'll assume that it's a string and
1190                  * print it as such.
1191                  */
1192                 char *s = alloca(nbytes + 1);
1193                 bcopy(c, s, nbytes);
1194                 s[nbytes] = '\0';
1195                 return (dt_printf(dtp, fp, "  %-*s", width, s));
1196         }
1197 
1198 raw:
1199         if (dt_printf(dtp, fp, "\n%*s      ", margin, "") < 0)
1200                 return (-1);


1765                 return (dt_set_errno(dtp, EDT_BADNORMAL));
1766         }
1767 
1768         if (remaining < 0) {
1769                 func = dtrace_aggregate_walk_valsorted;
1770                 remaining = -remaining;
1771         } else {
1772                 func = dtrace_aggregate_walk_valrevsorted;
1773         }
1774 
1775         assert(remaining >= 0);
1776         trunc.dttd_remaining = remaining;
1777 
1778         (void) func(dtp, dt_trunc_agg, &trunc);
1779 
1780         return (0);
1781 }
1782 
1783 static int
1784 dt_print_datum(dtrace_hdl_t *dtp, FILE *fp, dtrace_recdesc_t *rec,
1785     caddr_t addr, size_t size, const dtrace_aggdata_t *aggdata,
1786     uint64_t normal, dt_print_aggdata_t *pd)
1787 {
1788         int err, width;
1789         dtrace_actkind_t act = rec->dtrd_action;
1790         boolean_t packed = pd->dtpa_agghist || pd->dtpa_aggpack;
1791         dtrace_aggdesc_t *agg = aggdata->dtada_desc;
1792 
1793         static struct {
1794                 size_t size;
1795                 int width;
1796                 int packedwidth;
1797         } *fmt, fmttab[] = {
1798                 { sizeof (uint8_t),     3,      3 },
1799                 { sizeof (uint16_t),    5,      5 },
1800                 { sizeof (uint32_t),    8,      8 },
1801                 { sizeof (uint64_t),    16,     16 },
1802                 { 0,                    -50,    16 }
1803         };
1804 
1805         if (packed && pd->dtpa_agghisthdr != agg->dtagd_varid) {
1806                 dtrace_recdesc_t *r;
1807 
1808                 width = 0;
1809 
1810                 /*
1811                  * To print our quantization header for either an agghist or
1812                  * aggpack aggregation, we need to iterate through all of our
1813                  * of our records to determine their width.
1814                  */
1815                 for (r = rec; !DTRACEACT_ISAGG(r->dtrd_action); r++) {
1816                         for (fmt = fmttab; fmt->size &&
1817                             fmt->size != r->dtrd_size; fmt++)
1818                                 continue;
1819 
1820                         width += fmt->packedwidth + 1;
1821                 }
1822 
1823                 if (pd->dtpa_agghist) {
1824                         if (dt_print_quanthdr(dtp, fp, width) < 0)
1825                                 return (-1);
1826                 } else {
1827                         if (dt_print_quanthdr_packed(dtp, fp,
1828                             width, aggdata, r->dtrd_action) < 0)
1829                                 return (-1);
1830                 }
1831 
1832                 pd->dtpa_agghisthdr = agg->dtagd_varid;
1833         }
1834 
1835         if (pd->dtpa_agghist && DTRACEACT_ISAGG(act)) {
1836                 char positives = aggdata->dtada_flags & DTRACE_A_HASPOSITIVES;
1837                 char negatives = aggdata->dtada_flags & DTRACE_A_HASNEGATIVES;
1838                 int64_t val;
1839 
1840                 assert(act == DTRACEAGG_SUM || act == DTRACEAGG_COUNT);
1841                 val = (long long)*((uint64_t *)addr);
1842 
1843                 if (dt_printf(dtp, fp, " ") < 0)
1844                         return (-1);
1845 
1846                 return (dt_print_quantline(dtp, fp, val, normal,
1847                     aggdata->dtada_total, positives, negatives));
1848         }
1849 
1850         if (pd->dtpa_aggpack && DTRACEACT_ISAGG(act)) {
1851                 switch (act) {
1852                 case DTRACEAGG_QUANTIZE:
1853                         return (dt_print_quantize_packed(dtp,
1854                             fp, addr, size, aggdata));
1855                 case DTRACEAGG_LQUANTIZE:
1856                         return (dt_print_lquantize_packed(dtp,
1857                             fp, addr, size, aggdata));
1858                 default:
1859                         break;
1860                 }
1861         }
1862 
1863         switch (act) {
1864         case DTRACEACT_STACK:
1865                 return (dt_print_stack(dtp, fp, NULL, addr,
1866                     rec->dtrd_arg, rec->dtrd_size / rec->dtrd_arg));
1867 
1868         case DTRACEACT_USTACK:
1869         case DTRACEACT_JSTACK:
1870                 return (dt_print_ustack(dtp, fp, NULL, addr, rec->dtrd_arg));
1871 
1872         case DTRACEACT_USYM:
1873         case DTRACEACT_UADDR:
1874                 return (dt_print_usym(dtp, fp, addr, act));
1875 
1876         case DTRACEACT_UMOD:
1877                 return (dt_print_umod(dtp, fp, NULL, addr));
1878 
1879         case DTRACEACT_SYM:
1880                 return (dt_print_sym(dtp, fp, NULL, addr));
1881 


1884 
1885         case DTRACEAGG_QUANTIZE:
1886                 return (dt_print_quantize(dtp, fp, addr, size, normal));
1887 
1888         case DTRACEAGG_LQUANTIZE:
1889                 return (dt_print_lquantize(dtp, fp, addr, size, normal));
1890 
1891         case DTRACEAGG_LLQUANTIZE:
1892                 return (dt_print_llquantize(dtp, fp, addr, size, normal));
1893 
1894         case DTRACEAGG_AVG:
1895                 return (dt_print_average(dtp, fp, addr, size, normal));
1896 
1897         case DTRACEAGG_STDDEV:
1898                 return (dt_print_stddev(dtp, fp, addr, size, normal));
1899 
1900         default:
1901                 break;
1902         }
1903 
1904         for (fmt = fmttab; fmt->size && fmt->size != size; fmt++)
1905                 continue;
1906 
1907         width = packed ? fmt->packedwidth : fmt->width;
1908 
1909         switch (size) {
1910         case sizeof (uint64_t):
1911                 err = dt_printf(dtp, fp, " %*lld", width,
1912                     /* LINTED - alignment */
1913                     (long long)*((uint64_t *)addr) / normal);
1914                 break;
1915         case sizeof (uint32_t):
1916                 /* LINTED - alignment */
1917                 err = dt_printf(dtp, fp, " %*d", width, *((uint32_t *)addr) /
1918                     (uint32_t)normal);
1919                 break;
1920         case sizeof (uint16_t):
1921                 /* LINTED - alignment */
1922                 err = dt_printf(dtp, fp, " %*d", width, *((uint16_t *)addr) /
1923                     (uint32_t)normal);
1924                 break;
1925         case sizeof (uint8_t):
1926                 err = dt_printf(dtp, fp, " %*d", width, *((uint8_t *)addr) /
1927                     (uint32_t)normal);
1928                 break;
1929         default:
1930                 err = dt_print_bytes(dtp, fp, addr, size, width, 0, 0);
1931                 break;
1932         }
1933 
1934         return (err);
1935 }
1936 
1937 int
1938 dt_print_aggs(const dtrace_aggdata_t **aggsdata, int naggvars, void *arg)
1939 {
1940         int i, aggact = 0;
1941         dt_print_aggdata_t *pd = arg;
1942         const dtrace_aggdata_t *aggdata = aggsdata[0];
1943         dtrace_aggdesc_t *agg = aggdata->dtada_desc;
1944         FILE *fp = pd->dtpa_fp;
1945         dtrace_hdl_t *dtp = pd->dtpa_dtp;
1946         dtrace_recdesc_t *rec;
1947         dtrace_actkind_t act;
1948         caddr_t addr;
1949         size_t size;
1950 
1951         pd->dtpa_agghist = (aggdata->dtada_flags & DTRACE_A_TOTAL);
1952         pd->dtpa_aggpack = (aggdata->dtada_flags & DTRACE_A_MINMAXBIN);
1953 
1954         /*
1955          * Iterate over each record description in the key, printing the traced
1956          * data, skipping the first datum (the tuple member created by the
1957          * compiler).
1958          */
1959         for (i = 1; i < agg->dtagd_nrecs; i++) {
1960                 rec = &agg->dtagd_rec[i];
1961                 act = rec->dtrd_action;
1962                 addr = aggdata->dtada_data + rec->dtrd_offset;
1963                 size = rec->dtrd_size;
1964 
1965                 if (DTRACEACT_ISAGG(act)) {
1966                         aggact = i;
1967                         break;
1968                 }
1969 
1970                 if (dt_print_datum(dtp, fp, rec, addr,
1971                     size, aggdata, 1, pd) < 0)
1972                         return (-1);
1973 
1974                 if (dt_buffered_flush(dtp, NULL, rec, aggdata,
1975                     DTRACE_BUFDATA_AGGKEY) < 0)
1976                         return (-1);
1977         }
1978 
1979         assert(aggact != 0);
1980 
1981         for (i = (naggvars == 1 ? 0 : 1); i < naggvars; i++) {
1982                 uint64_t normal;
1983 
1984                 aggdata = aggsdata[i];
1985                 agg = aggdata->dtada_desc;
1986                 rec = &agg->dtagd_rec[aggact];
1987                 act = rec->dtrd_action;
1988                 addr = aggdata->dtada_data + rec->dtrd_offset;
1989                 size = rec->dtrd_size;
1990 
1991                 assert(DTRACEACT_ISAGG(act));
1992                 normal = aggdata->dtada_normal;
1993 
1994                 if (dt_print_datum(dtp, fp, rec, addr,
1995                     size, aggdata, normal, pd) < 0)
1996                         return (-1);
1997 
1998                 if (dt_buffered_flush(dtp, NULL, rec, aggdata,
1999                     DTRACE_BUFDATA_AGGVAL) < 0)
2000                         return (-1);
2001 
2002                 if (!pd->dtpa_allunprint)
2003                         agg->dtagd_flags |= DTRACE_AGD_PRINTED;
2004         }
2005 
2006         if (!pd->dtpa_agghist && !pd->dtpa_aggpack) {
2007                 if (dt_printf(dtp, fp, "\n") < 0)
2008                         return (-1);
2009         }
2010 
2011         if (dt_buffered_flush(dtp, NULL, NULL, aggdata,
2012             DTRACE_BUFDATA_AGGFORMAT | DTRACE_BUFDATA_AGGLAST) < 0)
2013                 return (-1);
2014 
2015         return (0);
2016 }
2017 
2018 int
2019 dt_print_agg(const dtrace_aggdata_t *aggdata, void *arg)
2020 {
2021         dt_print_aggdata_t *pd = arg;
2022         dtrace_aggdesc_t *agg = aggdata->dtada_desc;
2023         dtrace_aggvarid_t aggvarid = pd->dtpa_id;
2024 
2025         if (pd->dtpa_allunprint) {
2026                 if (agg->dtagd_flags & DTRACE_AGD_PRINTED)
2027                         return (0);
2028         } else {
2029                 /*


2446                                 }
2447 
2448                                 if (dt_printf(dtp, fp, "\n") < 0 ||
2449                                     dtrace_aggregate_walk_joined(dtp, aggvars,
2450                                     naggvars, dt_print_aggs, &pd) < 0) {
2451                                         dt_free(dtp, aggvars);
2452                                         return (-1);
2453                                 }
2454 
2455                                 dt_free(dtp, aggvars);
2456                                 goto nextrec;
2457                         }
2458 
2459                         if (act == DTRACEACT_TRACEMEM) {
2460                                 if (tracememsize == 0 ||
2461                                     tracememsize > rec->dtrd_size) {
2462                                         tracememsize = rec->dtrd_size;
2463                                 }
2464 
2465                                 n = dt_print_bytes(dtp, fp, addr,
2466                                     tracememsize, -33, quiet, 1);
2467 
2468                                 tracememsize = 0;
2469 
2470                                 if (n < 0)
2471                                         return (-1);
2472 
2473                                 goto nextrec;
2474                         }
2475 
2476                         switch (rec->dtrd_size) {
2477                         case sizeof (uint64_t):
2478                                 n = dt_printf(dtp, fp,
2479                                     quiet ? "%lld" : " %16lld",
2480                                     /* LINTED - alignment */
2481                                     *((unsigned long long *)addr));
2482                                 break;
2483                         case sizeof (uint32_t):
2484                                 n = dt_printf(dtp, fp, quiet ? "%d" : " %8d",
2485                                     /* LINTED - alignment */
2486                                     *((uint32_t *)addr));
2487                                 break;
2488                         case sizeof (uint16_t):
2489                                 n = dt_printf(dtp, fp, quiet ? "%d" : " %5d",
2490                                     /* LINTED - alignment */
2491                                     *((uint16_t *)addr));
2492                                 break;
2493                         case sizeof (uint8_t):
2494                                 n = dt_printf(dtp, fp, quiet ? "%d" : " %3d",
2495                                     *((uint8_t *)addr));
2496                                 break;
2497                         default:
2498                                 n = dt_print_bytes(dtp, fp, addr,
2499                                     rec->dtrd_size, -33, quiet, 0);
2500                                 break;
2501                         }
2502 
2503                         if (n < 0)
2504                                 return (-1); /* errno is set for us */
2505 
2506 nextrec:
2507                         if (dt_buffered_flush(dtp, &data, rec, NULL, 0) < 0)
2508                                 return (-1); /* errno is set for us */
2509                 }
2510 
2511                 /*
2512                  * Call the record callback with a NULL record to indicate
2513                  * that we're done processing this EPID.
2514                  */
2515                 rval = (*rfunc)(&data, NULL, arg);
2516 nextepid:
2517                 offs += epd->dtepd_size;
2518                 dtp->dt_last_epid = id;
2519                 if (just_one) {