perf tools: Introduce usage_with_options_msg()
[firefly-linux-kernel-4.4.55.git] / tools / perf / builtin-record.c
index a660022f2c929cd97061848311e24ec4cac5e289..de02267c73d87549711723d5b1afa7d3a4befe6d 100644 (file)
 #include "util/cpumap.h"
 #include "util/thread_map.h"
 #include "util/data.h"
+#include "util/perf_regs.h"
 #include "util/auxtrace.h"
 #include "util/parse-branch-options.h"
+#include "util/parse-regs-options.h"
 
 #include <unistd.h>
 #include <sched.h>
@@ -47,7 +49,7 @@ struct record {
        int                     realtime_prio;
        bool                    no_buildid;
        bool                    no_buildid_cache;
-       long                    samples;
+       unsigned long long      samples;
 };
 
 static int record__write(struct record *rec, void *bf, size_t size)
@@ -279,7 +281,7 @@ static int record__open(struct record *rec)
 
        evlist__for_each(evlist, pos) {
 try_again:
-               if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) {
+               if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) {
                        if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) {
                                if (verbose)
                                        ui__warning("%s\n", msg);
@@ -634,8 +636,29 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
        /*
         * Let the child rip
         */
-       if (forks)
+       if (forks) {
+               union perf_event *event;
+
+               event = malloc(sizeof(event->comm) + machine->id_hdr_size);
+               if (event == NULL) {
+                       err = -ENOMEM;
+                       goto out_child;
+               }
+
+               /*
+                * Some H/W events are generated before COMM event
+                * which is emitted during exec(), so perf script
+                * cannot see a correct process name for those events.
+                * Synthesize COMM event to prevent it.
+                */
+               perf_event__synthesize_comm(tool, event,
+                                           rec->evlist->workload.pid,
+                                           process_synthesized_event,
+                                           machine);
+               free(event);
+
                perf_evlist__start_workload(rec->evlist);
+       }
 
        if (opts->initial_delay) {
                usleep(opts->initial_delay * 1000);
@@ -644,7 +667,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
 
        auxtrace_snapshot_enabled = 1;
        for (;;) {
-               int hits = rec->samples;
+               unsigned long long hits = rec->samples;
 
                if (record__mmap_read_all(rec) < 0) {
                        auxtrace_snapshot_enabled = 0;
@@ -987,13 +1010,8 @@ static struct record record = {
        },
 };
 
-#define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: "
-
-#ifdef HAVE_DWARF_UNWIND_SUPPORT
-const char record_callchain_help[] = CALLCHAIN_HELP "fp dwarf lbr";
-#else
-const char record_callchain_help[] = CALLCHAIN_HELP "fp lbr";
-#endif
+const char record_callchain_help[] = CALLCHAIN_RECORD_HELP
+       "\n\t\t\t\tDefault: fp";
 
 /*
  * XXX Will stay a global variable till we fix builtin-script.c to stop messing
@@ -1041,7 +1059,7 @@ struct option __record_options[] = {
                           NULL, "enables call-graph recording" ,
                           &record_callchain_opt),
        OPT_CALLBACK(0, "call-graph", &record.opts,
-                    "mode[,dump_size]", record_callchain_help,
+                    "record_mode[,record_size]", record_callchain_help,
                     &record_parse_callchain_opt),
        OPT_INCR('v', "verbose", &verbose,
                    "be more verbose (show counter open errors, etc)"),
@@ -1080,8 +1098,9 @@ struct option __record_options[] = {
                    "sample transaction flags (special events only)"),
        OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread,
                    "use per-thread mmaps"),
-       OPT_BOOLEAN('I', "intr-regs", &record.opts.sample_intr_regs,
-                   "Sample machine registers on interrupt"),
+       OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register",
+                   "sample selected machine registers on interrupt,"
+                   " use -I ? to list register names", parse_regs),
        OPT_BOOLEAN(0, "running-time", &record.opts.running_time,
                    "Record running/enabled time of read (:S) events"),
        OPT_CALLBACK('k', "clockid", &record.opts,
@@ -1116,14 +1135,15 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
                usage_with_options(record_usage, record_options);
 
        if (nr_cgroups && !rec->opts.target.system_wide) {
-               ui__error("cgroup monitoring only available in"
-                         " system-wide mode\n");
-               usage_with_options(record_usage, record_options);
+               usage_with_options_msg(record_usage, record_options,
+                       "cgroup monitoring only available in system-wide mode");
+
        }
        if (rec->opts.record_switch_events &&
            !perf_can_record_switch_events()) {
-               ui__error("kernel does not support recording context switch events (--switch-events option)\n");
-               usage_with_options(record_usage, record_options);
+               ui__error("kernel does not support recording context switch events\n");
+               parse_options_usage(record_usage, record_options, "switch-events", 0);
+               return -EINVAL;
        }
 
        if (!rec->itr) {