Deleted Added
full compact
pmcstat.c (169069) pmcstat.c (174396)
1/*-
2 * Copyright (c) 2003-2007, Joseph Koshy
1/*-
2 * Copyright (c) 2003-2007, Joseph Koshy
3 * Copyright (c) 2007 The FreeBSD Foundation
3 * All rights reserved.
4 *
4 * All rights reserved.
5 *
6 * Portions of this software were developed by A. Joseph Koshy under
7 * sponsorship from the FreeBSD Foundation and Google, Inc.
8 *
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.

--- 7 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>
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.

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

24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/usr.sbin/pmcstat/pmcstat.c 169069 2007-04-27 12:09:31Z jkoshy $");
32__FBSDID("$FreeBSD: head/usr.sbin/pmcstat/pmcstat.c 174396 2007-12-07 08:26:21Z jkoshy $");
29
30#include <sys/types.h>
31#include <sys/event.h>
32#include <sys/param.h>
33#include <sys/queue.h>
34#include <sys/socket.h>
35#include <sys/stat.h>
36#include <sys/sysctl.h>

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

481 errx(EX_USAGE,
482 "[options] [commandline]\n"
483 "\t Measure process and/or system performance using hardware\n"
484 "\t performance monitoring counters.\n"
485 "\t Options include:\n"
486 "\t -C\t\t (toggle) show cumulative counts\n"
487 "\t -D path\t create profiles in directory \"path\"\n"
488 "\t -E\t\t (toggle) show counts at process exit\n"
33
34#include <sys/types.h>
35#include <sys/event.h>
36#include <sys/param.h>
37#include <sys/queue.h>
38#include <sys/socket.h>
39#include <sys/stat.h>
40#include <sys/sysctl.h>

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

485 errx(EX_USAGE,
486 "[options] [commandline]\n"
487 "\t Measure process and/or system performance using hardware\n"
488 "\t performance monitoring counters.\n"
489 "\t Options include:\n"
490 "\t -C\t\t (toggle) show cumulative counts\n"
491 "\t -D path\t create profiles in directory \"path\"\n"
492 "\t -E\t\t (toggle) show counts at process exit\n"
493 "\t -G file\t write a system-wide callgraph to \"file\"\n"
489 "\t -M file\t print executable/gmon file map to \"file\"\n"
494 "\t -M file\t print executable/gmon file map to \"file\"\n"
495 "\t -N\t\t (toggle) capture callchains\n"
490 "\t -O file\t send log output to \"file\"\n"
491 "\t -P spec\t allocate a process-private sampling PMC\n"
492 "\t -R file\t read events from \"file\"\n"
493 "\t -S spec\t allocate a system-wide sampling PMC\n"
494 "\t -W\t\t (toggle) show counts per context switch\n"
495 "\t -c cpu-list\t set cpus for subsequent system-wide PMCs\n"
496 "\t -d\t\t (toggle) track descendants\n"
497 "\t -g\t\t produce gprof(1) compatible profiles\n"
498 "\t -k dir\t\t set the path to the kernel\n"
499 "\t -n rate\t set sampling rate\n"
500 "\t -o file\t send print output to \"file\"\n"
501 "\t -p spec\t allocate a process-private counting PMC\n"
502 "\t -q\t\t suppress verbosity\n"
503 "\t -r fsroot\t specify FS root directory\n"
504 "\t -s spec\t allocate a system-wide counting PMC\n"
505 "\t -t pid\t\t attach to running process with pid \"pid\"\n"
506 "\t -v\t\t increase verbosity\n"
496 "\t -O file\t send log output to \"file\"\n"
497 "\t -P spec\t allocate a process-private sampling PMC\n"
498 "\t -R file\t read events from \"file\"\n"
499 "\t -S spec\t allocate a system-wide sampling PMC\n"
500 "\t -W\t\t (toggle) show counts per context switch\n"
501 "\t -c cpu-list\t set cpus for subsequent system-wide PMCs\n"
502 "\t -d\t\t (toggle) track descendants\n"
503 "\t -g\t\t produce gprof(1) compatible profiles\n"
504 "\t -k dir\t\t set the path to the kernel\n"
505 "\t -n rate\t set sampling rate\n"
506 "\t -o file\t send print output to \"file\"\n"
507 "\t -p spec\t allocate a process-private counting PMC\n"
508 "\t -q\t\t suppress verbosity\n"
509 "\t -r fsroot\t specify FS root directory\n"
510 "\t -s spec\t allocate a system-wide counting PMC\n"
511 "\t -t pid\t\t attach to running process with pid \"pid\"\n"
512 "\t -v\t\t increase verbosity\n"
507 "\t -w secs\t set printing time interval"
513 "\t -w secs\t set printing time interval\n"
514 "\t -z depth\t limit callchain display depth"
508 );
509}
510
511/*
512 * Main
513 */
514
515int
516main(int argc, char **argv)
517{
518 double interval;
515 );
516}
517
518/*
519 * Main
520 */
521
522int
523main(int argc, char **argv)
524{
525 double interval;
519 int option, npmc, ncpu;
526 int option, npmc, ncpu, haltedcpus;
520 int c, check_driver_stats, current_cpu, current_sampling_count;
527 int c, check_driver_stats, current_cpu, current_sampling_count;
521 int do_print, do_descendants;
522 int do_logproccsw, do_logprocexit;
528 int do_callchain, do_descendants, do_logproccsw, do_logprocexit;
529 int do_print;
523 size_t dummy;
530 size_t dummy;
531 int graphdepth;
524 int pipefd[2];
525 int use_cumulative_counts;
526 uint32_t cpumask;
527 char *end, *tmp;
532 int pipefd[2];
533 int use_cumulative_counts;
534 uint32_t cpumask;
535 char *end, *tmp;
528 const char *errmsg;
536 const char *errmsg, *graphfilename;
529 enum pmcstat_state runstate;
530 struct pmc_driverstats ds_start, ds_end;
531 struct pmcstat_ev *ev;
532 struct sigaction sa;
533 struct kevent kev;
534 struct winsize ws;
535 struct stat sb;
536 char buffer[PATH_MAX];
537
538 check_driver_stats = 0;
539 current_cpu = 0;
540 current_sampling_count = DEFAULT_SAMPLE_COUNT;
537 enum pmcstat_state runstate;
538 struct pmc_driverstats ds_start, ds_end;
539 struct pmcstat_ev *ev;
540 struct sigaction sa;
541 struct kevent kev;
542 struct winsize ws;
543 struct stat sb;
544 char buffer[PATH_MAX];
545
546 check_driver_stats = 0;
547 current_cpu = 0;
548 current_sampling_count = DEFAULT_SAMPLE_COUNT;
549 do_callchain = 1;
541 do_descendants = 0;
542 do_logproccsw = 0;
543 do_logprocexit = 0;
544 use_cumulative_counts = 0;
550 do_descendants = 0;
551 do_logproccsw = 0;
552 do_logprocexit = 0;
553 use_cumulative_counts = 0;
554 graphfilename = "-";
545 args.pa_required = 0;
546 args.pa_flags = 0;
547 args.pa_verbosity = 1;
548 args.pa_logfd = -1;
549 args.pa_fsroot = "";
550 args.pa_kernel = strdup("/boot/kernel");
551 args.pa_samplesdir = ".";
552 args.pa_printfile = stderr;
555 args.pa_required = 0;
556 args.pa_flags = 0;
557 args.pa_verbosity = 1;
558 args.pa_logfd = -1;
559 args.pa_fsroot = "";
560 args.pa_kernel = strdup("/boot/kernel");
561 args.pa_samplesdir = ".";
562 args.pa_printfile = stderr;
563 args.pa_graphdepth = DEFAULT_CALLGRAPH_DEPTH;
564 args.pa_graphfile = NULL;
553 args.pa_interval = DEFAULT_WAIT_INTERVAL;
554 args.pa_mapfilename = NULL;
565 args.pa_interval = DEFAULT_WAIT_INTERVAL;
566 args.pa_mapfilename = NULL;
567 args.pa_inputpath = NULL;
568 args.pa_outputpath = NULL;
555 STAILQ_INIT(&args.pa_events);
556 SLIST_INIT(&args.pa_targets);
557 bzero(&ds_start, sizeof(ds_start));
558 bzero(&ds_end, sizeof(ds_end));
559 ev = NULL;
560
569 STAILQ_INIT(&args.pa_events);
570 SLIST_INIT(&args.pa_targets);
571 bzero(&ds_start, sizeof(ds_start));
572 bzero(&ds_end, sizeof(ds_end));
573 ev = NULL;
574
561 dummy = sizeof(ncpu);
575 /*
576 * The initial CPU mask specifies all non-halted CPUS in the
577 * system.
578 */
579 dummy = sizeof(int);
562 if (sysctlbyname("hw.ncpu", &ncpu, &dummy, NULL, 0) < 0)
580 if (sysctlbyname("hw.ncpu", &ncpu, &dummy, NULL, 0) < 0)
563 err(EX_OSERR, "ERROR: Cannot determine #cpus");
581 err(EX_OSERR, "ERROR: Cannot determine the number of CPUs");
564 cpumask = (1 << ncpu) - 1;
582 cpumask = (1 << ncpu) - 1;
583 if (sysctlbyname("machdep.hlt_cpus", &haltedcpus, &dummy,
584 NULL, 0) < 0)
585 err(EX_OSERR, "ERROR: Cannot determine which CPUs are halted");
586 cpumask &= ~haltedcpus;
565
566 while ((option = getopt(argc, argv,
587
588 while ((option = getopt(argc, argv,
567 "CD:EM:O:P:R:S:Wc:dgk:n:o:p:qr:s:t:vw:")) != -1)
589 "CD:EG:M:NO:P:R:S:Wc:dgk:n:o:p:qr:s:t:vw:z:")) != -1)
568 switch (option) {
569 case 'C': /* cumulative values */
570 use_cumulative_counts = !use_cumulative_counts;
571 args.pa_required |= FLAG_HAS_COUNTING_PMCS;
572 break;
573
574 case 'c': /* CPU */
575

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

593 args.pa_required |= FLAG_DO_GPROF;
594 break;
595
596 case 'd': /* toggle descendents */
597 do_descendants = !do_descendants;
598 args.pa_required |= FLAG_HAS_PROCESS_PMCS;
599 break;
600
590 switch (option) {
591 case 'C': /* cumulative values */
592 use_cumulative_counts = !use_cumulative_counts;
593 args.pa_required |= FLAG_HAS_COUNTING_PMCS;
594 break;
595
596 case 'c': /* CPU */
597

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

615 args.pa_required |= FLAG_DO_GPROF;
616 break;
617
618 case 'd': /* toggle descendents */
619 do_descendants = !do_descendants;
620 args.pa_required |= FLAG_HAS_PROCESS_PMCS;
621 break;
622
623 case 'G': /* produce a system-wide callgraph */
624 args.pa_flags |= FLAG_DO_CALLGRAPHS;
625 graphfilename = optarg;
626 break;
627
601 case 'g': /* produce gprof compatible profiles */
602 args.pa_flags |= FLAG_DO_GPROF;
603 break;
604
605 case 'k': /* pathname to the kernel */
606 free(args.pa_kernel);
607 args.pa_kernel = strdup(optarg);
628 case 'g': /* produce gprof compatible profiles */
629 args.pa_flags |= FLAG_DO_GPROF;
630 break;
631
632 case 'k': /* pathname to the kernel */
633 free(args.pa_kernel);
634 args.pa_kernel = strdup(optarg);
608 args.pa_required |= FLAG_DO_GPROF;
635 args.pa_required |= FLAG_DO_ANALYSIS;
609 args.pa_flags |= FLAG_HAS_KERNELPATH;
610 break;
611
612 case 'E': /* log process exit */
613 do_logprocexit = !do_logprocexit;
614 args.pa_required |= (FLAG_HAS_PROCESS_PMCS |
615 FLAG_HAS_COUNTING_PMCS | FLAG_HAS_OUTPUT_LOGFILE);
616 break;
617
618 case 'M': /* mapfile */
619 args.pa_mapfilename = optarg;
620 break;
621
636 args.pa_flags |= FLAG_HAS_KERNELPATH;
637 break;
638
639 case 'E': /* log process exit */
640 do_logprocexit = !do_logprocexit;
641 args.pa_required |= (FLAG_HAS_PROCESS_PMCS |
642 FLAG_HAS_COUNTING_PMCS | FLAG_HAS_OUTPUT_LOGFILE);
643 break;
644
645 case 'M': /* mapfile */
646 args.pa_mapfilename = optarg;
647 break;
648
649 case 'N':
650 do_callchain = !do_callchain;
651 args.pa_required |= FLAG_HAS_SAMPLING_PMCS;
652 break;
653
622 case 'p': /* process virtual counting PMC */
623 case 's': /* system-wide counting PMC */
624 case 'P': /* process virtual sampling PMC */
625 case 'S': /* system-wide sampling PMC */
626 if ((ev = malloc(sizeof(*ev))) == NULL)
627 errx(EX_SOFTWARE, "ERROR: Out of memory.");
628
629 switch (option) {

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

659 ev->ev_count = -1;
660
661 if (option == 'S' || option == 's')
662 ev->ev_cpu = ffs(cpumask) - 1;
663 else
664 ev->ev_cpu = PMC_CPU_ANY;
665
666 ev->ev_flags = 0;
654 case 'p': /* process virtual counting PMC */
655 case 's': /* system-wide counting PMC */
656 case 'P': /* process virtual sampling PMC */
657 case 'S': /* system-wide sampling PMC */
658 if ((ev = malloc(sizeof(*ev))) == NULL)
659 errx(EX_SOFTWARE, "ERROR: Out of memory.");
660
661 switch (option) {

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

691 ev->ev_count = -1;
692
693 if (option == 'S' || option == 's')
694 ev->ev_cpu = ffs(cpumask) - 1;
695 else
696 ev->ev_cpu = PMC_CPU_ANY;
697
698 ev->ev_flags = 0;
699 if (do_callchain)
700 ev->ev_flags |= PMC_F_CALLCHAIN;
667 if (do_descendants)
668 ev->ev_flags |= PMC_F_DESCENDANTS;
669 if (do_logprocexit)
670 ev->ev_flags |= PMC_F_LOG_PROCEXIT;
671 if (do_logproccsw)
672 ev->ev_flags |= PMC_F_LOG_PROCCSW;
673
674 ev->ev_cumulative = use_cumulative_counts;

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

720 args.pa_verbosity = 0;
721 break;
722
723 case 'r': /* root FS path */
724 args.pa_fsroot = optarg;
725 break;
726
727 case 'R': /* read an existing log file */
701 if (do_descendants)
702 ev->ev_flags |= PMC_F_DESCENDANTS;
703 if (do_logprocexit)
704 ev->ev_flags |= PMC_F_LOG_PROCEXIT;
705 if (do_logproccsw)
706 ev->ev_flags |= PMC_F_LOG_PROCCSW;
707
708 ev->ev_cumulative = use_cumulative_counts;

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

754 args.pa_verbosity = 0;
755 break;
756
757 case 'r': /* root FS path */
758 args.pa_fsroot = optarg;
759 break;
760
761 case 'R': /* read an existing log file */
728 if (args.pa_logparser != NULL)
762 if (args.pa_inputpath != NULL)
729 errx(EX_USAGE, "ERROR: option -R may only be "
730 "specified once.");
731 args.pa_inputpath = optarg;
732 if (args.pa_printfile == stderr)
733 args.pa_printfile = stdout;
734 args.pa_flags |= FLAG_READ_LOGFILE;
735 break;
736

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

756 break;
757
758 case 'W': /* toggle LOG_CSW */
759 do_logproccsw = !do_logproccsw;
760 args.pa_required |= (FLAG_HAS_PROCESS_PMCS |
761 FLAG_HAS_COUNTING_PMCS | FLAG_HAS_OUTPUT_LOGFILE);
762 break;
763
763 errx(EX_USAGE, "ERROR: option -R may only be "
764 "specified once.");
765 args.pa_inputpath = optarg;
766 if (args.pa_printfile == stderr)
767 args.pa_printfile = stdout;
768 args.pa_flags |= FLAG_READ_LOGFILE;
769 break;
770

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

790 break;
791
792 case 'W': /* toggle LOG_CSW */
793 do_logproccsw = !do_logproccsw;
794 args.pa_required |= (FLAG_HAS_PROCESS_PMCS |
795 FLAG_HAS_COUNTING_PMCS | FLAG_HAS_OUTPUT_LOGFILE);
796 break;
797
798 case 'z':
799 graphdepth = strtod(optarg, &end);
800 if (*end != '\0' || graphdepth <= 0)
801 errx(EX_USAGE, "ERROR: Illegal callchain "
802 "depth \"%s\".", optarg);
803 args.pa_graphdepth = graphdepth;
804 args.pa_required |= FLAG_DO_CALLGRAPHS;
805 break;
806
764 case '?':
765 default:
766 pmcstat_show_usage();
767 break;
768
769 }
770
771 args.pa_argc = (argc -= optind);
772 args.pa_argv = (argv += optind);
773
807 case '?':
808 default:
809 pmcstat_show_usage();
810 break;
811
812 }
813
814 args.pa_argc = (argc -= optind);
815 args.pa_argv = (argv += optind);
816
817 args.pa_cpumask = cpumask; /* For selecting CPUs using -R. */
818
774 if (argc) /* command line present */
775 args.pa_flags |= FLAG_HAS_COMMANDLINE;
776
819 if (argc) /* command line present */
820 args.pa_flags |= FLAG_HAS_COMMANDLINE;
821
822 if (args.pa_flags & (FLAG_DO_GPROF | FLAG_DO_CALLGRAPHS))
823 args.pa_flags |= FLAG_DO_ANALYSIS;
824
777 /*
778 * Check invocation syntax.
779 */
780
781 /* disallow -O and -R together */
782 if (args.pa_outputpath && args.pa_inputpath)
783 errx(EX_USAGE, "ERROR: options -O and -R are mutually "
784 "exclusive.");

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

817 "target process or a command line.");
818
819 /* check for process-mode options without a process-mode PMC */
820 if ((args.pa_required & FLAG_HAS_PROCESS_PMCS) &&
821 (args.pa_flags & FLAG_HAS_PROCESS_PMCS) == 0)
822 errx(EX_USAGE, "ERROR: options -d, -E, and -W require a "
823 "process mode PMC to be specified.");
824
825 /*
826 * Check invocation syntax.
827 */
828
829 /* disallow -O and -R together */
830 if (args.pa_outputpath && args.pa_inputpath)
831 errx(EX_USAGE, "ERROR: options -O and -R are mutually "
832 "exclusive.");

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

865 "target process or a command line.");
866
867 /* check for process-mode options without a process-mode PMC */
868 if ((args.pa_required & FLAG_HAS_PROCESS_PMCS) &&
869 (args.pa_flags & FLAG_HAS_PROCESS_PMCS) == 0)
870 errx(EX_USAGE, "ERROR: options -d, -E, and -W require a "
871 "process mode PMC to be specified.");
872
825 /* check for -c cpu and not system mode PMCs */
873 /* check for -c cpu with no system mode PMCs or logfile. */
826 if ((args.pa_required & FLAG_HAS_SYSTEM_PMCS) &&
874 if ((args.pa_required & FLAG_HAS_SYSTEM_PMCS) &&
827 (args.pa_flags & FLAG_HAS_SYSTEM_PMCS) == 0)
875 (args.pa_flags & FLAG_HAS_SYSTEM_PMCS) == 0 &&
876 (args.pa_flags & FLAG_READ_LOGFILE) == 0)
828 errx(EX_USAGE, "ERROR: option -c requires at least one "
829 "system mode PMC to be specified.");
830
831 /* check for counting mode options without a counting PMC */
832 if ((args.pa_required & FLAG_HAS_COUNTING_PMCS) &&
833 (args.pa_flags & FLAG_HAS_COUNTING_PMCS) == 0)
834 errx(EX_USAGE, "ERROR: options -C, -W, -o and -w require at "
835 "least one counting mode PMC to be specified.");
836
837 /* check for sampling mode options without a sampling PMC spec */
838 if ((args.pa_required & FLAG_HAS_SAMPLING_PMCS) &&
839 (args.pa_flags & FLAG_HAS_SAMPLING_PMCS) == 0)
877 errx(EX_USAGE, "ERROR: option -c requires at least one "
878 "system mode PMC to be specified.");
879
880 /* check for counting mode options without a counting PMC */
881 if ((args.pa_required & FLAG_HAS_COUNTING_PMCS) &&
882 (args.pa_flags & FLAG_HAS_COUNTING_PMCS) == 0)
883 errx(EX_USAGE, "ERROR: options -C, -W, -o and -w require at "
884 "least one counting mode PMC to be specified.");
885
886 /* check for sampling mode options without a sampling PMC spec */
887 if ((args.pa_required & FLAG_HAS_SAMPLING_PMCS) &&
888 (args.pa_flags & FLAG_HAS_SAMPLING_PMCS) == 0)
840 errx(EX_USAGE, "ERROR: options -n and -O require at least "
841 "one sampling mode PMC to be specified.");
889 errx(EX_USAGE, "ERROR: options -N, -n and -O require at "
890 "least one sampling mode PMC to be specified.");
842
891
843 /* check if -g is being used correctly */
844 if ((args.pa_flags & FLAG_DO_GPROF) &&
892 /* check if -g/-G are being used correctly */
893 if ((args.pa_flags & FLAG_DO_ANALYSIS) &&
845 !(args.pa_flags & (FLAG_HAS_SAMPLING_PMCS|FLAG_READ_LOGFILE)))
894 !(args.pa_flags & (FLAG_HAS_SAMPLING_PMCS|FLAG_READ_LOGFILE)))
846 errx(EX_USAGE, "ERROR: option -g requires sampling PMCs or -R "
847 "to be specified.");
895 errx(EX_USAGE, "ERROR: options -g/-G require sampling PMCs "
896 "or -R to be specified.");
848
849 /* check if -O was spuriously specified */
850 if ((args.pa_flags & FLAG_HAS_OUTPUT_LOGFILE) &&
851 (args.pa_required & FLAG_HAS_OUTPUT_LOGFILE) == 0)
852 errx(EX_USAGE,
853 "ERROR: option -O is used only with options "
854 "-E, -P, -S and -W.");
855
897
898 /* check if -O was spuriously specified */
899 if ((args.pa_flags & FLAG_HAS_OUTPUT_LOGFILE) &&
900 (args.pa_required & FLAG_HAS_OUTPUT_LOGFILE) == 0)
901 errx(EX_USAGE,
902 "ERROR: option -O is used only with options "
903 "-E, -P, -S and -W.");
904
856 /* -D dir and -k kernel path require -g or -R */
905 /* -k kernel path require -g/-G or -R */
857 if ((args.pa_flags & FLAG_HAS_KERNELPATH) &&
906 if ((args.pa_flags & FLAG_HAS_KERNELPATH) &&
858 (args.pa_flags & FLAG_DO_GPROF) == 0 &&
907 (args.pa_flags & FLAG_DO_ANALYSIS) == 0 &&
859 (args.pa_flags & FLAG_READ_LOGFILE) == 0)
860 errx(EX_USAGE, "ERROR: option -k is only used with -g/-R.");
861
908 (args.pa_flags & FLAG_READ_LOGFILE) == 0)
909 errx(EX_USAGE, "ERROR: option -k is only used with -g/-R.");
910
911 /* -D only applies to gprof output mode (-g) */
862 if ((args.pa_flags & FLAG_HAS_SAMPLESDIR) &&
912 if ((args.pa_flags & FLAG_HAS_SAMPLESDIR) &&
863 (args.pa_flags & FLAG_DO_GPROF) == 0 &&
864 (args.pa_flags & FLAG_READ_LOGFILE) == 0)
865 errx(EX_USAGE, "ERROR: option -D is only used with -g/-R.");
913 (args.pa_flags & FLAG_DO_GPROF) == 0)
914 errx(EX_USAGE, "ERROR: option -D is only used with -g.");
866
867 /* -M mapfile requires -g or -R */
868 if (args.pa_mapfilename != NULL &&
869 (args.pa_flags & FLAG_DO_GPROF) == 0 &&
870 (args.pa_flags & FLAG_READ_LOGFILE) == 0)
871 errx(EX_USAGE, "ERROR: option -M is only used with -g/-R.");
872
873 /*
874 * Disallow textual output of sampling PMCs if counting PMCs
875 * have also been asked for, mostly because the combined output
876 * is difficult to make sense of.
877 */
878 if ((args.pa_flags & FLAG_HAS_COUNTING_PMCS) &&
879 (args.pa_flags & FLAG_HAS_SAMPLING_PMCS) &&
880 ((args.pa_flags & FLAG_HAS_OUTPUT_LOGFILE) == 0))
881 errx(EX_USAGE, "ERROR: option -O is required if counting and "
882 "sampling PMCs are specified together.");
883
884 /*
915
916 /* -M mapfile requires -g or -R */
917 if (args.pa_mapfilename != NULL &&
918 (args.pa_flags & FLAG_DO_GPROF) == 0 &&
919 (args.pa_flags & FLAG_READ_LOGFILE) == 0)
920 errx(EX_USAGE, "ERROR: option -M is only used with -g/-R.");
921
922 /*
923 * Disallow textual output of sampling PMCs if counting PMCs
924 * have also been asked for, mostly because the combined output
925 * is difficult to make sense of.
926 */
927 if ((args.pa_flags & FLAG_HAS_COUNTING_PMCS) &&
928 (args.pa_flags & FLAG_HAS_SAMPLING_PMCS) &&
929 ((args.pa_flags & FLAG_HAS_OUTPUT_LOGFILE) == 0))
930 errx(EX_USAGE, "ERROR: option -O is required if counting and "
931 "sampling PMCs are specified together.");
932
933 /*
885 * Check if "-k kerneldir" was specified, and if whether 'kerneldir'
886 * actually refers to a a file. If so, use `dirname path` to determine
887 * the kernel directory.
934 * Check if "-k kerneldir" was specified, and if whether
935 * 'kerneldir' actually refers to a a file. If so, use
936 * `dirname path` to determine the kernel directory.
888 */
889 if (args.pa_flags & FLAG_HAS_KERNELPATH) {
890 (void) snprintf(buffer, sizeof(buffer), "%s%s", args.pa_fsroot,
891 args.pa_kernel);
892 if (stat(buffer, &sb) < 0)
893 err(EX_OSERR, "ERROR: Cannot locate kernel \"%s\"",
894 buffer);
895 if (!S_ISREG(sb.st_mode) && !S_ISDIR(sb.st_mode))

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

905 err(EX_OSERR, "ERROR: Cannot stat \"%s\"",
906 buffer);
907 if (!S_ISDIR(sb.st_mode))
908 errx(EX_USAGE, "ERROR: \"%s\" is not a "
909 "directory.", buffer);
910 }
911 }
912
937 */
938 if (args.pa_flags & FLAG_HAS_KERNELPATH) {
939 (void) snprintf(buffer, sizeof(buffer), "%s%s", args.pa_fsroot,
940 args.pa_kernel);
941 if (stat(buffer, &sb) < 0)
942 err(EX_OSERR, "ERROR: Cannot locate kernel \"%s\"",
943 buffer);
944 if (!S_ISREG(sb.st_mode) && !S_ISDIR(sb.st_mode))

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

954 err(EX_OSERR, "ERROR: Cannot stat \"%s\"",
955 buffer);
956 if (!S_ISDIR(sb.st_mode))
957 errx(EX_USAGE, "ERROR: \"%s\" is not a "
958 "directory.", buffer);
959 }
960 }
961
962 /*
963 * If we have a callgraph be created, select the outputfile.
964 */
965 if (args.pa_flags & FLAG_DO_CALLGRAPHS) {
966 if (strcmp(graphfilename, "-") == 0)
967 args.pa_graphfile = args.pa_printfile;
968 else {
969 args.pa_graphfile = fopen(graphfilename, "w");
970 if (args.pa_graphfile == NULL)
971 err(EX_OSERR, "ERROR: cannot open \"%s\" "
972 "for writing", graphfilename);
973 }
974 }
975
913 /* if we've been asked to process a log file, do that and exit */
914 if (args.pa_flags & FLAG_READ_LOGFILE) {
915 /*
916 * Print the log in textual form if we haven't been
976 /* if we've been asked to process a log file, do that and exit */
977 if (args.pa_flags & FLAG_READ_LOGFILE) {
978 /*
979 * Print the log in textual form if we haven't been
917 * asked to generate gmon.out files.
980 * asked to generate profiling information.
918 */
981 */
919 if ((args.pa_flags & FLAG_DO_GPROF) == 0)
982 if ((args.pa_flags & FLAG_DO_ANALYSIS) == 0)
920 args.pa_flags |= FLAG_DO_PRINT;
921
922 pmcstat_initialize_logging(&args);
923 args.pa_logfd = pmcstat_open_log(args.pa_inputpath,
924 PMCSTAT_OPEN_FOR_READ);
925 if ((args.pa_logparser = pmclog_open(args.pa_logfd)) == NULL)
926 err(EX_OSERR, "ERROR: Cannot create parser");
927 pmcstat_process_log(&args);

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

1157 * We get a SIGIO if a PMC loses all
1158 * of its targets, or if logfile
1159 * writes encounter an error.
1160 */
1161 if (args.pa_flags & (FLAG_HAS_OUTPUT_LOGFILE |
1162 FLAG_HAS_PIPE)) {
1163 runstate = pmcstat_close_log(&args);
1164 if (args.pa_flags &
983 args.pa_flags |= FLAG_DO_PRINT;
984
985 pmcstat_initialize_logging(&args);
986 args.pa_logfd = pmcstat_open_log(args.pa_inputpath,
987 PMCSTAT_OPEN_FOR_READ);
988 if ((args.pa_logparser = pmclog_open(args.pa_logfd)) == NULL)
989 err(EX_OSERR, "ERROR: Cannot create parser");
990 pmcstat_process_log(&args);

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

1220 * We get a SIGIO if a PMC loses all
1221 * of its targets, or if logfile
1222 * writes encounter an error.
1223 */
1224 if (args.pa_flags & (FLAG_HAS_OUTPUT_LOGFILE |
1225 FLAG_HAS_PIPE)) {
1226 runstate = pmcstat_close_log(&args);
1227 if (args.pa_flags &
1165 (FLAG_DO_PRINT|FLAG_DO_GPROF))
1228 (FLAG_DO_PRINT|FLAG_DO_ANALYSIS))
1166 pmcstat_process_log(&args);
1167 }
1168 do_print = 1; /* print PMCs at exit */
1169 runstate = PMCSTAT_FINISHED;
1170 } else if (kev.ident == SIGINT) {
1171 /* Kill the child process if we started it */
1172 if (args.pa_flags & FLAG_HAS_COMMANDLINE)
1173 pmcstat_kill_process(&args);

--- 57 unchanged lines hidden ---
1229 pmcstat_process_log(&args);
1230 }
1231 do_print = 1; /* print PMCs at exit */
1232 runstate = PMCSTAT_FINISHED;
1233 } else if (kev.ident == SIGINT) {
1234 /* Kill the child process if we started it */
1235 if (args.pa_flags & FLAG_HAS_COMMANDLINE)
1236 pmcstat_kill_process(&args);

--- 57 unchanged lines hidden ---