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 5a08731ecScth * Common Development and Distribution License (the "License"). 6a08731ecScth * 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 /* 224944376cSJohn Levon * 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/pset.h> 277c478bd9Sstevel@tonic-gate #include <sys/types.h> 287c478bd9Sstevel@tonic-gate #include <sys/time.h> 297c478bd9Sstevel@tonic-gate #include <sys/sysinfo.h> 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate #include <assert.h> 327c478bd9Sstevel@tonic-gate #include <stdio.h> 337c478bd9Sstevel@tonic-gate #include <stdlib.h> 347c478bd9Sstevel@tonic-gate #include <stdarg.h> 357c478bd9Sstevel@tonic-gate #include <ctype.h> 367c478bd9Sstevel@tonic-gate #include <unistd.h> 377c478bd9Sstevel@tonic-gate #include <memory.h> 387c478bd9Sstevel@tonic-gate #include <string.h> 397c478bd9Sstevel@tonic-gate #include <strings.h> 407c478bd9Sstevel@tonic-gate #include <fcntl.h> 417c478bd9Sstevel@tonic-gate #include <errno.h> 427c478bd9Sstevel@tonic-gate #include <kstat.h> 437c478bd9Sstevel@tonic-gate #include <poll.h> 4400c76d6fStc35445 #include <signal.h> 454944376cSJohn Levon #include <locale.h> 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate #include "statcommon.h" 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate #define SNAP(s, i, l, n) ((s) ? agg_proc_snap(s, i, l, n) : 0) 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate #define REPRINT 20 527c478bd9Sstevel@tonic-gate 5300c76d6fStc35445 char *cmdname = "mpstat"; 5400c76d6fStc35445 int caught_cont = 0; 557c478bd9Sstevel@tonic-gate 56*26fd7700SKrishnendu Sadhukhan - Sun Microsystems static uint_t timestamp_fmt = NODATE; 574944376cSJohn Levon 587c478bd9Sstevel@tonic-gate static int hz; 597c478bd9Sstevel@tonic-gate static int display_pset = -1; 607c478bd9Sstevel@tonic-gate static int show_set = 0; 617c478bd9Sstevel@tonic-gate static int suppress_state; 627c478bd9Sstevel@tonic-gate 637c478bd9Sstevel@tonic-gate static void print_header(int, int); 647c478bd9Sstevel@tonic-gate static void show_cpu_usage(struct snapshot *, struct snapshot *, int); 657c478bd9Sstevel@tonic-gate static void usage(void); 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate int 687c478bd9Sstevel@tonic-gate main(int argc, char **argv) 697c478bd9Sstevel@tonic-gate { 707c478bd9Sstevel@tonic-gate int c; 717c478bd9Sstevel@tonic-gate int display_agg = 0; 727c478bd9Sstevel@tonic-gate int iter = 1; 737c478bd9Sstevel@tonic-gate int interval = 0; 747c478bd9Sstevel@tonic-gate char *endptr; 757c478bd9Sstevel@tonic-gate int infinite_cycles = 0; 767c478bd9Sstevel@tonic-gate kstat_ctl_t *kc; 777c478bd9Sstevel@tonic-gate struct snapshot *old = NULL; 787c478bd9Sstevel@tonic-gate struct snapshot *new = NULL; 797c478bd9Sstevel@tonic-gate enum snapshot_types types = SNAP_CPUS; 8000c76d6fStc35445 hrtime_t start_n; 8100c76d6fStc35445 hrtime_t period_n; 827c478bd9Sstevel@tonic-gate 834944376cSJohn Levon (void) setlocale(LC_ALL, ""); 844944376cSJohn Levon #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 854944376cSJohn Levon #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 864944376cSJohn Levon #endif 874944376cSJohn Levon (void) textdomain(TEXT_DOMAIN); 884944376cSJohn Levon 894944376cSJohn Levon while ((c = getopt(argc, argv, "apP:qT:")) != (int)EOF) 907c478bd9Sstevel@tonic-gate switch (c) { 917c478bd9Sstevel@tonic-gate case 'a': 927c478bd9Sstevel@tonic-gate /* 937c478bd9Sstevel@tonic-gate * Display aggregate data for processor sets. 947c478bd9Sstevel@tonic-gate */ 957c478bd9Sstevel@tonic-gate display_agg = 1; 967c478bd9Sstevel@tonic-gate break; 977c478bd9Sstevel@tonic-gate case 'p': 987c478bd9Sstevel@tonic-gate /* 997c478bd9Sstevel@tonic-gate * Display all processor sets. 1007c478bd9Sstevel@tonic-gate */ 1017c478bd9Sstevel@tonic-gate if (display_pset != -1) 1027c478bd9Sstevel@tonic-gate usage(); 1037c478bd9Sstevel@tonic-gate show_set = 1; 1047c478bd9Sstevel@tonic-gate break; 1057c478bd9Sstevel@tonic-gate case 'P': 1067c478bd9Sstevel@tonic-gate /* 1077c478bd9Sstevel@tonic-gate * Display specific processor set. 1087c478bd9Sstevel@tonic-gate */ 1097c478bd9Sstevel@tonic-gate if (show_set == 1) 1107c478bd9Sstevel@tonic-gate usage(); 1117c478bd9Sstevel@tonic-gate display_pset = (int)strtol 1127c478bd9Sstevel@tonic-gate (optarg, &endptr, 10); 1137c478bd9Sstevel@tonic-gate if (*endptr != NULL) 1147c478bd9Sstevel@tonic-gate usage(); 1157c478bd9Sstevel@tonic-gate /* 1167c478bd9Sstevel@tonic-gate * Not valid to specify a negative processor 1177c478bd9Sstevel@tonic-gate * set value. 1187c478bd9Sstevel@tonic-gate */ 1197c478bd9Sstevel@tonic-gate if (display_pset < 0) 1207c478bd9Sstevel@tonic-gate usage(); 1217c478bd9Sstevel@tonic-gate break; 1227c478bd9Sstevel@tonic-gate case 'q': 1237c478bd9Sstevel@tonic-gate suppress_state = 1; 1247c478bd9Sstevel@tonic-gate break; 1254944376cSJohn Levon case 'T': 1264944376cSJohn Levon if (optarg) { 1274944376cSJohn Levon if (*optarg == 'u') 1284944376cSJohn Levon timestamp_fmt = UDATE; 1294944376cSJohn Levon else if (*optarg == 'd') 1304944376cSJohn Levon timestamp_fmt = DDATE; 1314944376cSJohn Levon else 1324944376cSJohn Levon usage(); 1334944376cSJohn Levon } else { 1344944376cSJohn Levon usage(); 1354944376cSJohn Levon } 1364944376cSJohn Levon break; 1377c478bd9Sstevel@tonic-gate case '?': 1387c478bd9Sstevel@tonic-gate usage(); 1397c478bd9Sstevel@tonic-gate break; 1407c478bd9Sstevel@tonic-gate } 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate hz = sysconf(_SC_CLK_TCK); 1437c478bd9Sstevel@tonic-gate 1447c478bd9Sstevel@tonic-gate if (argc > optind) { 1457c478bd9Sstevel@tonic-gate interval = (int)strtol(argv[optind], &endptr, 10); 1467c478bd9Sstevel@tonic-gate if (*endptr != NULL) 1477c478bd9Sstevel@tonic-gate usage(); 14800c76d6fStc35445 period_n = (hrtime_t)interval * NANOSEC; 1497c478bd9Sstevel@tonic-gate if (argc > optind + 1) { 1507c478bd9Sstevel@tonic-gate iter = (unsigned int)strtoul 1517c478bd9Sstevel@tonic-gate (argv[optind + 1], &endptr, 10); 1527c478bd9Sstevel@tonic-gate if (*endptr != NULL || iter < 0) 1537c478bd9Sstevel@tonic-gate usage(); 1547c478bd9Sstevel@tonic-gate if (iter == 0) 1557c478bd9Sstevel@tonic-gate return (0); 1567c478bd9Sstevel@tonic-gate } else { 1577c478bd9Sstevel@tonic-gate infinite_cycles = 1; 1587c478bd9Sstevel@tonic-gate } 1597c478bd9Sstevel@tonic-gate } 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate if (display_agg || show_set || display_pset != -1) 1627c478bd9Sstevel@tonic-gate types |= SNAP_PSETS; 1637c478bd9Sstevel@tonic-gate 1647c478bd9Sstevel@tonic-gate kc = open_kstat(); 1657c478bd9Sstevel@tonic-gate 16600c76d6fStc35445 /* Set up handler for SIGCONT */ 16700c76d6fStc35445 if (signal(SIGCONT, cont_handler) == SIG_ERR) 16800c76d6fStc35445 fail(1, "signal failed"); 16900c76d6fStc35445 17000c76d6fStc35445 start_n = gethrtime(); 17100c76d6fStc35445 1727c478bd9Sstevel@tonic-gate while (infinite_cycles || iter > 0) { 1737c478bd9Sstevel@tonic-gate free_snapshot(old); 1747c478bd9Sstevel@tonic-gate old = new; 1757c478bd9Sstevel@tonic-gate new = acquire_snapshot(kc, types, NULL); 1767c478bd9Sstevel@tonic-gate 1777c478bd9Sstevel@tonic-gate if (!suppress_state) 1787c478bd9Sstevel@tonic-gate snapshot_report_changes(old, new); 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate /* if config changed, show stats from boot */ 1817c478bd9Sstevel@tonic-gate if (snapshot_has_changed(old, new)) { 1827c478bd9Sstevel@tonic-gate free_snapshot(old); 1837c478bd9Sstevel@tonic-gate old = NULL; 1847c478bd9Sstevel@tonic-gate } 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate show_cpu_usage(old, new, display_agg); 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate if (!infinite_cycles && --iter < 1) 1897c478bd9Sstevel@tonic-gate break; 1907c478bd9Sstevel@tonic-gate 19100c76d6fStc35445 /* Have a kip */ 19200c76d6fStc35445 sleep_until(&start_n, period_n, infinite_cycles, &caught_cont); 1937c478bd9Sstevel@tonic-gate } 194a08731ecScth (void) kstat_close(kc); 195a08731ecScth 1967c478bd9Sstevel@tonic-gate return (0); 1977c478bd9Sstevel@tonic-gate } 1987c478bd9Sstevel@tonic-gate 1997c478bd9Sstevel@tonic-gate /* 2007c478bd9Sstevel@tonic-gate * Print an mpstat output header. 2017c478bd9Sstevel@tonic-gate */ 2027c478bd9Sstevel@tonic-gate static void 2037c478bd9Sstevel@tonic-gate print_header(int display_agg, int show_set) 2047c478bd9Sstevel@tonic-gate { 2057c478bd9Sstevel@tonic-gate if (display_agg == 1) 2067c478bd9Sstevel@tonic-gate (void) printf("SET minf mjf xcal intr ithr csw icsw migr " 2077c478bd9Sstevel@tonic-gate "smtx srw syscl usr sys wt idl sze"); 2087c478bd9Sstevel@tonic-gate else { 2097c478bd9Sstevel@tonic-gate (void) printf("CPU minf mjf xcal intr ithr csw icsw migr " 2107c478bd9Sstevel@tonic-gate "smtx srw syscl usr sys wt idl"); 2117c478bd9Sstevel@tonic-gate if (show_set == 1) 2127c478bd9Sstevel@tonic-gate (void) printf(" set"); 2137c478bd9Sstevel@tonic-gate } 2147c478bd9Sstevel@tonic-gate (void) printf("\n"); 2157c478bd9Sstevel@tonic-gate } 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate static void 2187c478bd9Sstevel@tonic-gate print_cpu(struct cpu_snapshot *c1, struct cpu_snapshot *c2) 2197c478bd9Sstevel@tonic-gate { 2207c478bd9Sstevel@tonic-gate uint64_t ticks = 0; 2217c478bd9Sstevel@tonic-gate double etime, percent; 2227c478bd9Sstevel@tonic-gate kstat_t *old_vm = NULL; 2237c478bd9Sstevel@tonic-gate kstat_t *old_sys = NULL; 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate if (display_pset != -1 && display_pset != c2->cs_pset_id) 2267c478bd9Sstevel@tonic-gate return; 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate /* 2297c478bd9Sstevel@tonic-gate * the first mpstat output will have c1 = NULL, to give 2307c478bd9Sstevel@tonic-gate * results since boot 2317c478bd9Sstevel@tonic-gate */ 2327c478bd9Sstevel@tonic-gate if (c1) { 2337c478bd9Sstevel@tonic-gate old_vm = &c1->cs_vm; 2347c478bd9Sstevel@tonic-gate old_sys = &c1->cs_sys; 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gate /* check there are stats to report */ 2377c478bd9Sstevel@tonic-gate if (!CPU_ACTIVE(c1)) 2387c478bd9Sstevel@tonic-gate return; 2397c478bd9Sstevel@tonic-gate } 2407c478bd9Sstevel@tonic-gate 2417c478bd9Sstevel@tonic-gate /* check there are stats to report */ 2427c478bd9Sstevel@tonic-gate if (!CPU_ACTIVE(c2)) 2437c478bd9Sstevel@tonic-gate return; 2447c478bd9Sstevel@tonic-gate 2457c478bd9Sstevel@tonic-gate ticks = cpu_ticks_delta(old_sys, &c2->cs_sys); 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate etime = (double)ticks / hz; 2487c478bd9Sstevel@tonic-gate if (etime == 0.0) /* Prevent divide by zero errors */ 2497c478bd9Sstevel@tonic-gate etime = 1.0; 2507c478bd9Sstevel@tonic-gate percent = 100.0 / etime / hz; 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate (void) printf("%3d %4.0f %3.0f %4.0f %5.0f %4.0f " 2537c478bd9Sstevel@tonic-gate "%4.0f %4.0f %4.0f %4.0f %4.0f %5.0f %3.0f %3.0f " 2547c478bd9Sstevel@tonic-gate "%3.0f %3.0f", 2557c478bd9Sstevel@tonic-gate c2->cs_id, 2567c478bd9Sstevel@tonic-gate (kstat_delta(old_vm, &c2->cs_vm, "hat_fault") + 2577c478bd9Sstevel@tonic-gate kstat_delta(old_vm, &c2->cs_vm, "as_fault")) / etime, 2587c478bd9Sstevel@tonic-gate kstat_delta(old_vm, &c2->cs_vm, "maj_fault") / etime, 2597c478bd9Sstevel@tonic-gate kstat_delta(old_sys, &c2->cs_sys, "xcalls") / etime, 2607c478bd9Sstevel@tonic-gate kstat_delta(old_sys, &c2->cs_sys, "intr") / etime, 2617c478bd9Sstevel@tonic-gate kstat_delta(old_sys, &c2->cs_sys, "intrthread") / etime, 2627c478bd9Sstevel@tonic-gate kstat_delta(old_sys, &c2->cs_sys, "pswitch") / etime, 2637c478bd9Sstevel@tonic-gate kstat_delta(old_sys, &c2->cs_sys, "inv_swtch") / etime, 2647c478bd9Sstevel@tonic-gate kstat_delta(old_sys, &c2->cs_sys, "cpumigrate") / etime, 2657c478bd9Sstevel@tonic-gate kstat_delta(old_sys, &c2->cs_sys, "mutex_adenters") / etime, 2667c478bd9Sstevel@tonic-gate (kstat_delta(old_sys, &c2->cs_sys, "rw_rdfails") + 2677c478bd9Sstevel@tonic-gate kstat_delta(old_sys, &c2->cs_sys, "rw_wrfails")) / etime, 2687c478bd9Sstevel@tonic-gate kstat_delta(old_sys, &c2->cs_sys, "syscall") / etime, 2697c478bd9Sstevel@tonic-gate kstat_delta(old_sys, &c2->cs_sys, "cpu_ticks_user") * percent, 2707c478bd9Sstevel@tonic-gate kstat_delta(old_sys, &c2->cs_sys, "cpu_ticks_kernel") * percent, 2717c478bd9Sstevel@tonic-gate kstat_delta(old_sys, &c2->cs_sys, "cpu_ticks_wait") * percent, 2727c478bd9Sstevel@tonic-gate kstat_delta(old_sys, &c2->cs_sys, "cpu_ticks_idle") * percent); 2737c478bd9Sstevel@tonic-gate 2747c478bd9Sstevel@tonic-gate if (show_set) 2757c478bd9Sstevel@tonic-gate (void) printf(" %3d", c2->cs_pset_id); 2767c478bd9Sstevel@tonic-gate (void) printf("\n"); 2777c478bd9Sstevel@tonic-gate } 2787c478bd9Sstevel@tonic-gate 2797c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 2807c478bd9Sstevel@tonic-gate static void 2817c478bd9Sstevel@tonic-gate compare_cpu(void *v1, void *v2, void *data) 2827c478bd9Sstevel@tonic-gate { 2837c478bd9Sstevel@tonic-gate struct cpu_snapshot *c1 = (struct cpu_snapshot *)v1; 2847c478bd9Sstevel@tonic-gate struct cpu_snapshot *c2 = (struct cpu_snapshot *)v2; 2857c478bd9Sstevel@tonic-gate 2867c478bd9Sstevel@tonic-gate if (c2 == NULL) 2877c478bd9Sstevel@tonic-gate return; 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate print_cpu(c1, c2); 2907c478bd9Sstevel@tonic-gate } 2917c478bd9Sstevel@tonic-gate 2927c478bd9Sstevel@tonic-gate static int 2937c478bd9Sstevel@tonic-gate pset_has_stats(struct pset_snapshot *p) 2947c478bd9Sstevel@tonic-gate { 2957c478bd9Sstevel@tonic-gate int count = 0; 2967c478bd9Sstevel@tonic-gate size_t i; 2977c478bd9Sstevel@tonic-gate for (i = 0; i < p->ps_nr_cpus; i++) { 2987c478bd9Sstevel@tonic-gate if (CPU_ACTIVE(p->ps_cpus[i])) 2997c478bd9Sstevel@tonic-gate count++; 3007c478bd9Sstevel@tonic-gate } 3017c478bd9Sstevel@tonic-gate return (count); 3027c478bd9Sstevel@tonic-gate } 3037c478bd9Sstevel@tonic-gate 3047c478bd9Sstevel@tonic-gate static void 3057c478bd9Sstevel@tonic-gate agg_stat(kstat_t *k1, kstat_t *k2, char *name) 3067c478bd9Sstevel@tonic-gate { 3077c478bd9Sstevel@tonic-gate kstat_named_t *ksn = kstat_data_lookup(k1, name); 3087c478bd9Sstevel@tonic-gate kstat_named_t *ksn2 = kstat_data_lookup(k2, name); 3097c478bd9Sstevel@tonic-gate ksn->value.ui64 += ksn2->value.ui64; 3107c478bd9Sstevel@tonic-gate } 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate static kstat_t * 3137c478bd9Sstevel@tonic-gate agg_vm(struct pset_snapshot *p, kstat_t *ks) 3147c478bd9Sstevel@tonic-gate { 3157c478bd9Sstevel@tonic-gate size_t i; 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate if (p->ps_nr_cpus == NULL) 3187c478bd9Sstevel@tonic-gate return (NULL); 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate if (kstat_copy(&p->ps_cpus[0]->cs_vm, ks)) 3217c478bd9Sstevel@tonic-gate return (NULL); 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate for (i = 1; i < p->ps_nr_cpus; i++) { 3247c478bd9Sstevel@tonic-gate agg_stat(ks, &p->ps_cpus[i]->cs_vm, "hat_fault"); 3257c478bd9Sstevel@tonic-gate agg_stat(ks, &p->ps_cpus[i]->cs_vm, "as_fault"); 3267c478bd9Sstevel@tonic-gate agg_stat(ks, &p->ps_cpus[i]->cs_vm, "maj_fault"); 3277c478bd9Sstevel@tonic-gate } 3287c478bd9Sstevel@tonic-gate 3297c478bd9Sstevel@tonic-gate return (ks); 3307c478bd9Sstevel@tonic-gate } 3317c478bd9Sstevel@tonic-gate 3327c478bd9Sstevel@tonic-gate static kstat_t * 3337c478bd9Sstevel@tonic-gate agg_sys(struct pset_snapshot *p, kstat_t *ks) 3347c478bd9Sstevel@tonic-gate { 3357c478bd9Sstevel@tonic-gate size_t i; 3367c478bd9Sstevel@tonic-gate 3377c478bd9Sstevel@tonic-gate if (p->ps_nr_cpus == NULL) 3387c478bd9Sstevel@tonic-gate return (NULL); 3397c478bd9Sstevel@tonic-gate 3407c478bd9Sstevel@tonic-gate if (kstat_copy(&p->ps_cpus[0]->cs_sys, ks)) 3417c478bd9Sstevel@tonic-gate return (NULL); 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate for (i = 1; i < p->ps_nr_cpus; i++) { 3447c478bd9Sstevel@tonic-gate agg_stat(ks, &p->ps_cpus[i]->cs_sys, "xcalls"); 3457c478bd9Sstevel@tonic-gate agg_stat(ks, &p->ps_cpus[i]->cs_sys, "intr"); 3467c478bd9Sstevel@tonic-gate agg_stat(ks, &p->ps_cpus[i]->cs_sys, "intrthread"); 3477c478bd9Sstevel@tonic-gate agg_stat(ks, &p->ps_cpus[i]->cs_sys, "pswitch"); 3487c478bd9Sstevel@tonic-gate agg_stat(ks, &p->ps_cpus[i]->cs_sys, "inv_swtch"); 3497c478bd9Sstevel@tonic-gate agg_stat(ks, &p->ps_cpus[i]->cs_sys, "cpumigrate"); 3507c478bd9Sstevel@tonic-gate agg_stat(ks, &p->ps_cpus[i]->cs_sys, "mutex_adenters"); 3517c478bd9Sstevel@tonic-gate agg_stat(ks, &p->ps_cpus[i]->cs_sys, "rw_rdfails"); 3527c478bd9Sstevel@tonic-gate agg_stat(ks, &p->ps_cpus[i]->cs_sys, "rw_wrfails"); 3537c478bd9Sstevel@tonic-gate agg_stat(ks, &p->ps_cpus[i]->cs_sys, "syscall"); 3547c478bd9Sstevel@tonic-gate agg_stat(ks, &p->ps_cpus[i]->cs_sys, "cpu_ticks_user"); 3557c478bd9Sstevel@tonic-gate agg_stat(ks, &p->ps_cpus[i]->cs_sys, "cpu_ticks_kernel"); 3567c478bd9Sstevel@tonic-gate agg_stat(ks, &p->ps_cpus[i]->cs_sys, "cpu_ticks_wait"); 3577c478bd9Sstevel@tonic-gate agg_stat(ks, &p->ps_cpus[i]->cs_sys, "cpu_ticks_idle"); 3587c478bd9Sstevel@tonic-gate } 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate return (ks); 3617c478bd9Sstevel@tonic-gate } 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate static uint64_t 3647c478bd9Sstevel@tonic-gate get_nr_ticks(struct pset_snapshot *p1, struct pset_snapshot *p2) 3657c478bd9Sstevel@tonic-gate { 3667c478bd9Sstevel@tonic-gate kstat_t *old = NULL; 3677c478bd9Sstevel@tonic-gate kstat_t *new = NULL; 3687c478bd9Sstevel@tonic-gate size_t i = 0; 3697c478bd9Sstevel@tonic-gate 3707c478bd9Sstevel@tonic-gate for (i = 0; p1 && i < p1->ps_nr_cpus; i++) { 3717c478bd9Sstevel@tonic-gate if (p1->ps_cpus[i]->cs_sys.ks_data) { 3727c478bd9Sstevel@tonic-gate old = &p1->ps_cpus[i]->cs_sys; 3737c478bd9Sstevel@tonic-gate break; 3747c478bd9Sstevel@tonic-gate } 3757c478bd9Sstevel@tonic-gate } 3767c478bd9Sstevel@tonic-gate 3777c478bd9Sstevel@tonic-gate for (i = 0; p2 && i < p2->ps_nr_cpus; i++) { 3787c478bd9Sstevel@tonic-gate if (p2->ps_cpus[i]->cs_sys.ks_data) { 3797c478bd9Sstevel@tonic-gate new = &p2->ps_cpus[i]->cs_sys; 3807c478bd9Sstevel@tonic-gate break; 3817c478bd9Sstevel@tonic-gate } 3827c478bd9Sstevel@tonic-gate } 3837c478bd9Sstevel@tonic-gate 3847c478bd9Sstevel@tonic-gate if (old == NULL && new == NULL) 3857c478bd9Sstevel@tonic-gate return (0); 3867c478bd9Sstevel@tonic-gate 3877c478bd9Sstevel@tonic-gate if (new == NULL) { 3887c478bd9Sstevel@tonic-gate new = old; 3897c478bd9Sstevel@tonic-gate old = NULL; 3907c478bd9Sstevel@tonic-gate } 3917c478bd9Sstevel@tonic-gate 3927c478bd9Sstevel@tonic-gate return (cpu_ticks_delta(old, new)); 3937c478bd9Sstevel@tonic-gate } 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate static void 3967c478bd9Sstevel@tonic-gate print_pset(struct pset_snapshot *p1, struct pset_snapshot *p2) 3977c478bd9Sstevel@tonic-gate { 3987c478bd9Sstevel@tonic-gate uint64_t ticks = 0; 3997c478bd9Sstevel@tonic-gate double etime, percent; 4007c478bd9Sstevel@tonic-gate kstat_t old_vm; 4017c478bd9Sstevel@tonic-gate kstat_t old_sys; 4027c478bd9Sstevel@tonic-gate kstat_t new_vm; 4037c478bd9Sstevel@tonic-gate kstat_t new_sys; 4047c478bd9Sstevel@tonic-gate 4057c478bd9Sstevel@tonic-gate if (display_pset != -1 && display_pset != p2->ps_id) 4067c478bd9Sstevel@tonic-gate return; 4077c478bd9Sstevel@tonic-gate 4087c478bd9Sstevel@tonic-gate if ((p1 && !pset_has_stats(p1)) || !pset_has_stats(p2)) 4097c478bd9Sstevel@tonic-gate return; 4107c478bd9Sstevel@tonic-gate 4117c478bd9Sstevel@tonic-gate old_vm.ks_data = old_sys.ks_data = NULL; 4127c478bd9Sstevel@tonic-gate new_vm.ks_data = new_sys.ks_data = NULL; 4137c478bd9Sstevel@tonic-gate 4147c478bd9Sstevel@tonic-gate /* 4157c478bd9Sstevel@tonic-gate * FIXME: these aggs will count "new" or disappeared cpus 4167c478bd9Sstevel@tonic-gate * in a set, leaving an apparent huge change. 4177c478bd9Sstevel@tonic-gate */ 4187c478bd9Sstevel@tonic-gate 4197c478bd9Sstevel@tonic-gate /* 4207c478bd9Sstevel@tonic-gate * the first mpstat output will have p1 = NULL, to give 4217c478bd9Sstevel@tonic-gate * results since boot 4227c478bd9Sstevel@tonic-gate */ 4237c478bd9Sstevel@tonic-gate if (p1) { 4247c478bd9Sstevel@tonic-gate if (!agg_vm(p1, &old_vm) || !agg_sys(p1, &old_sys)) 4257c478bd9Sstevel@tonic-gate goto out; 4267c478bd9Sstevel@tonic-gate } 4277c478bd9Sstevel@tonic-gate 4287c478bd9Sstevel@tonic-gate if (!agg_vm(p2, &new_vm) || !agg_sys(p2, &new_sys)) 4297c478bd9Sstevel@tonic-gate goto out; 4307c478bd9Sstevel@tonic-gate 4317c478bd9Sstevel@tonic-gate ticks = get_nr_ticks(p1, p2); 4327c478bd9Sstevel@tonic-gate 4337c478bd9Sstevel@tonic-gate etime = (double)ticks / hz; 4347c478bd9Sstevel@tonic-gate if (etime == 0.0) /* Prevent divide by zero errors */ 4357c478bd9Sstevel@tonic-gate etime = 1.0; 4367c478bd9Sstevel@tonic-gate percent = 100.0 / p2->ps_nr_cpus / etime / hz; 4377c478bd9Sstevel@tonic-gate 4387c478bd9Sstevel@tonic-gate (void) printf("%3d %4.0f %3.0f %4.0f %5.0f %4.0f " 4397c478bd9Sstevel@tonic-gate "%4.0f %4.0f %4.0f %4.0f %4.0f %5.0f %3.0f %3.0f " 4407c478bd9Sstevel@tonic-gate "%3.0f %3.0f %3d\n", 4417c478bd9Sstevel@tonic-gate p2->ps_id, 4427c478bd9Sstevel@tonic-gate (kstat_delta(&old_vm, &new_vm, "hat_fault") + 4437c478bd9Sstevel@tonic-gate kstat_delta(&old_vm, &new_vm, "as_fault")) / etime, 4447c478bd9Sstevel@tonic-gate kstat_delta(&old_vm, &new_vm, "maj_fault") / etime, 4457c478bd9Sstevel@tonic-gate kstat_delta(&old_sys, &new_sys, "xcalls") / etime, 4467c478bd9Sstevel@tonic-gate kstat_delta(&old_sys, &new_sys, "intr") / etime, 4477c478bd9Sstevel@tonic-gate kstat_delta(&old_sys, &new_sys, "intrthread") / etime, 4487c478bd9Sstevel@tonic-gate kstat_delta(&old_sys, &new_sys, "pswitch") / etime, 4497c478bd9Sstevel@tonic-gate kstat_delta(&old_sys, &new_sys, "inv_swtch") / etime, 4507c478bd9Sstevel@tonic-gate kstat_delta(&old_sys, &new_sys, "cpumigrate") / etime, 4517c478bd9Sstevel@tonic-gate kstat_delta(&old_sys, &new_sys, "mutex_adenters") / etime, 4527c478bd9Sstevel@tonic-gate (kstat_delta(&old_sys, &new_sys, "rw_rdfails") + 4537c478bd9Sstevel@tonic-gate kstat_delta(&old_sys, &new_sys, "rw_wrfails")) / etime, 4547c478bd9Sstevel@tonic-gate kstat_delta(&old_sys, &new_sys, "syscall") / etime, 4557c478bd9Sstevel@tonic-gate kstat_delta(&old_sys, &new_sys, "cpu_ticks_user") * percent, 4567c478bd9Sstevel@tonic-gate kstat_delta(&old_sys, &new_sys, "cpu_ticks_kernel") * percent, 4577c478bd9Sstevel@tonic-gate kstat_delta(&old_sys, &new_sys, "cpu_ticks_wait") * percent, 4587c478bd9Sstevel@tonic-gate kstat_delta(&old_sys, &new_sys, "cpu_ticks_idle") * percent, 4597c478bd9Sstevel@tonic-gate p2->ps_nr_cpus); 4607c478bd9Sstevel@tonic-gate 4617c478bd9Sstevel@tonic-gate out: 4627c478bd9Sstevel@tonic-gate free(old_vm.ks_data); 4637c478bd9Sstevel@tonic-gate free(old_sys.ks_data); 4647c478bd9Sstevel@tonic-gate free(new_vm.ks_data); 4657c478bd9Sstevel@tonic-gate free(new_sys.ks_data); 4667c478bd9Sstevel@tonic-gate } 4677c478bd9Sstevel@tonic-gate 4687c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 4697c478bd9Sstevel@tonic-gate static void 4707c478bd9Sstevel@tonic-gate compare_pset(void *v1, void *v2, void *data) 4717c478bd9Sstevel@tonic-gate { 4727c478bd9Sstevel@tonic-gate struct pset_snapshot *p1 = (struct pset_snapshot *)v1; 4737c478bd9Sstevel@tonic-gate struct pset_snapshot *p2 = (struct pset_snapshot *)v2; 4747c478bd9Sstevel@tonic-gate 4757c478bd9Sstevel@tonic-gate if (p2 == NULL) 4767c478bd9Sstevel@tonic-gate return; 4777c478bd9Sstevel@tonic-gate 4787c478bd9Sstevel@tonic-gate print_pset(p1, p2); 4797c478bd9Sstevel@tonic-gate } 4807c478bd9Sstevel@tonic-gate 4817c478bd9Sstevel@tonic-gate 4827c478bd9Sstevel@tonic-gate /* 4837c478bd9Sstevel@tonic-gate * Report statistics for a sample interval. 4847c478bd9Sstevel@tonic-gate */ 4857c478bd9Sstevel@tonic-gate static void 4867c478bd9Sstevel@tonic-gate show_cpu_usage(struct snapshot *old, struct snapshot *new, int display_agg) 4877c478bd9Sstevel@tonic-gate { 4887c478bd9Sstevel@tonic-gate static int lines_until_reprint = 0; 4897c478bd9Sstevel@tonic-gate enum snapshot_types type = SNAP_CPUS; 4907c478bd9Sstevel@tonic-gate snapshot_cb cb = compare_cpu; 4917c478bd9Sstevel@tonic-gate 4924944376cSJohn Levon if (timestamp_fmt != NODATE) 493*26fd7700SKrishnendu Sadhukhan - Sun Microsystems print_timestamp(timestamp_fmt); 4944944376cSJohn Levon 4957c478bd9Sstevel@tonic-gate if (lines_until_reprint == 0 || nr_active_cpus(new) > 1) { 4967c478bd9Sstevel@tonic-gate print_header(display_agg, show_set); 4977c478bd9Sstevel@tonic-gate lines_until_reprint = REPRINT; 4987c478bd9Sstevel@tonic-gate } 4997c478bd9Sstevel@tonic-gate 5007c478bd9Sstevel@tonic-gate lines_until_reprint--; 5017c478bd9Sstevel@tonic-gate 5027c478bd9Sstevel@tonic-gate if (display_agg) { 5037c478bd9Sstevel@tonic-gate type = SNAP_PSETS; 5047c478bd9Sstevel@tonic-gate cb = compare_pset; 5057c478bd9Sstevel@tonic-gate } 5067c478bd9Sstevel@tonic-gate 5077c478bd9Sstevel@tonic-gate /* print stats since boot the first time round */ 5087c478bd9Sstevel@tonic-gate (void) snapshot_walk(type, old, new, cb, NULL); 5097c478bd9Sstevel@tonic-gate (void) fflush(stdout); 5107c478bd9Sstevel@tonic-gate } 5117c478bd9Sstevel@tonic-gate 5127c478bd9Sstevel@tonic-gate /* 5137c478bd9Sstevel@tonic-gate * Usage message on error. 5147c478bd9Sstevel@tonic-gate */ 5157c478bd9Sstevel@tonic-gate static void 5167c478bd9Sstevel@tonic-gate usage(void) 5177c478bd9Sstevel@tonic-gate { 5187c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 5194944376cSJohn Levon "Usage: mpstat [-aq] [-p | -P processor_set] [-T d|u] " 5204944376cSJohn Levon "[interval [count]]\n"); 5217c478bd9Sstevel@tonic-gate exit(1); 5227c478bd9Sstevel@tonic-gate } 523