perf evsel: Rename perf_evsel__config*() to evsel__config*()
[linux-2.6-microblaze.git] / tools / perf / util / record.c
index 7def661..18ce2cd 100644 (file)
 #include <subcmd/parse-options.h>
 #include <perf/cpumap.h>
 #include "cloexec.h"
+#include "util/perf_api_probe.h"
 #include "record.h"
 #include "../perf-sys.h"
 
-typedef void (*setup_probe_fn_t)(struct evsel *evsel);
-
-static int perf_do_probe_api(setup_probe_fn_t fn, int cpu, const char *str)
+/*
+ * evsel__config_leader_sampling() uses special rules for leader sampling.
+ * However, if the leader is an AUX area event, then assume the event to sample
+ * is the next event.
+ */
+static struct evsel *perf_evsel__read_sampler(struct evsel *evsel,
+                                             struct evlist *evlist)
 {
-       struct evlist *evlist;
-       struct evsel *evsel;
-       unsigned long flags = perf_event_open_cloexec_flag();
-       int err = -EAGAIN, fd;
-       static pid_t pid = -1;
-
-       evlist = evlist__new();
-       if (!evlist)
-               return -ENOMEM;
-
-       if (parse_events(evlist, str, NULL))
-               goto out_delete;
-
-       evsel = evlist__first(evlist);
+       struct evsel *leader = evsel->leader;
 
-       while (1) {
-               fd = sys_perf_event_open(&evsel->core.attr, pid, cpu, -1, flags);
-               if (fd < 0) {
-                       if (pid == -1 && errno == EACCES) {
-                               pid = 0;
-                               continue;
-                       }
-                       goto out_delete;
+       if (evsel__is_aux_event(leader)) {
+               evlist__for_each_entry(evlist, evsel) {
+                       if (evsel->leader == leader && evsel != evsel->leader)
+                               return evsel;
                }
-               break;
-       }
-       close(fd);
-
-       fn(evsel);
-
-       fd = sys_perf_event_open(&evsel->core.attr, pid, cpu, -1, flags);
-       if (fd < 0) {
-               if (errno == EINVAL)
-                       err = -EINVAL;
-               goto out_delete;
        }
-       close(fd);
-       err = 0;
-
-out_delete:
-       evlist__delete(evlist);
-       return err;
-}
-
-static bool perf_probe_api(setup_probe_fn_t fn)
-{
-       const char *try[] = {"cycles:u", "instructions:u", "cpu-clock:u", NULL};
-       struct perf_cpu_map *cpus;
-       int cpu, ret, i = 0;
-
-       cpus = perf_cpu_map__new(NULL);
-       if (!cpus)
-               return false;
-       cpu = cpus->map[0];
-       perf_cpu_map__put(cpus);
-
-       do {
-               ret = perf_do_probe_api(fn, cpu, try[i++]);
-               if (!ret)
-                       return true;
-       } while (ret == -EAGAIN && try[i]);
 
-       return false;
+       return leader;
 }
 
-static void perf_probe_sample_identifier(struct evsel *evsel)
+static void evsel__config_leader_sampling(struct evsel *evsel, struct evlist *evlist)
 {
-       evsel->core.attr.sample_type |= PERF_SAMPLE_IDENTIFIER;
-}
-
-static void perf_probe_comm_exec(struct evsel *evsel)
-{
-       evsel->core.attr.comm_exec = 1;
-}
-
-static void perf_probe_context_switch(struct evsel *evsel)
-{
-       evsel->core.attr.context_switch = 1;
-}
-
-bool perf_can_sample_identifier(void)
-{
-       return perf_probe_api(perf_probe_sample_identifier);
-}
+       struct perf_event_attr *attr = &evsel->core.attr;
+       struct evsel *leader = evsel->leader;
+       struct evsel *read_sampler;
 
-static bool perf_can_comm_exec(void)
-{
-       return perf_probe_api(perf_probe_comm_exec);
-}
+       if (!leader->sample_read)
+               return;
 
-bool perf_can_record_switch_events(void)
-{
-       return perf_probe_api(perf_probe_context_switch);
-}
+       read_sampler = perf_evsel__read_sampler(evsel, evlist);
 
-bool perf_can_record_cpu_wide(void)
-{
-       struct perf_event_attr attr = {
-               .type = PERF_TYPE_SOFTWARE,
-               .config = PERF_COUNT_SW_CPU_CLOCK,
-               .exclude_kernel = 1,
-       };
-       struct perf_cpu_map *cpus;
-       int cpu, fd;
-
-       cpus = perf_cpu_map__new(NULL);
-       if (!cpus)
-               return false;
-       cpu = cpus->map[0];
-       perf_cpu_map__put(cpus);
+       if (evsel == read_sampler)
+               return;
 
-       fd = sys_perf_event_open(&attr, -1, cpu, -1, 0);
-       if (fd < 0)
-               return false;
-       close(fd);
-
-       return true;
-}
-
-/*
- * Architectures are expected to know if AUX area sampling is supported by the
- * hardware. Here we check for kernel support.
- */
-bool perf_can_aux_sample(void)
-{
-       struct perf_event_attr attr = {
-               .size = sizeof(struct perf_event_attr),
-               .exclude_kernel = 1,
-               /*
-                * Non-zero value causes the kernel to calculate the effective
-                * attribute size up to that byte.
-                */
-               .aux_sample_size = 1,
-       };
-       int fd;
-
-       fd = sys_perf_event_open(&attr, -1, 0, -1, 0);
        /*
-        * If the kernel attribute is big enough to contain aux_sample_size
-        * then we assume that it is supported. We are relying on the kernel to
-        * validate the attribute size before anything else that could be wrong.
+        * Disable sampling for all group members other than the leader in
+        * case the leader 'leads' the sampling, except when the leader is an
+        * AUX area event, in which case the 2nd event in the group is the one
+        * that 'leads' the sampling.
         */
-       if (fd < 0 && errno == E2BIG)
-               return false;
-       if (fd >= 0)
-               close(fd);
+       attr->freq           = 0;
+       attr->sample_freq    = 0;
+       attr->sample_period  = 0;
+       attr->write_backward = 0;
 
-       return true;
+       /*
+        * We don't get a sample for slave events, we make them when delivering
+        * the group leader sample. Set the slave event to follow the master
+        * sample_type to ease up reporting.
+        * An AUX area event also has sample_type requirements, so also include
+        * the sample type bits from the leader's sample_type to cover that
+        * case.
+        */
+       attr->sample_type = read_sampler->core.attr.sample_type |
+                           leader->core.attr.sample_type;
 }
 
 void perf_evlist__config(struct evlist *evlist, struct record_opts *opts,
@@ -188,11 +92,15 @@ void perf_evlist__config(struct evlist *evlist, struct record_opts *opts,
        use_comm_exec = perf_can_comm_exec();
 
        evlist__for_each_entry(evlist, evsel) {
-               perf_evsel__config(evsel, opts, callchain);
+               evsel__config(evsel, opts, callchain);
                if (evsel->tracking && use_comm_exec)
                        evsel->core.attr.comm_exec = 1;
        }
 
+       /* Configure leader sampling here now that the sample type is known */
+       evlist__for_each_entry(evlist, evsel)
+               evsel__config_leader_sampling(evsel, evlist);
+
        if (opts->full_auxtrace) {
                /*
                 * Need to be able to synthesize and parse selected events with