perf evsel: Support printing evsel name for 'duration_time'
[linux-2.6-microblaze.git] / tools / perf / util / evsel.c
index 3bbf73e..84cfb9f 100644 (file)
@@ -295,7 +295,6 @@ struct perf_evsel *perf_evsel__new_cycles(bool precise)
        if (!precise)
                goto new_event;
 
-       perf_event_attr__set_max_precise_ip(&attr);
        /*
         * Now let the usual logic to set up the perf_event_attr defaults
         * to kick in when we return and before perf_evsel__open() is called.
@@ -305,6 +304,8 @@ new_event:
        if (evsel == NULL)
                goto out;
 
+       evsel->precise_max = true;
+
        /* use asprintf() because free(evsel) assumes name is allocated */
        if (asprintf(&evsel->name, "cycles%s%s%.*s",
                     (attr.precise_ip || attr.exclude_kernel) ? ":" : "",
@@ -579,6 +580,12 @@ static int perf_evsel__raw_name(struct perf_evsel *evsel, char *bf, size_t size)
        return ret + perf_evsel__add_modifiers(evsel, bf + ret, size - ret);
 }
 
+static int perf_evsel__tool_name(char *bf, size_t size)
+{
+       int ret = scnprintf(bf, size, "duration_time");
+       return ret;
+}
+
 const char *perf_evsel__name(struct perf_evsel *evsel)
 {
        char bf[128];
@@ -600,7 +607,10 @@ const char *perf_evsel__name(struct perf_evsel *evsel)
                break;
 
        case PERF_TYPE_SOFTWARE:
-               perf_evsel__sw_name(evsel, bf, sizeof(bf));
+               if (evsel->tool_event)
+                       perf_evsel__tool_name(bf, sizeof(bf));
+               else
+                       perf_evsel__sw_name(evsel, bf, sizeof(bf));
                break;
 
        case PERF_TYPE_TRACEPOINT:
@@ -1036,7 +1046,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
        attr->mmap2 = track && !perf_missing_features.mmap2;
        attr->comm  = track;
        attr->ksymbol = track && !perf_missing_features.ksymbol;
-       attr->bpf_event = track && opts->bpf_event &&
+       attr->bpf_event = track && !opts->no_bpf_event &&
                !perf_missing_features.bpf_event;
 
        if (opts->record_namespaces)
@@ -1083,7 +1093,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
        }
 
        if (evsel->precise_max)
-               perf_event_attr__set_max_precise_ip(attr);
+               attr->precise_ip = 3;
 
        if (opts->all_user) {
                attr->exclude_kernel = 1;
@@ -1292,6 +1302,7 @@ void perf_evsel__exit(struct perf_evsel *evsel)
 {
        assert(list_empty(&evsel->node));
        assert(evsel->evlist == NULL);
+       perf_evsel__free_counts(evsel);
        perf_evsel__free_fd(evsel);
        perf_evsel__free_id(evsel);
        perf_evsel__free_config_terms(evsel);
@@ -1342,10 +1353,9 @@ void perf_counts_values__scale(struct perf_counts_values *count,
                        count->val = 0;
                } else if (count->run < count->ena) {
                        scaled = 1;
-                       count->val = (u64)((double) count->val * count->ena / count->run + 0.5);
+                       count->val = (u64)((double) count->val * count->ena / count->run);
                }
-       } else
-               count->ena = count->run = 0;
+       }
 
        if (pscaled)
                *pscaled = scaled;
@@ -1749,6 +1759,59 @@ static bool ignore_missing_thread(struct perf_evsel *evsel,
        return true;
 }
 
+static void display_attr(struct perf_event_attr *attr)
+{
+       if (verbose >= 2) {
+               fprintf(stderr, "%.60s\n", graph_dotted_line);
+               fprintf(stderr, "perf_event_attr:\n");
+               perf_event_attr__fprintf(stderr, attr, __open_attr__fprintf, NULL);
+               fprintf(stderr, "%.60s\n", graph_dotted_line);
+       }
+}
+
+static int perf_event_open(struct perf_evsel *evsel,
+                          pid_t pid, int cpu, int group_fd,
+                          unsigned long flags)
+{
+       int precise_ip = evsel->attr.precise_ip;
+       int fd;
+
+       while (1) {
+               pr_debug2("sys_perf_event_open: pid %d  cpu %d  group_fd %d  flags %#lx",
+                         pid, cpu, group_fd, flags);
+
+               fd = sys_perf_event_open(&evsel->attr, pid, cpu, group_fd, flags);
+               if (fd >= 0)
+                       break;
+
+               /*
+                * Do quick precise_ip fallback if:
+                *  - there is precise_ip set in perf_event_attr
+                *  - maximum precise is requested
+                *  - sys_perf_event_open failed with ENOTSUP error,
+                *    which is associated with wrong precise_ip
+                */
+               if (!precise_ip || !evsel->precise_max || (errno != ENOTSUP))
+                       break;
+
+               /*
+                * We tried all the precise_ip values, and it's
+                * still failing, so leave it to standard fallback.
+                */
+               if (!evsel->attr.precise_ip) {
+                       evsel->attr.precise_ip = precise_ip;
+                       break;
+               }
+
+               pr_debug2("\nsys_perf_event_open failed, error %d\n", -ENOTSUP);
+               evsel->attr.precise_ip--;
+               pr_debug2("decreasing precise_ip by one (%d)\n", evsel->attr.precise_ip);
+               display_attr(&evsel->attr);
+       }
+
+       return fd;
+}
+
 int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
                     struct thread_map *threads)
 {
@@ -1824,12 +1887,7 @@ retry_sample_id:
        if (perf_missing_features.sample_id_all)
                evsel->attr.sample_id_all = 0;
 
-       if (verbose >= 2) {
-               fprintf(stderr, "%.60s\n", graph_dotted_line);
-               fprintf(stderr, "perf_event_attr:\n");
-               perf_event_attr__fprintf(stderr, &evsel->attr, __open_attr__fprintf, NULL);
-               fprintf(stderr, "%.60s\n", graph_dotted_line);
-       }
+       display_attr(&evsel->attr);
 
        for (cpu = 0; cpu < cpus->nr; cpu++) {
 
@@ -1841,13 +1899,10 @@ retry_sample_id:
 
                        group_fd = get_group_fd(evsel, cpu, thread);
 retry_open:
-                       pr_debug2("sys_perf_event_open: pid %d  cpu %d  group_fd %d  flags %#lx",
-                                 pid, cpus->map[cpu], group_fd, flags);
-
                        test_attr__ready();
 
-                       fd = sys_perf_event_open(&evsel->attr, pid, cpus->map[cpu],
-                                                group_fd, flags);
+                       fd = perf_event_open(evsel, pid, cpus->map[cpu],
+                                            group_fd, flags);
 
                        FD(evsel, cpu, thread) = fd;