17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 581eba2fdSas198278 * Common Development and Distribution License (the "License"). 681eba2fdSas198278 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*26fd7700SKrishnendu Sadhukhan - Sun Microsystems * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #include <sys/types.h> 277c478bd9Sstevel@tonic-gate #include <sys/processor.h> 287c478bd9Sstevel@tonic-gate #include <sys/pset.h> 297c478bd9Sstevel@tonic-gate #include <sys/lwp.h> 307c478bd9Sstevel@tonic-gate #include <sys/priocntl.h> 317c478bd9Sstevel@tonic-gate #include <sys/fxpriocntl.h> 327c478bd9Sstevel@tonic-gate #include <time.h> 337c478bd9Sstevel@tonic-gate #include <stdio.h> 347c478bd9Sstevel@tonic-gate #include <stdlib.h> 357c478bd9Sstevel@tonic-gate #include <inttypes.h> 367c478bd9Sstevel@tonic-gate #include <unistd.h> 377c478bd9Sstevel@tonic-gate #include <limits.h> 387c478bd9Sstevel@tonic-gate #include <string.h> 397c478bd9Sstevel@tonic-gate #include <strings.h> 407c478bd9Sstevel@tonic-gate #include <thread.h> 417c478bd9Sstevel@tonic-gate #include <errno.h> 427c478bd9Sstevel@tonic-gate #include <libintl.h> 437c478bd9Sstevel@tonic-gate #include <locale.h> 447c478bd9Sstevel@tonic-gate #include <kstat.h> 457c478bd9Sstevel@tonic-gate #include <synch.h> 467c478bd9Sstevel@tonic-gate #include <libcpc.h> 4781eba2fdSas198278 #include <sys/resource.h> 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate #include "cpucmds.h" 50*26fd7700SKrishnendu Sadhukhan - Sun Microsystems #include "statcommon.h" 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate static struct options { 537c478bd9Sstevel@tonic-gate int debug; 547c478bd9Sstevel@tonic-gate int dotitle; 557c478bd9Sstevel@tonic-gate int dohelp; 567c478bd9Sstevel@tonic-gate int dotick; 577c478bd9Sstevel@tonic-gate int dosoaker; 587c478bd9Sstevel@tonic-gate int doperiod; 597c478bd9Sstevel@tonic-gate char *pgmname; 607c478bd9Sstevel@tonic-gate uint_t mseconds; 617c478bd9Sstevel@tonic-gate uint_t nsamples; 627c478bd9Sstevel@tonic-gate uint_t nsets; 637c478bd9Sstevel@tonic-gate uint_t mseconds_rest; 647c478bd9Sstevel@tonic-gate cpc_setgrp_t *master; 657c478bd9Sstevel@tonic-gate } __options; 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate /* 687c478bd9Sstevel@tonic-gate * States for soaker threads. 697c478bd9Sstevel@tonic-gate */ 707c478bd9Sstevel@tonic-gate #define SOAK_PAUSE 0 717c478bd9Sstevel@tonic-gate #define SOAK_RUN 1 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate struct tstate { 747c478bd9Sstevel@tonic-gate processorid_t cpuid; 757c478bd9Sstevel@tonic-gate int chip_id; 767c478bd9Sstevel@tonic-gate cpc_setgrp_t *sgrp; 777c478bd9Sstevel@tonic-gate int status; 787c478bd9Sstevel@tonic-gate thread_t tid; 797c478bd9Sstevel@tonic-gate int soak_state; 807c478bd9Sstevel@tonic-gate mutex_t soak_lock; 817c478bd9Sstevel@tonic-gate cond_t soak_cv; 827c478bd9Sstevel@tonic-gate }; 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate static const struct options *opts = (const struct options *)&__options; 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate static cpc_t *cpc; 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate struct tstate *gstate; 897c478bd9Sstevel@tonic-gate static int ncpus; 907c478bd9Sstevel@tonic-gate static int max_chip_id; 917c478bd9Sstevel@tonic-gate static int *chip_designees; /* cpuid of CPU which counts for phs chip */ 927c478bd9Sstevel@tonic-gate static int smt = 0; /* If set, cpustat needs to be SMT-aware. */ 937c478bd9Sstevel@tonic-gate static pcinfo_t fxinfo = { 0, "FX", NULL }; /* FX scheduler class info */ 947c478bd9Sstevel@tonic-gate 95*26fd7700SKrishnendu Sadhukhan - Sun Microsystems static uint_t timestamp_fmt = NODATE; 96*26fd7700SKrishnendu Sadhukhan - Sun Microsystems 977c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 987c478bd9Sstevel@tonic-gate static void 997c478bd9Sstevel@tonic-gate cpustat_errfn(const char *fn, int subcode, const char *fmt, va_list ap) 1007c478bd9Sstevel@tonic-gate { 1017c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: ", opts->pgmname); 1027c478bd9Sstevel@tonic-gate if (opts->debug) 1037c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: ", fn); 1047c478bd9Sstevel@tonic-gate (void) vfprintf(stderr, fmt, ap); 1057c478bd9Sstevel@tonic-gate } 1067c478bd9Sstevel@tonic-gate 1077c478bd9Sstevel@tonic-gate static int cpustat(void); 1087c478bd9Sstevel@tonic-gate static int get_chipid(kstat_ctl_t *kc, processorid_t cpuid); 1097c478bd9Sstevel@tonic-gate static void *soaker(void *arg); 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 1137c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 1147c478bd9Sstevel@tonic-gate #endif 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate int 1177c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) 1187c478bd9Sstevel@tonic-gate { 1197c478bd9Sstevel@tonic-gate struct options *opts = &__options; 1207c478bd9Sstevel@tonic-gate int c, errcnt = 0, ret; 1217c478bd9Sstevel@tonic-gate cpc_setgrp_t *sgrp; 1227c478bd9Sstevel@tonic-gate char *errstr; 1237c478bd9Sstevel@tonic-gate double period; 1247c478bd9Sstevel@tonic-gate char *endp; 12581eba2fdSas198278 struct rlimit rl; 1267c478bd9Sstevel@tonic-gate 1277c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 1287c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 1297c478bd9Sstevel@tonic-gate 1307c478bd9Sstevel@tonic-gate if ((opts->pgmname = strrchr(argv[0], '/')) == NULL) 1317c478bd9Sstevel@tonic-gate opts->pgmname = argv[0]; 1327c478bd9Sstevel@tonic-gate else 1337c478bd9Sstevel@tonic-gate opts->pgmname++; 1347c478bd9Sstevel@tonic-gate 13581eba2fdSas198278 /* Make sure we can open enough files */ 13681eba2fdSas198278 rl.rlim_max = rl.rlim_cur = RLIM_INFINITY; 13781eba2fdSas198278 if (setrlimit(RLIMIT_NOFILE, &rl) != 0) { 13881eba2fdSas198278 errstr = strerror(errno); 13981eba2fdSas198278 (void) fprintf(stderr, 14081eba2fdSas198278 gettext("%s: setrlimit failed - %s\n"), 14181eba2fdSas198278 opts->pgmname, errstr); 14281eba2fdSas198278 } 14381eba2fdSas198278 1447c478bd9Sstevel@tonic-gate if ((cpc = cpc_open(CPC_VER_CURRENT)) == NULL) { 1457c478bd9Sstevel@tonic-gate errstr = strerror(errno); 1467c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: cannot access performance " 1477c478bd9Sstevel@tonic-gate "counters - %s\n"), opts->pgmname, errstr); 1487c478bd9Sstevel@tonic-gate return (1); 1497c478bd9Sstevel@tonic-gate } 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate (void) cpc_seterrhndlr(cpc, cpustat_errfn); 1527c478bd9Sstevel@tonic-gate strtoset_errfn = cpustat_errfn; 1537c478bd9Sstevel@tonic-gate 1547c478bd9Sstevel@tonic-gate /* 1557c478bd9Sstevel@tonic-gate * Check to see if cpustat needs to be SMT-aware. 1567c478bd9Sstevel@tonic-gate */ 1577c478bd9Sstevel@tonic-gate smt = smt_limited_cpc_hw(cpc); 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate /* 1607c478bd9Sstevel@tonic-gate * Establish some defaults 1617c478bd9Sstevel@tonic-gate */ 1627c478bd9Sstevel@tonic-gate opts->mseconds = 5000; 1637c478bd9Sstevel@tonic-gate opts->nsamples = UINT_MAX; 1647c478bd9Sstevel@tonic-gate opts->dotitle = 1; 1657c478bd9Sstevel@tonic-gate if ((opts->master = cpc_setgrp_new(cpc, smt)) == NULL) { 1667c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: out of heap\n"), 1677c478bd9Sstevel@tonic-gate opts->pgmname); 1687c478bd9Sstevel@tonic-gate return (1); 1697c478bd9Sstevel@tonic-gate } 1707c478bd9Sstevel@tonic-gate 171*26fd7700SKrishnendu Sadhukhan - Sun Microsystems while ((c = getopt(argc, argv, "Dc:hntT:sp:")) != EOF && errcnt == 0) 1727c478bd9Sstevel@tonic-gate switch (c) { 1737c478bd9Sstevel@tonic-gate case 'D': /* enable debugging */ 1747c478bd9Sstevel@tonic-gate opts->debug++; 1757c478bd9Sstevel@tonic-gate break; 1767c478bd9Sstevel@tonic-gate case 'c': /* specify statistics */ 1777c478bd9Sstevel@tonic-gate if ((sgrp = cpc_setgrp_newset(opts->master, 1787c478bd9Sstevel@tonic-gate optarg, &errcnt)) != NULL) 1797c478bd9Sstevel@tonic-gate opts->master = sgrp; 1807c478bd9Sstevel@tonic-gate break; 1817c478bd9Sstevel@tonic-gate case 'n': /* no titles */ 1827c478bd9Sstevel@tonic-gate opts->dotitle = 0; 1837c478bd9Sstevel@tonic-gate break; 1847c478bd9Sstevel@tonic-gate case 'p': /* periodic behavior */ 1857c478bd9Sstevel@tonic-gate opts->doperiod = 1; 1867c478bd9Sstevel@tonic-gate period = strtod(optarg, &endp); 1877c478bd9Sstevel@tonic-gate if (*endp != '\0') { 1887c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: invalid " 1897c478bd9Sstevel@tonic-gate "parameter \"%s\"\n"), opts->pgmname, 1907c478bd9Sstevel@tonic-gate optarg); 1917c478bd9Sstevel@tonic-gate errcnt++; 1927c478bd9Sstevel@tonic-gate } 1937c478bd9Sstevel@tonic-gate break; 1947c478bd9Sstevel@tonic-gate case 's': /* run soaker thread */ 1957c478bd9Sstevel@tonic-gate opts->dosoaker = 1; 1967c478bd9Sstevel@tonic-gate break; 1977c478bd9Sstevel@tonic-gate case 't': /* print %tick */ 1987c478bd9Sstevel@tonic-gate opts->dotick = 1; 1997c478bd9Sstevel@tonic-gate break; 200*26fd7700SKrishnendu Sadhukhan - Sun Microsystems case 'T': 201*26fd7700SKrishnendu Sadhukhan - Sun Microsystems if (optarg) { 202*26fd7700SKrishnendu Sadhukhan - Sun Microsystems if (*optarg == 'u') 203*26fd7700SKrishnendu Sadhukhan - Sun Microsystems timestamp_fmt = UDATE; 204*26fd7700SKrishnendu Sadhukhan - Sun Microsystems else if (*optarg == 'd') 205*26fd7700SKrishnendu Sadhukhan - Sun Microsystems timestamp_fmt = DDATE; 206*26fd7700SKrishnendu Sadhukhan - Sun Microsystems else 207*26fd7700SKrishnendu Sadhukhan - Sun Microsystems errcnt++; 208*26fd7700SKrishnendu Sadhukhan - Sun Microsystems } else { 209*26fd7700SKrishnendu Sadhukhan - Sun Microsystems errcnt++; 210*26fd7700SKrishnendu Sadhukhan - Sun Microsystems } 211*26fd7700SKrishnendu Sadhukhan - Sun Microsystems break; 2127c478bd9Sstevel@tonic-gate case 'h': /* help */ 2137c478bd9Sstevel@tonic-gate opts->dohelp = 1; 2147c478bd9Sstevel@tonic-gate break; 2157c478bd9Sstevel@tonic-gate case '?': 2167c478bd9Sstevel@tonic-gate default: 2177c478bd9Sstevel@tonic-gate errcnt++; 2187c478bd9Sstevel@tonic-gate break; 2197c478bd9Sstevel@tonic-gate } 2207c478bd9Sstevel@tonic-gate 2217c478bd9Sstevel@tonic-gate switch (argc - optind) { 2227c478bd9Sstevel@tonic-gate case 0: 2237c478bd9Sstevel@tonic-gate break; 2247c478bd9Sstevel@tonic-gate case 2: 2257c478bd9Sstevel@tonic-gate opts->nsamples = strtol(argv[optind + 1], &endp, 10); 2267c478bd9Sstevel@tonic-gate if (*endp != '\0') { 2277c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2287c478bd9Sstevel@tonic-gate gettext("%s: invalid argument \"%s\"\n"), 2297c478bd9Sstevel@tonic-gate opts->pgmname, argv[optind + 1]); 2307c478bd9Sstevel@tonic-gate errcnt++; 2317c478bd9Sstevel@tonic-gate break; 2327c478bd9Sstevel@tonic-gate } 2337c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 2347c478bd9Sstevel@tonic-gate case 1: 2357c478bd9Sstevel@tonic-gate opts->mseconds = (uint_t)(strtod(argv[optind], &endp) * 1000.0); 2367c478bd9Sstevel@tonic-gate if (*endp != '\0') { 2377c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2387c478bd9Sstevel@tonic-gate gettext("%s: invalid argument \"%s\"\n"), 2397c478bd9Sstevel@tonic-gate opts->pgmname, argv[optind]); 2407c478bd9Sstevel@tonic-gate errcnt++; 2417c478bd9Sstevel@tonic-gate } 2427c478bd9Sstevel@tonic-gate break; 2437c478bd9Sstevel@tonic-gate default: 2447c478bd9Sstevel@tonic-gate errcnt++; 2457c478bd9Sstevel@tonic-gate break; 2467c478bd9Sstevel@tonic-gate } 2477c478bd9Sstevel@tonic-gate 2487c478bd9Sstevel@tonic-gate if (opts->nsamples == 0 || opts->mseconds == 0) 2497c478bd9Sstevel@tonic-gate errcnt++; 2507c478bd9Sstevel@tonic-gate 2517c478bd9Sstevel@tonic-gate if (errcnt != 0 || opts->dohelp || 2527c478bd9Sstevel@tonic-gate (opts->nsets = cpc_setgrp_numsets(opts->master)) == 0) { 2537c478bd9Sstevel@tonic-gate (void) fprintf(opts->dohelp ? stdout : stderr, gettext( 2547c478bd9Sstevel@tonic-gate "Usage:\n\t%s [-c events] [-p period] [-nstD] " 255*26fd7700SKrishnendu Sadhukhan - Sun Microsystems "[-T d|u] [interval [count]]\n\n" 2567c478bd9Sstevel@tonic-gate "\t-c events specify processor events to be monitored\n" 2577c478bd9Sstevel@tonic-gate "\t-n\t suppress titles\n" 2587c478bd9Sstevel@tonic-gate "\t-p period cycle through event list periodically\n" 2597c478bd9Sstevel@tonic-gate "\t-s\t run user soaker thread for system-only events\n" 2607c478bd9Sstevel@tonic-gate "\t-t\t include %s register\n" 261*26fd7700SKrishnendu Sadhukhan - Sun Microsystems "\t-T d|u\t Display a timestamp in date (d) or unix " 262*26fd7700SKrishnendu Sadhukhan - Sun Microsystems "time_t (u)\n" 2637c478bd9Sstevel@tonic-gate "\t-D\t enable debug mode\n" 2647c478bd9Sstevel@tonic-gate "\t-h\t print extended usage information\n\n" 2657c478bd9Sstevel@tonic-gate "\tUse cputrack(1) to monitor per-process statistics.\n"), 2667c478bd9Sstevel@tonic-gate opts->pgmname, CPC_TICKREG_NAME); 2677c478bd9Sstevel@tonic-gate if (opts->dohelp) { 2687c478bd9Sstevel@tonic-gate (void) putchar('\n'); 2697c478bd9Sstevel@tonic-gate (void) capabilities(cpc, stdout); 2707c478bd9Sstevel@tonic-gate exit(0); 2717c478bd9Sstevel@tonic-gate } 2727c478bd9Sstevel@tonic-gate exit(2); 2737c478bd9Sstevel@tonic-gate } 2747c478bd9Sstevel@tonic-gate 2757c478bd9Sstevel@tonic-gate /* 2767c478bd9Sstevel@tonic-gate * If the user requested periodic behavior, calculate the rest time 2777c478bd9Sstevel@tonic-gate * between cycles. 2787c478bd9Sstevel@tonic-gate */ 2797c478bd9Sstevel@tonic-gate if (opts->doperiod) { 2807c478bd9Sstevel@tonic-gate opts->mseconds_rest = (uint_t)((period * 1000.0) - 2817c478bd9Sstevel@tonic-gate (opts->mseconds * opts->nsets)); 2827c478bd9Sstevel@tonic-gate if ((int)opts->mseconds_rest < 0) 2837c478bd9Sstevel@tonic-gate opts->mseconds_rest = 0; 2847c478bd9Sstevel@tonic-gate if (opts->nsamples != UINT_MAX) 2857c478bd9Sstevel@tonic-gate opts->nsamples *= opts->nsets; 2867c478bd9Sstevel@tonic-gate } 2877c478bd9Sstevel@tonic-gate 2887c478bd9Sstevel@tonic-gate cpc_setgrp_reset(opts->master); 2897c478bd9Sstevel@tonic-gate (void) setvbuf(stdout, NULL, _IOLBF, 0); 2907c478bd9Sstevel@tonic-gate 2917c478bd9Sstevel@tonic-gate /* 2927c478bd9Sstevel@tonic-gate * If no system-mode only sets were created, no soaker threads will be 2937c478bd9Sstevel@tonic-gate * needed. 2947c478bd9Sstevel@tonic-gate */ 2957c478bd9Sstevel@tonic-gate if (opts->dosoaker == 1 && cpc_setgrp_has_sysonly(opts->master) == 0) 2967c478bd9Sstevel@tonic-gate opts->dosoaker = 0; 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate ret = cpustat(); 2997c478bd9Sstevel@tonic-gate 3007c478bd9Sstevel@tonic-gate (void) cpc_close(cpc); 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate return (ret); 3037c478bd9Sstevel@tonic-gate } 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate static void 3067c478bd9Sstevel@tonic-gate print_title(cpc_setgrp_t *sgrp) 3077c478bd9Sstevel@tonic-gate { 3087c478bd9Sstevel@tonic-gate (void) printf("%7s %3s %5s ", "time", "cpu", "event"); 3097c478bd9Sstevel@tonic-gate if (opts->dotick) 3107c478bd9Sstevel@tonic-gate (void) printf("%9s ", CPC_TICKREG_NAME); 3117c478bd9Sstevel@tonic-gate (void) printf("%s\n", cpc_setgrp_gethdr(sgrp)); 3127c478bd9Sstevel@tonic-gate } 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate static void 3157c478bd9Sstevel@tonic-gate print_sample(processorid_t cpuid, cpc_buf_t *buf, int nreq, const char *setname, 3167c478bd9Sstevel@tonic-gate int sibling) 3177c478bd9Sstevel@tonic-gate { 3187c478bd9Sstevel@tonic-gate char line[1024]; 3197c478bd9Sstevel@tonic-gate int ccnt; 3207c478bd9Sstevel@tonic-gate int i; 3217c478bd9Sstevel@tonic-gate uint64_t val; 3227c478bd9Sstevel@tonic-gate uint64_t tick; 3237c478bd9Sstevel@tonic-gate hrtime_t hrtime; 3247c478bd9Sstevel@tonic-gate 3257c478bd9Sstevel@tonic-gate hrtime = cpc_buf_hrtime(cpc, buf); 3267c478bd9Sstevel@tonic-gate tick = cpc_buf_tick(cpc, buf); 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate ccnt = snprintf(line, sizeof (line), "%7.3f %3d %5s ", 3297c478bd9Sstevel@tonic-gate mstimestamp(hrtime), (int)cpuid, "tick"); 3307c478bd9Sstevel@tonic-gate if (opts->dotick) 3317c478bd9Sstevel@tonic-gate ccnt += snprintf(line + ccnt, sizeof (line) - ccnt, 3327c478bd9Sstevel@tonic-gate "%9" PRId64 " ", tick); 3337c478bd9Sstevel@tonic-gate for (i = 0; i < nreq; i++) { 3347c478bd9Sstevel@tonic-gate (void) cpc_buf_get(cpc, buf, i, &val); 3357c478bd9Sstevel@tonic-gate ccnt += snprintf(line + ccnt, sizeof (line) - ccnt, 3367c478bd9Sstevel@tonic-gate "%9" PRId64 " ", val); 3377c478bd9Sstevel@tonic-gate } 3387c478bd9Sstevel@tonic-gate if (opts->nsets > 1) 3397c478bd9Sstevel@tonic-gate ccnt += snprintf(line + ccnt, sizeof (line) - ccnt, 3407c478bd9Sstevel@tonic-gate " # %s\n", setname); 3417c478bd9Sstevel@tonic-gate else 3427c478bd9Sstevel@tonic-gate ccnt += snprintf(line + ccnt, sizeof (line) - ccnt, "\n"); 3437c478bd9Sstevel@tonic-gate 3447c478bd9Sstevel@tonic-gate if (sibling) { 3457c478bd9Sstevel@tonic-gate /* 3467c478bd9Sstevel@tonic-gate * This sample is being printed for a "sibling" CPU -- that is, 3477c478bd9Sstevel@tonic-gate * a CPU which does not have its own CPC set bound. It is being 3487c478bd9Sstevel@tonic-gate * measured via a set bound to another CPU sharing its physical 3497c478bd9Sstevel@tonic-gate * processor. 3507c478bd9Sstevel@tonic-gate */ 3517c478bd9Sstevel@tonic-gate int designee = chip_designees[gstate[cpuid].chip_id]; 3527c478bd9Sstevel@tonic-gate char *p; 3537c478bd9Sstevel@tonic-gate 3547c478bd9Sstevel@tonic-gate if ((p = strrchr(line, '#')) == NULL) 3557c478bd9Sstevel@tonic-gate p = strrchr(line, '\n'); 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gate if (p != NULL) { 3587c478bd9Sstevel@tonic-gate *p = '\0'; 3597c478bd9Sstevel@tonic-gate ccnt = strlen(line); 3607c478bd9Sstevel@tonic-gate ccnt += snprintf(line + ccnt, sizeof (line) - ccnt, 3617c478bd9Sstevel@tonic-gate "# counter shared with CPU %d\n", designee); 3627c478bd9Sstevel@tonic-gate } 3637c478bd9Sstevel@tonic-gate } 3647c478bd9Sstevel@tonic-gate 365*26fd7700SKrishnendu Sadhukhan - Sun Microsystems if (timestamp_fmt != NODATE) 366*26fd7700SKrishnendu Sadhukhan - Sun Microsystems print_timestamp(timestamp_fmt); 3677c478bd9Sstevel@tonic-gate if (ccnt > sizeof (line)) 3687c478bd9Sstevel@tonic-gate ccnt = sizeof (line); 3697c478bd9Sstevel@tonic-gate if (ccnt > 0) 3707c478bd9Sstevel@tonic-gate (void) write(1, line, ccnt); 3717c478bd9Sstevel@tonic-gate 3727c478bd9Sstevel@tonic-gate /* 3737c478bd9Sstevel@tonic-gate * If this CPU is the chip designee for any other CPUs, print a line for 3747c478bd9Sstevel@tonic-gate * them here. 3757c478bd9Sstevel@tonic-gate */ 3767c478bd9Sstevel@tonic-gate if (smt && (sibling == 0)) { 3777c478bd9Sstevel@tonic-gate for (i = 0; i < ncpus; i++) { 3787c478bd9Sstevel@tonic-gate if ((i != cpuid) && (gstate[i].cpuid != -1) && 3797c478bd9Sstevel@tonic-gate (chip_designees[gstate[i].chip_id] == cpuid)) 3807c478bd9Sstevel@tonic-gate print_sample(i, buf, nreq, setname, 1); 3817c478bd9Sstevel@tonic-gate } 3827c478bd9Sstevel@tonic-gate } 3837c478bd9Sstevel@tonic-gate } 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate static void 3867c478bd9Sstevel@tonic-gate print_total(int ncpus, cpc_buf_t *buf, int nreq, const char *setname) 3877c478bd9Sstevel@tonic-gate { 3887c478bd9Sstevel@tonic-gate int i; 3897c478bd9Sstevel@tonic-gate uint64_t val; 3907c478bd9Sstevel@tonic-gate 3917c478bd9Sstevel@tonic-gate (void) printf("%7.3f %3d %5s ", mstimestamp(cpc_buf_hrtime(cpc, buf)), 3927c478bd9Sstevel@tonic-gate ncpus, "total"); 3937c478bd9Sstevel@tonic-gate if (opts->dotick) 3947c478bd9Sstevel@tonic-gate (void) printf("%9" PRId64 " ", cpc_buf_tick(cpc, buf)); 3957c478bd9Sstevel@tonic-gate for (i = 0; i < nreq; i++) { 3967c478bd9Sstevel@tonic-gate (void) cpc_buf_get(cpc, buf, i, &val); 3977c478bd9Sstevel@tonic-gate (void) printf("%9" PRId64 " ", val); 3987c478bd9Sstevel@tonic-gate } 3997c478bd9Sstevel@tonic-gate if (opts->nsets > 1) 4007c478bd9Sstevel@tonic-gate (void) printf(" # %s", setname); 4017c478bd9Sstevel@tonic-gate (void) fputc('\n', stdout); 4027c478bd9Sstevel@tonic-gate } 4037c478bd9Sstevel@tonic-gate 4047c478bd9Sstevel@tonic-gate #define NSECS_PER_MSEC 1000000ll 4057c478bd9Sstevel@tonic-gate #define NSECS_PER_SEC 1000000000ll 4067c478bd9Sstevel@tonic-gate 4077c478bd9Sstevel@tonic-gate static void * 4087c478bd9Sstevel@tonic-gate gtick(void *arg) 4097c478bd9Sstevel@tonic-gate { 4107c478bd9Sstevel@tonic-gate struct tstate *state = arg; 4117c478bd9Sstevel@tonic-gate char *errstr; 4127c478bd9Sstevel@tonic-gate uint_t nsamples; 4137c478bd9Sstevel@tonic-gate uint_t sample_cnt = 1; 4147c478bd9Sstevel@tonic-gate hrtime_t ht, htdelta, restdelta; 4157c478bd9Sstevel@tonic-gate cpc_setgrp_t *sgrp = state->sgrp; 4167c478bd9Sstevel@tonic-gate cpc_set_t *this = cpc_setgrp_getset(sgrp); 4177c478bd9Sstevel@tonic-gate const char *name = cpc_setgrp_getname(sgrp); 4187c478bd9Sstevel@tonic-gate cpc_buf_t **data1, **data2, **scratch; 4197c478bd9Sstevel@tonic-gate cpc_buf_t *tmp; 4207c478bd9Sstevel@tonic-gate int nreqs; 4217c478bd9Sstevel@tonic-gate thread_t tid; 4227c478bd9Sstevel@tonic-gate 4237c478bd9Sstevel@tonic-gate htdelta = NSECS_PER_MSEC * opts->mseconds; 4247c478bd9Sstevel@tonic-gate restdelta = NSECS_PER_MSEC * opts->mseconds_rest; 4257c478bd9Sstevel@tonic-gate ht = gethrtime(); 4267c478bd9Sstevel@tonic-gate 4277c478bd9Sstevel@tonic-gate /* 4287c478bd9Sstevel@tonic-gate * If this CPU is SMT, we run one gtick() thread per _physical_ CPU, 4297c478bd9Sstevel@tonic-gate * instead of per cpu_t. The following check returns if it detects that 4307c478bd9Sstevel@tonic-gate * this cpu_t has not been designated to do the counting for this 4317c478bd9Sstevel@tonic-gate * physical CPU. 4327c478bd9Sstevel@tonic-gate */ 4337c478bd9Sstevel@tonic-gate if (smt && chip_designees[state->chip_id] != state->cpuid) 4347c478bd9Sstevel@tonic-gate return (NULL); 4357c478bd9Sstevel@tonic-gate 4367c478bd9Sstevel@tonic-gate /* 4377c478bd9Sstevel@tonic-gate * If we need to run a soaker thread on this CPU, start it here. 4387c478bd9Sstevel@tonic-gate */ 4397c478bd9Sstevel@tonic-gate if (opts->dosoaker) { 4407c478bd9Sstevel@tonic-gate if (cond_init(&state->soak_cv, USYNC_THREAD, NULL) != 0) 4417c478bd9Sstevel@tonic-gate goto bad; 4427c478bd9Sstevel@tonic-gate if (mutex_init(&state->soak_lock, USYNC_THREAD, 4437c478bd9Sstevel@tonic-gate NULL) != 0) 4447c478bd9Sstevel@tonic-gate goto bad; 4457c478bd9Sstevel@tonic-gate (void) mutex_lock(&state->soak_lock); 4467c478bd9Sstevel@tonic-gate state->soak_state = SOAK_PAUSE; 4477c478bd9Sstevel@tonic-gate if (thr_create(NULL, 0, soaker, state, NULL, &tid) != 0) 4487c478bd9Sstevel@tonic-gate goto bad; 4497c478bd9Sstevel@tonic-gate 4507c478bd9Sstevel@tonic-gate while (state->soak_state == SOAK_PAUSE) 4517c478bd9Sstevel@tonic-gate (void) cond_wait(&state->soak_cv, 4527c478bd9Sstevel@tonic-gate &state->soak_lock); 4537c478bd9Sstevel@tonic-gate (void) mutex_unlock(&state->soak_lock); 4547c478bd9Sstevel@tonic-gate 4557c478bd9Sstevel@tonic-gate /* 4567c478bd9Sstevel@tonic-gate * If the soaker needs to pause for the first set, stop it now. 4577c478bd9Sstevel@tonic-gate */ 4587c478bd9Sstevel@tonic-gate if (cpc_setgrp_sysonly(sgrp) == 0) { 4597c478bd9Sstevel@tonic-gate (void) mutex_lock(&state->soak_lock); 4607c478bd9Sstevel@tonic-gate state->soak_state = SOAK_PAUSE; 4617c478bd9Sstevel@tonic-gate (void) mutex_unlock(&state->soak_lock); 4627c478bd9Sstevel@tonic-gate } 4637c478bd9Sstevel@tonic-gate } 4647c478bd9Sstevel@tonic-gate if (cpc_bind_cpu(cpc, state->cpuid, this, 0) == -1) 4657c478bd9Sstevel@tonic-gate goto bad; 4667c478bd9Sstevel@tonic-gate 4677c478bd9Sstevel@tonic-gate for (nsamples = opts->nsamples; nsamples; nsamples--, sample_cnt++) { 4687c478bd9Sstevel@tonic-gate hrtime_t htnow; 4697c478bd9Sstevel@tonic-gate struct timespec ts; 4707c478bd9Sstevel@tonic-gate 4717c478bd9Sstevel@tonic-gate nreqs = cpc_setgrp_getbufs(sgrp, &data1, &data2, &scratch); 4727c478bd9Sstevel@tonic-gate 4737c478bd9Sstevel@tonic-gate ht += htdelta; 4747c478bd9Sstevel@tonic-gate htnow = gethrtime(); 4757c478bd9Sstevel@tonic-gate if (ht <= htnow) 4767c478bd9Sstevel@tonic-gate continue; 4777c478bd9Sstevel@tonic-gate ts.tv_sec = (time_t)((ht - htnow) / NSECS_PER_SEC); 4787c478bd9Sstevel@tonic-gate ts.tv_nsec = (suseconds_t)((ht - htnow) % NSECS_PER_SEC); 4797c478bd9Sstevel@tonic-gate 4807c478bd9Sstevel@tonic-gate (void) nanosleep(&ts, NULL); 4817c478bd9Sstevel@tonic-gate 4827c478bd9Sstevel@tonic-gate if (opts->nsets == 1) { 4837c478bd9Sstevel@tonic-gate /* 4847c478bd9Sstevel@tonic-gate * If we're dealing with one set, buffer usage is: 4857c478bd9Sstevel@tonic-gate * 4867c478bd9Sstevel@tonic-gate * data1 = most recent data snapshot 4877c478bd9Sstevel@tonic-gate * data2 = previous data snapshot 4887c478bd9Sstevel@tonic-gate * scratch = used for diffing data1 and data2 4897c478bd9Sstevel@tonic-gate * 4907c478bd9Sstevel@tonic-gate * Save the snapshot from the previous sample in data2 4917c478bd9Sstevel@tonic-gate * before putting the current sample in data1. 4927c478bd9Sstevel@tonic-gate */ 4937c478bd9Sstevel@tonic-gate tmp = *data1; 4947c478bd9Sstevel@tonic-gate *data1 = *data2; 4957c478bd9Sstevel@tonic-gate *data2 = tmp; 4967c478bd9Sstevel@tonic-gate if (cpc_set_sample(cpc, this, *data1) != 0) 4977c478bd9Sstevel@tonic-gate goto bad; 4987c478bd9Sstevel@tonic-gate cpc_buf_sub(cpc, *scratch, *data1, *data2); 4997c478bd9Sstevel@tonic-gate 5007c478bd9Sstevel@tonic-gate print_sample(state->cpuid, *scratch, nreqs, name, 0); 5017c478bd9Sstevel@tonic-gate } else { 5027c478bd9Sstevel@tonic-gate /* 5037c478bd9Sstevel@tonic-gate * More than one set is in use (multiple -c options 5047c478bd9Sstevel@tonic-gate * given). Buffer usage in this case is: 5057c478bd9Sstevel@tonic-gate * 5067c478bd9Sstevel@tonic-gate * data1 = total counts for this set since program began 5077c478bd9Sstevel@tonic-gate * data2 = unused 5087c478bd9Sstevel@tonic-gate * scratch = most recent data snapshot 5097c478bd9Sstevel@tonic-gate */ 5107c478bd9Sstevel@tonic-gate name = cpc_setgrp_getname(sgrp); 5117c478bd9Sstevel@tonic-gate nreqs = cpc_setgrp_getbufs(sgrp, &data1, &data2, 5127c478bd9Sstevel@tonic-gate &scratch); 5137c478bd9Sstevel@tonic-gate 5147c478bd9Sstevel@tonic-gate if (cpc_set_sample(cpc, this, *scratch) != 0) 5157c478bd9Sstevel@tonic-gate goto bad; 5167c478bd9Sstevel@tonic-gate 5177c478bd9Sstevel@tonic-gate cpc_buf_add(cpc, *data1, *data1, *scratch); 5187c478bd9Sstevel@tonic-gate 5197c478bd9Sstevel@tonic-gate if (cpc_unbind(cpc, this) != 0) 5207c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: error " 5217c478bd9Sstevel@tonic-gate "unbinding on cpu %d - %s\n"), 5227c478bd9Sstevel@tonic-gate opts->pgmname, state->cpuid, 5237c478bd9Sstevel@tonic-gate strerror(errno)); 5247c478bd9Sstevel@tonic-gate 5257c478bd9Sstevel@tonic-gate this = cpc_setgrp_nextset(sgrp); 5267c478bd9Sstevel@tonic-gate 5277c478bd9Sstevel@tonic-gate print_sample(state->cpuid, *scratch, nreqs, name, 0); 5287c478bd9Sstevel@tonic-gate 5297c478bd9Sstevel@tonic-gate /* 5307c478bd9Sstevel@tonic-gate * If periodic behavior was requested, rest here. 5317c478bd9Sstevel@tonic-gate */ 5327c478bd9Sstevel@tonic-gate if (opts->doperiod && opts->mseconds_rest > 0 && 5337c478bd9Sstevel@tonic-gate (sample_cnt % opts->nsets) == 0) { 5347c478bd9Sstevel@tonic-gate /* 5357c478bd9Sstevel@tonic-gate * Stop the soaker while the tool rests. 5367c478bd9Sstevel@tonic-gate */ 5377c478bd9Sstevel@tonic-gate if (opts->dosoaker) { 5387c478bd9Sstevel@tonic-gate (void) mutex_lock(&state->soak_lock); 5397c478bd9Sstevel@tonic-gate if (state->soak_state == SOAK_RUN) 5407c478bd9Sstevel@tonic-gate state->soak_state = SOAK_PAUSE; 5417c478bd9Sstevel@tonic-gate (void) mutex_unlock(&state->soak_lock); 5427c478bd9Sstevel@tonic-gate } 5437c478bd9Sstevel@tonic-gate 5447c478bd9Sstevel@tonic-gate htnow = gethrtime(); 5457c478bd9Sstevel@tonic-gate ht += restdelta; 5467c478bd9Sstevel@tonic-gate ts.tv_sec = (time_t)((ht - htnow) / 5477c478bd9Sstevel@tonic-gate NSECS_PER_SEC); 5487c478bd9Sstevel@tonic-gate ts.tv_nsec = (suseconds_t)((ht - htnow) % 5497c478bd9Sstevel@tonic-gate NSECS_PER_SEC); 5507c478bd9Sstevel@tonic-gate 5517c478bd9Sstevel@tonic-gate (void) nanosleep(&ts, NULL); 5527c478bd9Sstevel@tonic-gate } 5537c478bd9Sstevel@tonic-gate 5547c478bd9Sstevel@tonic-gate /* 5557c478bd9Sstevel@tonic-gate * Start or stop the soaker if needed. 5567c478bd9Sstevel@tonic-gate */ 5577c478bd9Sstevel@tonic-gate if (opts->dosoaker) { 5587c478bd9Sstevel@tonic-gate (void) mutex_lock(&state->soak_lock); 5597c478bd9Sstevel@tonic-gate if (cpc_setgrp_sysonly(sgrp) && 5607c478bd9Sstevel@tonic-gate state->soak_state == SOAK_PAUSE) { 5617c478bd9Sstevel@tonic-gate /* 5627c478bd9Sstevel@tonic-gate * Soaker is paused but the next set is 5637c478bd9Sstevel@tonic-gate * sysonly: start the soaker. 5647c478bd9Sstevel@tonic-gate */ 5657c478bd9Sstevel@tonic-gate state->soak_state = SOAK_RUN; 5667c478bd9Sstevel@tonic-gate (void) cond_signal(&state->soak_cv); 5677c478bd9Sstevel@tonic-gate } else if (cpc_setgrp_sysonly(sgrp) == 0 && 5687c478bd9Sstevel@tonic-gate state->soak_state == SOAK_RUN) 5697c478bd9Sstevel@tonic-gate /* 5707c478bd9Sstevel@tonic-gate * Soaker is running but the next set 5717c478bd9Sstevel@tonic-gate * counts user events: stop the soaker. 5727c478bd9Sstevel@tonic-gate */ 5737c478bd9Sstevel@tonic-gate state->soak_state = SOAK_PAUSE; 5747c478bd9Sstevel@tonic-gate (void) mutex_unlock(&state->soak_lock); 5757c478bd9Sstevel@tonic-gate } 5767c478bd9Sstevel@tonic-gate 5777c478bd9Sstevel@tonic-gate if (cpc_bind_cpu(cpc, state->cpuid, this, 0) != 0) 5787c478bd9Sstevel@tonic-gate goto bad; 5797c478bd9Sstevel@tonic-gate } 5807c478bd9Sstevel@tonic-gate } 5817c478bd9Sstevel@tonic-gate 5827c478bd9Sstevel@tonic-gate if (cpc_unbind(cpc, this) != 0) 5837c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: error unbinding on" 5847c478bd9Sstevel@tonic-gate " cpu %d - %s\n"), opts->pgmname, 5857c478bd9Sstevel@tonic-gate state->cpuid, strerror(errno)); 5867c478bd9Sstevel@tonic-gate 5877c478bd9Sstevel@tonic-gate /* 5887c478bd9Sstevel@tonic-gate * We're done, so stop the soaker if needed. 5897c478bd9Sstevel@tonic-gate */ 5907c478bd9Sstevel@tonic-gate if (opts->dosoaker) { 5917c478bd9Sstevel@tonic-gate (void) mutex_lock(&state->soak_lock); 5927c478bd9Sstevel@tonic-gate if (state->soak_state == SOAK_RUN) 5937c478bd9Sstevel@tonic-gate state->soak_state = SOAK_PAUSE; 5947c478bd9Sstevel@tonic-gate (void) mutex_unlock(&state->soak_lock); 5957c478bd9Sstevel@tonic-gate } 5967c478bd9Sstevel@tonic-gate 5977c478bd9Sstevel@tonic-gate return (NULL); 5987c478bd9Sstevel@tonic-gate bad: 5997c478bd9Sstevel@tonic-gate state->status = 3; 6007c478bd9Sstevel@tonic-gate errstr = strerror(errno); 6017c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: cpu%d - %s\n"), 6027c478bd9Sstevel@tonic-gate opts->pgmname, state->cpuid, errstr); 6037c478bd9Sstevel@tonic-gate return (NULL); 6047c478bd9Sstevel@tonic-gate } 6057c478bd9Sstevel@tonic-gate 6067c478bd9Sstevel@tonic-gate static int 6077c478bd9Sstevel@tonic-gate cpustat(void) 6087c478bd9Sstevel@tonic-gate { 6097c478bd9Sstevel@tonic-gate cpc_setgrp_t *accum; 6107c478bd9Sstevel@tonic-gate cpc_set_t *start; 6117c478bd9Sstevel@tonic-gate int c, i, retval; 6127c478bd9Sstevel@tonic-gate int lwps = 0; 6137c478bd9Sstevel@tonic-gate psetid_t mypset, cpupset; 6147c478bd9Sstevel@tonic-gate char *errstr; 6157c478bd9Sstevel@tonic-gate cpc_buf_t **data1, **data2, **scratch; 6167c478bd9Sstevel@tonic-gate int nreqs; 6177c478bd9Sstevel@tonic-gate kstat_ctl_t *kc; 6187c478bd9Sstevel@tonic-gate 6197c478bd9Sstevel@tonic-gate ncpus = (int)sysconf(_SC_NPROCESSORS_CONF); 6207c478bd9Sstevel@tonic-gate if ((gstate = calloc(ncpus, sizeof (*gstate))) == NULL) { 6217c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 6227c478bd9Sstevel@tonic-gate "%s: out of heap\n"), opts->pgmname); 6237c478bd9Sstevel@tonic-gate return (1); 6247c478bd9Sstevel@tonic-gate } 6257c478bd9Sstevel@tonic-gate 6267c478bd9Sstevel@tonic-gate max_chip_id = sysconf(_SC_CPUID_MAX); 6277c478bd9Sstevel@tonic-gate if ((chip_designees = malloc(max_chip_id * sizeof (int))) == NULL) { 6287c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 6297c478bd9Sstevel@tonic-gate "%s: out of heap\n"), opts->pgmname); 6307c478bd9Sstevel@tonic-gate return (1); 6317c478bd9Sstevel@tonic-gate } 6327c478bd9Sstevel@tonic-gate for (i = 0; i < max_chip_id; i++) 6337c478bd9Sstevel@tonic-gate chip_designees[i] = -1; 6347c478bd9Sstevel@tonic-gate 6357c478bd9Sstevel@tonic-gate if (smt) { 6367c478bd9Sstevel@tonic-gate if ((kc = kstat_open()) == NULL) { 6377c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 6387c478bd9Sstevel@tonic-gate "%s: kstat_open() failed: %s\n"), opts->pgmname, 6397c478bd9Sstevel@tonic-gate strerror(errno)); 6407c478bd9Sstevel@tonic-gate return (1); 6417c478bd9Sstevel@tonic-gate } 6427c478bd9Sstevel@tonic-gate } 6437c478bd9Sstevel@tonic-gate 6447c478bd9Sstevel@tonic-gate if (opts->dosoaker) 6457c478bd9Sstevel@tonic-gate if (priocntl(0, 0, PC_GETCID, &fxinfo) == -1) { 6467c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 6477c478bd9Sstevel@tonic-gate "%s: couldn't get FX scheduler class: %s\n"), 6487c478bd9Sstevel@tonic-gate opts->pgmname, strerror(errno)); 6497c478bd9Sstevel@tonic-gate return (1); 6507c478bd9Sstevel@tonic-gate } 6517c478bd9Sstevel@tonic-gate 6527c478bd9Sstevel@tonic-gate /* 6537c478bd9Sstevel@tonic-gate * Only include processors that are participating in the system 6547c478bd9Sstevel@tonic-gate */ 6557c478bd9Sstevel@tonic-gate for (c = 0, i = 0; i < ncpus; c++) { 6567c478bd9Sstevel@tonic-gate switch (p_online(c, P_STATUS)) { 6577c478bd9Sstevel@tonic-gate case P_ONLINE: 6587c478bd9Sstevel@tonic-gate case P_NOINTR: 6597c478bd9Sstevel@tonic-gate if (smt) { 6607c478bd9Sstevel@tonic-gate 6617c478bd9Sstevel@tonic-gate gstate[i].chip_id = get_chipid(kc, c); 6627c478bd9Sstevel@tonic-gate if (gstate[i].chip_id != -1 && 6637c478bd9Sstevel@tonic-gate chip_designees[gstate[i].chip_id] == -1) 6647c478bd9Sstevel@tonic-gate chip_designees[gstate[i].chip_id] = c; 6657c478bd9Sstevel@tonic-gate } 6667c478bd9Sstevel@tonic-gate 6677c478bd9Sstevel@tonic-gate gstate[i++].cpuid = c; 6687c478bd9Sstevel@tonic-gate break; 6697c478bd9Sstevel@tonic-gate case P_OFFLINE: 6707c478bd9Sstevel@tonic-gate case P_POWEROFF: 6717c478bd9Sstevel@tonic-gate case P_FAULTED: 6727c478bd9Sstevel@tonic-gate case P_SPARE: 6737c478bd9Sstevel@tonic-gate gstate[i++].cpuid = -1; 6747c478bd9Sstevel@tonic-gate break; 6757c478bd9Sstevel@tonic-gate default: 6767c478bd9Sstevel@tonic-gate gstate[i++].cpuid = -1; 6777c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 6787c478bd9Sstevel@tonic-gate gettext("%s: cpu%d in unknown state\n"), 6797c478bd9Sstevel@tonic-gate opts->pgmname, c); 6807c478bd9Sstevel@tonic-gate break; 6817c478bd9Sstevel@tonic-gate case -1: 6827c478bd9Sstevel@tonic-gate break; 6837c478bd9Sstevel@tonic-gate } 6847c478bd9Sstevel@tonic-gate } 6857c478bd9Sstevel@tonic-gate 6867c478bd9Sstevel@tonic-gate /* 6877c478bd9Sstevel@tonic-gate * Examine the processor sets; if we're in one, only attempt 6887c478bd9Sstevel@tonic-gate * to report on the set we're in. 6897c478bd9Sstevel@tonic-gate */ 6907c478bd9Sstevel@tonic-gate if (pset_bind(PS_QUERY, P_PID, P_MYID, &mypset) == -1) { 6917c478bd9Sstevel@tonic-gate errstr = strerror(errno); 6927c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: pset_bind - %s\n"), 6937c478bd9Sstevel@tonic-gate opts->pgmname, errstr); 6947c478bd9Sstevel@tonic-gate } else { 6957c478bd9Sstevel@tonic-gate for (i = 0; i < ncpus; i++) { 6967c478bd9Sstevel@tonic-gate struct tstate *this = &gstate[i]; 6977c478bd9Sstevel@tonic-gate 6987c478bd9Sstevel@tonic-gate if (this->cpuid == -1) 6997c478bd9Sstevel@tonic-gate continue; 7007c478bd9Sstevel@tonic-gate 7017c478bd9Sstevel@tonic-gate if (pset_assign(PS_QUERY, 7027c478bd9Sstevel@tonic-gate this->cpuid, &cpupset) == -1) { 7037c478bd9Sstevel@tonic-gate errstr = strerror(errno); 7047c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 7057c478bd9Sstevel@tonic-gate gettext("%s: pset_assign - %s\n"), 7067c478bd9Sstevel@tonic-gate opts->pgmname, errstr); 7077c478bd9Sstevel@tonic-gate continue; 7087c478bd9Sstevel@tonic-gate } 7097c478bd9Sstevel@tonic-gate 7107c478bd9Sstevel@tonic-gate if (mypset != cpupset) 7117c478bd9Sstevel@tonic-gate this->cpuid = -1; 7127c478bd9Sstevel@tonic-gate } 7137c478bd9Sstevel@tonic-gate } 7147c478bd9Sstevel@tonic-gate 7157c478bd9Sstevel@tonic-gate if (opts->dotitle) 7167c478bd9Sstevel@tonic-gate print_title(opts->master); 7177c478bd9Sstevel@tonic-gate zerotime(); 7187c478bd9Sstevel@tonic-gate 7197c478bd9Sstevel@tonic-gate for (i = 0; i < ncpus; i++) { 7207c478bd9Sstevel@tonic-gate struct tstate *this = &gstate[i]; 7217c478bd9Sstevel@tonic-gate 7227c478bd9Sstevel@tonic-gate if (this->cpuid == -1) 7237c478bd9Sstevel@tonic-gate continue; 7247c478bd9Sstevel@tonic-gate this->sgrp = cpc_setgrp_clone(opts->master); 7257c478bd9Sstevel@tonic-gate if (this->sgrp == NULL) { 7267c478bd9Sstevel@tonic-gate this->cpuid = -1; 7277c478bd9Sstevel@tonic-gate continue; 7287c478bd9Sstevel@tonic-gate } 7297c478bd9Sstevel@tonic-gate if (thr_create(NULL, 0, gtick, this, 7307c478bd9Sstevel@tonic-gate THR_BOUND|THR_NEW_LWP, &this->tid) == 0) 7317c478bd9Sstevel@tonic-gate lwps++; 7327c478bd9Sstevel@tonic-gate else { 7337c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 7347c478bd9Sstevel@tonic-gate gettext("%s: cannot create thread for cpu%d\n"), 7357c478bd9Sstevel@tonic-gate opts->pgmname, this->cpuid); 7367c478bd9Sstevel@tonic-gate this->status = 4; 7377c478bd9Sstevel@tonic-gate } 7387c478bd9Sstevel@tonic-gate } 7397c478bd9Sstevel@tonic-gate 7407c478bd9Sstevel@tonic-gate if (lwps != 0) 7417c478bd9Sstevel@tonic-gate for (i = 0; i < ncpus; i++) 7427c478bd9Sstevel@tonic-gate (void) thr_join(gstate[i].tid, NULL, NULL); 7437c478bd9Sstevel@tonic-gate 7447c478bd9Sstevel@tonic-gate if ((accum = cpc_setgrp_clone(opts->master)) == NULL) { 7457c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: out of heap\n"), 7467c478bd9Sstevel@tonic-gate opts->pgmname); 7477c478bd9Sstevel@tonic-gate return (1); 7487c478bd9Sstevel@tonic-gate } 7497c478bd9Sstevel@tonic-gate 7507c478bd9Sstevel@tonic-gate retval = 0; 7517c478bd9Sstevel@tonic-gate for (i = 0; i < ncpus; i++) { 7527c478bd9Sstevel@tonic-gate struct tstate *this = &gstate[i]; 7537c478bd9Sstevel@tonic-gate 7547c478bd9Sstevel@tonic-gate if (this->cpuid == -1) 7557c478bd9Sstevel@tonic-gate continue; 7567c478bd9Sstevel@tonic-gate cpc_setgrp_accum(accum, this->sgrp); 7577c478bd9Sstevel@tonic-gate cpc_setgrp_free(this->sgrp); 7587c478bd9Sstevel@tonic-gate this->sgrp = NULL; 7597c478bd9Sstevel@tonic-gate if (this->status != 0) 7607c478bd9Sstevel@tonic-gate retval = 1; 7617c478bd9Sstevel@tonic-gate } 7627c478bd9Sstevel@tonic-gate 7637c478bd9Sstevel@tonic-gate cpc_setgrp_reset(accum); 7647c478bd9Sstevel@tonic-gate start = cpc_setgrp_getset(accum); 7657c478bd9Sstevel@tonic-gate do { 7667c478bd9Sstevel@tonic-gate nreqs = cpc_setgrp_getbufs(accum, &data1, &data2, &scratch); 7677c478bd9Sstevel@tonic-gate print_total(lwps, *data1, nreqs, cpc_setgrp_getname(accum)); 7687c478bd9Sstevel@tonic-gate } while (cpc_setgrp_nextset(accum) != start); 7697c478bd9Sstevel@tonic-gate 7707c478bd9Sstevel@tonic-gate cpc_setgrp_free(accum); 7717c478bd9Sstevel@tonic-gate accum = NULL; 7727c478bd9Sstevel@tonic-gate 7737c478bd9Sstevel@tonic-gate free(gstate); 7747c478bd9Sstevel@tonic-gate return (retval); 7757c478bd9Sstevel@tonic-gate } 7767c478bd9Sstevel@tonic-gate 7777c478bd9Sstevel@tonic-gate static int 7787c478bd9Sstevel@tonic-gate get_chipid(kstat_ctl_t *kc, processorid_t cpuid) 7797c478bd9Sstevel@tonic-gate { 7807c478bd9Sstevel@tonic-gate kstat_t *ksp; 7817c478bd9Sstevel@tonic-gate kstat_named_t *k; 7827c478bd9Sstevel@tonic-gate 7837c478bd9Sstevel@tonic-gate if ((ksp = kstat_lookup(kc, "cpu_info", cpuid, NULL)) == NULL) 7847c478bd9Sstevel@tonic-gate return (-1); 7857c478bd9Sstevel@tonic-gate 7867c478bd9Sstevel@tonic-gate if (kstat_read(kc, ksp, NULL) == -1) { 7877c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 7887c478bd9Sstevel@tonic-gate gettext("%s: kstat_read() failed for cpu %d: %s\n"), 7897c478bd9Sstevel@tonic-gate opts->pgmname, cpuid, strerror(errno)); 7907c478bd9Sstevel@tonic-gate return (-1); 7917c478bd9Sstevel@tonic-gate } 7927c478bd9Sstevel@tonic-gate 7937c478bd9Sstevel@tonic-gate if ((k = (kstat_named_t *)kstat_data_lookup(ksp, "chip_id")) == NULL) { 7947c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 7957c478bd9Sstevel@tonic-gate gettext("%s: chip_id not found for cpu %d: %s\n"), 7967c478bd9Sstevel@tonic-gate opts->pgmname, cpuid, strerror(errno)); 7977c478bd9Sstevel@tonic-gate return (-1); 7987c478bd9Sstevel@tonic-gate } 7997c478bd9Sstevel@tonic-gate 8007c478bd9Sstevel@tonic-gate return (k->value.i32); 8017c478bd9Sstevel@tonic-gate } 8027c478bd9Sstevel@tonic-gate 8037c478bd9Sstevel@tonic-gate static void * 8047c478bd9Sstevel@tonic-gate soaker(void *arg) 8057c478bd9Sstevel@tonic-gate { 8067c478bd9Sstevel@tonic-gate struct tstate *state = arg; 8077c478bd9Sstevel@tonic-gate pcparms_t pcparms; 8087c478bd9Sstevel@tonic-gate fxparms_t *fx = (fxparms_t *)pcparms.pc_clparms; 8097c478bd9Sstevel@tonic-gate 8107c478bd9Sstevel@tonic-gate if (processor_bind(P_LWPID, P_MYID, state->cpuid, NULL) != 0) 8117c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: couldn't bind soaker " 8127c478bd9Sstevel@tonic-gate "thread to cpu%d: %s\n"), opts->pgmname, state->cpuid, 8137c478bd9Sstevel@tonic-gate strerror(errno)); 8147c478bd9Sstevel@tonic-gate 8157c478bd9Sstevel@tonic-gate /* 8167c478bd9Sstevel@tonic-gate * Put the soaker thread in the fixed priority (FX) class so it runs 8177c478bd9Sstevel@tonic-gate * at the lowest possible global priority. 8187c478bd9Sstevel@tonic-gate */ 8197c478bd9Sstevel@tonic-gate pcparms.pc_cid = fxinfo.pc_cid; 8207c478bd9Sstevel@tonic-gate fx->fx_upri = 0; 8217c478bd9Sstevel@tonic-gate fx->fx_uprilim = 0; 8227c478bd9Sstevel@tonic-gate fx->fx_tqsecs = fx->fx_tqnsecs = FX_TQDEF; 8237c478bd9Sstevel@tonic-gate 8247c478bd9Sstevel@tonic-gate if (priocntl(P_LWPID, P_MYID, PC_SETPARMS, &pcparms) != 0) 8257c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: couldn't put soaker " 8267c478bd9Sstevel@tonic-gate "thread in FX sched class: %s\n"), opts->pgmname, 8277c478bd9Sstevel@tonic-gate strerror(errno)); 8287c478bd9Sstevel@tonic-gate 8297c478bd9Sstevel@tonic-gate /* 8307c478bd9Sstevel@tonic-gate * Let the parent thread know we're ready to roll. 8317c478bd9Sstevel@tonic-gate */ 8327c478bd9Sstevel@tonic-gate (void) mutex_lock(&state->soak_lock); 8337c478bd9Sstevel@tonic-gate state->soak_state = SOAK_RUN; 8347c478bd9Sstevel@tonic-gate (void) cond_signal(&state->soak_cv); 8357c478bd9Sstevel@tonic-gate (void) mutex_unlock(&state->soak_lock); 8367c478bd9Sstevel@tonic-gate 8377c478bd9Sstevel@tonic-gate for (;;) { 8387c478bd9Sstevel@tonic-gate spin: 8397c478bd9Sstevel@tonic-gate (void) mutex_lock(&state->soak_lock); 8407c478bd9Sstevel@tonic-gate if (state->soak_state == SOAK_RUN) { 8417c478bd9Sstevel@tonic-gate (void) mutex_unlock(&state->soak_lock); 8427c478bd9Sstevel@tonic-gate goto spin; 8437c478bd9Sstevel@tonic-gate } 8447c478bd9Sstevel@tonic-gate 8457c478bd9Sstevel@tonic-gate while (state->soak_state == SOAK_PAUSE) 8467c478bd9Sstevel@tonic-gate (void) cond_wait(&state->soak_cv, 8477c478bd9Sstevel@tonic-gate &state->soak_lock); 8487c478bd9Sstevel@tonic-gate (void) mutex_unlock(&state->soak_lock); 8497c478bd9Sstevel@tonic-gate } 8507c478bd9Sstevel@tonic-gate 8517c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 8527c478bd9Sstevel@tonic-gate return (NULL); 8537c478bd9Sstevel@tonic-gate } 854