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