13554f22eSMatt Macy /*- 23554f22eSMatt Macy * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 33554f22eSMatt Macy * 43554f22eSMatt Macy * Copyright (c) 2003-2008, Joseph Koshy 53554f22eSMatt Macy * Copyright (c) 2007 The FreeBSD Foundation 63554f22eSMatt Macy * All rights reserved. 73554f22eSMatt Macy * Copyright (c) 2018, Matthew Macy 83554f22eSMatt Macy * 93554f22eSMatt Macy * Portions of this software were developed by A. Joseph Koshy under 103554f22eSMatt Macy * sponsorship from the FreeBSD Foundation and Google, Inc. 113554f22eSMatt Macy * 123554f22eSMatt Macy * Redistribution and use in source and binary forms, with or without 133554f22eSMatt Macy * modification, are permitted provided that the following conditions 143554f22eSMatt Macy * are met: 153554f22eSMatt Macy * 1. Redistributions of source code must retain the above copyright 163554f22eSMatt Macy * notice, this list of conditions and the following disclaimer. 173554f22eSMatt Macy * 2. Redistributions in binary form must reproduce the above copyright 183554f22eSMatt Macy * notice, this list of conditions and the following disclaimer in the 193554f22eSMatt Macy * documentation and/or other materials provided with the distribution. 203554f22eSMatt Macy * 213554f22eSMatt Macy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 223554f22eSMatt Macy * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 233554f22eSMatt Macy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 243554f22eSMatt Macy * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 253554f22eSMatt Macy * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 263554f22eSMatt Macy * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 273554f22eSMatt Macy * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 283554f22eSMatt Macy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 293554f22eSMatt Macy * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 303554f22eSMatt Macy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 313554f22eSMatt Macy * SUCH DAMAGE. 323554f22eSMatt Macy */ 333554f22eSMatt Macy 343554f22eSMatt Macy #include <sys/cdefs.h> 353554f22eSMatt Macy __FBSDID("$FreeBSD$"); 363554f22eSMatt Macy 373554f22eSMatt Macy #include <sys/param.h> 383554f22eSMatt Macy #include <sys/cpuset.h> 393554f22eSMatt Macy #include <sys/event.h> 403554f22eSMatt Macy #include <sys/queue.h> 413554f22eSMatt Macy #include <sys/socket.h> 423554f22eSMatt Macy #include <sys/stat.h> 433554f22eSMatt Macy #include <sys/sysctl.h> 443554f22eSMatt Macy #include <sys/time.h> 453554f22eSMatt Macy #include <sys/ttycom.h> 463554f22eSMatt Macy #include <sys/user.h> 473554f22eSMatt Macy #include <sys/wait.h> 483554f22eSMatt Macy 493554f22eSMatt Macy #include <assert.h> 503554f22eSMatt Macy #include <curses.h> 513554f22eSMatt Macy #include <err.h> 523554f22eSMatt Macy #include <errno.h> 533554f22eSMatt Macy #include <fcntl.h> 543554f22eSMatt Macy #include <getopt.h> 553554f22eSMatt Macy #include <kvm.h> 563554f22eSMatt Macy #include <libgen.h> 573554f22eSMatt Macy #include <limits.h> 583554f22eSMatt Macy #include <locale.h> 593554f22eSMatt Macy #include <math.h> 603554f22eSMatt Macy #include <pmc.h> 613554f22eSMatt Macy #include <pmclog.h> 623554f22eSMatt Macy #include <regex.h> 633554f22eSMatt Macy #include <signal.h> 643554f22eSMatt Macy #include <stdarg.h> 653554f22eSMatt Macy #include <stdint.h> 663554f22eSMatt Macy #include <stdio.h> 673554f22eSMatt Macy #include <stdlib.h> 683554f22eSMatt Macy #include <string.h> 693554f22eSMatt Macy #include <sysexits.h> 703554f22eSMatt Macy #include <unistd.h> 713554f22eSMatt Macy 723554f22eSMatt Macy #include <libpmcstat.h> 733554f22eSMatt Macy #include "cmd_pmc.h" 743554f22eSMatt Macy 753554f22eSMatt Macy static struct pmcstat_stats pmcstat_stats; /* statistics */ 763554f22eSMatt Macy 773554f22eSMatt Macy static struct pmc_plugins plugins[] = { 783554f22eSMatt Macy { 793554f22eSMatt Macy .pl_name = "none", 803554f22eSMatt Macy }, 813554f22eSMatt Macy { 823554f22eSMatt Macy .pl_name = NULL 833554f22eSMatt Macy } 843554f22eSMatt Macy }; 853554f22eSMatt Macy 863554f22eSMatt Macy int 873554f22eSMatt Macy pmc_util_get_pid(struct pmcstat_args *args) 883554f22eSMatt Macy { 893554f22eSMatt Macy struct pmcstat_target *pt; 903554f22eSMatt Macy 913554f22eSMatt Macy assert(args->pa_flags & FLAG_HAS_COMMANDLINE); 923554f22eSMatt Macy 933554f22eSMatt Macy /* 943554f22eSMatt Macy * If a command line was specified, it would be the very first 953554f22eSMatt Macy * in the list, before any other processes specified by -t. 963554f22eSMatt Macy */ 973554f22eSMatt Macy pt = SLIST_FIRST(&args->pa_targets); 983554f22eSMatt Macy return (pt->pt_pid); 993554f22eSMatt Macy } 1003554f22eSMatt Macy 1013554f22eSMatt Macy void 1023554f22eSMatt Macy pmc_util_kill_process(struct pmcstat_args *args) 1033554f22eSMatt Macy { 1043554f22eSMatt Macy struct pmcstat_target *pt; 1053554f22eSMatt Macy 1063554f22eSMatt Macy assert(args->pa_flags & FLAG_HAS_COMMANDLINE); 1073554f22eSMatt Macy 1083554f22eSMatt Macy /* 1093554f22eSMatt Macy * If a command line was specified, it would be the very first 1103554f22eSMatt Macy * in the list, before any other processes specified by -t. 1113554f22eSMatt Macy */ 1123554f22eSMatt Macy pt = SLIST_FIRST(&args->pa_targets); 1133554f22eSMatt Macy assert(pt != NULL); 1143554f22eSMatt Macy 1153554f22eSMatt Macy if (kill(pt->pt_pid, SIGINT) != 0) 1163554f22eSMatt Macy err(EX_OSERR, "ERROR: cannot signal child process"); 1173554f22eSMatt Macy } 1183554f22eSMatt Macy 1193554f22eSMatt Macy void 1203554f22eSMatt Macy pmc_util_shutdown_logging(struct pmcstat_args *args) 1213554f22eSMatt Macy { 1223554f22eSMatt Macy pmcstat_shutdown_logging(args, plugins, &pmcstat_stats); 1233554f22eSMatt Macy } 1243554f22eSMatt Macy 1253554f22eSMatt Macy void 1263554f22eSMatt Macy pmc_util_cleanup(struct pmcstat_args *args) 1273554f22eSMatt Macy { 1283554f22eSMatt Macy struct pmcstat_ev *ev; 1293554f22eSMatt Macy 1303554f22eSMatt Macy /* release allocated PMCs. */ 1313554f22eSMatt Macy STAILQ_FOREACH(ev, &args->pa_events, ev_next) 1323554f22eSMatt Macy if (ev->ev_pmcid != PMC_ID_INVALID) { 1333554f22eSMatt Macy if (pmc_stop(ev->ev_pmcid) < 0) 1343554f22eSMatt Macy err(EX_OSERR, 1353554f22eSMatt Macy "ERROR: cannot stop pmc 0x%x \"%s\"", 1363554f22eSMatt Macy ev->ev_pmcid, ev->ev_name); 1373554f22eSMatt Macy if (pmc_release(ev->ev_pmcid) < 0) 1383554f22eSMatt Macy err(EX_OSERR, 1393554f22eSMatt Macy "ERROR: cannot release pmc 0x%x \"%s\"", 1403554f22eSMatt Macy ev->ev_pmcid, ev->ev_name); 1413554f22eSMatt Macy } 1423554f22eSMatt Macy /* de-configure the log file if present. */ 1433554f22eSMatt Macy if (args->pa_flags & (FLAG_HAS_PIPE | FLAG_HAS_OUTPUT_LOGFILE)) 1443554f22eSMatt Macy (void)pmc_configure_logfile(-1); 1453554f22eSMatt Macy 1463554f22eSMatt Macy if (args->pa_logparser) { 1473554f22eSMatt Macy pmclog_close(args->pa_logparser); 1483554f22eSMatt Macy args->pa_logparser = NULL; 1493554f22eSMatt Macy } 1503554f22eSMatt Macy pmc_util_shutdown_logging(args); 1513554f22eSMatt Macy } 1523554f22eSMatt Macy 1533554f22eSMatt Macy void 1543554f22eSMatt Macy pmc_util_start_pmcs(struct pmcstat_args *args) 1553554f22eSMatt Macy { 1563554f22eSMatt Macy struct pmcstat_ev *ev; 1573554f22eSMatt Macy 1583554f22eSMatt Macy STAILQ_FOREACH(ev, &args->pa_events, ev_next) { 1593554f22eSMatt Macy 1603554f22eSMatt Macy assert(ev->ev_pmcid != PMC_ID_INVALID); 1613554f22eSMatt Macy 1623554f22eSMatt Macy if (pmc_start(ev->ev_pmcid) < 0) { 1633554f22eSMatt Macy warn("ERROR: Cannot start pmc 0x%x \"%s\"", 1643554f22eSMatt Macy ev->ev_pmcid, ev->ev_name); 1653554f22eSMatt Macy pmc_util_cleanup(args); 1663554f22eSMatt Macy exit(EX_OSERR); 1673554f22eSMatt Macy } 1683554f22eSMatt Macy } 1693554f22eSMatt Macy } 170