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