perf stat: Remove --per-thread pid/tid limitation
authorJin Yao <yao.jin@linux.intel.com>
Tue, 5 Dec 2017 14:03:10 +0000 (22:03 +0800)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Wed, 27 Dec 2017 15:15:47 +0000 (12:15 -0300)
Currently, if we execute 'perf stat --per-thread' without specifying
pid/tid, perf will return error.

root@skl:/tmp# perf stat --per-thread
The --per-thread option is only available when monitoring via -p -t options.
    -p, --pid <pid>       stat events on existing process id
    -t, --tid <tid>       stat events on existing thread id

This patch removes this limitation. If no pid/tid specified, it returns
all threads (get threads from /proc).

Note that it doesn't support cpu_list yet so if it's a cpu_list case,
then skip.

Signed-off-by: Jin Yao <yao.jin@linux.intel.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Kan Liang <kan.liang@intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1512482591-4646-11-git-send-email-yao.jin@linux.intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/builtin-stat.c
tools/perf/util/target.h

index f4129a5..ee708ba 100644 (file)
@@ -277,7 +277,7 @@ static int create_perf_stat_counter(struct perf_evsel *evsel)
                        attr->enable_on_exec = 1;
        }
 
-       if (target__has_cpu(&target))
+       if (target__has_cpu(&target) && !target__has_per_thread(&target))
                return perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel));
 
        return perf_evsel__open_per_thread(evsel, evsel_list->threads);
@@ -340,7 +340,7 @@ static int read_counter(struct perf_evsel *counter)
        int nthreads = thread_map__nr(evsel_list->threads);
        int ncpus, cpu, thread;
 
-       if (target__has_cpu(&target))
+       if (target__has_cpu(&target) && !target__has_per_thread(&target))
                ncpus = perf_evsel__nr_cpus(counter);
        else
                ncpus = 1;
@@ -2743,12 +2743,16 @@ int cmd_stat(int argc, const char **argv)
                run_count = 1;
        }
 
-       if ((stat_config.aggr_mode == AGGR_THREAD) && !target__has_task(&target)) {
-               fprintf(stderr, "The --per-thread option is only available "
-                       "when monitoring via -p -t options.\n");
-               parse_options_usage(NULL, stat_options, "p", 1);
-               parse_options_usage(NULL, stat_options, "t", 1);
-               goto out;
+       if ((stat_config.aggr_mode == AGGR_THREAD) &&
+               !target__has_task(&target)) {
+               if (!target.system_wide || target.cpu_list) {
+                       fprintf(stderr, "The --per-thread option is only "
+                               "available when monitoring via -p -t -a "
+                               "options or only --per-thread.\n");
+                       parse_options_usage(NULL, stat_options, "p", 1);
+                       parse_options_usage(NULL, stat_options, "t", 1);
+                       goto out;
+               }
        }
 
        /*
@@ -2772,6 +2776,9 @@ int cmd_stat(int argc, const char **argv)
 
        target__validate(&target);
 
+       if ((stat_config.aggr_mode == AGGR_THREAD) && (target.system_wide))
+               target.per_thread = true;
+
        if (perf_evlist__create_maps(evsel_list, &target) < 0) {
                if (target__has_task(&target)) {
                        pr_err("Problems finding threads of monitor\n");
index 446aa7a..6ef01a8 100644 (file)
@@ -64,6 +64,11 @@ static inline bool target__none(struct target *target)
        return !target__has_task(target) && !target__has_cpu(target);
 }
 
+static inline bool target__has_per_thread(struct target *target)
+{
+       return target->system_wide && target->per_thread;
+}
+
 static inline bool target__uses_dummy_map(struct target *target)
 {
        bool use_dummy = false;
@@ -73,6 +78,8 @@ static inline bool target__uses_dummy_map(struct target *target)
        else if (target__has_task(target) ||
                 (!target__has_cpu(target) && !target->uses_mmap))
                use_dummy = true;
+       else if (target__has_per_thread(target))
+               use_dummy = true;
 
        return use_dummy;
 }