xref: /freebsd-src/share/examples/perfmon/perfmon.c (revision b3e7694832e81d7a904a10f525f8797b753bf0d3)
18919eed4SGarrett Wollman /*
28919eed4SGarrett Wollman  * Copyright 1996 Massachusetts Institute of Technology
38919eed4SGarrett Wollman  *
48919eed4SGarrett Wollman  * Permission to use, copy, modify, and distribute this software and
58919eed4SGarrett Wollman  * its documentation for any purpose and without fee is hereby
68919eed4SGarrett Wollman  * granted, provided that both the above copyright notice and this
78919eed4SGarrett Wollman  * permission notice appear in all copies, that both the above
88919eed4SGarrett Wollman  * copyright notice and this permission notice appear in all
98919eed4SGarrett Wollman  * supporting documentation, and that the name of M.I.T. not be used
108919eed4SGarrett Wollman  * in advertising or publicity pertaining to distribution of the
118919eed4SGarrett Wollman  * software without specific, written prior permission.  M.I.T. makes
128919eed4SGarrett Wollman  * no representations about the suitability of this software for any
138919eed4SGarrett Wollman  * purpose.  It is provided "as is" without express or implied
148919eed4SGarrett Wollman  * warranty.
158919eed4SGarrett Wollman  *
168919eed4SGarrett Wollman  * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''.  M.I.T. DISCLAIMS
178919eed4SGarrett Wollman  * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
188919eed4SGarrett Wollman  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
198919eed4SGarrett Wollman  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
208919eed4SGarrett Wollman  * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
218919eed4SGarrett Wollman  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
228919eed4SGarrett Wollman  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
238919eed4SGarrett Wollman  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
248919eed4SGarrett Wollman  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
258919eed4SGarrett Wollman  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
268919eed4SGarrett Wollman  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
278919eed4SGarrett Wollman  * SUCH DAMAGE.
288919eed4SGarrett Wollman  */
298919eed4SGarrett Wollman 
308919eed4SGarrett Wollman #include <sys/types.h>
318919eed4SGarrett Wollman #include <sys/ioctl.h>
328919eed4SGarrett Wollman 
33*a29cc9a3SAndriy Gapon #include <machine/cpu.h>
348919eed4SGarrett Wollman #include <machine/perfmon.h>
358919eed4SGarrett Wollman 
368919eed4SGarrett Wollman #include <stdio.h>
378919eed4SGarrett Wollman #include <stdlib.h>
388919eed4SGarrett Wollman #include <string.h>
398919eed4SGarrett Wollman #include <err.h>
408919eed4SGarrett Wollman #include <unistd.h>
418919eed4SGarrett Wollman #include <fcntl.h>
428919eed4SGarrett Wollman #include <limits.h>
438919eed4SGarrett Wollman #include <errno.h>
448919eed4SGarrett Wollman 
458919eed4SGarrett Wollman static int getnum(const char *, int, int);
469018a5cbSBruce Evans static void usage(const char *) __dead2;
478919eed4SGarrett Wollman 
488919eed4SGarrett Wollman int
main(int argc,char ** argv)498919eed4SGarrett Wollman main(int argc, char **argv)
508919eed4SGarrett Wollman {
518919eed4SGarrett Wollman 	int c, fd, num;
528919eed4SGarrett Wollman 	int loops, i, sleeptime;
539018a5cbSBruce Evans 	char *cmd;
548919eed4SGarrett Wollman 	struct pmc pmc;
558919eed4SGarrett Wollman 	struct pmc_tstamp then, now;
568919eed4SGarrett Wollman 	struct pmc_data value;
578919eed4SGarrett Wollman 	quad_t *buf;
588919eed4SGarrett Wollman 	double total;
598919eed4SGarrett Wollman 
608919eed4SGarrett Wollman 	pmc.pmc_num = 0;
618919eed4SGarrett Wollman 	pmc.pmc_event = 0;
628919eed4SGarrett Wollman 	pmc.pmc_unit = 0;
638919eed4SGarrett Wollman 	pmc.pmc_flags = 0;
648919eed4SGarrett Wollman 	pmc.pmc_mask = 0;
659018a5cbSBruce Evans 	cmd = NULL;
668919eed4SGarrett Wollman 	loops = 50;
678919eed4SGarrett Wollman 	sleeptime = 0;
688919eed4SGarrett Wollman 
699018a5cbSBruce Evans 	while ((c = getopt(argc, argv, "s:l:uoeiU:m:c:")) != -1) {
708919eed4SGarrett Wollman 		switch(c) {
718919eed4SGarrett Wollman 		case 'u':
728919eed4SGarrett Wollman 			pmc.pmc_flags |= PMCF_USR;
738919eed4SGarrett Wollman 			break;
748919eed4SGarrett Wollman 		case 'o':
758919eed4SGarrett Wollman 			pmc.pmc_flags |= PMCF_OS;
768919eed4SGarrett Wollman 			break;
778919eed4SGarrett Wollman 		case 'e':
788919eed4SGarrett Wollman 			pmc.pmc_flags |= PMCF_E;
798919eed4SGarrett Wollman 			break;
808919eed4SGarrett Wollman 		case 'i':
818919eed4SGarrett Wollman 			pmc.pmc_flags |= PMCF_INV;
828919eed4SGarrett Wollman 			break;
838919eed4SGarrett Wollman 		case 'U':
848919eed4SGarrett Wollman 			pmc.pmc_unit = getnum(optarg, 0, 256);
858919eed4SGarrett Wollman 			break;
868919eed4SGarrett Wollman 		case 'm':
878919eed4SGarrett Wollman 			pmc.pmc_mask = getnum(optarg, 0, 256);
888919eed4SGarrett Wollman 			break;
898919eed4SGarrett Wollman 		case 'l':
908919eed4SGarrett Wollman 			loops = getnum(optarg, 1, INT_MAX - 1);
918919eed4SGarrett Wollman 			break;
928919eed4SGarrett Wollman 		case 's':
938919eed4SGarrett Wollman 			sleeptime = getnum(optarg, 0, INT_MAX - 1);
948919eed4SGarrett Wollman 			break;
959018a5cbSBruce Evans 		case 'c':
969018a5cbSBruce Evans 			cmd = optarg;
979018a5cbSBruce Evans 			break;
988919eed4SGarrett Wollman 		default:
998919eed4SGarrett Wollman 			usage(argv[0]);
1008919eed4SGarrett Wollman 		}
1018919eed4SGarrett Wollman 	}
1028919eed4SGarrett Wollman 
1038919eed4SGarrett Wollman 	if (argc - optind != 1)
1048919eed4SGarrett Wollman 		usage(argv[0]);
1058919eed4SGarrett Wollman 
1068919eed4SGarrett Wollman 	pmc.pmc_event = getnum(argv[optind], 0, 255);
1078919eed4SGarrett Wollman 
1088919eed4SGarrett Wollman 	buf = malloc((loops + 1) * sizeof *buf);
1098919eed4SGarrett Wollman 	if (!buf)
1108919eed4SGarrett Wollman 		err(1, "malloc(%lu)", (unsigned long)(loops +1) * sizeof *buf);
1118919eed4SGarrett Wollman 
1128919eed4SGarrett Wollman 	fd = open(_PATH_PERFMON, O_RDWR, 0);
1138919eed4SGarrett Wollman 	if (fd < 0)
1148919eed4SGarrett Wollman 		err(1, "open: " _PATH_PERFMON);
1158919eed4SGarrett Wollman 
1168919eed4SGarrett Wollman 	if (ioctl(fd, PMIOSETUP, &pmc) < 0)
1178919eed4SGarrett Wollman 		err(1, "ioctl(PMIOSETUP)");
1188919eed4SGarrett Wollman 
1198919eed4SGarrett Wollman 	if (ioctl(fd, PMIOTSTAMP, &then) < 0)
1208919eed4SGarrett Wollman 		err(1, "ioctl(PMIOTSTAMP)");
1218919eed4SGarrett Wollman 
1228919eed4SGarrett Wollman 	num = 0;
1238919eed4SGarrett Wollman 	if (ioctl(fd, PMIOSTART, &num) < 0)
1248919eed4SGarrett Wollman 		err(1, "ioctl(PMIOSTART)");
1258919eed4SGarrett Wollman 
1268919eed4SGarrett Wollman 	value.pmcd_num = 0;
1278919eed4SGarrett Wollman 	for (i = 0; i < loops; i++) {
1288919eed4SGarrett Wollman 		if (ioctl(fd, PMIOSTOP, &num) < 0)
1298919eed4SGarrett Wollman 			err(1, "ioctl(PMIOSTOP)");
1308919eed4SGarrett Wollman 		if (ioctl(fd, PMIOREAD, &value) < 0)
1318919eed4SGarrett Wollman 			err(1, "ioctl(PMIOREAD)");
1328919eed4SGarrett Wollman 		buf[i] = value.pmcd_value;
1338919eed4SGarrett Wollman 		if (ioctl(fd, PMIORESET, &value.pmcd_num) < 0)
1348919eed4SGarrett Wollman 			err(1, "ioctl(PMIORESET)");
1358919eed4SGarrett Wollman 		if (ioctl(fd, PMIOSTART, &num) < 0)
1368919eed4SGarrett Wollman 			err(1, "ioctl(PMIOSTART)");
1379018a5cbSBruce Evans 		if (sleeptime)
1389018a5cbSBruce Evans 			sleep(sleeptime);
1399018a5cbSBruce Evans 		if (cmd)
1409018a5cbSBruce Evans 			system(cmd);
1418919eed4SGarrett Wollman 	}
1428919eed4SGarrett Wollman 
1438919eed4SGarrett Wollman 	if (ioctl(fd, PMIOSTOP, &num) < 0)
1448919eed4SGarrett Wollman 		err(1, "ioctl(PMIOSTOP)");
1458919eed4SGarrett Wollman 	if (ioctl(fd, PMIOREAD, &value) < 0)
1468919eed4SGarrett Wollman 		err(1, "ioctl(PMIOREAD)");
1478919eed4SGarrett Wollman 	buf[i] = value.pmcd_value;
1488919eed4SGarrett Wollman 	if (ioctl(fd, PMIOTSTAMP, &now) < 0)
1498919eed4SGarrett Wollman 		err(1, "ioctl(PMIOTSTAMP)");
1508919eed4SGarrett Wollman 
1518919eed4SGarrett Wollman 	total = 0;
1528919eed4SGarrett Wollman 	for (i = 1; i <= loops; i++) {
1538919eed4SGarrett Wollman 		printf("%d: %qd\n", i, buf[i]);
1548919eed4SGarrett Wollman 		total += buf[i];
1558919eed4SGarrett Wollman 	}
1568919eed4SGarrett Wollman 	printf("total: %f\nmean: %f\n", total, total / loops);
1578919eed4SGarrett Wollman 
1588919eed4SGarrett Wollman 	printf("clocks (at %d-MHz): %qd\n", now.pmct_rate,
1598919eed4SGarrett Wollman 	       now.pmct_value - then.pmct_value);
1608919eed4SGarrett Wollman 
1618919eed4SGarrett Wollman 	return 0;
1628919eed4SGarrett Wollman }
1638919eed4SGarrett Wollman 
1648919eed4SGarrett Wollman static int
getnum(const char * buf,int min,int max)1658919eed4SGarrett Wollman getnum(const char *buf, int min, int max)
1668919eed4SGarrett Wollman {
1678919eed4SGarrett Wollman 	char *ep;
1688919eed4SGarrett Wollman 	long l;
1698919eed4SGarrett Wollman 
1708919eed4SGarrett Wollman 	errno = 0;
1718919eed4SGarrett Wollman 	l = strtol(buf, &ep, 0);
1728919eed4SGarrett Wollman 	if (*buf && !*ep && !errno) {
1738919eed4SGarrett Wollman 		if (l < min || l > max) {
174258c09afSKevin Lo 			errx(1, "%s: must be between %d and %d",
1758919eed4SGarrett Wollman 			     buf, min, max);
1768919eed4SGarrett Wollman 		}
1778919eed4SGarrett Wollman 		return (int)l;
1788919eed4SGarrett Wollman 	}
179258c09afSKevin Lo 
180258c09afSKevin Lo 	errx(1, "%s: parameter must be an integer", buf);
1818919eed4SGarrett Wollman }
1828919eed4SGarrett Wollman 
1838919eed4SGarrett Wollman static void
usage(const char * pname)1848919eed4SGarrett Wollman usage(const char *pname)
1858919eed4SGarrett Wollman {
1868919eed4SGarrett Wollman 	fprintf(stderr,
1879018a5cbSBruce Evans 	"usage: %s [-eiou] [-c command] [-l nloops] [-m mask] [-s sleeptime]\n"
1889018a5cbSBruce Evans 	"       [-U unit] counter\n",
1899018a5cbSBruce Evans 		pname);
1908919eed4SGarrett Wollman 	exit(1);
1918919eed4SGarrett Wollman }
192