]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - share/examples/perfmon/perfmon.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / share / examples / perfmon / perfmon.c
1 /*
2  * Copyright 1996 Massachusetts Institute of Technology
3  *
4  * Permission to use, copy, modify, and distribute this software and
5  * its documentation for any purpose and without fee is hereby
6  * granted, provided that both the above copyright notice and this
7  * permission notice appear in all copies, that both the above
8  * copyright notice and this permission notice appear in all
9  * supporting documentation, and that the name of M.I.T. not be used
10  * in advertising or publicity pertaining to distribution of the
11  * software without specific, written prior permission.  M.I.T. makes
12  * no representations about the suitability of this software for any
13  * purpose.  It is provided "as is" without express or implied
14  * warranty.
15  * 
16  * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''.  M.I.T. DISCLAIMS
17  * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
18  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
20  * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * $FreeBSD$
30  */
31
32 #include <sys/types.h>
33 #include <sys/ioctl.h>
34
35 #include <machine/cpu.h>
36 #include <machine/perfmon.h>
37
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <err.h>
42 #include <unistd.h>
43 #include <fcntl.h>
44 #include <limits.h>
45 #include <errno.h>
46
47 static int getnum(const char *, int, int);
48 static void usage(const char *) __dead2;
49
50 int
51 main(int argc, char **argv)
52 {
53         int c, fd, num;
54         int loops, i, sleeptime;
55         char *cmd;
56         struct pmc pmc;
57         struct pmc_tstamp then, now;
58         struct pmc_data value;
59         quad_t *buf;
60         double total;
61
62         pmc.pmc_num = 0;
63         pmc.pmc_event = 0;
64         pmc.pmc_unit = 0;
65         pmc.pmc_flags = 0;
66         pmc.pmc_mask = 0;
67         cmd = NULL;
68         loops = 50;
69         sleeptime = 0;
70
71         while ((c = getopt(argc, argv, "s:l:uoeiU:m:c:")) != -1) {
72                 switch(c) {
73                 case 'u':
74                         pmc.pmc_flags |= PMCF_USR;
75                         break;
76                 case 'o':
77                         pmc.pmc_flags |= PMCF_OS;
78                         break;
79                 case 'e':
80                         pmc.pmc_flags |= PMCF_E;
81                         break;
82                 case 'i':
83                         pmc.pmc_flags |= PMCF_INV;
84                         break;
85                 case 'U':
86                         pmc.pmc_unit = getnum(optarg, 0, 256);
87                         break;
88                 case 'm':
89                         pmc.pmc_mask = getnum(optarg, 0, 256);
90                         break;
91                 case 'l':
92                         loops = getnum(optarg, 1, INT_MAX - 1);
93                         break;
94                 case 's':
95                         sleeptime = getnum(optarg, 0, INT_MAX - 1);
96                         break;
97                 case 'c':
98                         cmd = optarg;
99                         break;
100                 default:
101                         usage(argv[0]);
102                 }
103         }
104
105         if (argc - optind != 1)
106                 usage(argv[0]);
107
108         pmc.pmc_event = getnum(argv[optind], 0, 255);
109
110         buf = malloc((loops + 1) * sizeof *buf);
111         if (!buf)
112                 err(1, "malloc(%lu)", (unsigned long)(loops +1) * sizeof *buf);
113
114         fd = open(_PATH_PERFMON, O_RDWR, 0);
115         if (fd < 0)
116                 err(1, "open: " _PATH_PERFMON);
117
118         if (ioctl(fd, PMIOSETUP, &pmc) < 0)
119                 err(1, "ioctl(PMIOSETUP)");
120
121         if (ioctl(fd, PMIOTSTAMP, &then) < 0)
122                 err(1, "ioctl(PMIOTSTAMP)");
123
124         num = 0;
125         if (ioctl(fd, PMIOSTART, &num) < 0)
126                 err(1, "ioctl(PMIOSTART)");
127
128         value.pmcd_num = 0;
129         for (i = 0; i < loops; i++) {
130                 if (ioctl(fd, PMIOSTOP, &num) < 0)
131                         err(1, "ioctl(PMIOSTOP)");
132                 if (ioctl(fd, PMIOREAD, &value) < 0)
133                         err(1, "ioctl(PMIOREAD)");
134                 buf[i] = value.pmcd_value;
135                 if (ioctl(fd, PMIORESET, &value.pmcd_num) < 0)
136                         err(1, "ioctl(PMIORESET)");
137                 if (ioctl(fd, PMIOSTART, &num) < 0)
138                         err(1, "ioctl(PMIOSTART)");
139                 if (sleeptime)
140                         sleep(sleeptime);
141                 if (cmd)
142                         system(cmd);
143         }
144
145         if (ioctl(fd, PMIOSTOP, &num) < 0)
146                 err(1, "ioctl(PMIOSTOP)");
147         if (ioctl(fd, PMIOREAD, &value) < 0)
148                 err(1, "ioctl(PMIOREAD)");
149         buf[i] = value.pmcd_value;
150         if (ioctl(fd, PMIOTSTAMP, &now) < 0)
151                 err(1, "ioctl(PMIOTSTAMP)");
152
153         total = 0;
154         for (i = 1; i <= loops; i++) {
155                 printf("%d: %qd\n", i, buf[i]);
156                 total += buf[i];
157         }
158         printf("total: %f\nmean: %f\n", total, total / loops);
159
160         printf("clocks (at %d-MHz): %qd\n", now.pmct_rate,
161                now.pmct_value - then.pmct_value);
162
163         return 0;
164 }
165
166 static int
167 getnum(const char *buf, int min, int max)
168 {
169         char *ep;
170         long l;
171
172         errno = 0;
173         l = strtol(buf, &ep, 0);
174         if (*buf && !*ep && !errno) {
175                 if (l < min || l > max) {
176                         errx(1, "%s: must be between %d and %d", 
177                              buf, min, max);
178                 }
179                 return (int)l;
180         } 
181
182         errx(1, "%s: parameter must be an integer", buf);
183 }
184
185 static void
186 usage(const char *pname)
187 {
188         fprintf(stderr, 
189         "usage: %s [-eiou] [-c command] [-l nloops] [-m mask] [-s sleeptime]\n"
190         "       [-U unit] counter\n",
191                 pname);
192         exit(1);
193 }