1 0 stevel /* 2 0 stevel * CDDL HEADER START 3 0 stevel * 4 0 stevel * The contents of this file are subject to the terms of the 5 8605 Jonathan * Common Development and Distribution License (the "License"). 6 8605 Jonathan * You may not use this file except in compliance with the License. 7 0 stevel * 8 0 stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 0 stevel * or http://www.opensolaris.org/os/licensing. 10 0 stevel * See the License for the specific language governing permissions 11 0 stevel * and limitations under the License. 12 0 stevel * 13 0 stevel * When distributing Covered Code, include this CDDL HEADER in each 14 0 stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 0 stevel * If applicable, add the following below this CDDL HEADER, with the 16 0 stevel * fields enclosed by brackets "[]" replaced with your own identifying 17 0 stevel * information: Portions Copyright [yyyy] [name of copyright owner] 18 0 stevel * 19 0 stevel * CDDL HEADER END 20 0 stevel */ 21 0 stevel /* 22 8605 Jonathan * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 0 stevel * Use is subject to license terms. 24 0 stevel */ 25 0 stevel 26 0 stevel #include <stdio.h> 27 0 stevel #include <stdarg.h> 28 0 stevel #include <dtrace.h> 29 0 stevel #include <errno.h> 30 0 stevel #include <string.h> 31 0 stevel #include <stdlib.h> 32 0 stevel #include <unistd.h> 33 0 stevel #include <limits.h> 34 0 stevel #include <strings.h> 35 0 stevel #include <termio.h> 36 0 stevel #include <signal.h> 37 10265 Krishnendu #include <locale.h> 38 10265 Krishnendu 39 10265 Krishnendu #include "statcommon.h" 40 0 stevel 41 0 stevel #define INTRSTAT_COLUMN_OFFS 14 42 0 stevel #define INTRSTAT_COLUMNS_PER_CPU 15 43 0 stevel #define INTRSTAT_CPUS_PER_LINE(w) \ 44 0 stevel (((w) - INTRSTAT_COLUMN_OFFS) / INTRSTAT_COLUMNS_PER_CPU) 45 10265 Krishnendu #define INTRSTAT_OPTSTR "x:c:C:T:" 46 10265 Krishnendu 47 10265 Krishnendu static uint_t timestamp_fmt = NODATE; 48 10265 Krishnendu 49 10265 Krishnendu #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 50 10265 Krishnendu #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it isn't */ 51 10265 Krishnendu #endif 52 0 stevel 53 0 stevel static dtrace_hdl_t *g_dtp; 54 0 stevel static int *g_present; 55 0 stevel static int g_max_cpus; 56 0 stevel static int g_start, g_end; 57 0 stevel static int g_header; 58 0 stevel static long g_sleeptime = 1; 59 0 stevel static hrtime_t g_interval = NANOSEC; 60 0 stevel static int g_intr; 61 0 stevel static psetid_t g_pset = PS_NONE; 62 0 stevel static processorid_t *g_pset_cpus; 63 0 stevel static uint_t g_pset_ncpus; 64 0 stevel static int g_cpus_per_line = INTRSTAT_CPUS_PER_LINE(80); 65 0 stevel 66 0 stevel static const char *g_pname = "intrstat"; 67 0 stevel static const char *g_prog = 68 0 stevel "interrupt-start" 69 191 ahl "/arg0 != NULL/" 70 0 stevel "{" 71 0 stevel " self->ts = vtimestamp;" 72 0 stevel "}" 73 0 stevel "" 74 0 stevel "interrupt-complete" 75 0 stevel "/self->ts/" 76 0 stevel "{" 77 0 stevel " this->devi = (struct dev_info *)arg0;" 78 0 stevel " @counts[stringof(`devnamesp[this->devi->devi_major].dn_name)," 79 0 stevel " this->devi->devi_instance] = count();" 80 0 stevel " @times[stringof(`devnamesp[this->devi->devi_major].dn_name)," 81 0 stevel " this->devi->devi_instance] = sum(vtimestamp - self->ts);" 82 0 stevel " self->ts = 0;" 83 0 stevel "}"; 84 0 stevel 85 0 stevel static void 86 0 stevel usage(void) 87 0 stevel { 88 0 stevel (void) fprintf(stderr, 89 8605 Jonathan "usage: intrstat [ -C psrset | -c cpulist ] [-x opt[=val]] " 90 10265 Krishnendu "[-T d|u] [interval [ count]]\n"); 91 0 stevel 92 0 stevel exit(EXIT_FAILURE); 93 0 stevel } 94 0 stevel 95 0 stevel static void 96 0 stevel fatal(const char *fmt, ...) 97 0 stevel { 98 0 stevel va_list ap; 99 0 stevel 100 0 stevel va_start(ap, fmt); 101 0 stevel 102 0 stevel (void) fprintf(stderr, "%s: ", g_pname); 103 0 stevel (void) vfprintf(stderr, fmt, ap); 104 0 stevel 105 0 stevel if (fmt[strlen(fmt) - 1] != '\n') 106 0 stevel (void) fprintf(stderr, ": %s\n", 107 0 stevel dtrace_errmsg(g_dtp, dtrace_errno(g_dtp))); 108 0 stevel 109 0 stevel exit(EXIT_FAILURE); 110 0 stevel } 111 0 stevel 112 0 stevel /*ARGSUSED*/ 113 0 stevel static void 114 0 stevel intr(int signo) 115 0 stevel { 116 0 stevel g_intr++; 117 0 stevel } 118 0 stevel 119 0 stevel static void 120 0 stevel status(void) 121 0 stevel {} 122 0 stevel 123 0 stevel static void 124 0 stevel set_width(void) 125 0 stevel { 126 0 stevel struct winsize win; 127 0 stevel 128 0 stevel if (!isatty(fileno(stdout))) 129 0 stevel return; 130 0 stevel 131 0 stevel if (ioctl(fileno(stdout), TIOCGWINSZ, &win) == -1) 132 0 stevel return; 133 0 stevel 134 0 stevel if (win.ws_col == 0) { 135 0 stevel /* 136 0 stevel * If TIOCGWINSZ returned 0 for the columns, just return -- 137 0 stevel * thereby using the default value of g_cpus_per_line. (This 138 0 stevel * happens, e.g., when running over a tip line.) 139 0 stevel */ 140 0 stevel return; 141 0 stevel } 142 0 stevel 143 0 stevel g_cpus_per_line = INTRSTAT_CPUS_PER_LINE(win.ws_col); 144 0 stevel 145 0 stevel if (g_cpus_per_line < 1) 146 0 stevel g_cpus_per_line = 1; 147 0 stevel } 148 0 stevel 149 0 stevel static void 150 0 stevel print_header() 151 0 stevel { 152 0 stevel int i, j; 153 0 stevel char c[256]; 154 0 stevel 155 0 stevel if (!g_header) 156 0 stevel return; 157 0 stevel 158 0 stevel (void) printf("\n%12s |", "device"); 159 0 stevel for (i = g_start, j = 0; i < g_max_cpus; i++) { 160 0 stevel if (!g_present[i]) 161 0 stevel continue; 162 0 stevel 163 0 stevel (void) sprintf(c, "cpu%d", i); 164 0 stevel (void) printf(" %9s %%tim", c); 165 0 stevel 166 0 stevel if (++j >= g_cpus_per_line) 167 0 stevel break; 168 0 stevel } 169 0 stevel 170 0 stevel (void) printf("\n-------------+"); 171 0 stevel 172 0 stevel while (j--) 173 0 stevel (void) printf("---------------"); 174 0 stevel 175 0 stevel (void) printf("\n"); 176 0 stevel g_header = 0; 177 0 stevel } 178 0 stevel 179 0 stevel /*ARGSUSED*/ 180 0 stevel static int 181 457 bmc walk(const dtrace_aggdata_t *data, void *arg) 182 0 stevel { 183 0 stevel dtrace_aggdesc_t *aggdesc = data->dtada_desc; 184 0 stevel dtrace_recdesc_t *nrec, *irec; 185 0 stevel char *name, c[256]; 186 0 stevel int32_t *instance; 187 457 bmc static const dtrace_aggdata_t *count; 188 0 stevel int i, j; 189 0 stevel 190 0 stevel if (count == NULL) { 191 0 stevel count = data; 192 0 stevel return (DTRACE_AGGWALK_NEXT); 193 0 stevel } 194 0 stevel 195 0 stevel nrec = &aggdesc->dtagd_rec[1]; 196 0 stevel irec = &aggdesc->dtagd_rec[2]; 197 0 stevel 198 0 stevel name = data->dtada_data + nrec->dtrd_offset; 199 0 stevel /* LINTED - alignment */ 200 0 stevel instance = (int32_t *)(data->dtada_data + irec->dtrd_offset); 201 0 stevel 202 0 stevel for (i = g_start, j = 0; i < g_max_cpus && j < g_cpus_per_line; i++) { 203 0 stevel /* LINTED - alignment */ 204 0 stevel uint64_t time = *((uint64_t *)(data->dtada_percpu[i])); 205 0 stevel /* LINTED - alignment */ 206 0 stevel uint64_t n = *((uint64_t *)(count->dtada_percpu[i])); 207 0 stevel 208 0 stevel if (!g_present[i]) 209 0 stevel continue; 210 0 stevel 211 0 stevel if (j++ == 0) { 212 0 stevel print_header(); 213 0 stevel (void) snprintf(c, sizeof (c), "%s#%d", 214 8605 Jonathan name, *instance); 215 0 stevel (void) printf("%12s |", c); 216 0 stevel } 217 0 stevel 218 0 stevel (void) printf(" %9lld %4.1f", 219 0 stevel (unsigned long long)((double)n / 220 0 stevel ((double)g_interval / (double)NANOSEC)), 221 0 stevel ((double)time * (double)100.0) / (double)g_interval); 222 0 stevel } 223 0 stevel 224 0 stevel (void) printf(j ? "\n" : ""); 225 0 stevel g_end = i; 226 0 stevel count = NULL; 227 0 stevel return (DTRACE_AGGWALK_NEXT); 228 0 stevel } 229 0 stevel 230 0 stevel static void 231 0 stevel select_cpu(processorid_t cpu) 232 0 stevel { 233 0 stevel if (g_pset != PS_NONE) 234 0 stevel fatal("cannot specify both a processor set and a processor\n"); 235 0 stevel 236 0 stevel if (cpu < 0 || cpu >= g_max_cpus) 237 0 stevel fatal("cpu %d out of range\n", cpu); 238 0 stevel 239 0 stevel if (p_online(cpu, P_STATUS) == -1) { 240 0 stevel if (errno != EINVAL) 241 0 stevel fatal("could not get status for cpu %d", cpu); 242 0 stevel fatal("cpu %d not present\n", cpu); 243 0 stevel } 244 0 stevel 245 0 stevel g_present[cpu] = 1; 246 0 stevel } 247 0 stevel 248 0 stevel static void 249 0 stevel select_cpus(processorid_t low, processorid_t high) 250 0 stevel { 251 0 stevel if (g_pset != PS_NONE) 252 0 stevel fatal("cannot specify both a processor set and processors\n"); 253 0 stevel 254 0 stevel if (low < 0 || low >= g_max_cpus) 255 0 stevel fatal("invalid cpu '%d'\n", low); 256 0 stevel 257 0 stevel if (high < 0 || high >= g_max_cpus) 258 0 stevel fatal("invalid cpu '%d'\n", high); 259 0 stevel 260 0 stevel if (low >= high) 261 0 stevel fatal("invalid range '%d' to '%d'\n", low, high); 262 0 stevel 263 0 stevel do { 264 0 stevel if (p_online(low, P_STATUS) != -1) 265 0 stevel g_present[low] = 1; 266 0 stevel } while (++low <= high); 267 0 stevel } 268 0 stevel 269 0 stevel static void 270 0 stevel select_pset(psetid_t pset) 271 0 stevel { 272 0 stevel processorid_t i; 273 0 stevel 274 0 stevel if (pset < 0) 275 0 stevel fatal("processor set %d is out of range\n", pset); 276 0 stevel 277 0 stevel /* 278 0 stevel * Only one processor set can be specified. 279 0 stevel */ 280 0 stevel if (g_pset != PS_NONE) 281 0 stevel fatal("at most one processor set may be specified\n"); 282 0 stevel 283 0 stevel /* 284 0 stevel * One cannot select processors _and_ a processor set. 285 0 stevel */ 286 0 stevel for (i = 0; i < g_max_cpus; i++) 287 0 stevel if (g_present[i]) 288 0 stevel break; 289 0 stevel 290 0 stevel if (i != g_max_cpus) 291 0 stevel fatal("cannot specify both a processor and a processor set\n"); 292 0 stevel 293 0 stevel g_pset = pset; 294 0 stevel g_pset_ncpus = g_max_cpus; 295 0 stevel 296 0 stevel if (pset_info(g_pset, NULL, &g_pset_ncpus, g_pset_cpus) == -1) 297 0 stevel fatal("invalid processor set: %d\n", g_pset); 298 0 stevel 299 0 stevel if (g_pset_ncpus == 0) 300 0 stevel fatal("processor set %d empty\n", g_pset); 301 0 stevel 302 0 stevel for (i = 0; i < g_pset_ncpus; i++) 303 0 stevel g_present[g_pset_cpus[i]] = 1; 304 0 stevel } 305 0 stevel 306 0 stevel static void 307 0 stevel check_pset(void) 308 0 stevel { 309 0 stevel uint_t ncpus = g_max_cpus; 310 0 stevel processorid_t i; 311 0 stevel 312 0 stevel if (g_pset == PS_NONE) 313 0 stevel return; 314 0 stevel 315 0 stevel if (pset_info(g_pset, NULL, &ncpus, g_pset_cpus) == -1) { 316 0 stevel if (errno == EINVAL) 317 0 stevel fatal("processor set %d destroyed\n", g_pset); 318 0 stevel 319 0 stevel fatal("couldn't get info for processor set %d", g_pset); 320 0 stevel } 321 0 stevel 322 0 stevel if (ncpus == 0) 323 0 stevel fatal("processor set %d empty\n", g_pset); 324 0 stevel 325 0 stevel if (ncpus == g_pset_ncpus) { 326 0 stevel for (i = 0; i < g_pset_ncpus; i++) { 327 0 stevel if (!g_present[g_pset_cpus[i]]) 328 0 stevel break; 329 0 stevel } 330 0 stevel 331 0 stevel /* 332 0 stevel * If the number of CPUs hasn't changed, and every CPU 333 0 stevel * in the processor set is also selected, we know that the 334 0 stevel * processor set itself hasn't changed. 335 0 stevel */ 336 0 stevel if (i == g_pset_ncpus) 337 0 stevel return; 338 0 stevel } 339 0 stevel 340 0 stevel /* 341 0 stevel * If we're here, we have a new processor set. First, we need 342 0 stevel * to zero out the present array. 343 0 stevel */ 344 0 stevel bzero(g_present, sizeof (processorid_t) * g_max_cpus); 345 0 stevel 346 0 stevel g_pset_ncpus = ncpus; 347 0 stevel 348 0 stevel for (i = 0; i < g_pset_ncpus; i++) 349 0 stevel g_present[g_pset_cpus[i]] = 1; 350 0 stevel } 351 0 stevel 352 0 stevel int 353 0 stevel main(int argc, char **argv) 354 0 stevel { 355 0 stevel dtrace_prog_t *prog; 356 0 stevel dtrace_proginfo_t info; 357 0 stevel int err, i, indefinite = 1; 358 0 stevel long iter; 359 0 stevel processorid_t id; 360 0 stevel struct sigaction act; 361 0 stevel struct itimerspec ts; 362 0 stevel struct sigevent ev; 363 0 stevel sigset_t set; 364 0 stevel timer_t tid; 365 8605 Jonathan char *end, *p; 366 0 stevel char c; 367 0 stevel hrtime_t last, now; 368 0 stevel dtrace_optval_t statustime; 369 0 stevel 370 10265 Krishnendu (void) setlocale(LC_ALL, ""); 371 10265 Krishnendu (void) textdomain(TEXT_DOMAIN); 372 10265 Krishnendu 373 0 stevel (void) sigemptyset(&act.sa_mask); 374 0 stevel act.sa_flags = 0; 375 0 stevel act.sa_handler = set_width; 376 0 stevel (void) sigaction(SIGWINCH, &act, NULL); 377 0 stevel 378 0 stevel (void) sigemptyset(&act.sa_mask); 379 0 stevel act.sa_flags = 0; 380 0 stevel act.sa_handler = intr; 381 0 stevel (void) sigaction(SIGUSR1, &act, NULL); 382 0 stevel 383 0 stevel (void) sigemptyset(&act.sa_mask); 384 0 stevel act.sa_flags = 0; 385 0 stevel act.sa_handler = status; 386 0 stevel (void) sigaction(SIGUSR2, &act, NULL); 387 0 stevel 388 0 stevel act.sa_handler = set_width; 389 0 stevel (void) sigaction(SIGWINCH, &act, NULL); 390 0 stevel set_width(); 391 0 stevel 392 0 stevel (void) sigemptyset(&set); 393 0 stevel (void) sigaddset(&set, SIGUSR1); 394 0 stevel (void) sigaddset(&set, SIGWINCH); 395 0 stevel (void) sigprocmask(SIG_BLOCK, &set, NULL); 396 0 stevel 397 0 stevel ev.sigev_notify = SIGEV_SIGNAL; 398 0 stevel ev.sigev_signo = SIGUSR1; 399 0 stevel 400 0 stevel if (timer_create(CLOCK_REALTIME, &ev, &tid) == -1) 401 0 stevel fatal("cannot create CLOCK_HIGHRES timer"); 402 0 stevel 403 0 stevel g_max_cpus = sysconf(_SC_CPUID_MAX) + 1; 404 0 stevel 405 0 stevel if ((g_present = malloc(sizeof (processorid_t) * g_max_cpus)) == NULL) 406 0 stevel fatal("could not allocate g_present array\n"); 407 0 stevel 408 0 stevel bzero(g_present, sizeof (processorid_t) * g_max_cpus); 409 0 stevel 410 0 stevel g_pset_cpus = malloc(sizeof (processorid_t) * g_max_cpus); 411 0 stevel if (g_pset_cpus == NULL) 412 0 stevel fatal("could not allocate g_pset_cpus"); 413 0 stevel 414 0 stevel bzero(g_pset_cpus, sizeof (processorid_t) * g_max_cpus); 415 0 stevel 416 8605 Jonathan while ((c = getopt(argc, argv, INTRSTAT_OPTSTR)) != EOF) { 417 0 stevel switch (c) { 418 0 stevel case 'c': { 419 0 stevel /* 420 0 stevel * We allow CPUs to be specified as an optionally 421 0 stevel * comma separated list of either CPU IDs or ranges 422 0 stevel * of CPU IDs. 423 0 stevel */ 424 0 stevel char *s = strtok(optarg, ","); 425 0 stevel 426 0 stevel while (s != NULL) { 427 0 stevel id = strtoul(s, &end, 0); 428 0 stevel 429 0 stevel if (id == ULONG_MAX && errno == ERANGE) { 430 0 stevel *end = '\0'; 431 0 stevel fatal("invalid cpu '%s'\n", s); 432 0 stevel } 433 0 stevel 434 0 stevel if (*(s = end) != '\0') { 435 0 stevel processorid_t p; 436 0 stevel 437 0 stevel if (*s != '-') 438 0 stevel fatal("invalid cpu '%s'\n", s); 439 0 stevel p = strtoul(++s, &end, 0); 440 0 stevel 441 0 stevel if (*end != '\0' || 442 0 stevel (p == ULONG_MAX && errno == ERANGE)) 443 0 stevel fatal("invalid cpu '%s'\n", s); 444 0 stevel 445 0 stevel select_cpus(id, p); 446 0 stevel } else { 447 0 stevel select_cpu(id); 448 0 stevel } 449 0 stevel 450 0 stevel s = strtok(NULL, ","); 451 0 stevel } 452 0 stevel 453 0 stevel break; 454 0 stevel } 455 0 stevel 456 0 stevel case 'C': { 457 0 stevel psetid_t pset = strtoul(optarg, &end, 0); 458 0 stevel 459 0 stevel if (*end != '\0' || 460 0 stevel (pset == ULONG_MAX && errno == ERANGE)) 461 0 stevel fatal("invalid processor set '%s'\n", optarg); 462 0 stevel 463 0 stevel select_pset(pset); 464 0 stevel break; 465 0 stevel } 466 10265 Krishnendu 467 10265 Krishnendu case 'T': 468 10265 Krishnendu if (optarg) { 469 10265 Krishnendu if (*optarg == 'u') 470 10265 Krishnendu timestamp_fmt = UDATE; 471 10265 Krishnendu else if (*optarg == 'd') 472 10265 Krishnendu timestamp_fmt = DDATE; 473 10265 Krishnendu else 474 10265 Krishnendu usage(); 475 10265 Krishnendu } else { 476 10265 Krishnendu usage(); 477 10265 Krishnendu } 478 10265 Krishnendu break; 479 0 stevel 480 0 stevel default: 481 8605 Jonathan if (strchr(INTRSTAT_OPTSTR, c) == NULL) 482 8605 Jonathan usage(); 483 8605 Jonathan } 484 8605 Jonathan } 485 8605 Jonathan 486 8605 Jonathan if ((g_dtp = dtrace_open(DTRACE_VERSION, 0, &err)) == NULL) { 487 8605 Jonathan fatal("cannot open dtrace library: %s\n", 488 8605 Jonathan dtrace_errmsg(NULL, err)); 489 8605 Jonathan } 490 8605 Jonathan 491 8605 Jonathan if ((prog = dtrace_program_strcompile(g_dtp, g_prog, 492 8605 Jonathan DTRACE_PROBESPEC_NAME, 0, 0, NULL)) == NULL) 493 8605 Jonathan fatal("invalid program"); 494 8605 Jonathan 495 8605 Jonathan if (dtrace_program_exec(g_dtp, prog, &info) == -1) 496 8605 Jonathan fatal("failed to enable probes"); 497 8605 Jonathan 498 8605 Jonathan if (dtrace_setopt(g_dtp, "aggsize", "128k") == -1) 499 8605 Jonathan fatal("failed to set 'aggsize'"); 500 8605 Jonathan 501 8605 Jonathan if (dtrace_setopt(g_dtp, "aggrate", "0") == -1) 502 8605 Jonathan fatal("failed to set 'aggrate'"); 503 8605 Jonathan 504 8605 Jonathan if (dtrace_setopt(g_dtp, "aggpercpu", 0) == -1) 505 8605 Jonathan fatal("failed to set 'aggpercpu'"); 506 8605 Jonathan 507 8605 Jonathan optind = 1; 508 8605 Jonathan while ((c = getopt(argc, argv, INTRSTAT_OPTSTR)) != EOF) { 509 8605 Jonathan switch (c) { 510 8605 Jonathan case 'x': 511 8605 Jonathan if ((p = strchr(optarg, '=')) != NULL) 512 8605 Jonathan *p++ = '\0'; 513 8605 Jonathan 514 8605 Jonathan if (dtrace_setopt(g_dtp, optarg, p) != 0) 515 8605 Jonathan fatal("failed to set -x %s", optarg); 516 8605 Jonathan break; 517 0 stevel } 518 0 stevel } 519 0 stevel 520 0 stevel if (optind != argc) { 521 0 stevel g_sleeptime = strtol(argv[optind], &end, 10); 522 0 stevel 523 0 stevel if (*end != NULL || g_sleeptime == 0) 524 0 stevel fatal("invalid interval '%s'\n", argv[1]); 525 0 stevel 526 0 stevel if (g_sleeptime <= 0) 527 0 stevel fatal("interval must be greater than zero.\n"); 528 0 stevel 529 0 stevel if (g_sleeptime == LONG_MAX && errno == ERANGE) 530 0 stevel fatal("invalid interval '%s'\n", argv[optind]); 531 0 stevel 532 0 stevel if (++optind != argc) { 533 0 stevel char *s = argv[optind]; 534 0 stevel 535 0 stevel iter = strtol(s, &end, 0); 536 0 stevel indefinite = 0; 537 0 stevel 538 0 stevel if (*end != '\0' || iter <= 0 || 539 0 stevel (iter == LONG_MAX && errno == ERANGE)) 540 0 stevel fatal("invalid count '%s'\n", s); 541 0 stevel } 542 0 stevel } 543 0 stevel 544 0 stevel ts.it_value.tv_sec = g_sleeptime; 545 0 stevel ts.it_value.tv_nsec = 0; 546 0 stevel ts.it_interval.tv_sec = g_sleeptime; 547 0 stevel ts.it_interval.tv_nsec = 0; 548 0 stevel 549 0 stevel if (timer_settime(tid, TIMER_RELTIME, &ts, NULL) == -1) 550 0 stevel fatal("cannot set time on CLOCK_REALTIME timer"); 551 0 stevel 552 0 stevel for (i = 0; i < g_max_cpus && !g_present[i]; i++) 553 0 stevel continue; 554 0 stevel 555 0 stevel if (i == g_max_cpus) { 556 0 stevel for (i = 0; i < g_max_cpus; i++) 557 0 stevel g_present[i] = p_online(i, P_STATUS) == -1 ? 0 : 1; 558 0 stevel } 559 0 stevel 560 0 stevel if (dtrace_go(g_dtp) != 0) 561 0 stevel fatal("dtrace_go()"); 562 0 stevel 563 0 stevel last = gethrtime(); 564 0 stevel 565 0 stevel if (dtrace_getopt(g_dtp, "statusrate", &statustime) == -1) 566 0 stevel fatal("failed to get 'statusrate'"); 567 0 stevel 568 0 stevel if (statustime < ((dtrace_optval_t)g_sleeptime * NANOSEC)) { 569 0 stevel ev.sigev_notify = SIGEV_SIGNAL; 570 0 stevel ev.sigev_signo = SIGUSR2; 571 0 stevel 572 0 stevel if (timer_create(CLOCK_REALTIME, &ev, &tid) == -1) 573 0 stevel fatal("cannot create status timer"); 574 0 stevel 575 0 stevel ts.it_value.tv_sec = statustime / NANOSEC; 576 0 stevel ts.it_value.tv_nsec = statustime % NANOSEC; 577 0 stevel ts.it_interval = ts.it_value; 578 0 stevel 579 0 stevel if (timer_settime(tid, TIMER_RELTIME, &ts, NULL) == -1) 580 0 stevel fatal("cannot set time on status timer"); 581 0 stevel } 582 0 stevel 583 0 stevel (void) sigemptyset(&set); 584 0 stevel 585 0 stevel while (indefinite || iter) { 586 0 stevel 587 0 stevel (void) sigsuspend(&set); 588 0 stevel 589 8605 Jonathan if (dtrace_status(g_dtp) == -1) 590 8605 Jonathan fatal("dtrace_status()"); 591 0 stevel 592 0 stevel if (g_intr == 0) 593 0 stevel continue; 594 0 stevel 595 0 stevel iter--; 596 0 stevel g_intr--; 597 0 stevel check_pset(); 598 0 stevel 599 0 stevel now = gethrtime(); 600 0 stevel g_interval = now - last; 601 0 stevel last = now; 602 0 stevel 603 0 stevel if (dtrace_aggregate_snap(g_dtp) != 0) 604 0 stevel fatal("failed to add to aggregate"); 605 0 stevel 606 0 stevel g_start = g_end = 0; 607 0 stevel 608 10265 Krishnendu if (timestamp_fmt != NODATE) 609 10265 Krishnendu print_timestamp(timestamp_fmt); 610 10265 Krishnendu 611 0 stevel do { 612 0 stevel g_header = 1; 613 0 stevel 614 0 stevel if (dtrace_aggregate_walk_keyvarsorted(g_dtp, 615 0 stevel walk, NULL) != 0) 616 0 stevel fatal("failed to sort aggregate"); 617 0 stevel 618 0 stevel if (g_start == g_end) 619 0 stevel break; 620 0 stevel } while ((g_start = g_end) < g_max_cpus); 621 0 stevel 622 0 stevel dtrace_aggregate_clear(g_dtp); 623 0 stevel } 624 0 stevel 625 0 stevel return (0); 626 0 stevel } 627