perfmon.c revision 14895
1177633Sdfr/* 2177633Sdfr * Copyright 1996 Massachusetts Institute of Technology 3177633Sdfr * 4177633Sdfr * Permission to use, copy, modify, and distribute this software and 5177633Sdfr * its documentation for any purpose and without fee is hereby 6177633Sdfr * granted, provided that both the above copyright notice and this 7177633Sdfr * permission notice appear in all copies, that both the above 8177633Sdfr * copyright notice and this permission notice appear in all 9177633Sdfr * supporting documentation, and that the name of M.I.T. not be used 10177633Sdfr * in advertising or publicity pertaining to distribution of the 11177633Sdfr * software without specific, written prior permission. M.I.T. makes 12177633Sdfr * no representations about the suitability of this software for any 13177633Sdfr * purpose. It is provided "as is" without express or implied 14177633Sdfr * warranty. 15177633Sdfr * 16177633Sdfr * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS 17177633Sdfr * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, 18177633Sdfr * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19177633Sdfr * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT 20177633Sdfr * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21177633Sdfr * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22177633Sdfr * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 23177633Sdfr * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24177633Sdfr * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25177633Sdfr * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 26177633Sdfr * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27177633Sdfr * SUCH DAMAGE. 28177633Sdfr * 29177633Sdfr * $Id$ 30177633Sdfr */ 31177633Sdfr 32177633Sdfr#include <sys/types.h> 33177633Sdfr#include <sys/ioctl.h> 34177633Sdfr 35177633Sdfr#include <machine/cpu.h> 36177633Sdfr#include <machine/perfmon.h> 37177633Sdfr 38177633Sdfr#include <stdio.h> 39177633Sdfr#include <stdlib.h> 40177633Sdfr#include <string.h> 41177633Sdfr#include <err.h> 42177633Sdfr#include <unistd.h> 43177633Sdfr#include <fcntl.h> 44177633Sdfr#include <limits.h> 45177633Sdfr#include <errno.h> 46177633Sdfr 47177633Sdfrstatic int getnum(const char *, int, int); 48180025Sdfrstatic void __dead usage(const char *) __dead2; 49177633Sdfr 50177633Sdfrint 51177633Sdfrmain(int argc, char **argv) 52177633Sdfr{ 53177633Sdfr int c, fd, num; 54177633Sdfr int loops, i, sleeptime; 55177633Sdfr struct pmc pmc; 56177633Sdfr struct pmc_tstamp then, now; 57177633Sdfr struct pmc_data value; 58177633Sdfr quad_t *buf; 59177633Sdfr double total; 60196503Szec 61196503Szec pmc.pmc_num = 0; 62177633Sdfr pmc.pmc_event = 0; 63177685Sdfr pmc.pmc_unit = 0; 64177633Sdfr pmc.pmc_flags = 0; 65177633Sdfr pmc.pmc_mask = 0; 66177633Sdfr loops = 50; 67177633Sdfr sleeptime = 0; 68177633Sdfr 69177633Sdfr while ((c = getopt(argc, argv, "s:l:uoeiU:m:")) != EOF) { 70177633Sdfr switch(c) { 71177633Sdfr case 'u': 72177633Sdfr pmc.pmc_flags |= PMCF_USR; 73177633Sdfr break; 74177633Sdfr case 'o': 75177633Sdfr pmc.pmc_flags |= PMCF_OS; 76180025Sdfr break; 77184588Sdfr case 'e': 78177633Sdfr pmc.pmc_flags |= PMCF_E; 79177633Sdfr break; 80177633Sdfr case 'i': 81177633Sdfr pmc.pmc_flags |= PMCF_INV; 82184588Sdfr break; 83177633Sdfr case 'U': 84193272Sjhb pmc.pmc_unit = getnum(optarg, 0, 256); 85177633Sdfr break; 86177633Sdfr case 'm': 87177633Sdfr pmc.pmc_mask = getnum(optarg, 0, 256); 88177633Sdfr break; 89177633Sdfr case 'l': 90177633Sdfr loops = getnum(optarg, 1, INT_MAX - 1); 91184588Sdfr break; 92177633Sdfr case 's': 93177633Sdfr sleeptime = getnum(optarg, 0, INT_MAX - 1); 94177633Sdfr break; 95177633Sdfr default: 96177633Sdfr usage(argv[0]); 97177633Sdfr } 98177633Sdfr } 99180025Sdfr 100180025Sdfr if (argc - optind != 1) 101180025Sdfr usage(argv[0]); 102177633Sdfr 103177633Sdfr pmc.pmc_event = getnum(argv[optind], 0, 255); 104177633Sdfr 105180025Sdfr buf = malloc((loops + 1) * sizeof *buf); 106177633Sdfr if (!buf) 107177633Sdfr err(1, "malloc(%lu)", (unsigned long)(loops +1) * sizeof *buf); 108177633Sdfr 109184588Sdfr fd = open(_PATH_PERFMON, O_RDWR, 0); 110177633Sdfr if (fd < 0) 111177633Sdfr err(1, "open: " _PATH_PERFMON); 112177633Sdfr 113177633Sdfr if (ioctl(fd, PMIOSETUP, &pmc) < 0) 114177633Sdfr err(1, "ioctl(PMIOSETUP)"); 115177633Sdfr 116177633Sdfr if (ioctl(fd, PMIOTSTAMP, &then) < 0) 117193272Sjhb err(1, "ioctl(PMIOTSTAMP)"); 118177633Sdfr 119177633Sdfr num = 0; 120177633Sdfr if (ioctl(fd, PMIOSTART, &num) < 0) 121177633Sdfr err(1, "ioctl(PMIOSTART)"); 122177633Sdfr 123177633Sdfr value.pmcd_num = 0; 124177633Sdfr for (i = 0; i < loops; i++) { 125177633Sdfr if (sleeptime) 126177633Sdfr sleep(sleeptime); 127177633Sdfr if (ioctl(fd, PMIOSTOP, &num) < 0) 128193437Srmacklem err(1, "ioctl(PMIOSTOP)"); 129177633Sdfr if (ioctl(fd, PMIOREAD, &value) < 0) 130177633Sdfr err(1, "ioctl(PMIOREAD)"); 131193437Srmacklem buf[i] = value.pmcd_value; 132193437Srmacklem if (ioctl(fd, PMIORESET, &value.pmcd_num) < 0) 133177633Sdfr err(1, "ioctl(PMIORESET)"); 134177633Sdfr if (ioctl(fd, PMIOSTART, &num) < 0) 135177633Sdfr err(1, "ioctl(PMIOSTART)"); 136177633Sdfr } 137180025Sdfr 138184588Sdfr if (ioctl(fd, PMIOSTOP, &num) < 0) 139184588Sdfr err(1, "ioctl(PMIOSTOP)"); 140177633Sdfr if (ioctl(fd, PMIOREAD, &value) < 0) 141177633Sdfr err(1, "ioctl(PMIOREAD)"); 142177633Sdfr buf[i] = value.pmcd_value; 143177633Sdfr if (ioctl(fd, PMIOTSTAMP, &now) < 0) 144177633Sdfr err(1, "ioctl(PMIOTSTAMP)"); 145177633Sdfr 146177633Sdfr total = 0; 147177633Sdfr for (i = 1; i <= loops; i++) { 148177633Sdfr printf("%d: %qd\n", i, buf[i]); 149177633Sdfr total += buf[i]; 150177633Sdfr } 151177633Sdfr printf("total: %f\nmean: %f\n", total, total / loops); 152177633Sdfr 153177633Sdfr printf("clocks (at %d-MHz): %qd\n", now.pmct_rate, 154177633Sdfr now.pmct_value - then.pmct_value); 155177633Sdfr 156177633Sdfr return 0; 157184588Sdfr} 158184588Sdfr 159184588Sdfrstatic int 160177633Sdfrgetnum(const char *buf, int min, int max) 161177633Sdfr{ 162184588Sdfr char *ep; 163184588Sdfr long l; 164184588Sdfr 165177633Sdfr errno = 0; 166177633Sdfr l = strtol(buf, &ep, 0); 167177633Sdfr if (*buf && !*ep && !errno) { 168177633Sdfr if (l < min || l > max) { 169177633Sdfr errx(1, "`%s': must be between %d and %d", 170177633Sdfr buf, min, max); 171177633Sdfr } 172177633Sdfr return (int)l; 173177633Sdfr } else if(errno) { 174177633Sdfr errx(1, "`%s': must be between %ld and %ld", 175177633Sdfr LONG_MIN, LONG_MAX); 176177633Sdfr } 177177633Sdfr errx(1, "`%s': parameter must be an integer"); 178177633Sdfr} 179177633Sdfr 180177633Sdfrstatic void 181177633Sdfrusage(const char *pname) 182177633Sdfr{ 183177633Sdfr fprintf(stderr, 184177633Sdfr "%s: usage:\n\t%s [-eiou] [-l nloops] [-U unit] [-m mask] " 185177633Sdfr "counter\n", pname, pname); 186177633Sdfr exit(1); 187177633Sdfr} 188177633Sdfr