xref: /freebsd/usr.sbin/pmcstat/pmcstat.c (revision ea60845d09e6bcb73038858af28bd191219b610b)
1 /*-
2  * Copyright (c) 2003-2006, Joseph Koshy
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29 
30 #include <sys/types.h>
31 #include <sys/event.h>
32 #include <sys/queue.h>
33 #include <sys/socket.h>
34 #include <sys/stat.h>
35 #include <sys/sysctl.h>
36 #include <sys/time.h>
37 #include <sys/ttycom.h>
38 #include <sys/wait.h>
39 
40 #include <assert.h>
41 #include <err.h>
42 #include <errno.h>
43 #include <fcntl.h>
44 #include <libgen.h>
45 #include <limits.h>
46 #include <math.h>
47 #include <pmc.h>
48 #include <pmclog.h>
49 #include <signal.h>
50 #include <stdarg.h>
51 #include <stdint.h>
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <string.h>
55 #include <sysexits.h>
56 #include <unistd.h>
57 
58 #include "pmcstat.h"
59 
60 /*
61  * A given invocation of pmcstat(8) can manage multiple PMCs of both
62  * the system-wide and per-process variety.  Each of these could be in
63  * 'counting mode' or in 'sampling mode'.
64  *
65  * For 'counting mode' PMCs, pmcstat(8) will periodically issue a
66  * pmc_read() at the configured time interval and print out the value
67  * of the requested PMCs.
68  *
69  * For 'sampling mode' PMCs it can log to a file for offline analysis,
70  * or can analyse sampling data "on the fly", either by converting
71  * samples to printed textual form or by creating gprof(1) compatible
72  * profiles, one per program executed.  When creating gprof(1)
73  * profiles it can optionally merge entries from multiple processes
74  * for a given executable into a single profile file.
75  *
76  * pmcstat(8) can also execute a command line and attach PMCs to the
77  * resulting child process.  The protocol used is as follows:
78  *
79  * - parent creates a socketpair for two way communication and
80  *   fork()s.
81  * - subsequently:
82  *
83  *   /Parent/				/Child/
84  *
85  *   - Wait for childs token.
86  *					- Sends token.
87  *					- Awaits signal to start.
88  *  - Attaches PMCs to the child's pid
89  *    and starts them. Sets up
90  *    monitoring for the child.
91  *  - Signals child to start.
92  *					- Recieves signal, attempts exec().
93  *
94  * After this point normal processing can happen.
95  */
96 
97 /* Globals */
98 
99 int	pmcstat_interrupt = 0;
100 int	pmcstat_displayheight = DEFAULT_DISPLAY_HEIGHT;
101 int	pmcstat_sockpair[NSOCKPAIRFD];
102 int	pmcstat_kq;
103 
104 void
105 pmcstat_attach_pmcs(struct pmcstat_args *a)
106 {
107 	struct pmcstat_ev *ev;
108 
109 	/* Attach all process PMCs to the child process. */
110 	STAILQ_FOREACH(ev, &a->pa_head, ev_next)
111 	    if (PMC_IS_VIRTUAL_MODE(ev->ev_mode) &&
112 		pmc_attach(ev->ev_pmcid, a->pa_pid) != 0)
113 		    err(EX_OSERR, "ERROR: cannot attach pmc \"%s\" to "
114 			"process %d", ev->ev_name, (int) a->pa_pid);
115 
116 }
117 
118 
119 void
120 pmcstat_cleanup(struct pmcstat_args *a)
121 {
122 	struct pmcstat_ev *ev, *tmp;
123 
124 	/* release allocated PMCs. */
125 	STAILQ_FOREACH_SAFE(ev, &a->pa_head, ev_next, tmp)
126 	    if (ev->ev_pmcid != PMC_ID_INVALID) {
127 		if (pmc_release(ev->ev_pmcid) < 0)
128 			err(EX_OSERR, "ERROR: cannot release pmc "
129 			    "0x%x \"%s\"", ev->ev_pmcid, ev->ev_name);
130 		free(ev->ev_name);
131 		free(ev->ev_spec);
132 		STAILQ_REMOVE(&a->pa_head, ev, pmcstat_ev, ev_next);
133 		free(ev);
134 	    }
135 
136 	/* de-configure the log file if present. */
137 	if (a->pa_flags & (FLAG_HAS_PIPE | FLAG_HAS_OUTPUT_LOGFILE))
138 		(void) pmc_configure_logfile(-1);
139 
140 	if (a->pa_logparser) {
141 		pmclog_close(a->pa_logparser);
142 		a->pa_logparser = NULL;
143 	}
144 
145 	if (a->pa_flags & (FLAG_HAS_PIPE | FLAG_HAS_OUTPUT_LOGFILE))
146 		pmcstat_shutdown_logging(a);
147 }
148 
149 void
150 pmcstat_clone_event_descriptor(struct pmcstat_args *a, struct pmcstat_ev *ev,
151     uint32_t cpumask)
152 {
153 	int cpu;
154 	struct pmcstat_ev *ev_clone;
155 
156 	while ((cpu = ffs(cpumask)) > 0) {
157 		cpu--;
158 
159 		if ((ev_clone = malloc(sizeof(*ev_clone))) == NULL)
160 			errx(EX_SOFTWARE, "ERROR: Out of memory");
161 		(void) memset(ev_clone, 0, sizeof(*ev_clone));
162 
163 		ev_clone->ev_count = ev->ev_count;
164 		ev_clone->ev_cpu   = cpu;
165 		ev_clone->ev_cumulative = ev->ev_cumulative;
166 		ev_clone->ev_flags = ev->ev_flags;
167 		ev_clone->ev_mode  = ev->ev_mode;
168 		ev_clone->ev_name  = strdup(ev->ev_name);
169 		ev_clone->ev_pmcid = ev->ev_pmcid;
170 		ev_clone->ev_saved = ev->ev_saved;
171 		ev_clone->ev_spec  = strdup(ev->ev_spec);
172 
173 		STAILQ_INSERT_TAIL(&a->pa_head, ev_clone, ev_next);
174 
175 		cpumask &= ~(1 << cpu);
176 	}
177 }
178 
179 void
180 pmcstat_create_process(struct pmcstat_args *a)
181 {
182 	char token;
183 	struct kevent kev;
184 
185 	if (socketpair(AF_UNIX, SOCK_STREAM, 0, pmcstat_sockpair) < 0)
186 		err(EX_OSERR, "ERROR: cannot create socket pair");
187 
188 	switch (a->pa_pid = fork()) {
189 	case -1:
190 		err(EX_OSERR, "ERROR: cannot fork");
191 		/*NOTREACHED*/
192 
193 	case 0:		/* child */
194 		(void) close(pmcstat_sockpair[PARENTSOCKET]);
195 
196 		/* Write a token to tell our parent we've started executing. */
197 		if (write(pmcstat_sockpair[CHILDSOCKET], "+", 1) != 1)
198 			err(EX_OSERR, "ERROR (child): cannot write token");
199 
200 		/* Wait for our parent to signal us to start. */
201 		if (read(pmcstat_sockpair[CHILDSOCKET], &token, 1) < 0)
202 			err(EX_OSERR, "ERROR (child): cannot read token");
203 		(void) close(pmcstat_sockpair[CHILDSOCKET]);
204 
205 		/* exec() the program requested */
206 		execvp(*a->pa_argv, a->pa_argv);
207 		/* and if that fails, notify the parent */
208 		kill(getppid(), SIGCHLD);
209 		err(EX_OSERR, "ERROR: execvp \"%s\" failed", *a->pa_argv);
210 		/*NOTREACHED*/
211 
212 	default:	/* parent */
213 		(void) close(pmcstat_sockpair[CHILDSOCKET]);
214 		break;
215 	}
216 
217 	/* Ask to be notified via a kevent when the target process exits. */
218 	EV_SET(&kev, a->pa_pid, EVFILT_PROC, EV_ADD|EV_ONESHOT, NOTE_EXIT, 0,
219 	    NULL);
220 	if (kevent(pmcstat_kq, &kev, 1, NULL, 0, NULL) < 0)
221 		err(EX_OSERR, "ERROR: cannot monitor child process %d",
222 		    a->pa_pid);
223 
224 	/* Wait for the child to signal that its ready to go. */
225 	if (read(pmcstat_sockpair[PARENTSOCKET], &token, 1) < 0)
226 		err(EX_OSERR, "ERROR (parent): cannot read token");
227 
228 	return;
229 }
230 
231 uint32_t
232 pmcstat_get_cpumask(const char *cpuspec)
233 {
234 	uint32_t cpumask;
235 	int cpu;
236 	const char *s;
237 	char *end;
238 
239 	s = cpuspec;
240 	cpumask = 0ULL;
241 
242 	do {
243 		cpu = strtol(s, &end, 0);
244 		if (cpu < 0 || end == s)
245 			errx(EX_USAGE, "ERROR: Illegal CPU specification "
246 			    "\"%s\".", cpuspec);
247 		cpumask |= (1 << cpu);
248 		s = end + strspn(end, ", \t");
249 	} while (*s);
250 
251 	return (cpumask);
252 }
253 
254 void
255 pmcstat_start_pmcs(struct pmcstat_args *a)
256 {
257 	struct pmcstat_ev *ev;
258 
259 	STAILQ_FOREACH(ev, &args.pa_head, ev_next) {
260 
261 	    assert(ev->ev_pmcid != PMC_ID_INVALID);
262 
263 	    if (pmc_start(ev->ev_pmcid) < 0) {
264 	        warn("ERROR: Cannot start pmc 0x%x \"%s\"",
265 		    ev->ev_pmcid, ev->ev_name);
266 		pmcstat_cleanup(a);
267 		exit(EX_OSERR);
268 	    }
269 	}
270 
271 }
272 
273 void
274 pmcstat_print_headers(struct pmcstat_args *a)
275 {
276 	struct pmcstat_ev *ev;
277 	int c, w;
278 
279 	(void) fprintf(a->pa_printfile, PRINT_HEADER_PREFIX);
280 
281 	STAILQ_FOREACH(ev, &a->pa_head, ev_next) {
282 		if (PMC_IS_SAMPLING_MODE(ev->ev_mode))
283 			continue;
284 
285 		c = PMC_IS_SYSTEM_MODE(ev->ev_mode) ? 's' : 'p';
286 
287 		if (ev->ev_fieldskip != 0)
288 			(void) fprintf(a->pa_printfile, "%*s",
289 			    ev->ev_fieldskip, "");
290 		w = ev->ev_fieldwidth - ev->ev_fieldskip - 2;
291 
292 		if (c == 's')
293 			(void) fprintf(a->pa_printfile, "s/%02d/%-*s ",
294 			    ev->ev_cpu, w-3, ev->ev_name);
295 		else
296 			(void) fprintf(a->pa_printfile, "p/%*s ", w,
297 			    ev->ev_name);
298 	}
299 
300 	(void) fflush(a->pa_printfile);
301 }
302 
303 void
304 pmcstat_print_counters(struct pmcstat_args *a)
305 {
306 	int extra_width;
307 	struct pmcstat_ev *ev;
308 	pmc_value_t value;
309 
310 	extra_width = sizeof(PRINT_HEADER_PREFIX) - 1;
311 
312 	STAILQ_FOREACH(ev, &a->pa_head, ev_next) {
313 
314 		/* skip sampling mode counters */
315 		if (PMC_IS_SAMPLING_MODE(ev->ev_mode))
316 			continue;
317 
318 		if (pmc_read(ev->ev_pmcid, &value) < 0)
319 			err(EX_OSERR, "ERROR: Cannot read pmc "
320 			    "\"%s\"", ev->ev_name);
321 
322 		(void) fprintf(a->pa_printfile, "%*ju ",
323 		    ev->ev_fieldwidth + extra_width,
324 		    (uintmax_t) ev->ev_cumulative ? value :
325 		    (value - ev->ev_saved));
326 
327 		if (ev->ev_cumulative == 0)
328 			ev->ev_saved = value;
329 		extra_width = 0;
330 	}
331 
332 	(void) fflush(a->pa_printfile);
333 }
334 
335 /*
336  * Print output
337  */
338 
339 void
340 pmcstat_print_pmcs(struct pmcstat_args *a)
341 {
342 	static int linecount = 0;
343 
344 	/* check if we need to print a header line */
345 	if (++linecount > pmcstat_displayheight) {
346 		(void) fprintf(a->pa_printfile, "\n");
347 		linecount = 1;
348 	}
349 	if (linecount == 1)
350 		pmcstat_print_headers(a);
351 	(void) fprintf(a->pa_printfile, "\n");
352 
353 	pmcstat_print_counters(a);
354 
355 	return;
356 }
357 
358 /*
359  * Do process profiling
360  *
361  * If a pid was specified, attach each allocated PMC to the target
362  * process.  Otherwise, fork a child and attach the PMCs to the child,
363  * and have the child exec() the target program.
364  */
365 
366 void
367 pmcstat_start_process(void)
368 {
369 	/* Signal the child to proceed. */
370 	if (write(pmcstat_sockpair[PARENTSOCKET], "!", 1) != 1)
371 		err(EX_OSERR, "ERROR (parent): write of token failed");
372 
373 	(void) close(pmcstat_sockpair[PARENTSOCKET]);
374 }
375 
376 void
377 pmcstat_show_usage(void)
378 {
379 	errx(EX_USAGE,
380 	    "[options] [commandline]\n"
381 	    "\t Measure process and/or system performance using hardware\n"
382 	    "\t performance monitoring counters.\n"
383 	    "\t Options include:\n"
384 	    "\t -C\t\t (toggle) show cumulative counts\n"
385 	    "\t -D path\t create profiles in directory \"path\"\n"
386 	    "\t -E\t\t (toggle) show counts at process exit\n"
387 	    "\t -M file\t print executable/gmon file map to \"file\"\n"
388 	    "\t -O file\t send log output to \"file\"\n"
389 	    "\t -P spec\t allocate a process-private sampling PMC\n"
390 	    "\t -R file\t read events from \"file\"\n"
391 	    "\t -S spec\t allocate a system-wide sampling PMC\n"
392 	    "\t -W\t\t (toggle) show counts per context switch\n"
393 	    "\t -c cpu-list\t set cpus for subsequent system-wide PMCs\n"
394 	    "\t -d\t\t (toggle) track descendants\n"
395 	    "\t -g\t\t produce gprof(1) compatible profiles\n"
396 	    "\t -k dir\t\t set the path to the kernel\n"
397 	    "\t -n rate\t set sampling rate\n"
398 	    "\t -o file\t send print output to \"file\"\n"
399 	    "\t -p spec\t allocate a process-private counting PMC\n"
400 	    "\t -q\t\t suppress verbosity\n"
401 	    "\t -r fsroot\t specify FS root directory\n"
402 	    "\t -s spec\t allocate a system-wide counting PMC\n"
403 	    "\t -t pid\t\t attach to running process with pid \"pid\"\n"
404 	    "\t -v\t\t increase verbosity\n"
405 	    "\t -w secs\t set printing time interval"
406 	);
407 }
408 
409 /*
410  * Main
411  */
412 
413 int
414 main(int argc, char **argv)
415 {
416 	double interval;
417 	int option, npmc, ncpu;
418 	int c, check_driver_stats, current_cpu, current_sampling_count;
419 	int do_print, do_descendants;
420 	int do_logproccsw, do_logprocexit;
421 	size_t dummy;
422 	int pipefd[2];
423 	int use_cumulative_counts;
424 	uint32_t cpumask;
425 	pid_t pid;
426 	char *end, *tmp;
427 	const char *errmsg;
428 	enum pmcstat_state runstate;
429 	struct pmc_driverstats ds_start, ds_end;
430 	struct pmcstat_ev *ev;
431 	struct sigaction sa;
432 	struct kevent kev;
433 	struct winsize ws;
434 	struct stat sb;
435 	char buffer[PATH_MAX];
436 
437 	check_driver_stats      = 0;
438 	current_cpu 		= 0;
439 	current_sampling_count  = DEFAULT_SAMPLE_COUNT;
440 	do_descendants          = 0;
441 	do_logproccsw           = 0;
442 	do_logprocexit          = 0;
443 	use_cumulative_counts   = 0;
444 	args.pa_required	= 0;
445 	args.pa_flags		= 0;
446 	args.pa_verbosity	= 1;
447 	args.pa_pid		= (pid_t) -1;
448 	args.pa_logfd		= -1;
449 	args.pa_fsroot		= "";
450 	args.pa_kernel		= strdup("/boot/kernel");
451 	args.pa_samplesdir	= ".";
452 	args.pa_printfile	= stderr;
453 	args.pa_interval	= DEFAULT_WAIT_INTERVAL;
454 	args.pa_mapfilename	= NULL;
455 	STAILQ_INIT(&args.pa_head);
456 	bzero(&ds_start, sizeof(ds_start));
457 	bzero(&ds_end, sizeof(ds_end));
458 	ev = NULL;
459 
460 	dummy = sizeof(ncpu);
461 	if (sysctlbyname("hw.ncpu", &ncpu, &dummy, NULL, 0) < 0)
462 		err(EX_OSERR, "ERROR: Cannot determine #cpus");
463 	cpumask = (1 << ncpu) - 1;
464 
465 	while ((option = getopt(argc, argv,
466 	    "CD:EM:O:P:R:S:Wc:dgk:n:o:p:qr:s:t:vw:")) != -1)
467 		switch (option) {
468 		case 'C':	/* cumulative values */
469 			use_cumulative_counts = !use_cumulative_counts;
470 			args.pa_required |= FLAG_HAS_COUNTING_PMCS;
471 			break;
472 
473 		case 'c':	/* CPU */
474 
475 			if (optarg[0] == '*' && optarg[1] == '\0')
476 				cpumask = (1 << ncpu) - 1;
477 			else
478 				cpumask = pmcstat_get_cpumask(optarg);
479 
480 			args.pa_required |= FLAG_HAS_SYSTEM_PMCS;
481 			break;
482 
483 		case 'D':
484 			if (stat(optarg, &sb) < 0)
485 				err(EX_OSERR, "ERROR: Cannot stat \"%s\"",
486 				    optarg);
487 			if (!S_ISDIR(sb.st_mode))
488 				errx(EX_USAGE, "ERROR: \"%s\" is not a "
489 				    "directory.", optarg);
490 			args.pa_samplesdir = optarg;
491 			args.pa_flags     |= FLAG_HAS_SAMPLESDIR;
492 			args.pa_required  |= FLAG_DO_GPROF;
493 			break;
494 
495 		case 'd':	/* toggle descendents */
496 			do_descendants = !do_descendants;
497 			args.pa_required |= FLAG_HAS_PROCESS_PMCS;
498 			break;
499 
500 		case 'g':	/* produce gprof compatible profiles */
501 			args.pa_flags |= FLAG_DO_GPROF;
502 			break;
503 
504 		case 'k':	/* pathname to the kernel */
505 			free(args.pa_kernel);
506 			args.pa_kernel = strdup(optarg);
507 			args.pa_required |= FLAG_DO_GPROF;
508 			args.pa_flags    |= FLAG_HAS_KERNELPATH;
509 			break;
510 
511 		case 'E':	/* log process exit */
512 			do_logprocexit = !do_logprocexit;
513 			args.pa_required |= (FLAG_HAS_PROCESS_PMCS |
514 			    FLAG_HAS_COUNTING_PMCS | FLAG_HAS_OUTPUT_LOGFILE);
515 			break;
516 
517 		case 'M':	/* mapfile */
518 			args.pa_mapfilename = optarg;
519 			break;
520 
521 		case 'p':	/* process virtual counting PMC */
522 		case 's':	/* system-wide counting PMC */
523 		case 'P':	/* process virtual sampling PMC */
524 		case 'S':	/* system-wide sampling PMC */
525 			if ((ev = malloc(sizeof(*ev))) == NULL)
526 				errx(EX_SOFTWARE, "ERROR: Out of memory.");
527 
528 			switch (option) {
529 			case 'p': ev->ev_mode = PMC_MODE_TC; break;
530 			case 's': ev->ev_mode = PMC_MODE_SC; break;
531 			case 'P': ev->ev_mode = PMC_MODE_TS; break;
532 			case 'S': ev->ev_mode = PMC_MODE_SS; break;
533 			}
534 
535 			if (option == 'P' || option == 'p') {
536 				args.pa_flags |= FLAG_HAS_PROCESS_PMCS;
537 				args.pa_required |= (FLAG_HAS_COMMANDLINE |
538 				    FLAG_HAS_PID);
539 			}
540 
541 			if (option == 'P' || option == 'S') {
542 				args.pa_flags |= FLAG_HAS_SAMPLING_PMCS;
543 				args.pa_required |= (FLAG_HAS_PIPE |
544 				    FLAG_HAS_OUTPUT_LOGFILE);
545 			}
546 
547 			if (option == 'p' || option == 's')
548 				args.pa_flags |= FLAG_HAS_COUNTING_PMCS;
549 
550 			if (option == 's' || option == 'S')
551 				args.pa_flags |= FLAG_HAS_SYSTEM_PMCS;
552 
553 			ev->ev_spec  = strdup(optarg);
554 
555 			if (option == 'S' || option == 'P')
556 				ev->ev_count = current_sampling_count;
557 			else
558 				ev->ev_count = -1;
559 
560 			if (option == 'S' || option == 's')
561 				ev->ev_cpu = ffs(cpumask) - 1;
562 			else
563 				ev->ev_cpu = PMC_CPU_ANY;
564 
565 			ev->ev_flags = 0;
566 			if (do_descendants)
567 				ev->ev_flags |= PMC_F_DESCENDANTS;
568 			if (do_logprocexit)
569 				ev->ev_flags |= PMC_F_LOG_PROCEXIT;
570 			if (do_logproccsw)
571 				ev->ev_flags |= PMC_F_LOG_PROCCSW;
572 
573 			ev->ev_cumulative  = use_cumulative_counts;
574 
575 			ev->ev_saved = 0LL;
576 			ev->ev_pmcid = PMC_ID_INVALID;
577 
578 			/* extract event name */
579 			c = strcspn(optarg, ", \t");
580 			ev->ev_name = malloc(c + 1);
581 			(void) strncpy(ev->ev_name, optarg, c);
582 			*(ev->ev_name + c) = '\0';
583 
584 			STAILQ_INSERT_TAIL(&args.pa_head, ev, ev_next);
585 
586 			if (option == 's' || option == 'S')
587 				pmcstat_clone_event_descriptor(&args, ev,
588 				    cpumask & ~(1 << ev->ev_cpu));
589 
590 			break;
591 
592 		case 'n':	/* sampling count */
593 			current_sampling_count = strtol(optarg, &end, 0);
594 			if (*end != '\0' || current_sampling_count <= 0)
595 				errx(EX_USAGE,
596 				    "ERROR: Illegal count value \"%s\".",
597 				    optarg);
598 			args.pa_required |= FLAG_HAS_SAMPLING_PMCS;
599 			break;
600 
601 		case 'o':	/* outputfile */
602 			if (args.pa_printfile != NULL)
603 				(void) fclose(args.pa_printfile);
604 			if ((args.pa_printfile = fopen(optarg, "w")) == NULL)
605 				errx(EX_OSERR, "ERROR: cannot open \"%s\" for "
606 				    "writing.", optarg);
607 			args.pa_flags |= FLAG_DO_PRINT;
608 			break;
609 
610 		case 'O':	/* sampling output */
611 			if (args.pa_outputpath)
612 				errx(EX_USAGE, "ERROR: option -O may only be "
613 				    "specified once.");
614 			args.pa_outputpath = optarg;
615 			args.pa_flags |= FLAG_HAS_OUTPUT_LOGFILE;
616 			break;
617 
618 		case 'q':	/* quiet mode */
619 			args.pa_verbosity = 0;
620 			break;
621 
622 		case 'r':	/* root FS path */
623 			args.pa_fsroot = optarg;
624 			break;
625 
626 		case 'R':	/* read an existing log file */
627 			if (args.pa_logparser != NULL)
628 				errx(EX_USAGE, "ERROR: option -R may only be "
629 				    "specified once.");
630 			args.pa_inputpath = optarg;
631 			if (args.pa_printfile == stderr)
632 				args.pa_printfile = stdout;
633 			args.pa_flags |= FLAG_READ_LOGFILE;
634 			break;
635 
636 		case 't':	/* target pid */
637 			pid = strtol(optarg, &end, 0);
638 			if (*end != '\0' || pid <= 0)
639 				errx(EX_USAGE, "ERROR: Illegal pid value "
640 				    "\"%s\".", optarg);
641 
642 			args.pa_flags |= FLAG_HAS_PID;
643 			args.pa_required |= FLAG_HAS_PROCESS_PMCS;
644 			args.pa_pid = pid;
645 			break;
646 
647 		case 'v':	/* verbose */
648 			args.pa_verbosity++;
649 			break;
650 
651 		case 'w':	/* wait interval */
652 			interval = strtod(optarg, &end);
653 			if (*end != '\0' || interval <= 0)
654 				errx(EX_USAGE, "ERROR: Illegal wait interval "
655 				    "value \"%s\".", optarg);
656 			args.pa_flags |= FLAG_HAS_WAIT_INTERVAL;
657 			args.pa_required |= FLAG_HAS_COUNTING_PMCS;
658 			args.pa_interval = interval;
659 			break;
660 
661 		case 'W':	/* toggle LOG_CSW */
662 			do_logproccsw = !do_logproccsw;
663 			args.pa_required |= (FLAG_HAS_PROCESS_PMCS |
664 			    FLAG_HAS_COUNTING_PMCS | FLAG_HAS_OUTPUT_LOGFILE);
665 			break;
666 
667 		case '?':
668 		default:
669 			pmcstat_show_usage();
670 			break;
671 
672 		}
673 
674 	args.pa_argc = (argc -= optind);
675 	args.pa_argv = (argv += optind);
676 
677 	if (argc)	/* command line present */
678 		args.pa_flags |= FLAG_HAS_COMMANDLINE;
679 
680 	/*
681 	 * Check invocation syntax.
682 	 */
683 
684 	/* disallow -O and -R together */
685 	if (args.pa_outputpath && args.pa_inputpath)
686 		errx(EX_USAGE, "ERROR: options -O and -R are mutually "
687 		    "exclusive.");
688 
689 	if (args.pa_flags & FLAG_READ_LOGFILE) {
690 		errmsg = NULL;
691 		if (args.pa_flags & FLAG_HAS_COMMANDLINE)
692 			errmsg = "a command line specification";
693 		else if (args.pa_flags & FLAG_HAS_PID)
694 			errmsg = "option -t";
695 		else if (!STAILQ_EMPTY(&args.pa_head))
696 			errmsg = "a PMC event specification";
697 		if (errmsg)
698 			errx(EX_USAGE, "ERROR: option -R may not be used with "
699 			    "%s.", errmsg);
700 	} else if (STAILQ_EMPTY(&args.pa_head))
701 		/* All other uses require a PMC spec. */
702 		pmcstat_show_usage();
703 
704 	/* check for -t pid without a process PMC spec */
705 	if ((args.pa_required & FLAG_HAS_PID) &&
706 	    (args.pa_flags & FLAG_HAS_PROCESS_PMCS) == 0)
707 		errx(EX_USAGE, "ERROR: option -t requires a process mode PMC "
708 		    "to be specified.");
709 
710 	/* check for process-mode options without a command or -t pid */
711 	if ((args.pa_required & FLAG_HAS_PROCESS_PMCS) &&
712 	    (args.pa_flags & (FLAG_HAS_COMMANDLINE | FLAG_HAS_PID)) == 0)
713 		errx(EX_USAGE, "ERROR: options -d, -E, -p, -P, and -W require "
714 		    "a command line or target process.");
715 
716 	/* check for -p | -P without a target process of some sort */
717 	if ((args.pa_required & (FLAG_HAS_COMMANDLINE | FLAG_HAS_PID)) &&
718 	    (args.pa_flags & (FLAG_HAS_COMMANDLINE | FLAG_HAS_PID)) == 0)
719 		errx(EX_USAGE, "ERROR: options -P and -p require a "
720 		    "target process or a command line.");
721 
722 	/* check for process-mode options without a process-mode PMC */
723 	if ((args.pa_required & FLAG_HAS_PROCESS_PMCS) &&
724 	    (args.pa_flags & FLAG_HAS_PROCESS_PMCS) == 0)
725 		errx(EX_USAGE, "ERROR: options -d, -E, and -W require a "
726 		    "process mode PMC to be specified.");
727 
728 	/* check for -c cpu and not system mode PMCs */
729 	if ((args.pa_required & FLAG_HAS_SYSTEM_PMCS) &&
730 	    (args.pa_flags & FLAG_HAS_SYSTEM_PMCS) == 0)
731 		errx(EX_USAGE, "ERROR: option -c requires at least one "
732 		    "system mode PMC to be specified.");
733 
734 	/* check for counting mode options without a counting PMC */
735 	if ((args.pa_required & FLAG_HAS_COUNTING_PMCS) &&
736 	    (args.pa_flags & FLAG_HAS_COUNTING_PMCS) == 0)
737 		errx(EX_USAGE, "ERROR: options -C, -W, -o and -w require at "
738 		    "least one counting mode PMC to be specified.");
739 
740 	/* check for sampling mode options without a sampling PMC spec */
741 	if ((args.pa_required & FLAG_HAS_SAMPLING_PMCS) &&
742 	    (args.pa_flags & FLAG_HAS_SAMPLING_PMCS) == 0)
743 		errx(EX_USAGE, "ERROR: options -n and -O require at least "
744 		    "one sampling mode PMC to be specified.");
745 
746 	if ((args.pa_flags & (FLAG_HAS_PID | FLAG_HAS_COMMANDLINE)) ==
747 	    (FLAG_HAS_PID | FLAG_HAS_COMMANDLINE))
748 		errx(EX_USAGE,
749 		    "ERROR: option -t cannot be specified with a command "
750 		    "line.");
751 
752 	/* check if -g is being used correctly */
753 	if ((args.pa_flags & FLAG_DO_GPROF) &&
754 	    !(args.pa_flags & (FLAG_HAS_SAMPLING_PMCS|FLAG_READ_LOGFILE)))
755 		errx(EX_USAGE, "ERROR: option -g requires sampling PMCs or -R "
756 		    "to be specified.");
757 
758 	/* check if -O was spuriously specified */
759 	if ((args.pa_flags & FLAG_HAS_OUTPUT_LOGFILE) &&
760 	    (args.pa_required & FLAG_HAS_OUTPUT_LOGFILE) == 0)
761 		errx(EX_USAGE,
762 		    "ERROR: option -O is used only with options "
763 		    "-E, -P, -S and -W.");
764 
765 	/* -D dir and -k kernel path require -g or -R */
766 	if ((args.pa_flags & FLAG_HAS_KERNELPATH) &&
767 	    (args.pa_flags & FLAG_DO_GPROF) == 0 &&
768 	    (args.pa_flags & FLAG_READ_LOGFILE) == 0)
769 	    errx(EX_USAGE, "ERROR: option -k is only used with -g/-R.");
770 
771 	if ((args.pa_flags & FLAG_HAS_SAMPLESDIR) &&
772 	    (args.pa_flags & FLAG_DO_GPROF) == 0 &&
773 	    (args.pa_flags & FLAG_READ_LOGFILE) == 0)
774 	    errx(EX_USAGE, "ERROR: option -D is only used with -g/-R.");
775 
776 	/* -M mapfile requires -g or -R */
777 	if (args.pa_mapfilename != NULL &&
778 	    (args.pa_flags & FLAG_DO_GPROF) == 0 &&
779 	    (args.pa_flags & FLAG_READ_LOGFILE) == 0)
780 	    errx(EX_USAGE, "ERROR: option -M is only used with -g/-R.");
781 
782 	/*
783 	 * Disallow textual output of sampling PMCs if counting PMCs
784 	 * have also been asked for, mostly because the combined output
785 	 * is difficult to make sense of.
786 	 */
787 	if ((args.pa_flags & FLAG_HAS_COUNTING_PMCS) &&
788 	    (args.pa_flags & FLAG_HAS_SAMPLING_PMCS) &&
789 	    ((args.pa_flags & FLAG_HAS_OUTPUT_LOGFILE) == 0))
790 		errx(EX_USAGE, "ERROR: option -O is required if counting and "
791 		    "sampling PMCs are specified together.");
792 
793 	/*
794 	 * Check if "-k kerneldir" was specified, and if whether 'kerneldir'
795 	 * actually refers to a a file.  If so, use `dirname path` to determine
796 	 * the kernel directory.
797 	 */
798 	if (args.pa_flags & FLAG_HAS_KERNELPATH) {
799 		(void) snprintf(buffer, sizeof(buffer), "%s%s", args.pa_fsroot,
800 		    args.pa_kernel);
801 		if (stat(buffer, &sb) < 0)
802 			err(EX_OSERR, "ERROR: Cannot locate kernel \"%s\"",
803 			    buffer);
804 		if (!S_ISREG(sb.st_mode) && !S_ISDIR(sb.st_mode))
805 			errx(EX_USAGE, "ERROR: \"%s\": Unsupported file type.",
806 			    buffer);
807 		if (!S_ISDIR(sb.st_mode)) {
808 			tmp = args.pa_kernel;
809 			args.pa_kernel = strdup(dirname(args.pa_kernel));
810 			free(tmp);
811 			(void) snprintf(buffer, sizeof(buffer), "%s%s",
812 			    args.pa_fsroot, args.pa_kernel);
813 			if (stat(buffer, &sb) < 0)
814 				err(EX_OSERR, "ERROR: Cannot stat \"%s\"",
815 				    buffer);
816 			if (!S_ISDIR(sb.st_mode))
817 				errx(EX_USAGE, "ERROR: \"%s\" is not a "
818 				    "directory.", buffer);
819 		}
820 	}
821 
822 	/* if we've been asked to process a log file, do that and exit */
823 	if (args.pa_flags & FLAG_READ_LOGFILE) {
824 		/*
825 		 * Print the log in textual form if we haven't been
826 		 * asked to generate gmon.out files.
827 		 */
828 		if ((args.pa_flags & FLAG_DO_GPROF) == 0)
829 			args.pa_flags |= FLAG_DO_PRINT;
830 
831 		pmcstat_initialize_logging(&args);
832 		args.pa_logfd = pmcstat_open_log(args.pa_inputpath,
833 		    PMCSTAT_OPEN_FOR_READ);
834 		if ((args.pa_logparser = pmclog_open(args.pa_logfd)) == NULL)
835 			err(EX_OSERR, "ERROR: Cannot create parser");
836 		pmcstat_process_log(&args);
837 		pmcstat_shutdown_logging(&args);
838 		exit(EX_OK);
839 	}
840 
841 	/* otherwise, we've been asked to collect data */
842 	if (pmc_init() < 0)
843 		err(EX_UNAVAILABLE,
844 		    "ERROR: Initialization of the pmc(3) library failed");
845 
846 	if ((npmc = pmc_npmc(0)) < 0) /* assume all CPUs are identical */
847 		err(EX_OSERR, "ERROR: Cannot determine the number of PMCs "
848 		    "on CPU %d", 0);
849 
850 	/* Allocate a kqueue */
851 	if ((pmcstat_kq = kqueue()) < 0)
852 		err(EX_OSERR, "ERROR: Cannot allocate kqueue");
853 
854 	/*
855 	 * Configure the specified log file or setup a default log
856 	 * consumer via a pipe.
857 	 */
858 	if (args.pa_required & FLAG_HAS_OUTPUT_LOGFILE) {
859 		if (args.pa_outputpath)
860 			args.pa_logfd = pmcstat_open_log(args.pa_outputpath,
861 			    PMCSTAT_OPEN_FOR_WRITE);
862 		else {
863 			/*
864 			 * process the log on the fly by reading it in
865 			 * through a pipe.
866 			 */
867 			if (pipe(pipefd) < 0)
868 				err(EX_OSERR, "ERROR: pipe(2) failed");
869 
870 			if (fcntl(pipefd[READPIPEFD], F_SETFL, O_NONBLOCK) < 0)
871 				err(EX_OSERR, "ERROR: fcntl(2) failed");
872 
873 			EV_SET(&kev, pipefd[READPIPEFD], EVFILT_READ, EV_ADD,
874 			    0, 0, NULL);
875 
876 			if (kevent(pmcstat_kq, &kev, 1, NULL, 0, NULL) < 0)
877 				err(EX_OSERR, "ERROR: Cannot register kevent");
878 
879 			args.pa_logfd = pipefd[WRITEPIPEFD];
880 
881 			args.pa_flags |= (FLAG_HAS_PIPE | FLAG_DO_PRINT);
882 			args.pa_logparser = pmclog_open(pipefd[READPIPEFD]);
883 		}
884 
885 		if (pmc_configure_logfile(args.pa_logfd) < 0)
886 			err(EX_OSERR, "ERROR: Cannot configure log file");
887 	}
888 
889 	/* remember to check for driver errors if we are sampling or logging */
890 	check_driver_stats = (args.pa_flags & FLAG_HAS_SAMPLING_PMCS) ||
891 	    (args.pa_flags & FLAG_HAS_OUTPUT_LOGFILE);
892 
893 	/*
894 	 * Allocate PMCs.
895 	 */
896 
897 	STAILQ_FOREACH(ev, &args.pa_head, ev_next) {
898 	    if (pmc_allocate(ev->ev_spec, ev->ev_mode,
899 		    ev->ev_flags, ev->ev_cpu, &ev->ev_pmcid) < 0)
900 		    err(EX_OSERR, "ERROR: Cannot allocate %s-mode pmc with "
901 			"specification \"%s\"",
902 			PMC_IS_SYSTEM_MODE(ev->ev_mode) ? "system" : "process",
903 			ev->ev_spec);
904 
905 	    if (PMC_IS_SAMPLING_MODE(ev->ev_mode) &&
906 		pmc_set(ev->ev_pmcid, ev->ev_count) < 0)
907 		    err(EX_OSERR, "ERROR: Cannot set sampling count "
908 			"for PMC \"%s\"", ev->ev_name);
909 	}
910 
911 	/* compute printout widths */
912 	STAILQ_FOREACH(ev, &args.pa_head, ev_next) {
913 		int counter_width;
914 		int display_width;
915 		int header_width;
916 
917 		(void) pmc_width(ev->ev_pmcid, &counter_width);
918 		header_width = strlen(ev->ev_name) + 2; /* prefix '%c/' */
919 		display_width = (int) floor(counter_width / 3.32193) + 1;
920 
921 		if (PMC_IS_SYSTEM_MODE(ev->ev_mode))
922 			header_width += 3; /* 2 digit CPU number + '/' */
923 
924 		if (header_width > display_width) {
925 			ev->ev_fieldskip = 0;
926 			ev->ev_fieldwidth = header_width;
927 		} else {
928 			ev->ev_fieldskip = display_width -
929 			    header_width;
930 			ev->ev_fieldwidth = display_width;
931 		}
932 	}
933 
934 	/*
935 	 * If our output is being set to a terminal, register a handler
936 	 * for window size changes.
937 	 */
938 
939 	if (isatty(fileno(args.pa_printfile))) {
940 
941 		if (ioctl(fileno(args.pa_printfile), TIOCGWINSZ, &ws) < 0)
942 			err(EX_OSERR, "ERROR: Cannot determine window size");
943 
944 		pmcstat_displayheight = ws.ws_row - 1;
945 
946 		EV_SET(&kev, SIGWINCH, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
947 
948 		if (kevent(pmcstat_kq, &kev, 1, NULL, 0, NULL) < 0)
949 			err(EX_OSERR, "ERROR: Cannot register kevent for "
950 			    "SIGWINCH");
951 	}
952 
953 	EV_SET(&kev, SIGINT, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
954 	if (kevent(pmcstat_kq, &kev, 1, NULL, 0, NULL) < 0)
955 		err(EX_OSERR, "ERROR: Cannot register kevent for SIGINT");
956 
957 	EV_SET(&kev, SIGIO, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
958 	if (kevent(pmcstat_kq, &kev, 1, NULL, 0, NULL) < 0)
959 		err(EX_OSERR, "ERROR: Cannot register kevent for SIGIO");
960 
961 	/*
962 	 * An exec() failure of a forked child is signalled by the
963 	 * child sending the parent a SIGCHLD.  We don't register an
964 	 * actual signal handler for SIGCHLD, but instead use our
965 	 * kqueue to pick up the signal.
966 	 */
967 	EV_SET(&kev, SIGCHLD, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
968 	if (kevent(pmcstat_kq, &kev, 1, NULL, 0, NULL) < 0)
969 		err(EX_OSERR, "ERROR: Cannot register kevent for SIGCHLD");
970 
971 	/* setup a timer if we have counting mode PMCs needing to be printed */
972 	if ((args.pa_flags & FLAG_HAS_COUNTING_PMCS) &&
973 	    (args.pa_required & FLAG_HAS_OUTPUT_LOGFILE) == 0) {
974 		EV_SET(&kev, 0, EVFILT_TIMER, EV_ADD, 0,
975 		    args.pa_interval * 1000, NULL);
976 
977 		if (kevent(pmcstat_kq, &kev, 1, NULL, 0, NULL) < 0)
978 			err(EX_OSERR, "ERROR: Cannot register kevent for "
979 			    "timer");
980 	}
981 
982 	/* attach PMCs to the target process, starting it if specified */
983 	if (args.pa_flags & FLAG_HAS_COMMANDLINE)
984 		pmcstat_create_process(&args);
985 
986 	if (check_driver_stats && pmc_get_driver_stats(&ds_start) < 0)
987 		err(EX_OSERR, "ERROR: Cannot retrieve driver statistics");
988 
989 	/* Attach process pmcs to the target process. */
990 	if (args.pa_pid != -1)
991 		pmcstat_attach_pmcs(&args);
992 
993 	/* start the pmcs */
994 	pmcstat_start_pmcs(&args);
995 
996 	/* start the (commandline) process if needed */
997 	if (args.pa_flags & FLAG_HAS_COMMANDLINE)
998 		pmcstat_start_process();
999 
1000 	/* initialize logging if printing the configured log */
1001 	if ((args.pa_flags & FLAG_DO_PRINT) &&
1002 	    (args.pa_flags & (FLAG_HAS_PIPE | FLAG_HAS_OUTPUT_LOGFILE)))
1003 		pmcstat_initialize_logging(&args);
1004 
1005 	/* Handle SIGINT using the kqueue loop */
1006 	sa.sa_handler = SIG_IGN;
1007 	sa.sa_flags   = 0;
1008 	(void) sigemptyset(&sa.sa_mask);
1009 
1010 	if (sigaction(SIGINT, &sa, NULL) < 0)
1011 		err(EX_OSERR, "ERROR: Cannot install signal handler");
1012 
1013 	/*
1014 	 * loop till either the target process (if any) exits, or we
1015 	 * are killed by a SIGINT.
1016 	 */
1017 	runstate = PMCSTAT_RUNNING;
1018 	do_print = 0;
1019 	do {
1020 		if ((c = kevent(pmcstat_kq, NULL, 0, &kev, 1, NULL)) <= 0) {
1021 			if (errno != EINTR)
1022 				err(EX_OSERR, "ERROR: kevent failed");
1023 			else
1024 				continue;
1025 		}
1026 
1027 		if (kev.flags & EV_ERROR)
1028 			errc(EX_OSERR, kev.data, "ERROR: kevent failed");
1029 
1030 		switch (kev.filter) {
1031 		case EVFILT_PROC:  /* target has exited */
1032 			if (args.pa_flags & (FLAG_HAS_OUTPUT_LOGFILE |
1033 				FLAG_HAS_PIPE))
1034 				runstate = pmcstat_close_log(&args);
1035 			else
1036 				runstate = PMCSTAT_FINISHED;
1037 			do_print = 1;
1038 			break;
1039 
1040 		case EVFILT_READ:  /* log file data is present */
1041 			runstate = pmcstat_process_log(&args);
1042 			break;
1043 
1044 		case EVFILT_SIGNAL:
1045 			if (kev.ident == SIGCHLD) {
1046 				/*
1047 				 * The child process sends us a
1048 				 * SIGCHLD if its exec() failed.  We
1049 				 * wait for it to exit and then exit
1050 				 * ourselves.
1051 				 */
1052 				(void) wait(&c);
1053 				runstate = PMCSTAT_FINISHED;
1054 			} else if (kev.ident == SIGIO) {
1055 				/*
1056 				 * We get a SIGIO if a PMC loses all
1057 				 * of its targets, or if logfile
1058 				 * writes encounter an error.
1059 				 */
1060 				if (args.pa_flags & (FLAG_HAS_OUTPUT_LOGFILE |
1061 				    FLAG_HAS_PIPE)) {
1062 					runstate = pmcstat_close_log(&args);
1063 					if (args.pa_flags &
1064 					    (FLAG_DO_PRINT|FLAG_DO_GPROF))
1065 						pmcstat_process_log(&args);
1066 				}
1067 				do_print = 1; /* print PMCs at exit */
1068 				runstate = PMCSTAT_FINISHED;
1069 			} else if (kev.ident == SIGINT) {
1070 				/* Kill the child process if we started it */
1071 				if (args.pa_flags & FLAG_HAS_COMMANDLINE)
1072 					if (kill(args.pa_pid, SIGINT) != 0)
1073 						err(EX_OSERR, "ERROR: cannot "
1074 						    "signal child process");
1075 				runstate = PMCSTAT_FINISHED;
1076 			} else if (kev.ident == SIGWINCH) {
1077 				if (ioctl(fileno(args.pa_printfile),
1078 					TIOCGWINSZ, &ws) < 0)
1079 				    err(EX_OSERR, "ERROR: Cannot determine "
1080 					"window size");
1081 				pmcstat_displayheight = ws.ws_row - 1;
1082 			} else
1083 				assert(0);
1084 
1085 			break;
1086 
1087 		case EVFILT_TIMER: /* print out counting PMCs */
1088 			do_print = 1;
1089 			break;
1090 
1091 		}
1092 
1093 		if (do_print &&
1094 		    (args.pa_required & FLAG_HAS_OUTPUT_LOGFILE) == 0) {
1095 			pmcstat_print_pmcs(&args);
1096 			if (runstate == PMCSTAT_FINISHED && /* final newline */
1097 			    (args.pa_flags & FLAG_DO_PRINT) == 0)
1098 				(void) fprintf(args.pa_printfile, "\n");
1099 			do_print = 0;
1100 		}
1101 
1102 	} while (runstate != PMCSTAT_FINISHED);
1103 
1104 	/* flush any pending log entries */
1105 	if (args.pa_flags & (FLAG_HAS_OUTPUT_LOGFILE | FLAG_HAS_PIPE))
1106 		pmc_flush_logfile();
1107 
1108 	pmcstat_cleanup(&args);
1109 
1110 	free(args.pa_kernel);
1111 
1112 	/* check if the driver lost any samples or events */
1113 	if (check_driver_stats) {
1114 		if (pmc_get_driver_stats(&ds_end) < 0)
1115 			err(EX_OSERR, "ERROR: Cannot retrieve driver "
1116 			    "statistics");
1117 		if (ds_start.pm_intr_bufferfull != ds_end.pm_intr_bufferfull &&
1118 		    args.pa_verbosity > 0)
1119 			warnx("WARNING: some samples were dropped.  Please "
1120 			    "consider tuning the \"kern.hwpmc.nsamples\" "
1121 			    "tunable.");
1122 		if (ds_start.pm_buffer_requests_failed !=
1123 		    ds_end.pm_buffer_requests_failed &&
1124 		    args.pa_verbosity > 0)
1125 			warnx("WARNING: some events were discarded.  Please "
1126 			    "consider tuning the \"kern.hwpmc.nbuffers\" "
1127 			    "tunable.");
1128 	}
1129 
1130 	exit(EX_OK);
1131 }
1132