static void go(void) { int i; struct { char *name; char *optname; dtrace_optval_t val; } bufs[] = { { "buffer size", "bufsize" }, { "aggregation size", "aggsize" }, { "speculation size", "specsize" }, { "dynamic variable size", "dynvarsize" }, { NULL } }, rates[] = { { "cleaning rate", "cleanrate" }, { "status rate", "statusrate" }, { NULL } }; for (i = 0; bufs[i].name != NULL; i++) { if (dtrace_getopt(g_dtp, bufs[i].optname, &bufs[i].val) == -1) fatal("couldn't get option %s", bufs[i].optname); } for (i = 0; rates[i].name != NULL; i++) { if (dtrace_getopt(g_dtp, rates[i].optname, &rates[i].val) == -1) fatal("couldn't get option %s", rates[i].optname); } if (dtrace_go(g_dtp) == -1) dfatal("could not enable tracing"); for (i = 0; bufs[i].name != NULL; i++) { dtrace_optval_t j = 0, mul = 10; dtrace_optval_t nsize; if (bufs[i].val == DTRACEOPT_UNSET) continue; (void) dtrace_getopt(g_dtp, bufs[i].optname, &nsize); if (nsize == DTRACEOPT_UNSET || nsize == 0) continue; if (nsize >= bufs[i].val - sizeof (uint64_t)) continue; for (; (INT64_C(1) << mul) <= nsize; j++, mul += 10) continue; if (!(nsize & ((INT64_C(1) << (mul - 10)) - 1))) { error("%s lowered to %lld%c\n", bufs[i].name, (long long)nsize >> (mul - 10), " kmgtpe"[j]); } else {
int main(int argc, char **argv) { int err; int opt_C = 0, opt_H = 0, opt_p = 0, opt_v = 0; char c, *p, *end; struct sigaction act; int done = 0; g_pname = basename(argv[0]); argv[0] = g_pname; /* rewrite argv[0] for getopt errors */ while ((c = getopt(argc, argv, PLOCKSTAT_OPTSTR)) != EOF) { switch (c) { case 'n': errno = 0; g_nent = strtoul(optarg, &end, 10); if (*end != '\0' || errno != 0) { (void) fprintf(stderr, "%s: invalid count " "'%s'\n", g_pname, optarg); usage(); } break; case 'p': opt_p = 1; break; case 'v': opt_v = 1; break; case 'A': opt_C = opt_H = 1; break; case 'C': opt_C = 1; break; case 'H': opt_H = 1; break; case 'V': g_opt_V = 1; break; default: if (strchr(PLOCKSTAT_OPTSTR, c) == NULL) usage(); } } /* * We need a command or at least one pid. */ if (argc == optind) usage(); if (opt_C == 0 && opt_H == 0) opt_C = 1; if ((g_dtp = dtrace_open(DTRACE_VERSION, 0, &err)) == NULL) fatal("failed to initialize dtrace: %s\n", dtrace_errmsg(NULL, err)); /* * The longest string we trace is 23 bytes long -- so 32 is plenty. */ if (dtrace_setopt(g_dtp, "strsize", "32") == -1) dfatal("failed to set 'strsize'"); /* * 1k should be more than enough for all trace() and printa() actions. */ if (dtrace_setopt(g_dtp, "bufsize", "1k") == -1) dfatal("failed to set 'bufsize'"); /* * The table we produce has the hottest locks at the top. */ if (dtrace_setopt(g_dtp, "aggsortrev", NULL) == -1) dfatal("failed to set 'aggsortrev'"); /* * These are two reasonable defaults which should suffice. */ if (dtrace_setopt(g_dtp, "aggsize", "256k") == -1) dfatal("failed to set 'aggsize'"); if (dtrace_setopt(g_dtp, "aggrate", "1sec") == -1) dfatal("failed to set 'aggrate'"); /* * Take a second pass through to look for options that set options now * that we have an open dtrace handle. */ optind = 1; while ((c = getopt(argc, argv, PLOCKSTAT_OPTSTR)) != EOF) { switch (c) { case 's': g_opt_s = 1; if (dtrace_setopt(g_dtp, "ustackframes", optarg) == -1) dfatal("failed to set 'ustackframes'"); break; case 'x': if ((p = strchr(optarg, '=')) != NULL) *p++ = '\0'; if (dtrace_setopt(g_dtp, optarg, p) != 0) dfatal("failed to set -x %s", optarg); break; case 'e': errno = 0; (void) strtoul(optarg, &end, 10); if (*optarg == '-' || *end != '\0' || errno != 0) { (void) fprintf(stderr, "%s: invalid timeout " "'%s'\n", g_pname, optarg); usage(); } /* * Construct a DTrace enabling that will exit after * the specified number of seconds. */ dprog_add("BEGIN\n{\n\tend = timestamp + "); dprog_add(optarg); dprog_add(" * 1000000000;\n}\n"); dprog_add("tick-10hz\n/timestamp >= end/\n"); dprog_add("{\n\texit(0);\n}\n"); break; } } argc -= optind; argv += optind; if (opt_H) { dprog_add(g_hold_init); if (g_opt_s == NULL) dprog_add(g_hold_times); else dprog_add(g_hold_histogram); } if (opt_C) { dprog_add(g_ctnd_init); if (g_opt_s == NULL) dprog_add(g_ctnd_times); else dprog_add(g_ctnd_histogram); } if (opt_p) { ulong_t pid; if (argc > 1) { (void) fprintf(stderr, "%s: only one pid is allowed\n", g_pname); usage(); } errno = 0; pid = strtoul(argv[0], &end, 10); if (*end != '\0' || errno != 0 || (pid_t)pid != pid) { (void) fprintf(stderr, "%s: invalid pid '%s'\n", g_pname, argv[0]); usage(); } if ((g_pr = dtrace_proc_grab(g_dtp, (pid_t)pid, 0)) == NULL) dfatal(NULL); } else { if ((g_pr = dtrace_proc_create(g_dtp, argv[0], argv)) == NULL) dfatal(NULL); } dprog_compile(); if (dtrace_handle_proc(g_dtp, &prochandler, NULL) == -1) dfatal("failed to establish proc handler"); (void) sigemptyset(&act.sa_mask); act.sa_flags = 0; act.sa_handler = intr; (void) sigaction(SIGINT, &act, NULL); (void) sigaction(SIGTERM, &act, NULL); if (dtrace_go(g_dtp) != 0) dfatal("dtrace_go()"); if (dtrace_getopt(g_dtp, "ustackframes", &g_nframes) != 0) dfatal("failed to get 'ustackframes'"); dtrace_proc_continue(g_dtp, g_pr); if (opt_v) (void) printf("%s: tracing enabled for pid %d\n", g_pname, (int)Pstatus(g_pr)->pr_pid); do { if (!g_intr && !done) dtrace_sleep(g_dtp); if (done || g_intr || g_exited) { done = 1; if (dtrace_stop(g_dtp) == -1) dfatal("couldn't stop tracing"); } switch (dtrace_work(g_dtp, stdout, NULL, chewrec, NULL)) { case DTRACE_WORKSTATUS_DONE: done = 1; break; case DTRACE_WORKSTATUS_OKAY: break; default: dfatal("processing aborted"); } } while (!done); dtrace_close(g_dtp); return (0); }