perf stat aggregation: Add separate core member
[linux-2.6-microblaze.git] / tools / perf / builtin-stat.c
index b01af17..8cc2496 100644 (file)
@@ -270,7 +270,7 @@ static void perf_stat__reset_stats(void)
 {
        int i;
 
-       perf_evlist__reset_stats(evsel_list);
+       evlist__reset_stats(evsel_list);
        perf_stat__reset_shadow_stats();
 
        for (i = 0; i < stat_config.stats_num; i++)
@@ -534,7 +534,7 @@ static void disable_counters(void)
 static volatile int workload_exec_errno;
 
 /*
- * perf_evlist__prepare_workload will send a SIGUSR1
+ * evlist__prepare_workload will send a SIGUSR1
  * if the fork fails, since we asked by setting its
  * want_signal to true.
  */
@@ -724,8 +724,7 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
        bool second_pass = false;
 
        if (forks) {
-               if (perf_evlist__prepare_workload(evsel_list, &target, argv, is_pipe,
-                                                 workload_exec_failed_signal) < 0) {
+               if (evlist__prepare_workload(evsel_list, &target, argv, is_pipe, workload_exec_failed_signal) < 0) {
                        perror("failed to prepare workload");
                        return -1;
                }
@@ -733,7 +732,7 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
        }
 
        if (group)
-               perf_evlist__set_leader(evsel_list);
+               evlist__set_leader(evsel_list);
 
        if (affinity__setup(&affinity) < 0)
                return -1;
@@ -760,7 +759,7 @@ try_again:
                                if ((errno == EINVAL || errno == EBADF) &&
                                    counter->leader != counter &&
                                    counter->weak_group) {
-                                       perf_evlist__reset_weak_group(evsel_list, counter, false);
+                                       evlist__reset_weak_group(evsel_list, counter, false);
                                        assert(counter->reset_group);
                                        second_pass = true;
                                        continue;
@@ -843,7 +842,7 @@ try_again_reset:
                        return -1;
        }
 
-       if (perf_evlist__apply_filters(evsel_list, &counter)) {
+       if (evlist__apply_filters(evsel_list, &counter)) {
                pr_err("failed to set filter \"%s\" on event %s with %d (%s)\n",
                        counter->filter, evsel__name(counter), errno,
                        str_error_r(errno, msg, sizeof(msg)));
@@ -876,7 +875,7 @@ try_again_reset:
        clock_gettime(CLOCK_MONOTONIC, &ref_time);
 
        if (forks) {
-               perf_evlist__start_workload(evsel_list);
+               evlist__start_workload(evsel_list);
                enable_counters();
 
                if (interval || timeout || evlist__ctlfd_initialized(evsel_list))
@@ -914,10 +913,10 @@ try_again_reset:
                update_stats(&walltime_nsecs_stats, t1 - t0);
 
                if (stat_config.aggr_mode == AGGR_GLOBAL)
-                       perf_evlist__save_aggr_prev_raw_counts(evsel_list);
+                       evlist__save_aggr_prev_raw_counts(evsel_list);
 
-               perf_evlist__copy_prev_raw_counts(evsel_list);
-               perf_evlist__reset_prev_raw_counts(evsel_list);
+               evlist__copy_prev_raw_counts(evsel_list);
+               evlist__reset_prev_raw_counts(evsel_list);
                runtime_stat_reset(&stat_config);
                perf_stat__reset_shadow_per_stat(&rt_stat);
        } else
@@ -972,9 +971,10 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)
        /* Do not print anything if we record to the pipe. */
        if (STAT_RECORD && perf_stat.data.is_pipe)
                return;
+       if (stat_config.quiet)
+               return;
 
-       perf_evlist__print_counters(evsel_list, &stat_config, &target,
-                                   ts, argc, argv);
+       evlist__print_counters(evsel_list, &stat_config, &target, ts, argc, argv);
 }
 
 static volatile int signr = -1;
@@ -1171,6 +1171,8 @@ static struct option stat_options[] = {
                    "threads of same physical core"),
        OPT_BOOLEAN(0, "summary", &stat_config.summary,
                       "print summary for interval mode"),
+       OPT_BOOLEAN(0, "quiet", &stat_config.quiet,
+                       "don't print output (useful with record)"),
 #ifdef HAVE_LIBPFM
        OPT_CALLBACK(0, "pfm-events", &evsel_list, "event",
                "libpfm4 event selector. use 'perf list' to list available events",
@@ -1184,65 +1186,67 @@ static struct option stat_options[] = {
        OPT_END()
 };
 
-static int perf_stat__get_socket(struct perf_stat_config *config __maybe_unused,
+static struct aggr_cpu_id perf_stat__get_socket(struct perf_stat_config *config __maybe_unused,
                                 struct perf_cpu_map *map, int cpu)
 {
        return cpu_map__get_socket(map, cpu, NULL);
 }
 
-static int perf_stat__get_die(struct perf_stat_config *config __maybe_unused,
+static struct aggr_cpu_id perf_stat__get_die(struct perf_stat_config *config __maybe_unused,
                              struct perf_cpu_map *map, int cpu)
 {
        return cpu_map__get_die(map, cpu, NULL);
 }
 
-static int perf_stat__get_core(struct perf_stat_config *config __maybe_unused,
+static struct aggr_cpu_id perf_stat__get_core(struct perf_stat_config *config __maybe_unused,
                               struct perf_cpu_map *map, int cpu)
 {
        return cpu_map__get_core(map, cpu, NULL);
 }
 
-static int perf_stat__get_node(struct perf_stat_config *config __maybe_unused,
+static struct aggr_cpu_id perf_stat__get_node(struct perf_stat_config *config __maybe_unused,
                               struct perf_cpu_map *map, int cpu)
 {
        return cpu_map__get_node(map, cpu, NULL);
 }
 
-static int perf_stat__get_aggr(struct perf_stat_config *config,
+static struct aggr_cpu_id perf_stat__get_aggr(struct perf_stat_config *config,
                               aggr_get_id_t get_id, struct perf_cpu_map *map, int idx)
 {
        int cpu;
+       struct aggr_cpu_id id = cpu_map__empty_aggr_cpu_id();
 
        if (idx >= map->nr)
-               return -1;
+               return id;
 
        cpu = map->map[idx];
 
-       if (config->cpus_aggr_map->map[cpu] == -1)
+       if (cpu_map__aggr_cpu_id_is_empty(config->cpus_aggr_map->map[cpu]))
                config->cpus_aggr_map->map[cpu] = get_id(config, map, idx);
 
-       return config->cpus_aggr_map->map[cpu];
+       id = config->cpus_aggr_map->map[cpu];
+       return id;
 }
 
-static int perf_stat__get_socket_cached(struct perf_stat_config *config,
+static struct aggr_cpu_id perf_stat__get_socket_cached(struct perf_stat_config *config,
                                        struct perf_cpu_map *map, int idx)
 {
        return perf_stat__get_aggr(config, perf_stat__get_socket, map, idx);
 }
 
-static int perf_stat__get_die_cached(struct perf_stat_config *config,
+static struct aggr_cpu_id perf_stat__get_die_cached(struct perf_stat_config *config,
                                        struct perf_cpu_map *map, int idx)
 {
        return perf_stat__get_aggr(config, perf_stat__get_die, map, idx);
 }
 
-static int perf_stat__get_core_cached(struct perf_stat_config *config,
+static struct aggr_cpu_id perf_stat__get_core_cached(struct perf_stat_config *config,
                                      struct perf_cpu_map *map, int idx)
 {
        return perf_stat__get_aggr(config, perf_stat__get_core, map, idx);
 }
 
-static int perf_stat__get_node_cached(struct perf_stat_config *config,
+static struct aggr_cpu_id perf_stat__get_node_cached(struct perf_stat_config *config,
                                      struct perf_cpu_map *map, int idx)
 {
        return perf_stat__get_aggr(config, perf_stat__get_node, map, idx);
@@ -1316,14 +1320,29 @@ static int perf_stat_init_aggr_mode(void)
         * the aggregation translate cpumap.
         */
        nr = perf_cpu_map__max(evsel_list->core.cpus);
-       stat_config.cpus_aggr_map = perf_cpu_map__empty_new(nr + 1);
+       stat_config.cpus_aggr_map = cpu_aggr_map__empty_new(nr + 1);
        return stat_config.cpus_aggr_map ? 0 : -ENOMEM;
 }
 
+static void cpu_aggr_map__delete(struct cpu_aggr_map *map)
+{
+       if (map) {
+               WARN_ONCE(refcount_read(&map->refcnt) != 0,
+                         "cpu_aggr_map refcnt unbalanced\n");
+               free(map);
+       }
+}
+
+static void cpu_aggr_map__put(struct cpu_aggr_map *map)
+{
+       if (map && refcount_dec_and_test(&map->refcnt))
+               cpu_aggr_map__delete(map);
+}
+
 static void perf_stat__exit_aggr_mode(void)
 {
-       perf_cpu_map__put(stat_config.aggr_map);
-       perf_cpu_map__put(stat_config.cpus_aggr_map);
+       cpu_aggr_map__put(stat_config.aggr_map);
+       cpu_aggr_map__put(stat_config.cpus_aggr_map);
        stat_config.aggr_map = NULL;
        stat_config.cpus_aggr_map = NULL;
 }
@@ -1343,117 +1362,108 @@ static inline int perf_env__get_cpu(struct perf_env *env, struct perf_cpu_map *m
        return cpu;
 }
 
-static int perf_env__get_socket(struct perf_cpu_map *map, int idx, void *data)
+static struct aggr_cpu_id perf_env__get_socket(struct perf_cpu_map *map, int idx, void *data)
 {
        struct perf_env *env = data;
        int cpu = perf_env__get_cpu(env, map, idx);
+       struct aggr_cpu_id id = cpu_map__empty_aggr_cpu_id();
 
-       return cpu == -1 ? -1 : env->cpu[cpu].socket_id;
+       if (cpu != -1)
+               id.socket = env->cpu[cpu].socket_id;
+
+       return id;
 }
 
-static int perf_env__get_die(struct perf_cpu_map *map, int idx, void *data)
+static struct aggr_cpu_id perf_env__get_die(struct perf_cpu_map *map, int idx, void *data)
 {
        struct perf_env *env = data;
-       int die_id = -1, cpu = perf_env__get_cpu(env, map, idx);
+       struct aggr_cpu_id id = cpu_map__empty_aggr_cpu_id();
+       int cpu = perf_env__get_cpu(env, map, idx);
 
        if (cpu != -1) {
                /*
-                * Encode socket in bit range 15:8
-                * die_id is relative to socket,
-                * we need a global id. So we combine
-                * socket + die id
+                * die_id is relative to socket, so start
+                * with the socket ID and then add die to
+                * make a unique ID.
                 */
-               if (WARN_ONCE(env->cpu[cpu].socket_id >> 8, "The socket id number is too big.\n"))
-                       return -1;
-
-               if (WARN_ONCE(env->cpu[cpu].die_id >> 8, "The die id number is too big.\n"))
-                       return -1;
-
-               die_id = (env->cpu[cpu].socket_id << 8) | (env->cpu[cpu].die_id & 0xff);
+               id.socket = env->cpu[cpu].socket_id;
+               id.die = env->cpu[cpu].die_id;
        }
 
-       return die_id;
+       return id;
 }
 
-static int perf_env__get_core(struct perf_cpu_map *map, int idx, void *data)
+static struct aggr_cpu_id perf_env__get_core(struct perf_cpu_map *map, int idx, void *data)
 {
        struct perf_env *env = data;
-       int core = -1, cpu = perf_env__get_cpu(env, map, idx);
+       struct aggr_cpu_id id = cpu_map__empty_aggr_cpu_id();
+       int cpu = perf_env__get_cpu(env, map, idx);
 
        if (cpu != -1) {
                /*
-                * Encode socket in bit range 31:24
-                * encode die id in bit range 23:16
                 * core_id is relative to socket and die,
-                * we need a global id. So we combine
-                * socket + die id + core id
+                * we need a global id. So we set
+                * socket, die id and core id
                 */
-               if (WARN_ONCE(env->cpu[cpu].socket_id >> 8, "The socket id number is too big.\n"))
-                       return -1;
-
-               if (WARN_ONCE(env->cpu[cpu].die_id >> 8, "The die id number is too big.\n"))
-                       return -1;
-
-               if (WARN_ONCE(env->cpu[cpu].core_id >> 16, "The core id number is too big.\n"))
-                       return -1;
-
-               core = (env->cpu[cpu].socket_id << 24) |
-                      (env->cpu[cpu].die_id << 16) |
-                      (env->cpu[cpu].core_id & 0xffff);
+               id.socket = env->cpu[cpu].socket_id;
+               id.die = env->cpu[cpu].die_id;
+               id.core = env->cpu[cpu].core_id;
        }
 
-       return core;
+       return id;
 }
 
-static int perf_env__get_node(struct perf_cpu_map *map, int idx, void *data)
+static struct aggr_cpu_id perf_env__get_node(struct perf_cpu_map *map, int idx, void *data)
 {
        int cpu = perf_env__get_cpu(data, map, idx);
+       struct aggr_cpu_id id = cpu_map__empty_aggr_cpu_id();
 
-       return perf_env__numa_node(data, cpu);
+       id.node = perf_env__numa_node(data, cpu);
+       return id;
 }
 
 static int perf_env__build_socket_map(struct perf_env *env, struct perf_cpu_map *cpus,
-                                     struct perf_cpu_map **sockp)
+                                     struct cpu_aggr_map **sockp)
 {
        return cpu_map__build_map(cpus, sockp, perf_env__get_socket, env);
 }
 
 static int perf_env__build_die_map(struct perf_env *env, struct perf_cpu_map *cpus,
-                                  struct perf_cpu_map **diep)
+                                  struct cpu_aggr_map **diep)
 {
        return cpu_map__build_map(cpus, diep, perf_env__get_die, env);
 }
 
 static int perf_env__build_core_map(struct perf_env *env, struct perf_cpu_map *cpus,
-                                   struct perf_cpu_map **corep)
+                                   struct cpu_aggr_map **corep)
 {
        return cpu_map__build_map(cpus, corep, perf_env__get_core, env);
 }
 
 static int perf_env__build_node_map(struct perf_env *env, struct perf_cpu_map *cpus,
-                                   struct perf_cpu_map **nodep)
+                                   struct cpu_aggr_map **nodep)
 {
        return cpu_map__build_map(cpus, nodep, perf_env__get_node, env);
 }
 
-static int perf_stat__get_socket_file(struct perf_stat_config *config __maybe_unused,
+static struct aggr_cpu_id perf_stat__get_socket_file(struct perf_stat_config *config __maybe_unused,
                                      struct perf_cpu_map *map, int idx)
 {
        return perf_env__get_socket(map, idx, &perf_stat.session->header.env);
 }
-static int perf_stat__get_die_file(struct perf_stat_config *config __maybe_unused,
+static struct aggr_cpu_id perf_stat__get_die_file(struct perf_stat_config *config __maybe_unused,
                                   struct perf_cpu_map *map, int idx)
 {
        return perf_env__get_die(map, idx, &perf_stat.session->header.env);
 }
 
-static int perf_stat__get_core_file(struct perf_stat_config *config __maybe_unused,
+static struct aggr_cpu_id perf_stat__get_core_file(struct perf_stat_config *config __maybe_unused,
                                    struct perf_cpu_map *map, int idx)
 {
        return perf_env__get_core(map, idx, &perf_stat.session->header.env);
 }
 
-static int perf_stat__get_node_file(struct perf_stat_config *config __maybe_unused,
+static struct aggr_cpu_id perf_stat__get_node_file(struct perf_stat_config *config __maybe_unused,
                                    struct perf_cpu_map *map, int idx)
 {
        return perf_env__get_node(map, idx, &perf_stat.session->header.env);
@@ -1904,7 +1914,7 @@ static int set_maps(struct perf_stat *st)
 
        perf_evlist__set_maps(&evsel_list->core, st->cpus, st->threads);
 
-       if (perf_evlist__alloc_stats(evsel_list, true))
+       if (evlist__alloc_stats(evsel_list, true))
                return -ENOMEM;
 
        st->maps_allocated = true;
@@ -2132,7 +2142,7 @@ int cmd_stat(int argc, const char **argv)
                goto out;
        }
 
-       if (!output) {
+       if (!output && !stat_config.quiet) {
                struct timespec tm;
                mode = append_file ? "a" : "w";
 
@@ -2235,8 +2245,11 @@ int cmd_stat(int argc, const char **argv)
                }
 
                if (evlist__expand_cgroup(evsel_list, stat_config.cgroup_list,
-                                         &stat_config.metric_events, true) < 0)
+                                         &stat_config.metric_events, true) < 0) {
+                       parse_options_usage(stat_usage, stat_options,
+                                           "for-each-cgroup", 0);
                        goto out;
+               }
        }
 
        target__validate(&target);
@@ -2244,7 +2257,7 @@ int cmd_stat(int argc, const char **argv)
        if ((stat_config.aggr_mode == AGGR_THREAD) && (target.system_wide))
                target.per_thread = true;
 
-       if (perf_evlist__create_maps(evsel_list, &target) < 0) {
+       if (evlist__create_maps(evsel_list, &target) < 0) {
                if (target__has_task(&target)) {
                        pr_err("Problems finding threads of monitor\n");
                        parse_options_usage(stat_usage, stat_options, "p", 1);
@@ -2303,7 +2316,7 @@ int cmd_stat(int argc, const char **argv)
                goto out;
        }
 
-       if (perf_evlist__alloc_stats(evsel_list, interval))
+       if (evlist__alloc_stats(evsel_list, interval))
                goto out;
 
        if (perf_stat_init_aggr_mode())
@@ -2343,7 +2356,7 @@ int cmd_stat(int argc, const char **argv)
                                run_idx + 1);
 
                if (run_idx != 0)
-                       perf_evlist__reset_prev_raw_counts(evsel_list);
+                       evlist__reset_prev_raw_counts(evsel_list);
 
                status = run_perf_stat(argc, argv, run_idx);
                if (forever && status != -1 && !interval) {
@@ -2394,7 +2407,7 @@ int cmd_stat(int argc, const char **argv)
        }
 
        perf_stat__exit_aggr_mode();
-       perf_evlist__free_stats(evsel_list);
+       evlist__free_stats(evsel_list);
 out:
        zfree(&stat_config.walltime_run);