Deleted Added
full compact
pmcstat.c (153704) pmcstat.c (157144)
1/*-
1/*-
2 * Copyright (c) 2003-2005, Joseph Koshy
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

--- 9 unchanged lines hidden (view full) ---

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>
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

--- 9 unchanged lines hidden (view full) ---

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: head/usr.sbin/pmcstat/pmcstat.c 153704 2005-12-24 17:00:33Z jkoshy $");
28__FBSDID("$FreeBSD: head/usr.sbin/pmcstat/pmcstat.c 157144 2006-03-26 12:20:54Z jkoshy $");
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/time.h>
36#include <sys/ttycom.h>
37#include <sys/wait.h>
38
39#include <assert.h>
40#include <err.h>
41#include <errno.h>
42#include <fcntl.h>
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/time.h>
36#include <sys/ttycom.h>
37#include <sys/wait.h>
38
39#include <assert.h>
40#include <err.h>
41#include <errno.h>
42#include <fcntl.h>
43#include <libgen.h>
43#include <limits.h>
44#include <math.h>
45#include <pmc.h>
46#include <pmclog.h>
47#include <signal.h>
48#include <stdarg.h>
49#include <stdint.h>
50#include <stdio.h>

--- 54 unchanged lines hidden (view full) ---

105 (void) pmc_configure_logfile(-1);
106
107 if (a->pa_logparser) {
108 pmclog_close(a->pa_logparser);
109 a->pa_logparser = NULL;
110 }
111
112 if (a->pa_flags & (FLAG_HAS_PIPE | FLAG_HAS_OUTPUT_LOGFILE))
44#include <limits.h>
45#include <math.h>
46#include <pmc.h>
47#include <pmclog.h>
48#include <signal.h>
49#include <stdarg.h>
50#include <stdint.h>
51#include <stdio.h>

--- 54 unchanged lines hidden (view full) ---

106 (void) pmc_configure_logfile(-1);
107
108 if (a->pa_logparser) {
109 pmclog_close(a->pa_logparser);
110 a->pa_logparser = NULL;
111 }
112
113 if (a->pa_flags & (FLAG_HAS_PIPE | FLAG_HAS_OUTPUT_LOGFILE))
113 pmcstat_shutdown_logging();
114 pmcstat_shutdown_logging(a);
114}
115
116void
117pmcstat_start_pmcs(struct pmcstat_args *a)
118{
119 struct pmcstat_ev *ev;
120
121 STAILQ_FOREACH(ev, &args.pa_head, ev_next) {

--- 190 unchanged lines hidden (view full) ---

312 errx(EX_USAGE,
313 "[options] [commandline]\n"
314 "\t Measure process and/or system performance using hardware\n"
315 "\t performance monitoring counters.\n"
316 "\t Options include:\n"
317 "\t -C\t\t (toggle) show cumulative counts\n"
318 "\t -D path\t create profiles in directory \"path\"\n"
319 "\t -E\t\t (toggle) show counts at process exit\n"
115}
116
117void
118pmcstat_start_pmcs(struct pmcstat_args *a)
119{
120 struct pmcstat_ev *ev;
121
122 STAILQ_FOREACH(ev, &args.pa_head, ev_next) {

--- 190 unchanged lines hidden (view full) ---

313 errx(EX_USAGE,
314 "[options] [commandline]\n"
315 "\t Measure process and/or system performance using hardware\n"
316 "\t performance monitoring counters.\n"
317 "\t Options include:\n"
318 "\t -C\t\t (toggle) show cumulative counts\n"
319 "\t -D path\t create profiles in directory \"path\"\n"
320 "\t -E\t\t (toggle) show counts at process exit\n"
321 "\t -M file\t print executable/gmon file map to \"file\"\n"
320 "\t -O file\t send log output to \"file\"\n"
321 "\t -P spec\t allocate a process-private sampling PMC\n"
322 "\t -R file\t read events from \"file\"\n"
323 "\t -S spec\t allocate a system-wide sampling PMC\n"
324 "\t -W\t\t (toggle) show counts per context switch\n"
325 "\t -c cpu\t\t set cpu for subsequent system-wide PMCs\n"
326 "\t -d\t\t (toggle) track descendants\n"
327 "\t -g\t\t produce gprof(1) compatible profiles\n"
322 "\t -O file\t send log output to \"file\"\n"
323 "\t -P spec\t allocate a process-private sampling PMC\n"
324 "\t -R file\t read events from \"file\"\n"
325 "\t -S spec\t allocate a system-wide sampling PMC\n"
326 "\t -W\t\t (toggle) show counts per context switch\n"
327 "\t -c cpu\t\t set cpu for subsequent system-wide PMCs\n"
328 "\t -d\t\t (toggle) track descendants\n"
329 "\t -g\t\t produce gprof(1) compatible profiles\n"
328 "\t -k file\t set the path to the kernel\n"
330 "\t -k dir\t set the path to the kernel\n"
329 "\t -n rate\t set sampling rate\n"
330 "\t -o file\t send print output to \"file\"\n"
331 "\t -p spec\t allocate a process-private counting PMC\n"
331 "\t -n rate\t set sampling rate\n"
332 "\t -o file\t send print output to \"file\"\n"
333 "\t -p spec\t allocate a process-private counting PMC\n"
334 "\t -q\t\t suppress verbosity\n"
335 "\t -r fsroot\t specify FS root directory\n"
332 "\t -s spec\t allocate a system-wide counting PMC\n"
333 "\t -t pid\t\t attach to running process with pid \"pid\"\n"
336 "\t -s spec\t allocate a system-wide counting PMC\n"
337 "\t -t pid\t\t attach to running process with pid \"pid\"\n"
338 "\t -v\t\t increase verbosity\n"
334 "\t -w secs\t set printing time interval"
335 );
336}
337
338/*
339 * Main
340 */
341
342int
343main(int argc, char **argv)
344{
345 double interval;
346 int option, npmc, ncpu;
347 int c, check_driver_stats, current_cpu, current_sampling_count;
348 int do_print, do_descendants;
349 int do_logproccsw, do_logprocexit;
350 int pipefd[2];
351 int use_cumulative_counts;
352 pid_t pid;
339 "\t -w secs\t set printing time interval"
340 );
341}
342
343/*
344 * Main
345 */
346
347int
348main(int argc, char **argv)
349{
350 double interval;
351 int option, npmc, ncpu;
352 int c, check_driver_stats, current_cpu, current_sampling_count;
353 int do_print, do_descendants;
354 int do_logproccsw, do_logprocexit;
355 int pipefd[2];
356 int use_cumulative_counts;
357 pid_t pid;
353 char *end;
358 char *end, *tmp;
354 const char *errmsg;
355 enum pmcstat_state runstate;
356 struct pmc_driverstats ds_start, ds_end;
357 struct pmcstat_ev *ev;
358 struct sigaction sa;
359 struct kevent kev;
360 struct winsize ws;
361 struct stat sb;
359 const char *errmsg;
360 enum pmcstat_state runstate;
361 struct pmc_driverstats ds_start, ds_end;
362 struct pmcstat_ev *ev;
363 struct sigaction sa;
364 struct kevent kev;
365 struct winsize ws;
366 struct stat sb;
367 char buffer[PATH_MAX];
362
363 check_driver_stats = 0;
364 current_cpu = 0;
365 current_sampling_count = DEFAULT_SAMPLE_COUNT;
366 do_descendants = 0;
367 do_logproccsw = 0;
368 do_logprocexit = 0;
369 use_cumulative_counts = 0;
370 args.pa_required = 0;
371 args.pa_flags = 0;
368
369 check_driver_stats = 0;
370 current_cpu = 0;
371 current_sampling_count = DEFAULT_SAMPLE_COUNT;
372 do_descendants = 0;
373 do_logproccsw = 0;
374 do_logprocexit = 0;
375 use_cumulative_counts = 0;
376 args.pa_required = 0;
377 args.pa_flags = 0;
378 args.pa_verbosity = 1;
372 args.pa_pid = (pid_t) -1;
373 args.pa_logfd = -1;
379 args.pa_pid = (pid_t) -1;
380 args.pa_logfd = -1;
381 args.pa_fsroot = "";
382 args.pa_kernel = strdup("/boot/kernel");
374 args.pa_samplesdir = ".";
383 args.pa_samplesdir = ".";
375 args.pa_kernel = "/boot/kernel/kernel";
376 args.pa_printfile = stderr;
377 args.pa_interval = DEFAULT_WAIT_INTERVAL;
384 args.pa_printfile = stderr;
385 args.pa_interval = DEFAULT_WAIT_INTERVAL;
386 args.pa_mapfilename = NULL;
378 STAILQ_INIT(&args.pa_head);
379 bzero(&ds_start, sizeof(ds_start));
380 bzero(&ds_end, sizeof(ds_end));
381 ev = NULL;
382
387 STAILQ_INIT(&args.pa_head);
388 bzero(&ds_start, sizeof(ds_start));
389 bzero(&ds_end, sizeof(ds_end));
390 ev = NULL;
391
383 while ((option = getopt(argc, argv, "CD:EO:P:R:S:Wc:dgk:n:o:p:s:t:w:"))
384 != -1)
392 while ((option = getopt(argc, argv,
393 "CD:EM:O:P:R:S:Wc:dgk:n:o:p:qr:s:t:vw:")) != -1)
385 switch (option) {
386 case 'C': /* cumulative values */
387 use_cumulative_counts = !use_cumulative_counts;
388 args.pa_required |= FLAG_HAS_COUNTING_PMCS;
389 break;
390
391 case 'c': /* CPU */
392 current_cpu = strtol(optarg, &end, 0);

--- 21 unchanged lines hidden (view full) ---

414 args.pa_required |= FLAG_HAS_PROCESS_PMCS;
415 break;
416
417 case 'g': /* produce gprof compatible profiles */
418 args.pa_flags |= FLAG_DO_GPROF;
419 break;
420
421 case 'k': /* pathname to the kernel */
394 switch (option) {
395 case 'C': /* cumulative values */
396 use_cumulative_counts = !use_cumulative_counts;
397 args.pa_required |= FLAG_HAS_COUNTING_PMCS;
398 break;
399
400 case 'c': /* CPU */
401 current_cpu = strtol(optarg, &end, 0);

--- 21 unchanged lines hidden (view full) ---

423 args.pa_required |= FLAG_HAS_PROCESS_PMCS;
424 break;
425
426 case 'g': /* produce gprof compatible profiles */
427 args.pa_flags |= FLAG_DO_GPROF;
428 break;
429
430 case 'k': /* pathname to the kernel */
422 args.pa_kernel = optarg;
431 free(args.pa_kernel);
432 args.pa_kernel = strdup(optarg);
423 args.pa_required |= FLAG_DO_GPROF;
424 args.pa_flags |= FLAG_HAS_KERNELPATH;
425 break;
426
427 case 'E': /* log process exit */
428 do_logprocexit = !do_logprocexit;
429 args.pa_required |= (FLAG_HAS_PROCESS_PMCS |
430 FLAG_HAS_COUNTING_PMCS | FLAG_HAS_OUTPUT_LOGFILE);
431 break;
432
433 args.pa_required |= FLAG_DO_GPROF;
434 args.pa_flags |= FLAG_HAS_KERNELPATH;
435 break;
436
437 case 'E': /* log process exit */
438 do_logprocexit = !do_logprocexit;
439 args.pa_required |= (FLAG_HAS_PROCESS_PMCS |
440 FLAG_HAS_COUNTING_PMCS | FLAG_HAS_OUTPUT_LOGFILE);
441 break;
442
443 case 'M': /* mapfile */
444 args.pa_mapfilename = optarg;
445 break;
446
433 case 'p': /* process virtual counting PMC */
434 case 's': /* system-wide counting PMC */
435 case 'P': /* process virtual sampling PMC */
436 case 'S': /* system-wide sampling PMC */
437 if ((ev = malloc(sizeof(*ev))) == NULL)
438 errx(EX_SOFTWARE, "ERROR: Out of memory.");
439
440 switch (option) {

--- 77 unchanged lines hidden (view full) ---

518 case 'O': /* sampling output */
519 if (args.pa_outputpath)
520 errx(EX_USAGE, "ERROR: option -O may only be "
521 "specified once.");
522 args.pa_outputpath = optarg;
523 args.pa_flags |= FLAG_HAS_OUTPUT_LOGFILE;
524 break;
525
447 case 'p': /* process virtual counting PMC */
448 case 's': /* system-wide counting PMC */
449 case 'P': /* process virtual sampling PMC */
450 case 'S': /* system-wide sampling PMC */
451 if ((ev = malloc(sizeof(*ev))) == NULL)
452 errx(EX_SOFTWARE, "ERROR: Out of memory.");
453
454 switch (option) {

--- 77 unchanged lines hidden (view full) ---

532 case 'O': /* sampling output */
533 if (args.pa_outputpath)
534 errx(EX_USAGE, "ERROR: option -O may only be "
535 "specified once.");
536 args.pa_outputpath = optarg;
537 args.pa_flags |= FLAG_HAS_OUTPUT_LOGFILE;
538 break;
539
540 case 'q': /* quiet mode */
541 args.pa_verbosity = 0;
542 break;
543
544 case 'r': /* root FS path */
545 args.pa_fsroot = optarg;
546 break;
547
526 case 'R': /* read an existing log file */
527 if (args.pa_logparser != NULL)
528 errx(EX_USAGE, "ERROR: option -R may only be "
529 "specified once.");
530 args.pa_inputpath = optarg;
531 if (args.pa_printfile == stderr)
532 args.pa_printfile = stdout;
533 args.pa_flags |= FLAG_READ_LOGFILE;

--- 5 unchanged lines hidden (view full) ---

539 errx(EX_USAGE, "ERROR: Illegal pid value "
540 "\"%s\".", optarg);
541
542 args.pa_flags |= FLAG_HAS_PID;
543 args.pa_required |= FLAG_HAS_PROCESS_PMCS;
544 args.pa_pid = pid;
545 break;
546
548 case 'R': /* read an existing log file */
549 if (args.pa_logparser != NULL)
550 errx(EX_USAGE, "ERROR: option -R may only be "
551 "specified once.");
552 args.pa_inputpath = optarg;
553 if (args.pa_printfile == stderr)
554 args.pa_printfile = stdout;
555 args.pa_flags |= FLAG_READ_LOGFILE;

--- 5 unchanged lines hidden (view full) ---

561 errx(EX_USAGE, "ERROR: Illegal pid value "
562 "\"%s\".", optarg);
563
564 args.pa_flags |= FLAG_HAS_PID;
565 args.pa_required |= FLAG_HAS_PROCESS_PMCS;
566 args.pa_pid = pid;
567 break;
568
569 case 'v': /* verbose */
570 args.pa_verbosity++;
571 break;
572
547 case 'w': /* wait interval */
548 interval = strtod(optarg, &end);
549 if (*end != '\0' || interval <= 0)
550 errx(EX_USAGE, "ERROR: Illegal wait interval "
551 "value \"%s\".", optarg);
552 args.pa_flags |= FLAG_HAS_WAIT_INTERVAL;
553 args.pa_required |= FLAG_HAS_COUNTING_PMCS;
554 args.pa_interval = interval;

--- 98 unchanged lines hidden (view full) ---

653
654 /* check if -O was spuriously specified */
655 if ((args.pa_flags & FLAG_HAS_OUTPUT_LOGFILE) &&
656 (args.pa_required & FLAG_HAS_OUTPUT_LOGFILE) == 0)
657 errx(EX_USAGE,
658 "ERROR: option -O is used only with options "
659 "-E, -P, -S and -W.");
660
573 case 'w': /* wait interval */
574 interval = strtod(optarg, &end);
575 if (*end != '\0' || interval <= 0)
576 errx(EX_USAGE, "ERROR: Illegal wait interval "
577 "value \"%s\".", optarg);
578 args.pa_flags |= FLAG_HAS_WAIT_INTERVAL;
579 args.pa_required |= FLAG_HAS_COUNTING_PMCS;
580 args.pa_interval = interval;

--- 98 unchanged lines hidden (view full) ---

679
680 /* check if -O was spuriously specified */
681 if ((args.pa_flags & FLAG_HAS_OUTPUT_LOGFILE) &&
682 (args.pa_required & FLAG_HAS_OUTPUT_LOGFILE) == 0)
683 errx(EX_USAGE,
684 "ERROR: option -O is used only with options "
685 "-E, -P, -S and -W.");
686
661 /* -D dir and -k kernel path require -g */
687 /* -D dir and -k kernel path require -g or -R */
662 if ((args.pa_flags & FLAG_HAS_KERNELPATH) &&
688 if ((args.pa_flags & FLAG_HAS_KERNELPATH) &&
663 ((args.pa_flags & FLAG_DO_GPROF) == 0))
664 errx(EX_USAGE, "ERROR: option -k is only used with -g.");
689 (args.pa_flags & FLAG_DO_GPROF) == 0 &&
690 (args.pa_flags & FLAG_READ_LOGFILE) == 0)
691 errx(EX_USAGE, "ERROR: option -k is only used with -g/-R.");
665
666 if ((args.pa_flags & FLAG_HAS_SAMPLESDIR) &&
692
693 if ((args.pa_flags & FLAG_HAS_SAMPLESDIR) &&
667 ((args.pa_flags & FLAG_DO_GPROF) == 0))
668 errx(EX_USAGE, "ERROR: option -D is only used with -g.");
694 (args.pa_flags & FLAG_DO_GPROF) == 0 &&
695 (args.pa_flags & FLAG_READ_LOGFILE) == 0)
696 errx(EX_USAGE, "ERROR: option -D is only used with -g/-R.");
669
697
698 /* -M mapfile requires -g or -R */
699 if (args.pa_mapfilename != NULL &&
700 (args.pa_flags & FLAG_DO_GPROF) == 0 &&
701 (args.pa_flags & FLAG_READ_LOGFILE) == 0)
702 errx(EX_USAGE, "ERROR: option -M is only used with -g/-R.");
703
670 /*
671 * Disallow textual output of sampling PMCs if counting PMCs
672 * have also been asked for, mostly because the combined output
673 * is difficult to make sense of.
674 */
675 if ((args.pa_flags & FLAG_HAS_COUNTING_PMCS) &&
676 (args.pa_flags & FLAG_HAS_SAMPLING_PMCS) &&
677 ((args.pa_required & FLAG_HAS_OUTPUT_LOGFILE) == 0))
678 errx(EX_USAGE, "ERROR: option -O is required if counting and "
679 "sampling PMCs are specified together.");
680
704 /*
705 * Disallow textual output of sampling PMCs if counting PMCs
706 * have also been asked for, mostly because the combined output
707 * is difficult to make sense of.
708 */
709 if ((args.pa_flags & FLAG_HAS_COUNTING_PMCS) &&
710 (args.pa_flags & FLAG_HAS_SAMPLING_PMCS) &&
711 ((args.pa_required & FLAG_HAS_OUTPUT_LOGFILE) == 0))
712 errx(EX_USAGE, "ERROR: option -O is required if counting and "
713 "sampling PMCs are specified together.");
714
715 /*
716 * Check if "-k kerneldir" was specified, and if whether 'kerneldir'
717 * actually refers to a a file. If so, use `dirname path` to determine
718 * the kernel directory.
719 */
720 if (args.pa_flags & FLAG_HAS_KERNELPATH) {
721 (void) snprintf(buffer, sizeof(buffer), "%s%s", args.pa_fsroot,
722 args.pa_kernel);
723 if (stat(buffer, &sb) < 0)
724 err(EX_OSERR, "ERROR: Cannot locate kernel \"%s\"",
725 buffer);
726 if (!S_ISREG(sb.st_mode) && !S_ISDIR(sb.st_mode))
727 errx(EX_USAGE, "ERROR: \"%s\": Unsupported file type.",
728 buffer);
729 if (!S_ISDIR(sb.st_mode)) {
730 tmp = args.pa_kernel;
731 args.pa_kernel = strdup(dirname(args.pa_kernel));
732 free(tmp);
733 (void) snprintf(buffer, sizeof(buffer), "%s%s",
734 args.pa_fsroot, args.pa_kernel);
735 if (stat(buffer, &sb) < 0)
736 err(EX_OSERR, "ERROR: Cannot stat \"%s\"",
737 buffer);
738 if (!S_ISDIR(sb.st_mode))
739 errx(EX_USAGE, "ERROR: \"%s\" is not a "
740 "directory.", buffer);
741 }
742 }
743
681 /* if we've been asked to process a log file, do that and exit */
682 if (args.pa_flags & FLAG_READ_LOGFILE) {
683 /*
684 * Print the log in textual form if we haven't been
685 * asked to generate gmon.out files.
686 */
687 if ((args.pa_flags & FLAG_DO_GPROF) == 0)
688 args.pa_flags |= FLAG_DO_PRINT;
689
690 pmcstat_initialize_logging(&args);
744 /* if we've been asked to process a log file, do that and exit */
745 if (args.pa_flags & FLAG_READ_LOGFILE) {
746 /*
747 * Print the log in textual form if we haven't been
748 * asked to generate gmon.out files.
749 */
750 if ((args.pa_flags & FLAG_DO_GPROF) == 0)
751 args.pa_flags |= FLAG_DO_PRINT;
752
753 pmcstat_initialize_logging(&args);
691 if ((args.pa_logfd = pmcstat_open(args.pa_inputpath,
754 if ((args.pa_logfd = pmcstat_open_log(args.pa_inputpath,
692 PMCSTAT_OPEN_FOR_READ)) < 0)
693 err(EX_OSERR, "ERROR: Cannot open \"%s\" for "
694 "reading", args.pa_inputpath);
695 if ((args.pa_logparser = pmclog_open(args.pa_logfd)) == NULL)
696 err(EX_OSERR, "ERROR: Cannot create parser");
697 pmcstat_process_log(&args);
755 PMCSTAT_OPEN_FOR_READ)) < 0)
756 err(EX_OSERR, "ERROR: Cannot open \"%s\" for "
757 "reading", args.pa_inputpath);
758 if ((args.pa_logparser = pmclog_open(args.pa_logfd)) == NULL)
759 err(EX_OSERR, "ERROR: Cannot create parser");
760 pmcstat_process_log(&args);
761 pmcstat_shutdown_logging(&args);
698 exit(EX_OK);
699 }
700
701 /* otherwise, we've been asked to collect data */
702 if (pmc_init() < 0)
703 err(EX_UNAVAILABLE,
704 "ERROR: Initialization of the pmc(3) library failed");
705

--- 10 unchanged lines hidden (view full) ---

716 err(EX_OSERR, "ERROR: Cannot allocate kqueue");
717
718 /*
719 * Configure the specified log file or setup a default log
720 * consumer via a pipe.
721 */
722 if (args.pa_required & FLAG_HAS_OUTPUT_LOGFILE) {
723 if (args.pa_outputpath) {
762 exit(EX_OK);
763 }
764
765 /* otherwise, we've been asked to collect data */
766 if (pmc_init() < 0)
767 err(EX_UNAVAILABLE,
768 "ERROR: Initialization of the pmc(3) library failed");
769

--- 10 unchanged lines hidden (view full) ---

780 err(EX_OSERR, "ERROR: Cannot allocate kqueue");
781
782 /*
783 * Configure the specified log file or setup a default log
784 * consumer via a pipe.
785 */
786 if (args.pa_required & FLAG_HAS_OUTPUT_LOGFILE) {
787 if (args.pa_outputpath) {
724 if ((args.pa_logfd = pmcstat_open(args.pa_outputpath,
788 if ((args.pa_logfd =
789 pmcstat_open_log(args.pa_outputpath,
725 PMCSTAT_OPEN_FOR_WRITE)) < 0)
726 err(EX_OSERR, "ERROR: Cannot open \"%s\" for "
727 "writing", args.pa_outputpath);
728 } else {
729 /*
730 * process the log on the fly by reading it in
731 * through a pipe.
732 */

--- 228 unchanged lines hidden (view full) ---

961 } while (runstate != PMCSTAT_FINISHED);
962
963 /* flush any pending log entries */
964 if (args.pa_flags & (FLAG_HAS_OUTPUT_LOGFILE | FLAG_HAS_PIPE))
965 pmc_flush_logfile();
966
967 pmcstat_cleanup(&args);
968
790 PMCSTAT_OPEN_FOR_WRITE)) < 0)
791 err(EX_OSERR, "ERROR: Cannot open \"%s\" for "
792 "writing", args.pa_outputpath);
793 } else {
794 /*
795 * process the log on the fly by reading it in
796 * through a pipe.
797 */

--- 228 unchanged lines hidden (view full) ---

1026 } while (runstate != PMCSTAT_FINISHED);
1027
1028 /* flush any pending log entries */
1029 if (args.pa_flags & (FLAG_HAS_OUTPUT_LOGFILE | FLAG_HAS_PIPE))
1030 pmc_flush_logfile();
1031
1032 pmcstat_cleanup(&args);
1033
1034 free(args.pa_kernel);
1035
969 /* check if the driver lost any samples or events */
970 if (check_driver_stats) {
971 if (pmc_get_driver_stats(&ds_end) < 0)
972 err(EX_OSERR, "ERROR: Cannot retrieve driver "
973 "statistics");
1036 /* check if the driver lost any samples or events */
1037 if (check_driver_stats) {
1038 if (pmc_get_driver_stats(&ds_end) < 0)
1039 err(EX_OSERR, "ERROR: Cannot retrieve driver "
1040 "statistics");
974 if (ds_start.pm_intr_bufferfull != ds_end.pm_intr_bufferfull)
1041 if (ds_start.pm_intr_bufferfull != ds_end.pm_intr_bufferfull &&
1042 args.pa_verbosity > 0)
975 warnx("WARNING: some samples were dropped. Please "
976 "consider tuning the \"kern.hwpmc.nsamples\" "
977 "tunable.");
978 if (ds_start.pm_buffer_requests_failed !=
1043 warnx("WARNING: some samples were dropped. Please "
1044 "consider tuning the \"kern.hwpmc.nsamples\" "
1045 "tunable.");
1046 if (ds_start.pm_buffer_requests_failed !=
979 ds_end.pm_buffer_requests_failed)
1047 ds_end.pm_buffer_requests_failed &&
1048 args.pa_verbosity > 0)
980 warnx("WARNING: some events were discarded. Please "
981 "consider tuning the \"kern.hwpmc.nbuffers\" "
982 "tunable.");
983 }
984
985 exit(EX_OK);
986}
1049 warnx("WARNING: some events were discarded. Please "
1050 "consider tuning the \"kern.hwpmc.nbuffers\" "
1051 "tunable.");
1052 }
1053
1054 exit(EX_OK);
1055}