1ebccf1e3SJoseph Koshy /*- 21de7b4b8SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 31de7b4b8SPedro F. Giffuni * 4ebccf1e3SJoseph Koshy * Copyright (c) 2003,2004 Joseph Koshy 5ebccf1e3SJoseph Koshy * All rights reserved. 6ebccf1e3SJoseph Koshy * 7ebccf1e3SJoseph Koshy * Redistribution and use in source and binary forms, with or without 8ebccf1e3SJoseph Koshy * modification, are permitted provided that the following conditions 9ebccf1e3SJoseph Koshy * are met: 10ebccf1e3SJoseph Koshy * 1. Redistributions of source code must retain the above copyright 11ebccf1e3SJoseph Koshy * notice, this list of conditions and the following disclaimer. 12ebccf1e3SJoseph Koshy * 2. Redistributions in binary form must reproduce the above copyright 13ebccf1e3SJoseph Koshy * notice, this list of conditions and the following disclaimer in the 14ebccf1e3SJoseph Koshy * documentation and/or other materials provided with the distribution. 15ebccf1e3SJoseph Koshy * 16ebccf1e3SJoseph Koshy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17ebccf1e3SJoseph Koshy * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18ebccf1e3SJoseph Koshy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19ebccf1e3SJoseph Koshy * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20ebccf1e3SJoseph Koshy * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21ebccf1e3SJoseph Koshy * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22ebccf1e3SJoseph Koshy * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23ebccf1e3SJoseph Koshy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24ebccf1e3SJoseph Koshy * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25ebccf1e3SJoseph Koshy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26ebccf1e3SJoseph Koshy * SUCH DAMAGE. 27ebccf1e3SJoseph Koshy * 28ebccf1e3SJoseph Koshy */ 29ebccf1e3SJoseph Koshy 30ebccf1e3SJoseph Koshy #include <sys/cdefs.h> 31ebccf1e3SJoseph Koshy __FBSDID("$FreeBSD$"); 32ebccf1e3SJoseph Koshy 332953224eSAttilio Rao #include <sys/param.h> 34ebccf1e3SJoseph Koshy #include <sys/queue.h> 35095489dbSAttilio Rao #include <sys/cpuset.h> 36ebccf1e3SJoseph Koshy #include <sys/sysctl.h> 37ebccf1e3SJoseph Koshy 38ebccf1e3SJoseph Koshy #include <assert.h> 39ebccf1e3SJoseph Koshy #include <err.h> 40ebccf1e3SJoseph Koshy #include <errno.h> 41ebccf1e3SJoseph Koshy #include <fcntl.h> 42ebccf1e3SJoseph Koshy #include <limits.h> 43ebccf1e3SJoseph Koshy #include <pmc.h> 44ebccf1e3SJoseph Koshy #include <stdarg.h> 45ebccf1e3SJoseph Koshy #include <stdio.h> 46ebccf1e3SJoseph Koshy #include <stdlib.h> 47ebccf1e3SJoseph Koshy #include <string.h> 48ebccf1e3SJoseph Koshy #include <sysexits.h> 49ebccf1e3SJoseph Koshy #include <unistd.h> 50ebccf1e3SJoseph Koshy 51ebccf1e3SJoseph Koshy /* Compile time defaults */ 52ebccf1e3SJoseph Koshy 53ebccf1e3SJoseph Koshy #define PMCC_PRINT_USAGE 0 54ebccf1e3SJoseph Koshy #define PMCC_PRINT_EVENTS 1 55ebccf1e3SJoseph Koshy #define PMCC_LIST_STATE 2 56ebccf1e3SJoseph Koshy #define PMCC_ENABLE_DISABLE 3 57ebccf1e3SJoseph Koshy #define PMCC_SHOW_STATISTICS 4 58ebccf1e3SJoseph Koshy 59ebccf1e3SJoseph Koshy #define PMCC_CPU_ALL -1 60ebccf1e3SJoseph Koshy #define PMCC_CPU_WILDCARD '*' 61ebccf1e3SJoseph Koshy 62ebccf1e3SJoseph Koshy #define PMCC_PMC_ALL -1 63ebccf1e3SJoseph Koshy #define PMCC_PMC_WILDCARD '*' 64ebccf1e3SJoseph Koshy 65ebccf1e3SJoseph Koshy #define PMCC_OP_IGNORE 0 66ebccf1e3SJoseph Koshy #define PMCC_OP_DISABLE 1 67ebccf1e3SJoseph Koshy #define PMCC_OP_ENABLE 2 68ebccf1e3SJoseph Koshy 69ebccf1e3SJoseph Koshy #define PMCC_PROGRAM_NAME "pmccontrol" 70ebccf1e3SJoseph Koshy 71bf70beceSEd Schouten static STAILQ_HEAD(pmcc_op_list, pmcc_op) head = STAILQ_HEAD_INITIALIZER(head); 72ebccf1e3SJoseph Koshy 73ebccf1e3SJoseph Koshy struct pmcc_op { 74ebccf1e3SJoseph Koshy char op_cpu; 75ebccf1e3SJoseph Koshy char op_pmc; 76ebccf1e3SJoseph Koshy char op_op; 77ebccf1e3SJoseph Koshy STAILQ_ENTRY(pmcc_op) op_next; 78ebccf1e3SJoseph Koshy }; 79ebccf1e3SJoseph Koshy 80ebccf1e3SJoseph Koshy /* Function Prototypes */ 81ebccf1e3SJoseph Koshy #if DEBUG 82ebccf1e3SJoseph Koshy static void pmcc_init_debug(void); 83ebccf1e3SJoseph Koshy #endif 84ebccf1e3SJoseph Koshy 85ebccf1e3SJoseph Koshy static int pmcc_do_list_state(void); 86ebccf1e3SJoseph Koshy static int pmcc_do_enable_disable(struct pmcc_op_list *); 87ebccf1e3SJoseph Koshy static int pmcc_do_list_events(void); 88ebccf1e3SJoseph Koshy 89ebccf1e3SJoseph Koshy /* Globals */ 90ebccf1e3SJoseph Koshy 91ebccf1e3SJoseph Koshy static char usage_message[] = 92ebccf1e3SJoseph Koshy "Usage:\n" 939798d180SJoseph Koshy " " PMCC_PROGRAM_NAME " -L\n" 94ebccf1e3SJoseph Koshy " " PMCC_PROGRAM_NAME " -l\n" 95ebccf1e3SJoseph Koshy " " PMCC_PROGRAM_NAME " -s\n" 96ebccf1e3SJoseph Koshy " " PMCC_PROGRAM_NAME " [-e pmc | -d pmc | -c cpu] ..."; 97ebccf1e3SJoseph Koshy 98ebccf1e3SJoseph Koshy #if DEBUG 99bf70beceSEd Schouten static FILE *debug_stream = NULL; 100ebccf1e3SJoseph Koshy #endif 101ebccf1e3SJoseph Koshy 102ebccf1e3SJoseph Koshy #if DEBUG 103ebccf1e3SJoseph Koshy #define DEBUG_MSG(...) \ 104*94dcc95fSElyes Haouas (void) fprintf(debug_stream, "[pmccontrol] " __VA_ARGS__) 105ebccf1e3SJoseph Koshy #else 106ebccf1e3SJoseph Koshy #define DEBUG_MSG(m) /* */ 107ebccf1e3SJoseph Koshy #endif /* !DEBUG */ 108ebccf1e3SJoseph Koshy 109ebccf1e3SJoseph Koshy #if DEBUG 110ebccf1e3SJoseph Koshy /* log debug messages to a separate file */ 111ebccf1e3SJoseph Koshy static void 112ebccf1e3SJoseph Koshy pmcc_init_debug(void) 113ebccf1e3SJoseph Koshy { 114ebccf1e3SJoseph Koshy char *fn; 115ebccf1e3SJoseph Koshy 116ebccf1e3SJoseph Koshy fn = getenv("PMCCONTROL_DEBUG"); 117ebccf1e3SJoseph Koshy if (fn != NULL) 118ebccf1e3SJoseph Koshy { 119ebccf1e3SJoseph Koshy debug_stream = fopen(fn, "w"); 120ebccf1e3SJoseph Koshy if (debug_stream == NULL) 121ebccf1e3SJoseph Koshy debug_stream = stderr; 122ebccf1e3SJoseph Koshy } else 123ebccf1e3SJoseph Koshy debug_stream = stderr; 124ebccf1e3SJoseph Koshy } 125ebccf1e3SJoseph Koshy #endif 126ebccf1e3SJoseph Koshy 127ebccf1e3SJoseph Koshy static int 128ebccf1e3SJoseph Koshy pmcc_do_enable_disable(struct pmcc_op_list *op_list) 129ebccf1e3SJoseph Koshy { 130ebccf1e3SJoseph Koshy int c, error, i, j, ncpu, npmc, t; 131ebccf1e3SJoseph Koshy struct pmcc_op *np; 132ebccf1e3SJoseph Koshy unsigned char *map; 13335cf650fSJoseph Koshy unsigned char op; 13435cf650fSJoseph Koshy int cpu, pmc; 135ebccf1e3SJoseph Koshy 136ebccf1e3SJoseph Koshy if ((ncpu = pmc_ncpu()) < 0) 137ebccf1e3SJoseph Koshy err(EX_OSERR, "Unable to determine the number of cpus"); 138ebccf1e3SJoseph Koshy 13935cf650fSJoseph Koshy /* Determine the maximum number of PMCs in any CPU. */ 140ebccf1e3SJoseph Koshy npmc = 0; 141ebccf1e3SJoseph Koshy for (c = 0; c < ncpu; c++) { 142ebccf1e3SJoseph Koshy if ((t = pmc_npmc(c)) < 0) 14337d6f8a9SDavid E. O'Brien err(EX_OSERR, 14437d6f8a9SDavid E. O'Brien "Unable to determine the number of PMCs in CPU %d", 14537d6f8a9SDavid E. O'Brien c); 146a301ee66SMarcelo Araujo npmc = MAX(t, npmc); 147ebccf1e3SJoseph Koshy } 148ebccf1e3SJoseph Koshy 149ebccf1e3SJoseph Koshy if (npmc == 0) 150ebccf1e3SJoseph Koshy errx(EX_CONFIG, "No PMCs found"); 151ebccf1e3SJoseph Koshy 15262debcc7SPedro F. Giffuni if ((map = calloc(npmc, ncpu)) == NULL) 153ebccf1e3SJoseph Koshy err(EX_SOFTWARE, "Out of memory"); 154ebccf1e3SJoseph Koshy 155ebccf1e3SJoseph Koshy error = 0; 156ebccf1e3SJoseph Koshy STAILQ_FOREACH(np, op_list, op_next) { 157ebccf1e3SJoseph Koshy 158ebccf1e3SJoseph Koshy cpu = np->op_cpu; 159ebccf1e3SJoseph Koshy pmc = np->op_pmc; 160ebccf1e3SJoseph Koshy op = np->op_op; 161ebccf1e3SJoseph Koshy 162ebccf1e3SJoseph Koshy if (cpu >= ncpu) 163ebccf1e3SJoseph Koshy errx(EX_DATAERR, "CPU id too large: \"%d\"", cpu); 164ebccf1e3SJoseph Koshy 165ebccf1e3SJoseph Koshy if (pmc >= npmc) 166ebccf1e3SJoseph Koshy errx(EX_DATAERR, "PMC id too large: \"%d\"", pmc); 167ebccf1e3SJoseph Koshy 168ebccf1e3SJoseph Koshy #define MARKMAP(M,C,P,V) do { \ 169ebccf1e3SJoseph Koshy *((M) + (C)*npmc + (P)) = (V); \ 170ebccf1e3SJoseph Koshy } while (0) 171ebccf1e3SJoseph Koshy 172ebccf1e3SJoseph Koshy #define SET_PMCS(C,P,V) do { \ 173ebccf1e3SJoseph Koshy if ((P) == PMCC_PMC_ALL) { \ 174ebccf1e3SJoseph Koshy for (j = 0; j < npmc; j++) \ 175ebccf1e3SJoseph Koshy MARKMAP(map, (C), j, (V)); \ 176ebccf1e3SJoseph Koshy } else \ 177ebccf1e3SJoseph Koshy MARKMAP(map, (C), (P), (V)); \ 178ebccf1e3SJoseph Koshy } while (0) 179ebccf1e3SJoseph Koshy 180ebccf1e3SJoseph Koshy #define MAP(M,C,P) (*((M) + (C)*npmc + (P))) 181ebccf1e3SJoseph Koshy 182ebccf1e3SJoseph Koshy if (cpu == PMCC_CPU_ALL) 18335cf650fSJoseph Koshy for (i = 0; i < ncpu; i++) { 184ebccf1e3SJoseph Koshy SET_PMCS(i, pmc, op); 18535cf650fSJoseph Koshy } 186ebccf1e3SJoseph Koshy else 187ebccf1e3SJoseph Koshy SET_PMCS(cpu, pmc, op); 188ebccf1e3SJoseph Koshy } 189ebccf1e3SJoseph Koshy 190ebccf1e3SJoseph Koshy /* Configure PMCS */ 191ebccf1e3SJoseph Koshy for (i = 0; i < ncpu; i++) 192ebccf1e3SJoseph Koshy for (j = 0; j < npmc; j++) { 193ebccf1e3SJoseph Koshy unsigned char b; 194ebccf1e3SJoseph Koshy 195ebccf1e3SJoseph Koshy b = MAP(map, i, j); 196ebccf1e3SJoseph Koshy 197ebccf1e3SJoseph Koshy error = 0; 198ebccf1e3SJoseph Koshy 199ebccf1e3SJoseph Koshy if (b == PMCC_OP_ENABLE) 200ebccf1e3SJoseph Koshy error = pmc_enable(i, j); 201ebccf1e3SJoseph Koshy else if (b == PMCC_OP_DISABLE) 202ebccf1e3SJoseph Koshy error = pmc_disable(i, j); 203ebccf1e3SJoseph Koshy 204ebccf1e3SJoseph Koshy if (error < 0) 205ebccf1e3SJoseph Koshy err(EX_OSERR, "%s of PMC %d on CPU %d failed", 20637d6f8a9SDavid E. O'Brien b == PMCC_OP_ENABLE ? "Enable" : "Disable", 20737d6f8a9SDavid E. O'Brien j, i); 208ebccf1e3SJoseph Koshy } 209ebccf1e3SJoseph Koshy 210ebccf1e3SJoseph Koshy return error; 211ebccf1e3SJoseph Koshy } 212ebccf1e3SJoseph Koshy 213ebccf1e3SJoseph Koshy static int 214ebccf1e3SJoseph Koshy pmcc_do_list_state(void) 215ebccf1e3SJoseph Koshy { 216095489dbSAttilio Rao cpuset_t logical_cpus_mask; 217095489dbSAttilio Rao long cpusetsize; 218095489dbSAttilio Rao size_t setsize; 219ebccf1e3SJoseph Koshy int c, cpu, n, npmc, ncpu; 220ebccf1e3SJoseph Koshy struct pmc_info *pd; 221f263522aSJoseph Koshy struct pmc_pmcinfo *pi; 222f263522aSJoseph Koshy const struct pmc_cpuinfo *pc; 223ebccf1e3SJoseph Koshy 224ebccf1e3SJoseph Koshy if (pmc_cpuinfo(&pc) != 0) 225ebccf1e3SJoseph Koshy err(EX_OSERR, "Unable to determine CPU information"); 226ebccf1e3SJoseph Koshy 22788660748SGeorge V. Neville-Neil printf("%d %s CPUs present, with %d PMCs per CPU\n", pc->pm_ncpu, 22888660748SGeorge V. Neville-Neil pmc_name_of_cputype(pc->pm_cputype), 22988660748SGeorge V. Neville-Neil pc->pm_npmc); 23088660748SGeorge V. Neville-Neil 231095489dbSAttilio Rao /* Determine the set of logical CPUs. */ 232095489dbSAttilio Rao cpusetsize = sysconf(_SC_CPUSET_SIZE); 233095489dbSAttilio Rao if (cpusetsize == -1 || (u_long)cpusetsize > sizeof(cpuset_t)) 234095489dbSAttilio Rao err(EX_OSERR, "Cannot determine which CPUs are logical"); 235095489dbSAttilio Rao CPU_ZERO(&logical_cpus_mask); 236095489dbSAttilio Rao setsize = (size_t)cpusetsize; 237ebccf1e3SJoseph Koshy if (sysctlbyname("machdep.logical_cpus_mask", &logical_cpus_mask, 238095489dbSAttilio Rao &setsize, NULL, 0) < 0) 239095489dbSAttilio Rao CPU_ZERO(&logical_cpus_mask); 240ebccf1e3SJoseph Koshy 241ebccf1e3SJoseph Koshy ncpu = pc->pm_ncpu; 242ebccf1e3SJoseph Koshy 243ebccf1e3SJoseph Koshy for (c = cpu = 0; cpu < ncpu; cpu++) { 2445943a2a3SJoseph Koshy #if defined(__i386__) || defined(__amd64__) 245ebccf1e3SJoseph Koshy if (pc->pm_cputype == PMC_CPU_INTEL_PIV && 246095489dbSAttilio Rao CPU_ISSET(cpu, &logical_cpus_mask)) 247ebccf1e3SJoseph Koshy continue; /* skip P4-style 'logical' cpus */ 248ebccf1e3SJoseph Koshy #endif 2495d09484bSJoseph Koshy if (pmc_pmcinfo(cpu, &pi) < 0) { 2505d09484bSJoseph Koshy if (errno == ENXIO) 2515d09484bSJoseph Koshy continue; 252ebccf1e3SJoseph Koshy err(EX_OSERR, "Unable to get PMC status for CPU %d", 253ebccf1e3SJoseph Koshy cpu); 2545d09484bSJoseph Koshy } 255ebccf1e3SJoseph Koshy 256ebccf1e3SJoseph Koshy printf("#CPU %d:\n", c++); 257ebccf1e3SJoseph Koshy npmc = pmc_npmc(cpu); 258ebccf1e3SJoseph Koshy printf("#N NAME CLASS STATE ROW-DISP\n"); 259ebccf1e3SJoseph Koshy 260ebccf1e3SJoseph Koshy for (n = 0; n < npmc; n++) { 261ebccf1e3SJoseph Koshy pd = &pi->pm_pmcs[n]; 262ebccf1e3SJoseph Koshy 263ebccf1e3SJoseph Koshy printf(" %-2d %-16s %-6s %-8s %-10s", 264ebccf1e3SJoseph Koshy n, 265ebccf1e3SJoseph Koshy pd->pm_name, 266ebccf1e3SJoseph Koshy pmc_name_of_class(pd->pm_class), 267ebccf1e3SJoseph Koshy pd->pm_enabled ? "ENABLED" : "DISABLED", 268ebccf1e3SJoseph Koshy pmc_name_of_disposition(pd->pm_rowdisp)); 269ebccf1e3SJoseph Koshy 270ebccf1e3SJoseph Koshy if (pd->pm_ownerpid != -1) { 271ebccf1e3SJoseph Koshy printf(" (pid %d)", pd->pm_ownerpid); 272ebccf1e3SJoseph Koshy printf(" %-32s", 273ebccf1e3SJoseph Koshy pmc_name_of_event(pd->pm_event)); 274ebccf1e3SJoseph Koshy if (PMC_IS_SAMPLING_MODE(pd->pm_mode)) 275ebccf1e3SJoseph Koshy printf(" (reload count %jd)", 276ebccf1e3SJoseph Koshy pd->pm_reloadcount); 277ebccf1e3SJoseph Koshy } 278ebccf1e3SJoseph Koshy printf("\n"); 279ebccf1e3SJoseph Koshy } 280ebccf1e3SJoseph Koshy free(pi); 281ebccf1e3SJoseph Koshy } 282ebccf1e3SJoseph Koshy return 0; 283ebccf1e3SJoseph Koshy } 284ebccf1e3SJoseph Koshy 285ebccf1e3SJoseph Koshy static int 286ebccf1e3SJoseph Koshy pmcc_do_list_events(void) 287ebccf1e3SJoseph Koshy { 288ebccf1e3SJoseph Koshy enum pmc_class c; 289ebccf1e3SJoseph Koshy unsigned int i, j, nevents; 290ebccf1e3SJoseph Koshy const char **eventnamelist; 291f263522aSJoseph Koshy const struct pmc_cpuinfo *ci; 292ebccf1e3SJoseph Koshy 293167cdaa7SMitchell Horne /* First, try pmu events. */ 294167cdaa7SMitchell Horne if (pmc_pmu_enabled()) { 295167cdaa7SMitchell Horne pmc_pmu_print_counters(NULL); 296167cdaa7SMitchell Horne return (0); 297167cdaa7SMitchell Horne } 298167cdaa7SMitchell Horne 299167cdaa7SMitchell Horne /* Otherwise, use the legacy pmc(3) interfaces. */ 300ebccf1e3SJoseph Koshy if (pmc_cpuinfo(&ci) != 0) 301ebccf1e3SJoseph Koshy err(EX_OSERR, "Unable to determine CPU information"); 302ebccf1e3SJoseph Koshy 303ebccf1e3SJoseph Koshy eventnamelist = NULL; 304ebccf1e3SJoseph Koshy 305ebccf1e3SJoseph Koshy for (i = 0; i < ci->pm_nclass; i++) { 306c5153e19SJoseph Koshy c = ci->pm_classes[i].pm_class; 307ebccf1e3SJoseph Koshy 308ebccf1e3SJoseph Koshy printf("%s\n", pmc_name_of_class(c)); 309ebccf1e3SJoseph Koshy if (pmc_event_names_of_class(c, &eventnamelist, &nevents) < 0) 31037d6f8a9SDavid E. O'Brien err(EX_OSERR, 31137d6f8a9SDavid E. O'Brien "ERROR: Cannot find information for event class \"%s\"", 31237d6f8a9SDavid E. O'Brien pmc_name_of_class(c)); 313ebccf1e3SJoseph Koshy 314ebccf1e3SJoseph Koshy for (j = 0; j < nevents; j++) 315ebccf1e3SJoseph Koshy printf("\t%s\n", eventnamelist[j]); 316ebccf1e3SJoseph Koshy 317ebccf1e3SJoseph Koshy free(eventnamelist); 318ebccf1e3SJoseph Koshy } 319ebccf1e3SJoseph Koshy return 0; 320ebccf1e3SJoseph Koshy } 321ebccf1e3SJoseph Koshy 322ebccf1e3SJoseph Koshy static int 323ebccf1e3SJoseph Koshy pmcc_show_statistics(void) 324ebccf1e3SJoseph Koshy { 325ebccf1e3SJoseph Koshy 326f263522aSJoseph Koshy struct pmc_driverstats gms; 327ebccf1e3SJoseph Koshy 328ebccf1e3SJoseph Koshy if (pmc_get_driver_stats(&gms) < 0) 329ebccf1e3SJoseph Koshy err(EX_OSERR, "ERROR: cannot retrieve driver statistics"); 330ebccf1e3SJoseph Koshy 331ebccf1e3SJoseph Koshy /* 332ebccf1e3SJoseph Koshy * Print statistics. 333ebccf1e3SJoseph Koshy */ 334ebccf1e3SJoseph Koshy 335f263522aSJoseph Koshy #define PRINT(N,V) (void) printf("%-40s %d\n", (N), gms.pm_##V) 336f263522aSJoseph Koshy PRINT("interrupts processed:", intr_processed); 337f263522aSJoseph Koshy PRINT("non-PMC interrupts:", intr_ignored); 338f35f2fc8SJoseph Koshy PRINT("sampling stalls due to space shortages:", intr_bufferfull); 339f263522aSJoseph Koshy PRINT("system calls:", syscalls); 340f263522aSJoseph Koshy PRINT("system calls with errors:", syscall_errors); 341f263522aSJoseph Koshy PRINT("buffer requests:", buffer_requests); 342f263522aSJoseph Koshy PRINT("buffer requests failed:", buffer_requests_failed); 343f263522aSJoseph Koshy PRINT("sampling log sweeps:", log_sweeps); 344ebccf1e3SJoseph Koshy 345ebccf1e3SJoseph Koshy return 0; 346ebccf1e3SJoseph Koshy } 347ebccf1e3SJoseph Koshy 348ebccf1e3SJoseph Koshy /* 349ebccf1e3SJoseph Koshy * Main 350ebccf1e3SJoseph Koshy */ 351ebccf1e3SJoseph Koshy 352ebccf1e3SJoseph Koshy int 353ebccf1e3SJoseph Koshy main(int argc, char **argv) 354ebccf1e3SJoseph Koshy { 355ebccf1e3SJoseph Koshy int error, command, currentcpu, option, pmc; 356ebccf1e3SJoseph Koshy char *dummy; 357ebccf1e3SJoseph Koshy struct pmcc_op *p; 358ebccf1e3SJoseph Koshy 359ebccf1e3SJoseph Koshy #if DEBUG 360ebccf1e3SJoseph Koshy pmcc_init_debug(); 361ebccf1e3SJoseph Koshy #endif 362ebccf1e3SJoseph Koshy 363ebccf1e3SJoseph Koshy /* parse args */ 364ebccf1e3SJoseph Koshy 365ebccf1e3SJoseph Koshy currentcpu = PMCC_CPU_ALL; 366ebccf1e3SJoseph Koshy command = PMCC_PRINT_USAGE; 367ebccf1e3SJoseph Koshy error = 0; 368ebccf1e3SJoseph Koshy 369ebccf1e3SJoseph Koshy STAILQ_INIT(&head); 370ebccf1e3SJoseph Koshy 371ebccf1e3SJoseph Koshy while ((option = getopt(argc, argv, ":c:d:e:lLs")) != -1) 372ebccf1e3SJoseph Koshy switch (option) { 373ebccf1e3SJoseph Koshy case 'L': 374ebccf1e3SJoseph Koshy if (command != PMCC_PRINT_USAGE) { 375ebccf1e3SJoseph Koshy error = 1; 376ebccf1e3SJoseph Koshy break; 377ebccf1e3SJoseph Koshy } 378ebccf1e3SJoseph Koshy command = PMCC_PRINT_EVENTS; 379ebccf1e3SJoseph Koshy break; 380ebccf1e3SJoseph Koshy 381ebccf1e3SJoseph Koshy case 'c': 382ebccf1e3SJoseph Koshy if (command != PMCC_PRINT_USAGE && 383ebccf1e3SJoseph Koshy command != PMCC_ENABLE_DISABLE) { 384ebccf1e3SJoseph Koshy error = 1; 385ebccf1e3SJoseph Koshy break; 386ebccf1e3SJoseph Koshy } 387ebccf1e3SJoseph Koshy command = PMCC_ENABLE_DISABLE; 388ebccf1e3SJoseph Koshy 389ebccf1e3SJoseph Koshy if (*optarg == PMCC_CPU_WILDCARD) 390ebccf1e3SJoseph Koshy currentcpu = PMCC_CPU_ALL; 391ebccf1e3SJoseph Koshy else { 392ebccf1e3SJoseph Koshy currentcpu = strtoul(optarg, &dummy, 0); 393ebccf1e3SJoseph Koshy if (*dummy != '\0' || currentcpu < 0) 394ebccf1e3SJoseph Koshy errx(EX_DATAERR, 395ebccf1e3SJoseph Koshy "\"%s\" is not a valid CPU id", 396ebccf1e3SJoseph Koshy optarg); 397ebccf1e3SJoseph Koshy } 398ebccf1e3SJoseph Koshy break; 399ebccf1e3SJoseph Koshy 400ebccf1e3SJoseph Koshy case 'd': 401ebccf1e3SJoseph Koshy case 'e': 402ebccf1e3SJoseph Koshy if (command != PMCC_PRINT_USAGE && 403ebccf1e3SJoseph Koshy command != PMCC_ENABLE_DISABLE) { 404ebccf1e3SJoseph Koshy error = 1; 405ebccf1e3SJoseph Koshy break; 406ebccf1e3SJoseph Koshy } 407ebccf1e3SJoseph Koshy command = PMCC_ENABLE_DISABLE; 408ebccf1e3SJoseph Koshy 409ebccf1e3SJoseph Koshy if (*optarg == PMCC_PMC_WILDCARD) 410ebccf1e3SJoseph Koshy pmc = PMCC_PMC_ALL; 411ebccf1e3SJoseph Koshy else { 412ebccf1e3SJoseph Koshy pmc = strtoul(optarg, &dummy, 0); 413ebccf1e3SJoseph Koshy if (*dummy != '\0' || pmc < 0) 414ebccf1e3SJoseph Koshy errx(EX_DATAERR, 415ebccf1e3SJoseph Koshy "\"%s\" is not a valid PMC id", 416ebccf1e3SJoseph Koshy optarg); 417ebccf1e3SJoseph Koshy } 418ebccf1e3SJoseph Koshy 419ebccf1e3SJoseph Koshy if ((p = malloc(sizeof(*p))) == NULL) 420ebccf1e3SJoseph Koshy err(EX_SOFTWARE, "Out of memory"); 421ebccf1e3SJoseph Koshy 422ebccf1e3SJoseph Koshy p->op_cpu = currentcpu; 423ebccf1e3SJoseph Koshy p->op_pmc = pmc; 424ebccf1e3SJoseph Koshy p->op_op = option == 'd' ? PMCC_OP_DISABLE : 425ebccf1e3SJoseph Koshy PMCC_OP_ENABLE; 426ebccf1e3SJoseph Koshy 427ebccf1e3SJoseph Koshy STAILQ_INSERT_TAIL(&head, p, op_next); 428ebccf1e3SJoseph Koshy break; 429ebccf1e3SJoseph Koshy 430ebccf1e3SJoseph Koshy case 'l': 431ebccf1e3SJoseph Koshy if (command != PMCC_PRINT_USAGE) { 432ebccf1e3SJoseph Koshy error = 1; 433ebccf1e3SJoseph Koshy break; 434ebccf1e3SJoseph Koshy } 435ebccf1e3SJoseph Koshy command = PMCC_LIST_STATE; 436ebccf1e3SJoseph Koshy break; 437ebccf1e3SJoseph Koshy 438ebccf1e3SJoseph Koshy case 's': 439ebccf1e3SJoseph Koshy if (command != PMCC_PRINT_USAGE) { 440ebccf1e3SJoseph Koshy error = 1; 441ebccf1e3SJoseph Koshy break; 442ebccf1e3SJoseph Koshy } 443ebccf1e3SJoseph Koshy command = PMCC_SHOW_STATISTICS; 444ebccf1e3SJoseph Koshy break; 445ebccf1e3SJoseph Koshy 446ebccf1e3SJoseph Koshy case ':': 447ebccf1e3SJoseph Koshy errx(EX_USAGE, 448ebccf1e3SJoseph Koshy "Missing argument to option '-%c'", optopt); 449ebccf1e3SJoseph Koshy break; 450ebccf1e3SJoseph Koshy 451ebccf1e3SJoseph Koshy case '?': 452ebccf1e3SJoseph Koshy warnx("Unrecognized option \"-%c\"", optopt); 453e2d0cd59SDimitry Andric errx(EX_USAGE, "%s", usage_message); 454ebccf1e3SJoseph Koshy break; 455ebccf1e3SJoseph Koshy 456ebccf1e3SJoseph Koshy default: 457ebccf1e3SJoseph Koshy error = 1; 458ebccf1e3SJoseph Koshy break; 459ebccf1e3SJoseph Koshy 460ebccf1e3SJoseph Koshy } 461ebccf1e3SJoseph Koshy 462ebccf1e3SJoseph Koshy if (command == PMCC_PRINT_USAGE) 463e2d0cd59SDimitry Andric (void) errx(EX_USAGE, "%s", usage_message); 464ebccf1e3SJoseph Koshy 465ebccf1e3SJoseph Koshy if (error) 466ebccf1e3SJoseph Koshy exit(EX_USAGE); 467ebccf1e3SJoseph Koshy 468ebccf1e3SJoseph Koshy if (pmc_init() < 0) 469ebccf1e3SJoseph Koshy err(EX_UNAVAILABLE, 470ebccf1e3SJoseph Koshy "Initialization of the pmc(3) library failed"); 471ebccf1e3SJoseph Koshy 472ebccf1e3SJoseph Koshy switch (command) { 473ebccf1e3SJoseph Koshy case PMCC_LIST_STATE: 474ebccf1e3SJoseph Koshy error = pmcc_do_list_state(); 475ebccf1e3SJoseph Koshy break; 476ebccf1e3SJoseph Koshy case PMCC_PRINT_EVENTS: 477ebccf1e3SJoseph Koshy error = pmcc_do_list_events(); 478ebccf1e3SJoseph Koshy break; 479ebccf1e3SJoseph Koshy case PMCC_SHOW_STATISTICS: 480ebccf1e3SJoseph Koshy error = pmcc_show_statistics(); 481ebccf1e3SJoseph Koshy break; 482ebccf1e3SJoseph Koshy case PMCC_ENABLE_DISABLE: 483ebccf1e3SJoseph Koshy if (STAILQ_EMPTY(&head)) 48437d6f8a9SDavid E. O'Brien errx(EX_USAGE, 48537d6f8a9SDavid E. O'Brien "No PMCs specified to enable or disable"); 486ebccf1e3SJoseph Koshy error = pmcc_do_enable_disable(&head); 487ebccf1e3SJoseph Koshy break; 488ebccf1e3SJoseph Koshy default: 489ebccf1e3SJoseph Koshy assert(0); 490ebccf1e3SJoseph Koshy 491ebccf1e3SJoseph Koshy } 492ebccf1e3SJoseph Koshy 493ebccf1e3SJoseph Koshy if (error != 0) 494ebccf1e3SJoseph Koshy err(EX_OSERR, "Command failed"); 495ebccf1e3SJoseph Koshy exit(0); 496ebccf1e3SJoseph Koshy } 497