Merge branch 'linus' into x86/asm, before applying dependent patch
[firefly-linux-kernel-4.4.55.git] / tools / perf / builtin-record.c
index 404ab34340523f934abc76fcfc6053907708e4fc..c3efdfb630b5b664349ed9e40c41374d3863752d 100644 (file)
@@ -70,8 +70,8 @@ static int process_synthesized_event(struct perf_tool *tool,
 static int record__mmap_read(struct record *rec, int idx)
 {
        struct perf_mmap *md = &rec->evlist->mmap[idx];
-       unsigned int head = perf_mmap__read_head(md);
-       unsigned int old = md->prev;
+       u64 head = perf_mmap__read_head(md);
+       u64 old = md->prev;
        unsigned char *data = md->base + page_size;
        unsigned long size;
        void *buf;
@@ -161,8 +161,9 @@ try_again:
                }
        }
 
-       if (perf_evlist__apply_filters(evlist)) {
-               error("failed to set filter with %d (%s)\n", errno,
+       if (perf_evlist__apply_filters(evlist, &pos)) {
+               error("failed to set filter \"%s\" on event %s with %d (%s)\n",
+                       pos->filter, perf_evsel__name(pos), errno,
                        strerror_r(errno, msg, sizeof(msg)));
                rc = -1;
                goto out;
@@ -225,7 +226,7 @@ static int process_buildids(struct record *rec)
         */
        symbol_conf.ignore_vmlinux_buildid = true;
 
-       return perf_session__process_events(session, &rec->tool);
+       return perf_session__process_events(session);
 }
 
 static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
@@ -343,7 +344,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
        signal(SIGINT, sig_handler);
        signal(SIGTERM, sig_handler);
 
-       session = perf_session__new(file, false, NULL);
+       session = perf_session__new(file, false, tool);
        if (session == NULL) {
                pr_err("Perf session creation failed.\n");
                return -1;
@@ -658,7 +659,7 @@ error:
 
 static void callchain_debug(void)
 {
-       static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF" };
+       static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" };
 
        pr_debug("callchain: type %s\n", str[callchain_param.record_mode]);
 
@@ -710,6 +711,90 @@ static int perf_record_config(const char *var, const char *value, void *cb)
        return perf_default_config(var, value, cb);
 }
 
+struct clockid_map {
+       const char *name;
+       int clockid;
+};
+
+#define CLOCKID_MAP(n, c)      \
+       { .name = n, .clockid = (c), }
+
+#define CLOCKID_END    { .name = NULL, }
+
+
+/*
+ * Add the missing ones, we need to build on many distros...
+ */
+#ifndef CLOCK_MONOTONIC_RAW
+#define CLOCK_MONOTONIC_RAW 4
+#endif
+#ifndef CLOCK_BOOTTIME
+#define CLOCK_BOOTTIME 7
+#endif
+#ifndef CLOCK_TAI
+#define CLOCK_TAI 11
+#endif
+
+static const struct clockid_map clockids[] = {
+       /* available for all events, NMI safe */
+       CLOCKID_MAP("monotonic", CLOCK_MONOTONIC),
+       CLOCKID_MAP("monotonic_raw", CLOCK_MONOTONIC_RAW),
+
+       /* available for some events */
+       CLOCKID_MAP("realtime", CLOCK_REALTIME),
+       CLOCKID_MAP("boottime", CLOCK_BOOTTIME),
+       CLOCKID_MAP("tai", CLOCK_TAI),
+
+       /* available for the lazy */
+       CLOCKID_MAP("mono", CLOCK_MONOTONIC),
+       CLOCKID_MAP("raw", CLOCK_MONOTONIC_RAW),
+       CLOCKID_MAP("real", CLOCK_REALTIME),
+       CLOCKID_MAP("boot", CLOCK_BOOTTIME),
+
+       CLOCKID_END,
+};
+
+static int parse_clockid(const struct option *opt, const char *str, int unset)
+{
+       struct record_opts *opts = (struct record_opts *)opt->value;
+       const struct clockid_map *cm;
+       const char *ostr = str;
+
+       if (unset) {
+               opts->use_clockid = 0;
+               return 0;
+       }
+
+       /* no arg passed */
+       if (!str)
+               return 0;
+
+       /* no setting it twice */
+       if (opts->use_clockid)
+               return -1;
+
+       opts->use_clockid = true;
+
+       /* if its a number, we're done */
+       if (sscanf(str, "%d", &opts->clockid) == 1)
+               return 0;
+
+       /* allow a "CLOCK_" prefix to the name */
+       if (!strncasecmp(str, "CLOCK_", 6))
+               str += 6;
+
+       for (cm = clockids; cm->name; cm++) {
+               if (!strcasecmp(str, cm->name)) {
+                       opts->clockid = cm->clockid;
+                       return 0;
+               }
+       }
+
+       opts->use_clockid = false;
+       ui__warning("unknown clockid %s, check man page\n", ostr);
+       return -1;
+}
+
 static const char * const __record_usage[] = {
        "perf record [<options>] [<command>]",
        "perf record [<options>] -- <command> [<options>]",
@@ -751,9 +836,9 @@ 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";
+const char record_callchain_help[] = CALLCHAIN_HELP "fp dwarf lbr";
 #else
-const char record_callchain_help[] = CALLCHAIN_HELP "fp";
+const char record_callchain_help[] = CALLCHAIN_HELP "fp lbr";
 #endif
 
 /*
@@ -839,6 +924,11 @@ struct option __record_options[] = {
                    "use per-thread mmaps"),
        OPT_BOOLEAN('I', "intr-regs", &record.opts.sample_intr_regs,
                    "Sample machine registers on interrupt"),
+       OPT_BOOLEAN(0, "running-time", &record.opts.running_time,
+                   "Record running/enabled time of read (:S) events"),
+       OPT_CALLBACK('k', "clockid", &record.opts,
+       "clockid", "clockid to use for events, see clock_gettime()",
+       parse_clockid),
        OPT_END()
 };