1145256Sjkoshy/*- 2145256Sjkoshy * Copyright (c) 2003,2004 Joseph Koshy 3145256Sjkoshy * All rights reserved. 4145256Sjkoshy * 5145256Sjkoshy * Redistribution and use in source and binary forms, with or without 6145256Sjkoshy * modification, are permitted provided that the following conditions 7145256Sjkoshy * are met: 8145256Sjkoshy * 1. Redistributions of source code must retain the above copyright 9145256Sjkoshy * notice, this list of conditions and the following disclaimer. 10145256Sjkoshy * 2. Redistributions in binary form must reproduce the above copyright 11145256Sjkoshy * notice, this list of conditions and the following disclaimer in the 12145256Sjkoshy * documentation and/or other materials provided with the distribution. 13145256Sjkoshy * 14145256Sjkoshy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15145256Sjkoshy * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16145256Sjkoshy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17145256Sjkoshy * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18145256Sjkoshy * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19145256Sjkoshy * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20145256Sjkoshy * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21145256Sjkoshy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22145256Sjkoshy * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23145256Sjkoshy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24145256Sjkoshy * SUCH DAMAGE. 25145256Sjkoshy * 26145256Sjkoshy */ 27145256Sjkoshy 28145256Sjkoshy#include <sys/cdefs.h> 29145256Sjkoshy__FBSDID("$FreeBSD$"); 30145256Sjkoshy 31222813Sattilio#include <sys/param.h> 32145256Sjkoshy#include <sys/queue.h> 33224058Sattilio#include <sys/cpuset.h> 34145256Sjkoshy#include <sys/sysctl.h> 35145256Sjkoshy 36145256Sjkoshy#include <assert.h> 37145256Sjkoshy#include <err.h> 38145256Sjkoshy#include <errno.h> 39145256Sjkoshy#include <fcntl.h> 40145256Sjkoshy#include <limits.h> 41145256Sjkoshy#include <pmc.h> 42145256Sjkoshy#include <stdarg.h> 43145256Sjkoshy#include <stdio.h> 44145256Sjkoshy#include <stdlib.h> 45145256Sjkoshy#include <string.h> 46145256Sjkoshy#include <sysexits.h> 47145256Sjkoshy#include <unistd.h> 48145256Sjkoshy 49145256Sjkoshy/* Compile time defaults */ 50145256Sjkoshy 51145256Sjkoshy#define PMCC_PRINT_USAGE 0 52145256Sjkoshy#define PMCC_PRINT_EVENTS 1 53145256Sjkoshy#define PMCC_LIST_STATE 2 54145256Sjkoshy#define PMCC_ENABLE_DISABLE 3 55145256Sjkoshy#define PMCC_SHOW_STATISTICS 4 56145256Sjkoshy 57145256Sjkoshy#define PMCC_CPU_ALL -1 58145256Sjkoshy#define PMCC_CPU_WILDCARD '*' 59145256Sjkoshy 60145256Sjkoshy#define PMCC_PMC_ALL -1 61145256Sjkoshy#define PMCC_PMC_WILDCARD '*' 62145256Sjkoshy 63145256Sjkoshy#define PMCC_OP_IGNORE 0 64145256Sjkoshy#define PMCC_OP_DISABLE 1 65145256Sjkoshy#define PMCC_OP_ENABLE 2 66145256Sjkoshy 67145256Sjkoshy#define PMCC_PROGRAM_NAME "pmccontrol" 68145256Sjkoshy 69241737Sedstatic STAILQ_HEAD(pmcc_op_list, pmcc_op) head = STAILQ_HEAD_INITIALIZER(head); 70145256Sjkoshy 71145256Sjkoshystruct pmcc_op { 72145256Sjkoshy char op_cpu; 73145256Sjkoshy char op_pmc; 74145256Sjkoshy char op_op; 75145256Sjkoshy STAILQ_ENTRY(pmcc_op) op_next; 76145256Sjkoshy}; 77145256Sjkoshy 78145256Sjkoshy/* Function Prototypes */ 79145256Sjkoshy#if DEBUG 80145256Sjkoshystatic void pmcc_init_debug(void); 81145256Sjkoshy#endif 82145256Sjkoshy 83145256Sjkoshystatic int pmcc_do_list_state(void); 84145256Sjkoshystatic int pmcc_do_enable_disable(struct pmcc_op_list *); 85145256Sjkoshystatic int pmcc_do_list_events(void); 86145256Sjkoshy 87145256Sjkoshy/* Globals */ 88145256Sjkoshy 89145256Sjkoshystatic char usage_message[] = 90145256Sjkoshy "Usage:\n" 91147581Sjkoshy " " PMCC_PROGRAM_NAME " -L\n" 92145256Sjkoshy " " PMCC_PROGRAM_NAME " -l\n" 93145256Sjkoshy " " PMCC_PROGRAM_NAME " -s\n" 94145256Sjkoshy " " PMCC_PROGRAM_NAME " [-e pmc | -d pmc | -c cpu] ..."; 95145256Sjkoshy 96145256Sjkoshy#if DEBUG 97241737Sedstatic FILE *debug_stream = NULL; 98145256Sjkoshy#endif 99145256Sjkoshy 100145256Sjkoshy#if DEBUG 101145256Sjkoshy#define DEBUG_MSG(...) \ 102145256Sjkoshy (void) fprintf(debug_stream, "[pmccontrol] " __VA_ARGS__); 103145256Sjkoshy#else 104145256Sjkoshy#define DEBUG_MSG(m) /* */ 105145256Sjkoshy#endif /* !DEBUG */ 106145256Sjkoshy 107145256Sjkoshy#if DEBUG 108145256Sjkoshy/* log debug messages to a separate file */ 109145256Sjkoshystatic void 110145256Sjkoshypmcc_init_debug(void) 111145256Sjkoshy{ 112145256Sjkoshy char *fn; 113145256Sjkoshy 114145256Sjkoshy fn = getenv("PMCCONTROL_DEBUG"); 115145256Sjkoshy if (fn != NULL) 116145256Sjkoshy { 117145256Sjkoshy debug_stream = fopen(fn, "w"); 118145256Sjkoshy if (debug_stream == NULL) 119145256Sjkoshy debug_stream = stderr; 120145256Sjkoshy } else 121145256Sjkoshy debug_stream = stderr; 122145256Sjkoshy} 123145256Sjkoshy#endif 124145256Sjkoshy 125145256Sjkoshystatic int 126145256Sjkoshypmcc_do_enable_disable(struct pmcc_op_list *op_list) 127145256Sjkoshy{ 128145256Sjkoshy int c, error, i, j, ncpu, npmc, t; 129145256Sjkoshy struct pmcc_op *np; 130145256Sjkoshy unsigned char *map; 131184782Sjkoshy unsigned char op; 132184782Sjkoshy int cpu, pmc; 133145256Sjkoshy 134145256Sjkoshy if ((ncpu = pmc_ncpu()) < 0) 135145256Sjkoshy err(EX_OSERR, "Unable to determine the number of cpus"); 136145256Sjkoshy 137184782Sjkoshy /* Determine the maximum number of PMCs in any CPU. */ 138145256Sjkoshy npmc = 0; 139145256Sjkoshy for (c = 0; c < ncpu; c++) { 140145256Sjkoshy if ((t = pmc_npmc(c)) < 0) 141227524Sobrien err(EX_OSERR, 142227524Sobrien "Unable to determine the number of PMCs in CPU %d", 143227524Sobrien c); 144145256Sjkoshy npmc = t > npmc ? t : npmc; 145145256Sjkoshy } 146145256Sjkoshy 147145256Sjkoshy if (npmc == 0) 148145256Sjkoshy errx(EX_CONFIG, "No PMCs found"); 149145256Sjkoshy 150145256Sjkoshy if ((map = malloc(npmc * ncpu)) == NULL) 151145256Sjkoshy err(EX_SOFTWARE, "Out of memory"); 152145256Sjkoshy 153145256Sjkoshy (void) memset(map, PMCC_OP_IGNORE, npmc*ncpu); 154145256Sjkoshy 155145256Sjkoshy error = 0; 156145256Sjkoshy STAILQ_FOREACH(np, op_list, op_next) { 157145256Sjkoshy 158145256Sjkoshy cpu = np->op_cpu; 159145256Sjkoshy pmc = np->op_pmc; 160145256Sjkoshy op = np->op_op; 161145256Sjkoshy 162145256Sjkoshy if (cpu >= ncpu) 163145256Sjkoshy errx(EX_DATAERR, "CPU id too large: \"%d\"", cpu); 164145256Sjkoshy 165145256Sjkoshy if (pmc >= npmc) 166145256Sjkoshy errx(EX_DATAERR, "PMC id too large: \"%d\"", pmc); 167145256Sjkoshy 168145256Sjkoshy#define MARKMAP(M,C,P,V) do { \ 169145256Sjkoshy *((M) + (C)*npmc + (P)) = (V); \ 170145256Sjkoshy} while (0) 171145256Sjkoshy 172145256Sjkoshy#define SET_PMCS(C,P,V) do { \ 173145256Sjkoshy if ((P) == PMCC_PMC_ALL) { \ 174145256Sjkoshy for (j = 0; j < npmc; j++) \ 175145256Sjkoshy MARKMAP(map, (C), j, (V)); \ 176145256Sjkoshy } else \ 177145256Sjkoshy MARKMAP(map, (C), (P), (V)); \ 178145256Sjkoshy} while (0) 179145256Sjkoshy 180145256Sjkoshy#define MAP(M,C,P) (*((M) + (C)*npmc + (P))) 181145256Sjkoshy 182145256Sjkoshy if (cpu == PMCC_CPU_ALL) 183184782Sjkoshy for (i = 0; i < ncpu; i++) { 184224057Savg SET_PMCS(i, pmc, op); 185184782Sjkoshy } 186145256Sjkoshy else 187145256Sjkoshy SET_PMCS(cpu, pmc, op); 188145256Sjkoshy } 189145256Sjkoshy 190145256Sjkoshy /* Configure PMCS */ 191145256Sjkoshy for (i = 0; i < ncpu; i++) 192145256Sjkoshy for (j = 0; j < npmc; j++) { 193145256Sjkoshy unsigned char b; 194145256Sjkoshy 195145256Sjkoshy b = MAP(map, i, j); 196145256Sjkoshy 197145256Sjkoshy error = 0; 198145256Sjkoshy 199145256Sjkoshy if (b == PMCC_OP_ENABLE) 200145256Sjkoshy error = pmc_enable(i, j); 201145256Sjkoshy else if (b == PMCC_OP_DISABLE) 202145256Sjkoshy error = pmc_disable(i, j); 203145256Sjkoshy 204145256Sjkoshy if (error < 0) 205145256Sjkoshy err(EX_OSERR, "%s of PMC %d on CPU %d failed", 206227524Sobrien b == PMCC_OP_ENABLE ? "Enable" : "Disable", 207227524Sobrien j, i); 208145256Sjkoshy } 209145256Sjkoshy 210145256Sjkoshy return error; 211145256Sjkoshy} 212145256Sjkoshy 213145256Sjkoshystatic int 214145256Sjkoshypmcc_do_list_state(void) 215145256Sjkoshy{ 216224058Sattilio cpuset_t logical_cpus_mask; 217224058Sattilio long cpusetsize; 218224058Sattilio size_t setsize; 219145256Sjkoshy int c, cpu, n, npmc, ncpu; 220145256Sjkoshy struct pmc_info *pd; 221147191Sjkoshy struct pmc_pmcinfo *pi; 222147191Sjkoshy const struct pmc_cpuinfo *pc; 223145256Sjkoshy 224145256Sjkoshy if (pmc_cpuinfo(&pc) != 0) 225145256Sjkoshy err(EX_OSERR, "Unable to determine CPU information"); 226145256Sjkoshy 227213691Sgnn printf("%d %s CPUs present, with %d PMCs per CPU\n", pc->pm_ncpu, 228213691Sgnn pmc_name_of_cputype(pc->pm_cputype), 229213691Sgnn pc->pm_npmc); 230213691Sgnn 231224058Sattilio /* Determine the set of logical CPUs. */ 232224058Sattilio cpusetsize = sysconf(_SC_CPUSET_SIZE); 233224058Sattilio if (cpusetsize == -1 || (u_long)cpusetsize > sizeof(cpuset_t)) 234224058Sattilio err(EX_OSERR, "Cannot determine which CPUs are logical"); 235224058Sattilio CPU_ZERO(&logical_cpus_mask); 236224058Sattilio setsize = (size_t)cpusetsize; 237145256Sjkoshy if (sysctlbyname("machdep.logical_cpus_mask", &logical_cpus_mask, 238224058Sattilio &setsize, NULL, 0) < 0) 239224058Sattilio CPU_ZERO(&logical_cpus_mask); 240145256Sjkoshy 241145256Sjkoshy ncpu = pc->pm_ncpu; 242145256Sjkoshy 243145256Sjkoshy for (c = cpu = 0; cpu < ncpu; cpu++) { 244156065Sjkoshy#if defined(__i386__) || defined(__amd64__) 245145256Sjkoshy if (pc->pm_cputype == PMC_CPU_INTEL_PIV && 246224058Sattilio CPU_ISSET(cpu, &logical_cpus_mask)) 247145256Sjkoshy continue; /* skip P4-style 'logical' cpus */ 248145256Sjkoshy#endif 249184998Sjkoshy if (pmc_pmcinfo(cpu, &pi) < 0) { 250184998Sjkoshy if (errno == ENXIO) 251184998Sjkoshy continue; 252145256Sjkoshy err(EX_OSERR, "Unable to get PMC status for CPU %d", 253145256Sjkoshy cpu); 254184998Sjkoshy } 255145256Sjkoshy 256145256Sjkoshy printf("#CPU %d:\n", c++); 257145256Sjkoshy npmc = pmc_npmc(cpu); 258145256Sjkoshy printf("#N NAME CLASS STATE ROW-DISP\n"); 259145256Sjkoshy 260145256Sjkoshy for (n = 0; n < npmc; n++) { 261145256Sjkoshy pd = &pi->pm_pmcs[n]; 262145256Sjkoshy 263145256Sjkoshy printf(" %-2d %-16s %-6s %-8s %-10s", 264145256Sjkoshy n, 265145256Sjkoshy pd->pm_name, 266145256Sjkoshy pmc_name_of_class(pd->pm_class), 267145256Sjkoshy pd->pm_enabled ? "ENABLED" : "DISABLED", 268145256Sjkoshy pmc_name_of_disposition(pd->pm_rowdisp)); 269145256Sjkoshy 270145256Sjkoshy if (pd->pm_ownerpid != -1) { 271145256Sjkoshy printf(" (pid %d)", pd->pm_ownerpid); 272145256Sjkoshy printf(" %-32s", 273145256Sjkoshy pmc_name_of_event(pd->pm_event)); 274145256Sjkoshy if (PMC_IS_SAMPLING_MODE(pd->pm_mode)) 275145256Sjkoshy printf(" (reload count %jd)", 276145256Sjkoshy pd->pm_reloadcount); 277145256Sjkoshy } 278145256Sjkoshy printf("\n"); 279145256Sjkoshy } 280145256Sjkoshy free(pi); 281145256Sjkoshy } 282145256Sjkoshy return 0; 283145256Sjkoshy} 284145256Sjkoshy 285145256Sjkoshystatic int 286145256Sjkoshypmcc_do_list_events(void) 287145256Sjkoshy{ 288145256Sjkoshy enum pmc_class c; 289145256Sjkoshy unsigned int i, j, nevents; 290145256Sjkoshy const char **eventnamelist; 291147191Sjkoshy const struct pmc_cpuinfo *ci; 292145256Sjkoshy 293145256Sjkoshy if (pmc_cpuinfo(&ci) != 0) 294145256Sjkoshy err(EX_OSERR, "Unable to determine CPU information"); 295145256Sjkoshy 296145256Sjkoshy eventnamelist = NULL; 297145256Sjkoshy 298145256Sjkoshy for (i = 0; i < ci->pm_nclass; i++) { 299145774Sjkoshy c = ci->pm_classes[i].pm_class; 300145256Sjkoshy 301145256Sjkoshy printf("%s\n", pmc_name_of_class(c)); 302145256Sjkoshy if (pmc_event_names_of_class(c, &eventnamelist, &nevents) < 0) 303227524Sobrien err(EX_OSERR, 304227524Sobrien"ERROR: Cannot find information for event class \"%s\"", 305227524Sobrien pmc_name_of_class(c)); 306145256Sjkoshy 307145256Sjkoshy for (j = 0; j < nevents; j++) 308145256Sjkoshy printf("\t%s\n", eventnamelist[j]); 309145256Sjkoshy 310145256Sjkoshy free(eventnamelist); 311145256Sjkoshy } 312145256Sjkoshy return 0; 313145256Sjkoshy} 314145256Sjkoshy 315145256Sjkoshystatic int 316145256Sjkoshypmcc_show_statistics(void) 317145256Sjkoshy{ 318145256Sjkoshy 319147191Sjkoshy struct pmc_driverstats gms; 320145256Sjkoshy 321145256Sjkoshy if (pmc_get_driver_stats(&gms) < 0) 322145256Sjkoshy err(EX_OSERR, "ERROR: cannot retrieve driver statistics"); 323145256Sjkoshy 324145256Sjkoshy /* 325145256Sjkoshy * Print statistics. 326145256Sjkoshy */ 327145256Sjkoshy 328147191Sjkoshy#define PRINT(N,V) (void) printf("%-40s %d\n", (N), gms.pm_##V) 329147191Sjkoshy PRINT("interrupts processed:", intr_processed); 330147191Sjkoshy PRINT("non-PMC interrupts:", intr_ignored); 331150703Sjkoshy PRINT("sampling stalls due to space shortages:", intr_bufferfull); 332147191Sjkoshy PRINT("system calls:", syscalls); 333147191Sjkoshy PRINT("system calls with errors:", syscall_errors); 334147191Sjkoshy PRINT("buffer requests:", buffer_requests); 335147191Sjkoshy PRINT("buffer requests failed:", buffer_requests_failed); 336147191Sjkoshy PRINT("sampling log sweeps:", log_sweeps); 337145256Sjkoshy 338145256Sjkoshy return 0; 339145256Sjkoshy} 340145256Sjkoshy 341145256Sjkoshy/* 342145256Sjkoshy * Main 343145256Sjkoshy */ 344145256Sjkoshy 345145256Sjkoshyint 346145256Sjkoshymain(int argc, char **argv) 347145256Sjkoshy{ 348145256Sjkoshy int error, command, currentcpu, option, pmc; 349145256Sjkoshy char *dummy; 350145256Sjkoshy struct pmcc_op *p; 351145256Sjkoshy 352145256Sjkoshy#if DEBUG 353145256Sjkoshy pmcc_init_debug(); 354145256Sjkoshy#endif 355145256Sjkoshy 356145256Sjkoshy /* parse args */ 357145256Sjkoshy 358145256Sjkoshy currentcpu = PMCC_CPU_ALL; 359145256Sjkoshy command = PMCC_PRINT_USAGE; 360145256Sjkoshy error = 0; 361145256Sjkoshy 362145256Sjkoshy STAILQ_INIT(&head); 363145256Sjkoshy 364145256Sjkoshy while ((option = getopt(argc, argv, ":c:d:e:lLs")) != -1) 365145256Sjkoshy switch (option) { 366145256Sjkoshy case 'L': 367145256Sjkoshy if (command != PMCC_PRINT_USAGE) { 368145256Sjkoshy error = 1; 369145256Sjkoshy break; 370145256Sjkoshy } 371145256Sjkoshy command = PMCC_PRINT_EVENTS; 372145256Sjkoshy break; 373145256Sjkoshy 374145256Sjkoshy case 'c': 375145256Sjkoshy if (command != PMCC_PRINT_USAGE && 376145256Sjkoshy command != PMCC_ENABLE_DISABLE) { 377145256Sjkoshy error = 1; 378145256Sjkoshy break; 379145256Sjkoshy } 380145256Sjkoshy command = PMCC_ENABLE_DISABLE; 381145256Sjkoshy 382145256Sjkoshy if (*optarg == PMCC_CPU_WILDCARD) 383145256Sjkoshy currentcpu = PMCC_CPU_ALL; 384145256Sjkoshy else { 385145256Sjkoshy currentcpu = strtoul(optarg, &dummy, 0); 386145256Sjkoshy if (*dummy != '\0' || currentcpu < 0) 387145256Sjkoshy errx(EX_DATAERR, 388145256Sjkoshy "\"%s\" is not a valid CPU id", 389145256Sjkoshy optarg); 390145256Sjkoshy } 391145256Sjkoshy break; 392145256Sjkoshy 393145256Sjkoshy case 'd': 394145256Sjkoshy case 'e': 395145256Sjkoshy if (command != PMCC_PRINT_USAGE && 396145256Sjkoshy command != PMCC_ENABLE_DISABLE) { 397145256Sjkoshy error = 1; 398145256Sjkoshy break; 399145256Sjkoshy } 400145256Sjkoshy command = PMCC_ENABLE_DISABLE; 401145256Sjkoshy 402145256Sjkoshy if (*optarg == PMCC_PMC_WILDCARD) 403145256Sjkoshy pmc = PMCC_PMC_ALL; 404145256Sjkoshy else { 405145256Sjkoshy pmc = strtoul(optarg, &dummy, 0); 406145256Sjkoshy if (*dummy != '\0' || pmc < 0) 407145256Sjkoshy errx(EX_DATAERR, 408145256Sjkoshy "\"%s\" is not a valid PMC id", 409145256Sjkoshy optarg); 410145256Sjkoshy } 411145256Sjkoshy 412145256Sjkoshy if ((p = malloc(sizeof(*p))) == NULL) 413145256Sjkoshy err(EX_SOFTWARE, "Out of memory"); 414145256Sjkoshy 415145256Sjkoshy p->op_cpu = currentcpu; 416145256Sjkoshy p->op_pmc = pmc; 417145256Sjkoshy p->op_op = option == 'd' ? PMCC_OP_DISABLE : 418145256Sjkoshy PMCC_OP_ENABLE; 419145256Sjkoshy 420145256Sjkoshy STAILQ_INSERT_TAIL(&head, p, op_next); 421145256Sjkoshy break; 422145256Sjkoshy 423145256Sjkoshy case 'l': 424145256Sjkoshy if (command != PMCC_PRINT_USAGE) { 425145256Sjkoshy error = 1; 426145256Sjkoshy break; 427145256Sjkoshy } 428145256Sjkoshy command = PMCC_LIST_STATE; 429145256Sjkoshy break; 430145256Sjkoshy 431145256Sjkoshy case 's': 432145256Sjkoshy if (command != PMCC_PRINT_USAGE) { 433145256Sjkoshy error = 1; 434145256Sjkoshy break; 435145256Sjkoshy } 436145256Sjkoshy command = PMCC_SHOW_STATISTICS; 437145256Sjkoshy break; 438145256Sjkoshy 439145256Sjkoshy case ':': 440145256Sjkoshy errx(EX_USAGE, 441145256Sjkoshy "Missing argument to option '-%c'", optopt); 442145256Sjkoshy break; 443145256Sjkoshy 444145256Sjkoshy case '?': 445145256Sjkoshy warnx("Unrecognized option \"-%c\"", optopt); 446228671Sdim errx(EX_USAGE, "%s", usage_message); 447145256Sjkoshy break; 448145256Sjkoshy 449145256Sjkoshy default: 450145256Sjkoshy error = 1; 451145256Sjkoshy break; 452145256Sjkoshy 453145256Sjkoshy } 454145256Sjkoshy 455145256Sjkoshy if (command == PMCC_PRINT_USAGE) 456228671Sdim (void) errx(EX_USAGE, "%s", usage_message); 457145256Sjkoshy 458145256Sjkoshy if (error) 459145256Sjkoshy exit(EX_USAGE); 460145256Sjkoshy 461145256Sjkoshy if (pmc_init() < 0) 462145256Sjkoshy err(EX_UNAVAILABLE, 463145256Sjkoshy "Initialization of the pmc(3) library failed"); 464145256Sjkoshy 465145256Sjkoshy switch (command) { 466145256Sjkoshy case PMCC_LIST_STATE: 467145256Sjkoshy error = pmcc_do_list_state(); 468145256Sjkoshy break; 469145256Sjkoshy case PMCC_PRINT_EVENTS: 470145256Sjkoshy error = pmcc_do_list_events(); 471145256Sjkoshy break; 472145256Sjkoshy case PMCC_SHOW_STATISTICS: 473145256Sjkoshy error = pmcc_show_statistics(); 474145256Sjkoshy break; 475145256Sjkoshy case PMCC_ENABLE_DISABLE: 476145256Sjkoshy if (STAILQ_EMPTY(&head)) 477227524Sobrien errx(EX_USAGE, 478227524Sobrien "No PMCs specified to enable or disable"); 479145256Sjkoshy error = pmcc_do_enable_disable(&head); 480145256Sjkoshy break; 481145256Sjkoshy default: 482145256Sjkoshy assert(0); 483145256Sjkoshy 484145256Sjkoshy } 485145256Sjkoshy 486145256Sjkoshy if (error != 0) 487145256Sjkoshy err(EX_OSERR, "Command failed"); 488145256Sjkoshy exit(0); 489145256Sjkoshy} 490