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 /* 22*00c76d6fStc35445 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #include <sys/pset.h> 297c478bd9Sstevel@tonic-gate #include <sys/types.h> 307c478bd9Sstevel@tonic-gate #include <sys/time.h> 317c478bd9Sstevel@tonic-gate #include <sys/sysinfo.h> 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate #include <assert.h> 347c478bd9Sstevel@tonic-gate #include <stdio.h> 357c478bd9Sstevel@tonic-gate #include <stdlib.h> 367c478bd9Sstevel@tonic-gate #include <stdarg.h> 377c478bd9Sstevel@tonic-gate #include <ctype.h> 387c478bd9Sstevel@tonic-gate #include <unistd.h> 397c478bd9Sstevel@tonic-gate #include <memory.h> 407c478bd9Sstevel@tonic-gate #include <string.h> 417c478bd9Sstevel@tonic-gate #include <strings.h> 427c478bd9Sstevel@tonic-gate #include <fcntl.h> 437c478bd9Sstevel@tonic-gate #include <errno.h> 447c478bd9Sstevel@tonic-gate #include <kstat.h> 457c478bd9Sstevel@tonic-gate #include <poll.h> 46*00c76d6fStc35445 #include <signal.h> 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate #include "statcommon.h" 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate #define SNAP(s, i, l, n) ((s) ? agg_proc_snap(s, i, l, n) : 0) 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate #define REPRINT 20 537c478bd9Sstevel@tonic-gate 54*00c76d6fStc35445 char *cmdname = "mpstat"; 55*00c76d6fStc35445 int caught_cont = 0; 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate static int hz; 587c478bd9Sstevel@tonic-gate static int display_pset = -1; 597c478bd9Sstevel@tonic-gate static int show_set = 0; 607c478bd9Sstevel@tonic-gate static int suppress_state; 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate static void print_header(int, int); 637c478bd9Sstevel@tonic-gate static void show_cpu_usage(struct snapshot *, struct snapshot *, int); 647c478bd9Sstevel@tonic-gate static void usage(void); 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate int 677c478bd9Sstevel@tonic-gate main(int argc, char **argv) 687c478bd9Sstevel@tonic-gate { 697c478bd9Sstevel@tonic-gate int c; 707c478bd9Sstevel@tonic-gate int display_agg = 0; 717c478bd9Sstevel@tonic-gate int iter = 1; 727c478bd9Sstevel@tonic-gate int interval = 0; 737c478bd9Sstevel@tonic-gate char *endptr; 747c478bd9Sstevel@tonic-gate int infinite_cycles = 0; 757c478bd9Sstevel@tonic-gate kstat_ctl_t *kc; 767c478bd9Sstevel@tonic-gate struct snapshot *old = NULL; 777c478bd9Sstevel@tonic-gate struct snapshot *new = NULL; 787c478bd9Sstevel@tonic-gate enum snapshot_types types = SNAP_CPUS; 79*00c76d6fStc35445 hrtime_t start_n; 80*00c76d6fStc35445 hrtime_t period_n; 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "apP:q")) != (int)EOF) 837c478bd9Sstevel@tonic-gate switch (c) { 847c478bd9Sstevel@tonic-gate case 'a': 857c478bd9Sstevel@tonic-gate /* 867c478bd9Sstevel@tonic-gate * Display aggregate data for processor sets. 877c478bd9Sstevel@tonic-gate */ 887c478bd9Sstevel@tonic-gate display_agg = 1; 897c478bd9Sstevel@tonic-gate break; 907c478bd9Sstevel@tonic-gate case 'p': 917c478bd9Sstevel@tonic-gate /* 927c478bd9Sstevel@tonic-gate * Display all processor sets. 937c478bd9Sstevel@tonic-gate */ 947c478bd9Sstevel@tonic-gate if (display_pset != -1) 957c478bd9Sstevel@tonic-gate usage(); 967c478bd9Sstevel@tonic-gate show_set = 1; 977c478bd9Sstevel@tonic-gate break; 987c478bd9Sstevel@tonic-gate case 'P': 997c478bd9Sstevel@tonic-gate /* 1007c478bd9Sstevel@tonic-gate * Display specific processor set. 1017c478bd9Sstevel@tonic-gate */ 1027c478bd9Sstevel@tonic-gate if (show_set == 1) 1037c478bd9Sstevel@tonic-gate usage(); 1047c478bd9Sstevel@tonic-gate display_pset = (int)strtol 1057c478bd9Sstevel@tonic-gate (optarg, &endptr, 10); 1067c478bd9Sstevel@tonic-gate if (*endptr != NULL) 1077c478bd9Sstevel@tonic-gate usage(); 1087c478bd9Sstevel@tonic-gate /* 1097c478bd9Sstevel@tonic-gate * Not valid to specify a negative processor 1107c478bd9Sstevel@tonic-gate * set value. 1117c478bd9Sstevel@tonic-gate */ 1127c478bd9Sstevel@tonic-gate if (display_pset < 0) 1137c478bd9Sstevel@tonic-gate usage(); 1147c478bd9Sstevel@tonic-gate break; 1157c478bd9Sstevel@tonic-gate case 'q': 1167c478bd9Sstevel@tonic-gate suppress_state = 1; 1177c478bd9Sstevel@tonic-gate break; 1187c478bd9Sstevel@tonic-gate case '?': 1197c478bd9Sstevel@tonic-gate usage(); 1207c478bd9Sstevel@tonic-gate break; 1217c478bd9Sstevel@tonic-gate } 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate hz = sysconf(_SC_CLK_TCK); 1247c478bd9Sstevel@tonic-gate 1257c478bd9Sstevel@tonic-gate if (argc > optind) { 1267c478bd9Sstevel@tonic-gate interval = (int)strtol(argv[optind], &endptr, 10); 1277c478bd9Sstevel@tonic-gate if (*endptr != NULL) 1287c478bd9Sstevel@tonic-gate usage(); 129*00c76d6fStc35445 period_n = (hrtime_t)interval * NANOSEC; 1307c478bd9Sstevel@tonic-gate if (argc > optind + 1) { 1317c478bd9Sstevel@tonic-gate iter = (unsigned int)strtoul 1327c478bd9Sstevel@tonic-gate (argv[optind + 1], &endptr, 10); 1337c478bd9Sstevel@tonic-gate if (*endptr != NULL || iter < 0) 1347c478bd9Sstevel@tonic-gate usage(); 1357c478bd9Sstevel@tonic-gate if (iter == 0) 1367c478bd9Sstevel@tonic-gate return (0); 1377c478bd9Sstevel@tonic-gate } else { 1387c478bd9Sstevel@tonic-gate infinite_cycles = 1; 1397c478bd9Sstevel@tonic-gate } 1407c478bd9Sstevel@tonic-gate } 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate if (display_agg || show_set || display_pset != -1) 1437c478bd9Sstevel@tonic-gate types |= SNAP_PSETS; 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate kc = open_kstat(); 1467c478bd9Sstevel@tonic-gate 147*00c76d6fStc35445 /* Set up handler for SIGCONT */ 148*00c76d6fStc35445 if (signal(SIGCONT, cont_handler) == SIG_ERR) 149*00c76d6fStc35445 fail(1, "signal failed"); 150*00c76d6fStc35445 151*00c76d6fStc35445 start_n = gethrtime(); 152*00c76d6fStc35445 1537c478bd9Sstevel@tonic-gate while (infinite_cycles || iter > 0) { 1547c478bd9Sstevel@tonic-gate free_snapshot(old); 1557c478bd9Sstevel@tonic-gate old = new; 1567c478bd9Sstevel@tonic-gate new = acquire_snapshot(kc, types, NULL); 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate if (!suppress_state) 1597c478bd9Sstevel@tonic-gate snapshot_report_changes(old, new); 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate /* if config changed, show stats from boot */ 1627c478bd9Sstevel@tonic-gate if (snapshot_has_changed(old, new)) { 1637c478bd9Sstevel@tonic-gate free_snapshot(old); 1647c478bd9Sstevel@tonic-gate old = NULL; 1657c478bd9Sstevel@tonic-gate } 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate show_cpu_usage(old, new, display_agg); 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate if (!infinite_cycles && --iter < 1) 1707c478bd9Sstevel@tonic-gate break; 1717c478bd9Sstevel@tonic-gate 172*00c76d6fStc35445 /* Have a kip */ 173*00c76d6fStc35445 sleep_until(&start_n, period_n, infinite_cycles, &caught_cont); 1747c478bd9Sstevel@tonic-gate } 175a08731ecScth (void) kstat_close(kc); 176a08731ecScth 1777c478bd9Sstevel@tonic-gate return (0); 1787c478bd9Sstevel@tonic-gate } 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate /* 1817c478bd9Sstevel@tonic-gate * Print an mpstat output header. 1827c478bd9Sstevel@tonic-gate */ 1837c478bd9Sstevel@tonic-gate static void 1847c478bd9Sstevel@tonic-gate print_header(int display_agg, int show_set) 1857c478bd9Sstevel@tonic-gate { 1867c478bd9Sstevel@tonic-gate if (display_agg == 1) 1877c478bd9Sstevel@tonic-gate (void) printf("SET minf mjf xcal intr ithr csw icsw migr " 1887c478bd9Sstevel@tonic-gate "smtx srw syscl usr sys wt idl sze"); 1897c478bd9Sstevel@tonic-gate else { 1907c478bd9Sstevel@tonic-gate (void) printf("CPU minf mjf xcal intr ithr csw icsw migr " 1917c478bd9Sstevel@tonic-gate "smtx srw syscl usr sys wt idl"); 1927c478bd9Sstevel@tonic-gate if (show_set == 1) 1937c478bd9Sstevel@tonic-gate (void) printf(" set"); 1947c478bd9Sstevel@tonic-gate } 1957c478bd9Sstevel@tonic-gate (void) printf("\n"); 1967c478bd9Sstevel@tonic-gate } 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate static void 1997c478bd9Sstevel@tonic-gate print_cpu(struct cpu_snapshot *c1, struct cpu_snapshot *c2) 2007c478bd9Sstevel@tonic-gate { 2017c478bd9Sstevel@tonic-gate uint64_t ticks = 0; 2027c478bd9Sstevel@tonic-gate double etime, percent; 2037c478bd9Sstevel@tonic-gate kstat_t *old_vm = NULL; 2047c478bd9Sstevel@tonic-gate kstat_t *old_sys = NULL; 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate if (display_pset != -1 && display_pset != c2->cs_pset_id) 2077c478bd9Sstevel@tonic-gate return; 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate /* 2107c478bd9Sstevel@tonic-gate * the first mpstat output will have c1 = NULL, to give 2117c478bd9Sstevel@tonic-gate * results since boot 2127c478bd9Sstevel@tonic-gate */ 2137c478bd9Sstevel@tonic-gate if (c1) { 2147c478bd9Sstevel@tonic-gate old_vm = &c1->cs_vm; 2157c478bd9Sstevel@tonic-gate old_sys = &c1->cs_sys; 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate /* check there are stats to report */ 2187c478bd9Sstevel@tonic-gate if (!CPU_ACTIVE(c1)) 2197c478bd9Sstevel@tonic-gate return; 2207c478bd9Sstevel@tonic-gate } 2217c478bd9Sstevel@tonic-gate 2227c478bd9Sstevel@tonic-gate /* check there are stats to report */ 2237c478bd9Sstevel@tonic-gate if (!CPU_ACTIVE(c2)) 2247c478bd9Sstevel@tonic-gate return; 2257c478bd9Sstevel@tonic-gate 2267c478bd9Sstevel@tonic-gate ticks = cpu_ticks_delta(old_sys, &c2->cs_sys); 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate etime = (double)ticks / hz; 2297c478bd9Sstevel@tonic-gate if (etime == 0.0) /* Prevent divide by zero errors */ 2307c478bd9Sstevel@tonic-gate etime = 1.0; 2317c478bd9Sstevel@tonic-gate percent = 100.0 / etime / hz; 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate (void) printf("%3d %4.0f %3.0f %4.0f %5.0f %4.0f " 2347c478bd9Sstevel@tonic-gate "%4.0f %4.0f %4.0f %4.0f %4.0f %5.0f %3.0f %3.0f " 2357c478bd9Sstevel@tonic-gate "%3.0f %3.0f", 2367c478bd9Sstevel@tonic-gate c2->cs_id, 2377c478bd9Sstevel@tonic-gate (kstat_delta(old_vm, &c2->cs_vm, "hat_fault") + 2387c478bd9Sstevel@tonic-gate kstat_delta(old_vm, &c2->cs_vm, "as_fault")) / etime, 2397c478bd9Sstevel@tonic-gate kstat_delta(old_vm, &c2->cs_vm, "maj_fault") / etime, 2407c478bd9Sstevel@tonic-gate kstat_delta(old_sys, &c2->cs_sys, "xcalls") / etime, 2417c478bd9Sstevel@tonic-gate kstat_delta(old_sys, &c2->cs_sys, "intr") / etime, 2427c478bd9Sstevel@tonic-gate kstat_delta(old_sys, &c2->cs_sys, "intrthread") / etime, 2437c478bd9Sstevel@tonic-gate kstat_delta(old_sys, &c2->cs_sys, "pswitch") / etime, 2447c478bd9Sstevel@tonic-gate kstat_delta(old_sys, &c2->cs_sys, "inv_swtch") / etime, 2457c478bd9Sstevel@tonic-gate kstat_delta(old_sys, &c2->cs_sys, "cpumigrate") / etime, 2467c478bd9Sstevel@tonic-gate kstat_delta(old_sys, &c2->cs_sys, "mutex_adenters") / etime, 2477c478bd9Sstevel@tonic-gate (kstat_delta(old_sys, &c2->cs_sys, "rw_rdfails") + 2487c478bd9Sstevel@tonic-gate kstat_delta(old_sys, &c2->cs_sys, "rw_wrfails")) / etime, 2497c478bd9Sstevel@tonic-gate kstat_delta(old_sys, &c2->cs_sys, "syscall") / etime, 2507c478bd9Sstevel@tonic-gate kstat_delta(old_sys, &c2->cs_sys, "cpu_ticks_user") * percent, 2517c478bd9Sstevel@tonic-gate kstat_delta(old_sys, &c2->cs_sys, "cpu_ticks_kernel") * percent, 2527c478bd9Sstevel@tonic-gate kstat_delta(old_sys, &c2->cs_sys, "cpu_ticks_wait") * percent, 2537c478bd9Sstevel@tonic-gate kstat_delta(old_sys, &c2->cs_sys, "cpu_ticks_idle") * percent); 2547c478bd9Sstevel@tonic-gate 2557c478bd9Sstevel@tonic-gate if (show_set) 2567c478bd9Sstevel@tonic-gate (void) printf(" %3d", c2->cs_pset_id); 2577c478bd9Sstevel@tonic-gate (void) printf("\n"); 2587c478bd9Sstevel@tonic-gate } 2597c478bd9Sstevel@tonic-gate 2607c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 2617c478bd9Sstevel@tonic-gate static void 2627c478bd9Sstevel@tonic-gate compare_cpu(void *v1, void *v2, void *data) 2637c478bd9Sstevel@tonic-gate { 2647c478bd9Sstevel@tonic-gate struct cpu_snapshot *c1 = (struct cpu_snapshot *)v1; 2657c478bd9Sstevel@tonic-gate struct cpu_snapshot *c2 = (struct cpu_snapshot *)v2; 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate if (c2 == NULL) 2687c478bd9Sstevel@tonic-gate return; 2697c478bd9Sstevel@tonic-gate 2707c478bd9Sstevel@tonic-gate print_cpu(c1, c2); 2717c478bd9Sstevel@tonic-gate } 2727c478bd9Sstevel@tonic-gate 2737c478bd9Sstevel@tonic-gate static int 2747c478bd9Sstevel@tonic-gate pset_has_stats(struct pset_snapshot *p) 2757c478bd9Sstevel@tonic-gate { 2767c478bd9Sstevel@tonic-gate int count = 0; 2777c478bd9Sstevel@tonic-gate size_t i; 2787c478bd9Sstevel@tonic-gate for (i = 0; i < p->ps_nr_cpus; i++) { 2797c478bd9Sstevel@tonic-gate if (CPU_ACTIVE(p->ps_cpus[i])) 2807c478bd9Sstevel@tonic-gate count++; 2817c478bd9Sstevel@tonic-gate } 2827c478bd9Sstevel@tonic-gate return (count); 2837c478bd9Sstevel@tonic-gate } 2847c478bd9Sstevel@tonic-gate 2857c478bd9Sstevel@tonic-gate static void 2867c478bd9Sstevel@tonic-gate agg_stat(kstat_t *k1, kstat_t *k2, char *name) 2877c478bd9Sstevel@tonic-gate { 2887c478bd9Sstevel@tonic-gate kstat_named_t *ksn = kstat_data_lookup(k1, name); 2897c478bd9Sstevel@tonic-gate kstat_named_t *ksn2 = kstat_data_lookup(k2, name); 2907c478bd9Sstevel@tonic-gate ksn->value.ui64 += ksn2->value.ui64; 2917c478bd9Sstevel@tonic-gate } 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate static kstat_t * 2947c478bd9Sstevel@tonic-gate agg_vm(struct pset_snapshot *p, kstat_t *ks) 2957c478bd9Sstevel@tonic-gate { 2967c478bd9Sstevel@tonic-gate size_t i; 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate if (p->ps_nr_cpus == NULL) 2997c478bd9Sstevel@tonic-gate return (NULL); 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate if (kstat_copy(&p->ps_cpus[0]->cs_vm, ks)) 3027c478bd9Sstevel@tonic-gate return (NULL); 3037c478bd9Sstevel@tonic-gate 3047c478bd9Sstevel@tonic-gate for (i = 1; i < p->ps_nr_cpus; i++) { 3057c478bd9Sstevel@tonic-gate agg_stat(ks, &p->ps_cpus[i]->cs_vm, "hat_fault"); 3067c478bd9Sstevel@tonic-gate agg_stat(ks, &p->ps_cpus[i]->cs_vm, "as_fault"); 3077c478bd9Sstevel@tonic-gate agg_stat(ks, &p->ps_cpus[i]->cs_vm, "maj_fault"); 3087c478bd9Sstevel@tonic-gate } 3097c478bd9Sstevel@tonic-gate 3107c478bd9Sstevel@tonic-gate return (ks); 3117c478bd9Sstevel@tonic-gate } 3127c478bd9Sstevel@tonic-gate 3137c478bd9Sstevel@tonic-gate static kstat_t * 3147c478bd9Sstevel@tonic-gate agg_sys(struct pset_snapshot *p, kstat_t *ks) 3157c478bd9Sstevel@tonic-gate { 3167c478bd9Sstevel@tonic-gate size_t i; 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate if (p->ps_nr_cpus == NULL) 3197c478bd9Sstevel@tonic-gate return (NULL); 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate if (kstat_copy(&p->ps_cpus[0]->cs_sys, ks)) 3227c478bd9Sstevel@tonic-gate return (NULL); 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate for (i = 1; i < p->ps_nr_cpus; i++) { 3257c478bd9Sstevel@tonic-gate agg_stat(ks, &p->ps_cpus[i]->cs_sys, "xcalls"); 3267c478bd9Sstevel@tonic-gate agg_stat(ks, &p->ps_cpus[i]->cs_sys, "intr"); 3277c478bd9Sstevel@tonic-gate agg_stat(ks, &p->ps_cpus[i]->cs_sys, "intrthread"); 3287c478bd9Sstevel@tonic-gate agg_stat(ks, &p->ps_cpus[i]->cs_sys, "pswitch"); 3297c478bd9Sstevel@tonic-gate agg_stat(ks, &p->ps_cpus[i]->cs_sys, "inv_swtch"); 3307c478bd9Sstevel@tonic-gate agg_stat(ks, &p->ps_cpus[i]->cs_sys, "cpumigrate"); 3317c478bd9Sstevel@tonic-gate agg_stat(ks, &p->ps_cpus[i]->cs_sys, "mutex_adenters"); 3327c478bd9Sstevel@tonic-gate agg_stat(ks, &p->ps_cpus[i]->cs_sys, "rw_rdfails"); 3337c478bd9Sstevel@tonic-gate agg_stat(ks, &p->ps_cpus[i]->cs_sys, "rw_wrfails"); 3347c478bd9Sstevel@tonic-gate agg_stat(ks, &p->ps_cpus[i]->cs_sys, "syscall"); 3357c478bd9Sstevel@tonic-gate agg_stat(ks, &p->ps_cpus[i]->cs_sys, "cpu_ticks_user"); 3367c478bd9Sstevel@tonic-gate agg_stat(ks, &p->ps_cpus[i]->cs_sys, "cpu_ticks_kernel"); 3377c478bd9Sstevel@tonic-gate agg_stat(ks, &p->ps_cpus[i]->cs_sys, "cpu_ticks_wait"); 3387c478bd9Sstevel@tonic-gate agg_stat(ks, &p->ps_cpus[i]->cs_sys, "cpu_ticks_idle"); 3397c478bd9Sstevel@tonic-gate } 3407c478bd9Sstevel@tonic-gate 3417c478bd9Sstevel@tonic-gate return (ks); 3427c478bd9Sstevel@tonic-gate } 3437c478bd9Sstevel@tonic-gate 3447c478bd9Sstevel@tonic-gate static uint64_t 3457c478bd9Sstevel@tonic-gate get_nr_ticks(struct pset_snapshot *p1, struct pset_snapshot *p2) 3467c478bd9Sstevel@tonic-gate { 3477c478bd9Sstevel@tonic-gate kstat_t *old = NULL; 3487c478bd9Sstevel@tonic-gate kstat_t *new = NULL; 3497c478bd9Sstevel@tonic-gate size_t i = 0; 3507c478bd9Sstevel@tonic-gate 3517c478bd9Sstevel@tonic-gate for (i = 0; p1 && i < p1->ps_nr_cpus; i++) { 3527c478bd9Sstevel@tonic-gate if (p1->ps_cpus[i]->cs_sys.ks_data) { 3537c478bd9Sstevel@tonic-gate old = &p1->ps_cpus[i]->cs_sys; 3547c478bd9Sstevel@tonic-gate break; 3557c478bd9Sstevel@tonic-gate } 3567c478bd9Sstevel@tonic-gate } 3577c478bd9Sstevel@tonic-gate 3587c478bd9Sstevel@tonic-gate for (i = 0; p2 && i < p2->ps_nr_cpus; i++) { 3597c478bd9Sstevel@tonic-gate if (p2->ps_cpus[i]->cs_sys.ks_data) { 3607c478bd9Sstevel@tonic-gate new = &p2->ps_cpus[i]->cs_sys; 3617c478bd9Sstevel@tonic-gate break; 3627c478bd9Sstevel@tonic-gate } 3637c478bd9Sstevel@tonic-gate } 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate if (old == NULL && new == NULL) 3667c478bd9Sstevel@tonic-gate return (0); 3677c478bd9Sstevel@tonic-gate 3687c478bd9Sstevel@tonic-gate if (new == NULL) { 3697c478bd9Sstevel@tonic-gate new = old; 3707c478bd9Sstevel@tonic-gate old = NULL; 3717c478bd9Sstevel@tonic-gate } 3727c478bd9Sstevel@tonic-gate 3737c478bd9Sstevel@tonic-gate return (cpu_ticks_delta(old, new)); 3747c478bd9Sstevel@tonic-gate } 3757c478bd9Sstevel@tonic-gate 3767c478bd9Sstevel@tonic-gate static void 3777c478bd9Sstevel@tonic-gate print_pset(struct pset_snapshot *p1, struct pset_snapshot *p2) 3787c478bd9Sstevel@tonic-gate { 3797c478bd9Sstevel@tonic-gate uint64_t ticks = 0; 3807c478bd9Sstevel@tonic-gate double etime, percent; 3817c478bd9Sstevel@tonic-gate kstat_t old_vm; 3827c478bd9Sstevel@tonic-gate kstat_t old_sys; 3837c478bd9Sstevel@tonic-gate kstat_t new_vm; 3847c478bd9Sstevel@tonic-gate kstat_t new_sys; 3857c478bd9Sstevel@tonic-gate 3867c478bd9Sstevel@tonic-gate if (display_pset != -1 && display_pset != p2->ps_id) 3877c478bd9Sstevel@tonic-gate return; 3887c478bd9Sstevel@tonic-gate 3897c478bd9Sstevel@tonic-gate if ((p1 && !pset_has_stats(p1)) || !pset_has_stats(p2)) 3907c478bd9Sstevel@tonic-gate return; 3917c478bd9Sstevel@tonic-gate 3927c478bd9Sstevel@tonic-gate old_vm.ks_data = old_sys.ks_data = NULL; 3937c478bd9Sstevel@tonic-gate new_vm.ks_data = new_sys.ks_data = NULL; 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate /* 3967c478bd9Sstevel@tonic-gate * FIXME: these aggs will count "new" or disappeared cpus 3977c478bd9Sstevel@tonic-gate * in a set, leaving an apparent huge change. 3987c478bd9Sstevel@tonic-gate */ 3997c478bd9Sstevel@tonic-gate 4007c478bd9Sstevel@tonic-gate /* 4017c478bd9Sstevel@tonic-gate * the first mpstat output will have p1 = NULL, to give 4027c478bd9Sstevel@tonic-gate * results since boot 4037c478bd9Sstevel@tonic-gate */ 4047c478bd9Sstevel@tonic-gate if (p1) { 4057c478bd9Sstevel@tonic-gate if (!agg_vm(p1, &old_vm) || !agg_sys(p1, &old_sys)) 4067c478bd9Sstevel@tonic-gate goto out; 4077c478bd9Sstevel@tonic-gate } 4087c478bd9Sstevel@tonic-gate 4097c478bd9Sstevel@tonic-gate if (!agg_vm(p2, &new_vm) || !agg_sys(p2, &new_sys)) 4107c478bd9Sstevel@tonic-gate goto out; 4117c478bd9Sstevel@tonic-gate 4127c478bd9Sstevel@tonic-gate ticks = get_nr_ticks(p1, p2); 4137c478bd9Sstevel@tonic-gate 4147c478bd9Sstevel@tonic-gate etime = (double)ticks / hz; 4157c478bd9Sstevel@tonic-gate if (etime == 0.0) /* Prevent divide by zero errors */ 4167c478bd9Sstevel@tonic-gate etime = 1.0; 4177c478bd9Sstevel@tonic-gate percent = 100.0 / p2->ps_nr_cpus / etime / hz; 4187c478bd9Sstevel@tonic-gate 4197c478bd9Sstevel@tonic-gate (void) printf("%3d %4.0f %3.0f %4.0f %5.0f %4.0f " 4207c478bd9Sstevel@tonic-gate "%4.0f %4.0f %4.0f %4.0f %4.0f %5.0f %3.0f %3.0f " 4217c478bd9Sstevel@tonic-gate "%3.0f %3.0f %3d\n", 4227c478bd9Sstevel@tonic-gate p2->ps_id, 4237c478bd9Sstevel@tonic-gate (kstat_delta(&old_vm, &new_vm, "hat_fault") + 4247c478bd9Sstevel@tonic-gate kstat_delta(&old_vm, &new_vm, "as_fault")) / etime, 4257c478bd9Sstevel@tonic-gate kstat_delta(&old_vm, &new_vm, "maj_fault") / etime, 4267c478bd9Sstevel@tonic-gate kstat_delta(&old_sys, &new_sys, "xcalls") / etime, 4277c478bd9Sstevel@tonic-gate kstat_delta(&old_sys, &new_sys, "intr") / etime, 4287c478bd9Sstevel@tonic-gate kstat_delta(&old_sys, &new_sys, "intrthread") / etime, 4297c478bd9Sstevel@tonic-gate kstat_delta(&old_sys, &new_sys, "pswitch") / etime, 4307c478bd9Sstevel@tonic-gate kstat_delta(&old_sys, &new_sys, "inv_swtch") / etime, 4317c478bd9Sstevel@tonic-gate kstat_delta(&old_sys, &new_sys, "cpumigrate") / etime, 4327c478bd9Sstevel@tonic-gate kstat_delta(&old_sys, &new_sys, "mutex_adenters") / etime, 4337c478bd9Sstevel@tonic-gate (kstat_delta(&old_sys, &new_sys, "rw_rdfails") + 4347c478bd9Sstevel@tonic-gate kstat_delta(&old_sys, &new_sys, "rw_wrfails")) / etime, 4357c478bd9Sstevel@tonic-gate kstat_delta(&old_sys, &new_sys, "syscall") / etime, 4367c478bd9Sstevel@tonic-gate kstat_delta(&old_sys, &new_sys, "cpu_ticks_user") * percent, 4377c478bd9Sstevel@tonic-gate kstat_delta(&old_sys, &new_sys, "cpu_ticks_kernel") * percent, 4387c478bd9Sstevel@tonic-gate kstat_delta(&old_sys, &new_sys, "cpu_ticks_wait") * percent, 4397c478bd9Sstevel@tonic-gate kstat_delta(&old_sys, &new_sys, "cpu_ticks_idle") * percent, 4407c478bd9Sstevel@tonic-gate p2->ps_nr_cpus); 4417c478bd9Sstevel@tonic-gate 4427c478bd9Sstevel@tonic-gate out: 4437c478bd9Sstevel@tonic-gate free(old_vm.ks_data); 4447c478bd9Sstevel@tonic-gate free(old_sys.ks_data); 4457c478bd9Sstevel@tonic-gate free(new_vm.ks_data); 4467c478bd9Sstevel@tonic-gate free(new_sys.ks_data); 4477c478bd9Sstevel@tonic-gate } 4487c478bd9Sstevel@tonic-gate 4497c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 4507c478bd9Sstevel@tonic-gate static void 4517c478bd9Sstevel@tonic-gate compare_pset(void *v1, void *v2, void *data) 4527c478bd9Sstevel@tonic-gate { 4537c478bd9Sstevel@tonic-gate struct pset_snapshot *p1 = (struct pset_snapshot *)v1; 4547c478bd9Sstevel@tonic-gate struct pset_snapshot *p2 = (struct pset_snapshot *)v2; 4557c478bd9Sstevel@tonic-gate 4567c478bd9Sstevel@tonic-gate if (p2 == NULL) 4577c478bd9Sstevel@tonic-gate return; 4587c478bd9Sstevel@tonic-gate 4597c478bd9Sstevel@tonic-gate print_pset(p1, p2); 4607c478bd9Sstevel@tonic-gate } 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate 4637c478bd9Sstevel@tonic-gate /* 4647c478bd9Sstevel@tonic-gate * Report statistics for a sample interval. 4657c478bd9Sstevel@tonic-gate */ 4667c478bd9Sstevel@tonic-gate static void 4677c478bd9Sstevel@tonic-gate show_cpu_usage(struct snapshot *old, struct snapshot *new, int display_agg) 4687c478bd9Sstevel@tonic-gate { 4697c478bd9Sstevel@tonic-gate static int lines_until_reprint = 0; 4707c478bd9Sstevel@tonic-gate enum snapshot_types type = SNAP_CPUS; 4717c478bd9Sstevel@tonic-gate snapshot_cb cb = compare_cpu; 4727c478bd9Sstevel@tonic-gate 4737c478bd9Sstevel@tonic-gate if (lines_until_reprint == 0 || nr_active_cpus(new) > 1) { 4747c478bd9Sstevel@tonic-gate print_header(display_agg, show_set); 4757c478bd9Sstevel@tonic-gate lines_until_reprint = REPRINT; 4767c478bd9Sstevel@tonic-gate } 4777c478bd9Sstevel@tonic-gate 4787c478bd9Sstevel@tonic-gate lines_until_reprint--; 4797c478bd9Sstevel@tonic-gate 4807c478bd9Sstevel@tonic-gate if (display_agg) { 4817c478bd9Sstevel@tonic-gate type = SNAP_PSETS; 4827c478bd9Sstevel@tonic-gate cb = compare_pset; 4837c478bd9Sstevel@tonic-gate } 4847c478bd9Sstevel@tonic-gate 4857c478bd9Sstevel@tonic-gate /* print stats since boot the first time round */ 4867c478bd9Sstevel@tonic-gate (void) snapshot_walk(type, old, new, cb, NULL); 4877c478bd9Sstevel@tonic-gate (void) fflush(stdout); 4887c478bd9Sstevel@tonic-gate } 4897c478bd9Sstevel@tonic-gate 4907c478bd9Sstevel@tonic-gate /* 4917c478bd9Sstevel@tonic-gate * Usage message on error. 4927c478bd9Sstevel@tonic-gate */ 4937c478bd9Sstevel@tonic-gate static void 4947c478bd9Sstevel@tonic-gate usage(void) 4957c478bd9Sstevel@tonic-gate { 4967c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 4977c478bd9Sstevel@tonic-gate "Usage: mpstat [-aq] [-p | -P processor_set] [interval [count]]\n"); 4987c478bd9Sstevel@tonic-gate exit(1); 4997c478bd9Sstevel@tonic-gate } 500