linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/43] perf stat: Make some of the stat code generic
@ 2018-08-30  6:32 Jiri Olsa
  2018-08-30  6:32 ` [PATCH 01/43] perf stat: Use evsel->threads in create_perf_stat_counter Jiri Olsa
                   ` (43 more replies)
  0 siblings, 44 replies; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

hi,
while going for the ability to store/display stat data
in perf record/top I ended up with bunch of generic
patches that make some of the stat functions standalone
and simplify/reduce the builtin-stat.c code.

This patchset mostly separates the display functions
into separate object, plus several other functions.

Also available in here:
  git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf.git
  perf/fixes

thanks,
jirka


---
Jiri Olsa (43):
      perf stat: Use evsel->threads in create_perf_stat_counter
      perf stat: Move initial_delay into struct perf_stat_config
      perf stat: Move no_inherit into struct perf_stat_config
      perf stat: Use local config arg for scale in create_perf_stat_counter
      perf stat: Add identifier flag into struct stat_opts
      perf tools: Switch session argument to evlist in perf_event__synthesize_attrs
      perf tools: Add perf_evsel__store_ids function
      perf stat: Move create_perf_stat_counter into stat.c
      perf stat: Rename is_pipe argument to attrs perf_stat_synthesize_config
      perf stat: Add struct perf_stat_config argument to perf_stat_synthesize_config
      perf stat: Add struct perf_tool argument to perf_stat_synthesize_config
      perf stat: Add struct perf_evlist argument to perf_stat_synthesize_config
      perf stat: Add perf_event__handler_t argument to perf_stat_synthesize_config
      perf stat: Move perf_stat_synthesize_config into stat.c
      perf stat: Add perf_evlist__print_counters function
      perf stat: Move STAT_RECORD out of perf_evlist__print_counters
      perf stat: Add stat_config argument to perf_evlist__print_counters
      perf stat: Pass stat_config argument to local print functions
      perf stat: Pass stat_config argument to global print functions
      perf stat: Move csv_* into struct perf_stat_config
      perf stat: Move interval_clear into struct perf_stat_config
      perf stat: Move metric_only into struct perf_stat_config
      perf stat: Move unit_width into struct perf_stat_config
      perf stat: Add target argument to perf_evlist__print_counters
      perf stat: Pass evlist argument to print functions
      perf stat: Use evsel->evlist instead of evsel_list in collect_all_aliases
      perf stat: Move run_count into struct perf_stat_config
      perf stat: Move metric_only_len into struct perf_stat_config
      perf stat: Pass stat_config to first_shadow_cpu
      perf stat: Pass evlist to aggr_update_shadow
      perf stat: Add walltime_nsecs_stats pointer into struct perf_stat_config
      perf stat: Move null_run into struct perf_stat_config
      perf stat: Move print_free_counters_hint into struct perf_stat_config
      perf stat: Move print_mixed_hw_group_error into struct perf_stat_config
      perf stat: Move ru_* data into struct perf_stat_config
      perf stat: Move *_aggr_* data into struct perf_stat_config
      perf stat: Do not use glovab evsel_list in print functions
      perf stat: Move big_num data into struct perf_stat_config
      perf stat: Move no_merge data into struct perf_stat_config
      perf stat: Propagate struct target arg to sort_aggr_thread
      perf stat: Move walltime_* data into struct perf_stat_config
      perf stat: Move metric_events into struct perf_stat_config
      perf stat: Move display functions into stat-display.c

 tools/perf/builtin-record.c    |    2 +-
 tools/perf/builtin-script.c    |    8 +-
 tools/perf/builtin-stat.c      | 1440 +++++++++--------------------------------------------------------------------------------------------------------------
 tools/perf/util/Build          |    1 +
 tools/perf/util/evsel.c        |   29 +++
 tools/perf/util/evsel.h        |    1 +
 tools/perf/util/header.c       |    6 +-
 tools/perf/util/header.h       |    2 +-
 tools/perf/util/stat-display.c | 1166 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/stat-shadow.c  |  147 +++++++------
 tools/perf/util/stat.c         |   95 ++++++++
 tools/perf/util/stat.h         |   72 +++++-
 12 files changed, 1545 insertions(+), 1424 deletions(-)
 create mode 100644 tools/perf/util/stat-display.c

^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH 01/43] perf stat: Use evsel->threads in create_perf_stat_counter
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:21   ` [tip:perf/core] perf stat: Use evsel->threads in create_perf_stat_counter() tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 02/43] perf stat: Move initial_delay into struct perf_stat_config Jiri Olsa
                   ` (42 subsequent siblings)
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

Getting rid of the evsel_list dependency, here we can use
the evsel->threads copy of the struct thread_map.

Link: http://lkml.kernel.org/n/tip-rkkk6a7dkmczvm8vj59aa326@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index d097b5b47eb8..d389ed623715 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -293,7 +293,7 @@ static int create_perf_stat_counter(struct perf_evsel *evsel)
 	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);
+	return perf_evsel__open_per_thread(evsel, evsel->threads);
 }
 
 static int process_synthesized_event(struct perf_tool *tool __maybe_unused,
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 02/43] perf stat: Move initial_delay into struct perf_stat_config
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
  2018-08-30  6:32 ` [PATCH 01/43] perf stat: Use evsel->threads in create_perf_stat_counter Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:21   ` [tip:perf/core] perf stat: Move 'initial_delay' to 'struct perf_stat_config' tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 03/43] perf stat: Move no_inherit into struct perf_stat_config Jiri Olsa
                   ` (41 subsequent siblings)
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

Moving static initial_delay into struct perf_stat_config,
so it can be passed around and used outside stat command.

Adding struct perf_stat_config argument into
create_perf_stat_counter function and using its
initial_delay instead of static one.

Link: http://lkml.kernel.org/n/tip-p2k4aymp7lxzqr7jyjcs6z80@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 16 ++++++++--------
 tools/perf/util/stat.h    | 18 ++++++++++--------
 2 files changed, 18 insertions(+), 16 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index d389ed623715..719abdd3b7de 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -164,7 +164,6 @@ static bool			group				= false;
 static const char		*pre_cmd			= NULL;
 static const char		*post_cmd			= NULL;
 static bool			sync_run			= false;
-static unsigned int		initial_delay			= 0;
 static unsigned int		unit_width			= 4; /* strlen("unit") */
 static bool			forever				= false;
 static bool			metric_only			= false;
@@ -236,7 +235,8 @@ static void perf_stat__reset_stats(void)
 		perf_stat__reset_shadow_per_stat(&stat_config.stats[i]);
 }
 
-static int create_perf_stat_counter(struct perf_evsel *evsel)
+static int create_perf_stat_counter(struct perf_evsel *evsel,
+				    struct perf_stat_config *config)
 {
 	struct perf_event_attr *attr = &evsel->attr;
 	struct perf_evsel *leader = evsel->leader;
@@ -286,7 +286,7 @@ static int create_perf_stat_counter(struct perf_evsel *evsel)
 		 * In case of initial_delay we enable tracee
 		 * events manually.
 		 */
-		if (target__none(&target) && !initial_delay)
+		if (target__none(&target) && !config->initial_delay)
 			attr->enable_on_exec = 1;
 	}
 
@@ -428,15 +428,15 @@ static void process_interval(void)
 
 static void enable_counters(void)
 {
-	if (initial_delay)
-		usleep(initial_delay * USEC_PER_MSEC);
+	if (stat_config.initial_delay)
+		usleep(stat_config.initial_delay * USEC_PER_MSEC);
 
 	/*
 	 * We need to enable counters only if:
 	 * - we don't have tracee (attaching to task or cpu)
 	 * - we have initial delay configured
 	 */
-	if (!target__none(&target) || initial_delay)
+	if (!target__none(&target) || stat_config.initial_delay)
 		perf_evlist__enable(evsel_list);
 }
 
@@ -609,7 +609,7 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
 
 	evlist__for_each_entry(evsel_list, counter) {
 try_again:
-		if (create_perf_stat_counter(counter) < 0) {
+		if (create_perf_stat_counter(counter, &stat_config) < 0) {
 
 			/* Weak group failed. Reset the group. */
 			if ((errno == EINVAL || errno == EBADF) &&
@@ -2027,7 +2027,7 @@ static const struct option stat_options[] = {
 		     "aggregate counts per physical processor core", AGGR_CORE),
 	OPT_SET_UINT(0, "per-thread", &stat_config.aggr_mode,
 		     "aggregate counts per thread", AGGR_THREAD),
-	OPT_UINTEGER('D', "delay", &initial_delay,
+	OPT_UINTEGER('D', "delay", &stat_config.initial_delay,
 		     "ms to wait before starting measurement after program start"),
 	OPT_CALLBACK_NOOPT(0, "metric-only", &metric_only, NULL,
 			"Only print computed metrics. No raw values", enable_metric_only),
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 36efb986f7fc..91e6609fce6e 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -6,6 +6,7 @@
 #include <stdio.h>
 #include "xyarray.h"
 #include "rblist.h"
+#include "perf.h"
 
 struct stats {
 	double n, mean, M2;
@@ -85,14 +86,15 @@ struct runtime_stat {
 };
 
 struct perf_stat_config {
-	enum aggr_mode	aggr_mode;
-	bool		scale;
-	FILE		*output;
-	unsigned int	interval;
-	unsigned int	timeout;
-	int		times;
-	struct runtime_stat *stats;
-	int		stats_num;
+	enum aggr_mode		 aggr_mode;
+	bool			 scale;
+	FILE			*output;
+	unsigned int		 interval;
+	unsigned int		 timeout;
+	unsigned int		 initial_delay;
+	int			 times;
+	struct runtime_stat	*stats;
+	int			 stats_num;
 };
 
 void update_stats(struct stats *stats, u64 val);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 03/43] perf stat: Move no_inherit into struct perf_stat_config
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
  2018-08-30  6:32 ` [PATCH 01/43] perf stat: Use evsel->threads in create_perf_stat_counter Jiri Olsa
  2018-08-30  6:32 ` [PATCH 02/43] perf stat: Move initial_delay into struct perf_stat_config Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:22   ` [tip:perf/core] perf stat: Move 'no_inherit' to 'struct perf_stat_config' tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 04/43] perf stat: Use local config arg for scale in create_perf_stat_counter Jiri Olsa
                   ` (40 subsequent siblings)
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

Moving static no_inherit into struct perf_stat_config,
so it can be passed around and used outside stat command.

Link: http://lkml.kernel.org/n/tip-md7htmdsje3od38k86do4899@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 5 ++---
 tools/perf/util/stat.h    | 1 +
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 719abdd3b7de..84dbac526925 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -148,7 +148,6 @@ typedef int (*aggr_get_id_t)(struct cpu_map *m, int cpu);
 #define METRIC_ONLY_LEN 20
 
 static int			run_count			=  1;
-static bool			no_inherit			= false;
 static volatile pid_t		child_pid			= -1;
 static bool			null_run			=  false;
 static int			detailed_run			=  0;
@@ -254,7 +253,7 @@ static int create_perf_stat_counter(struct perf_evsel *evsel,
 	if (leader->nr_members > 1)
 		attr->read_format |= PERF_FORMAT_ID|PERF_FORMAT_GROUP;
 
-	attr->inherit = !no_inherit;
+	attr->inherit = !config->no_inherit;
 
 	/*
 	 * Some events get initialized with sample_(period/type) set,
@@ -1969,7 +1968,7 @@ static const struct option stat_options[] = {
 		     parse_events_option),
 	OPT_CALLBACK(0, "filter", &evsel_list, "filter",
 		     "event filter", parse_filter),
-	OPT_BOOLEAN('i', "no-inherit", &no_inherit,
+	OPT_BOOLEAN('i', "no-inherit", &stat_config.no_inherit,
 		    "child tasks do not inherit counters"),
 	OPT_STRING('p', "pid", &target.pid, "pid",
 		   "stat events on existing process id"),
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 91e6609fce6e..53b2415ba3f3 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -88,6 +88,7 @@ struct runtime_stat {
 struct perf_stat_config {
 	enum aggr_mode		 aggr_mode;
 	bool			 scale;
+	bool			 no_inherit;
 	FILE			*output;
 	unsigned int		 interval;
 	unsigned int		 timeout;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 04/43] perf stat: Use local config arg for scale in create_perf_stat_counter
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
                   ` (2 preceding siblings ...)
  2018-08-30  6:32 ` [PATCH 03/43] perf stat: Move no_inherit into struct perf_stat_config Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:22   ` [tip:perf/core] perf stat: Use local config arg for scale in create_perf_stat_counter() tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 05/43] perf stat: Add identifier flag into struct stat_opts Jiri Olsa
                   ` (39 subsequent siblings)
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

Using local scale from local 'struct perf_stat_config' argument
instead of the global stat_config, to make the function independent.

Link: http://lkml.kernel.org/n/tip-gv2k5lpl0k0gc4kcfamohdk9@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 84dbac526925..47789558899a 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -240,7 +240,7 @@ static int create_perf_stat_counter(struct perf_evsel *evsel,
 	struct perf_event_attr *attr = &evsel->attr;
 	struct perf_evsel *leader = evsel->leader;
 
-	if (stat_config.scale) {
+	if (config->scale) {
 		attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
 				    PERF_FORMAT_TOTAL_TIME_RUNNING;
 	}
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 05/43] perf stat: Add identifier flag into struct stat_opts
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
                   ` (3 preceding siblings ...)
  2018-08-30  6:32 ` [PATCH 04/43] perf stat: Use local config arg for scale in create_perf_stat_counter Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:23   ` [tip:perf/core] perf stat: Add 'identifier' flag to 'struct perf_stat_config' tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 06/43] perf tools: Switch session argument to evlist in perf_event__synthesize_attrs Jiri Olsa
                   ` (38 subsequent siblings)
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

Adding identifier flag into struct stat_opts to carry the
info whether to use PERF_SAMPLE_IDENTIFIER for events.
It makes the create_perf_stat_counter function independent.

Link: http://lkml.kernel.org/n/tip-s1n7gth2e05oxai3gf2z5p3w@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 22 ++++++++++++----------
 tools/perf/util/stat.h    |  1 +
 2 files changed, 13 insertions(+), 10 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 47789558899a..48c88f568fe1 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -261,16 +261,7 @@ static int create_perf_stat_counter(struct perf_evsel *evsel,
 	 */
 	attr->sample_period = 0;
 
-	/*
-	 * But set sample_type to PERF_SAMPLE_IDENTIFIER, which should be harmless
-	 * while avoiding that older tools show confusing messages.
-	 *
-	 * However for pipe sessions we need to keep it zero,
-	 * because script's perf_evsel__check_attr is triggered
-	 * by attr->sample_type != 0, and we can't run it on
-	 * stat sessions.
-	 */
-	if (!(STAT_RECORD && perf_stat.data.is_pipe))
+	if (config->identifier)
 		attr->sample_type = PERF_SAMPLE_IDENTIFIER;
 
 	/*
@@ -3064,6 +3055,17 @@ int cmd_stat(int argc, const char **argv)
 	if (perf_stat_init_aggr_mode())
 		goto out;
 
+	/*
+	 * Set sample_type to PERF_SAMPLE_IDENTIFIER, which should be harmless
+	 * while avoiding that older tools show confusing messages.
+	 *
+	 * However for pipe sessions we need to keep it zero,
+	 * because script's perf_evsel__check_attr is triggered
+	 * by attr->sample_type != 0, and we can't run it on
+	 * stat sessions.
+	 */
+	stat_config.identifier = !(STAT_RECORD && perf_stat.data.is_pipe);
+
 	/*
 	 * We dont want to block the signals - that would cause
 	 * child tasks to inherit that and Ctrl-C would not work.
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 53b2415ba3f3..918cde064cdc 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -89,6 +89,7 @@ struct perf_stat_config {
 	enum aggr_mode		 aggr_mode;
 	bool			 scale;
 	bool			 no_inherit;
+	bool			 identifier;
 	FILE			*output;
 	unsigned int		 interval;
 	unsigned int		 timeout;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 06/43] perf tools: Switch session argument to evlist in perf_event__synthesize_attrs
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
                   ` (4 preceding siblings ...)
  2018-08-30  6:32 ` [PATCH 05/43] perf stat: Add identifier flag into struct stat_opts Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:23   ` [tip:perf/core] perf tools: Switch 'session' argument to 'evlist' in perf_event__synthesize_attrs() tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 07/43] perf tools: Add perf_evsel__store_ids function Jiri Olsa
                   ` (37 subsequent siblings)
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

To be able to pass in other than session's evlist.

Link: http://lkml.kernel.org/n/tip-crsckf9is77d25pwoc3ekmpo@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-record.c | 2 +-
 tools/perf/builtin-stat.c   | 2 +-
 tools/perf/util/header.c    | 6 +++---
 tools/perf/util/header.h    | 2 +-
 4 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 22ebeb92ac51..9853552bcf16 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -758,7 +758,7 @@ static int record__synthesize(struct record *rec, bool tail)
 		 * We need to synthesize events first, because some
 		 * features works on top of them (on report side).
 		 */
-		err = perf_event__synthesize_attrs(tool, session,
+		err = perf_event__synthesize_attrs(tool, rec->evlist,
 						   process_synthesized_event);
 		if (err < 0) {
 			pr_err("Couldn't synthesize attrs.\n");
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 48c88f568fe1..8291f503d0cc 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -459,7 +459,7 @@ static int perf_stat_synthesize_config(bool is_pipe)
 	int err;
 
 	if (is_pipe) {
-		err = perf_event__synthesize_attrs(NULL, perf_stat.session,
+		err = perf_event__synthesize_attrs(NULL, evsel_list,
 						   process_synthesized_event);
 		if (err < 0) {
 			pr_err("Couldn't synthesize attrs.\n");
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 3cadc252dd89..91e6d9cfd906 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -3637,13 +3637,13 @@ size_t perf_event__fprintf_event_update(union perf_event *event, FILE *fp)
 }
 
 int perf_event__synthesize_attrs(struct perf_tool *tool,
-				   struct perf_session *session,
-				   perf_event__handler_t process)
+				 struct perf_evlist *evlist,
+				 perf_event__handler_t process)
 {
 	struct perf_evsel *evsel;
 	int err = 0;
 
-	evlist__for_each_entry(session->evlist, evsel) {
+	evlist__for_each_entry(evlist, evsel) {
 		err = perf_event__synthesize_attr(tool, &evsel->attr, evsel->ids,
 						  evsel->id, process);
 		if (err) {
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 6d7fe44aadc0..ff2a1263fb9b 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -124,7 +124,7 @@ int perf_event__synthesize_attr(struct perf_tool *tool,
 				struct perf_event_attr *attr, u32 ids, u64 *id,
 				perf_event__handler_t process);
 int perf_event__synthesize_attrs(struct perf_tool *tool,
-				 struct perf_session *session,
+				 struct perf_evlist *evlist,
 				 perf_event__handler_t process);
 int perf_event__synthesize_event_update_unit(struct perf_tool *tool,
 					     struct perf_evsel *evsel,
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 07/43] perf tools: Add perf_evsel__store_ids function
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
                   ` (5 preceding siblings ...)
  2018-08-30  6:32 ` [PATCH 06/43] perf tools: Switch session argument to evlist in perf_event__synthesize_attrs Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:24   ` [tip:perf/core] perf evsel: Introduce perf_evsel__store_ids() tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 08/43] perf stat: Move create_perf_stat_counter into stat.c Jiri Olsa
                   ` (36 subsequent siblings)
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

Adding perf_evsel__store_ids function from stat's
store_counter_ids code into evsel object, so it
could be used globaly.

Link: http://lkml.kernel.org/n/tip-epqr71x8ufexd3or67kjqp9v@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 33 +--------------------------------
 tools/perf/util/evsel.c   | 29 +++++++++++++++++++++++++++++
 tools/perf/util/evsel.h   |  1 +
 3 files changed, 31 insertions(+), 32 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 8291f503d0cc..45bbd156d496 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -497,37 +497,6 @@ static int perf_stat_synthesize_config(bool is_pipe)
 	return 0;
 }
 
-#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
-
-static int __store_counter_ids(struct perf_evsel *counter)
-{
-	int cpu, thread;
-
-	for (cpu = 0; cpu < xyarray__max_x(counter->fd); cpu++) {
-		for (thread = 0; thread < xyarray__max_y(counter->fd);
-		     thread++) {
-			int fd = FD(counter, cpu, thread);
-
-			if (perf_evlist__id_add_fd(evsel_list, counter,
-						   cpu, thread, fd) < 0)
-				return -1;
-		}
-	}
-
-	return 0;
-}
-
-static int store_counter_ids(struct perf_evsel *counter)
-{
-	struct cpu_map *cpus = counter->cpus;
-	struct thread_map *threads = counter->threads;
-
-	if (perf_evsel__alloc_id(counter, cpus->nr, threads->nr))
-		return -ENOMEM;
-
-	return __store_counter_ids(counter);
-}
-
 static bool perf_evsel__should_store_id(struct perf_evsel *counter)
 {
 	return STAT_RECORD || counter->attr.read_format & PERF_FORMAT_ID;
@@ -658,7 +627,7 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
 			unit_width = l;
 
 		if (perf_evsel__should_store_id(counter) &&
-		    store_counter_ids(counter))
+		    perf_evsel__store_ids(counter, evsel_list))
 			return -1;
 	}
 
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 1a61628a1c12..4ec909d57e9c 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -2940,3 +2940,32 @@ struct perf_env *perf_evsel__env(struct perf_evsel *evsel)
 		return evsel->evlist->env;
 	return NULL;
 }
+
+static int store_evsel_ids(struct perf_evsel *evsel, struct perf_evlist *evlist)
+{
+	int cpu, thread;
+
+	for (cpu = 0; cpu < xyarray__max_x(evsel->fd); cpu++) {
+		for (thread = 0; thread < xyarray__max_y(evsel->fd);
+		     thread++) {
+			int fd = FD(evsel, cpu, thread);
+
+			if (perf_evlist__id_add_fd(evlist, evsel,
+						   cpu, thread, fd) < 0)
+				return -1;
+		}
+	}
+
+	return 0;
+}
+
+int perf_evsel__store_ids(struct perf_evsel *evsel, struct perf_evlist *evlist)
+{
+	struct cpu_map *cpus = evsel->cpus;
+	struct thread_map *threads = evsel->threads;
+
+	if (perf_evsel__alloc_id(evsel, cpus->nr, threads->nr))
+		return -ENOMEM;
+
+	return store_evsel_ids(evsel, evlist);
+}
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 163c960614d3..4f8430a85531 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -481,4 +481,5 @@ int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr,
 
 struct perf_env *perf_evsel__env(struct perf_evsel *evsel);
 
+int perf_evsel__store_ids(struct perf_evsel *evsel, struct perf_evlist *evlist);
 #endif /* __PERF_EVSEL_H */
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 08/43] perf stat: Move create_perf_stat_counter into stat.c
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
                   ` (6 preceding siblings ...)
  2018-08-30  6:32 ` [PATCH 07/43] perf tools: Add perf_evsel__store_ids function Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:24   ` [tip:perf/core] perf stat: Move create_perf_stat_counter() to stat.c tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 09/43] perf stat: Rename is_pipe argument to attrs perf_stat_synthesize_config Jiri Olsa
                   ` (35 subsequent siblings)
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

Moving create_perf_stat_counter to stat object,
so we could use it globally.

Link: http://lkml.kernel.org/n/tip-47odtb7otnqlo07h0crk6ftp@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 54 +--------------------------------------
 tools/perf/util/stat.c    | 53 ++++++++++++++++++++++++++++++++++++++
 tools/perf/util/stat.h    |  4 +++
 3 files changed, 58 insertions(+), 53 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 45bbd156d496..142cff8eb12b 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -234,58 +234,6 @@ static void perf_stat__reset_stats(void)
 		perf_stat__reset_shadow_per_stat(&stat_config.stats[i]);
 }
 
-static int create_perf_stat_counter(struct perf_evsel *evsel,
-				    struct perf_stat_config *config)
-{
-	struct perf_event_attr *attr = &evsel->attr;
-	struct perf_evsel *leader = evsel->leader;
-
-	if (config->scale) {
-		attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
-				    PERF_FORMAT_TOTAL_TIME_RUNNING;
-	}
-
-	/*
-	 * The event is part of non trivial group, let's enable
-	 * the group read (for leader) and ID retrieval for all
-	 * members.
-	 */
-	if (leader->nr_members > 1)
-		attr->read_format |= PERF_FORMAT_ID|PERF_FORMAT_GROUP;
-
-	attr->inherit = !config->no_inherit;
-
-	/*
-	 * Some events get initialized with sample_(period/type) set,
-	 * like tracepoints. Clear it up for counting.
-	 */
-	attr->sample_period = 0;
-
-	if (config->identifier)
-		attr->sample_type = PERF_SAMPLE_IDENTIFIER;
-
-	/*
-	 * Disabling all counters initially, they will be enabled
-	 * either manually by us or by kernel via enable_on_exec
-	 * set later.
-	 */
-	if (perf_evsel__is_group_leader(evsel)) {
-		attr->disabled = 1;
-
-		/*
-		 * In case of initial_delay we enable tracee
-		 * events manually.
-		 */
-		if (target__none(&target) && !config->initial_delay)
-			attr->enable_on_exec = 1;
-	}
-
-	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->threads);
-}
-
 static int process_synthesized_event(struct perf_tool *tool __maybe_unused,
 				     union perf_event *event,
 				     struct perf_sample *sample __maybe_unused,
@@ -568,7 +516,7 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
 
 	evlist__for_each_entry(evsel_list, counter) {
 try_again:
-		if (create_perf_stat_counter(counter, &stat_config) < 0) {
+		if (create_perf_stat_counter(counter, &stat_config, &target) < 0) {
 
 			/* Weak group failed. Reset the group. */
 			if ((errno == EINVAL || errno == EBADF) &&
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index a0061e0b0fad..3bd24255376a 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -435,3 +435,56 @@ size_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp)
 
 	return ret;
 }
+
+int create_perf_stat_counter(struct perf_evsel *evsel,
+			     struct perf_stat_config *config,
+			     struct target *target)
+{
+	struct perf_event_attr *attr = &evsel->attr;
+	struct perf_evsel *leader = evsel->leader;
+
+	if (config->scale) {
+		attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
+				    PERF_FORMAT_TOTAL_TIME_RUNNING;
+	}
+
+	/*
+	 * The event is part of non trivial group, let's enable
+	 * the group read (for leader) and ID retrieval for all
+	 * members.
+	 */
+	if (leader->nr_members > 1)
+		attr->read_format |= PERF_FORMAT_ID|PERF_FORMAT_GROUP;
+
+	attr->inherit = !config->no_inherit;
+
+	/*
+	 * Some events get initialized with sample_(period/type) set,
+	 * like tracepoints. Clear it up for counting.
+	 */
+	attr->sample_period = 0;
+
+	if (config->identifier)
+		attr->sample_type = PERF_SAMPLE_IDENTIFIER;
+
+	/*
+	 * Disabling all counters initially, they will be enabled
+	 * either manually by us or by kernel via enable_on_exec
+	 * set later.
+	 */
+	if (perf_evsel__is_group_leader(evsel)) {
+		attr->disabled = 1;
+
+		/*
+		 * In case of initial_delay we enable tracee
+		 * events manually.
+		 */
+		if (target__none(target) && !config->initial_delay)
+			attr->enable_on_exec = 1;
+	}
+
+	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->threads);
+}
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 918cde064cdc..8fb596641545 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -175,4 +175,8 @@ int perf_event__process_stat_event(struct perf_tool *tool,
 size_t perf_event__fprintf_stat(union perf_event *event, FILE *fp);
 size_t perf_event__fprintf_stat_round(union perf_event *event, FILE *fp);
 size_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp);
+
+int create_perf_stat_counter(struct perf_evsel *evsel,
+			     struct perf_stat_config *config,
+			     struct target *target);
 #endif
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 09/43] perf stat: Rename is_pipe argument to attrs perf_stat_synthesize_config
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
                   ` (7 preceding siblings ...)
  2018-08-30  6:32 ` [PATCH 08/43] perf stat: Move create_perf_stat_counter into stat.c Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:25   ` [tip:perf/core] perf stat: Rename 'is_pipe' argument to 'attrs' in perf_stat_synthesize_config() tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 10/43] perf stat: Add struct perf_stat_config argument to perf_stat_synthesize_config Jiri Olsa
                   ` (34 subsequent siblings)
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

The attrs name makes more sense.

Link: http://lkml.kernel.org/n/tip-3zodh2azuy9hf1gba71m28ox@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 142cff8eb12b..0a358c2e1a93 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -402,11 +402,11 @@ static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *inf
 	workload_exec_errno = info->si_value.sival_int;
 }
 
-static int perf_stat_synthesize_config(bool is_pipe)
+static int perf_stat_synthesize_config(bool attrs)
 {
 	int err;
 
-	if (is_pipe) {
+	if (attrs) {
 		err = perf_event__synthesize_attrs(NULL, evsel_list,
 						   process_synthesized_event);
 		if (err < 0) {
@@ -418,7 +418,7 @@ static int perf_stat_synthesize_config(bool is_pipe)
 	err = perf_event__synthesize_extra_attr(NULL,
 						evsel_list,
 						process_synthesized_event,
-						is_pipe);
+						attrs);
 
 	err = perf_event__synthesize_thread_map2(NULL, evsel_list->threads,
 						process_synthesized_event,
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 10/43] perf stat: Add struct perf_stat_config argument to perf_stat_synthesize_config
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
                   ` (8 preceding siblings ...)
  2018-08-30  6:32 ` [PATCH 09/43] perf stat: Rename is_pipe argument to attrs perf_stat_synthesize_config Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:26   ` [tip:perf/core] perf stat: Add 'struct perf_stat_config' argument to perf_stat_synthesize_config() tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 11/43] perf stat: Add struct perf_tool argument to perf_stat_synthesize_config Jiri Olsa
                   ` (33 subsequent siblings)
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

Adding struct perf_stat_config argument to perf_stat_synthesize_config,
so we could synthesize arbitrary config.

Link: http://lkml.kernel.org/n/tip-v84l6fy0d0nrict7jpknscem@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 0a358c2e1a93..d0d19a5ffa85 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -402,7 +402,8 @@ static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *inf
 	workload_exec_errno = info->si_value.sival_int;
 }
 
-static int perf_stat_synthesize_config(bool attrs)
+static int perf_stat_synthesize_config(struct perf_stat_config *config,
+				       bool attrs)
 {
 	int err;
 
@@ -435,7 +436,7 @@ static int perf_stat_synthesize_config(bool attrs)
 		return err;
 	}
 
-	err = perf_event__synthesize_stat_config(NULL, &stat_config,
+	err = perf_event__synthesize_stat_config(NULL, config,
 						 process_synthesized_event, NULL);
 	if (err < 0) {
 		pr_err("Couldn't synthesize config.\n");
@@ -606,7 +607,7 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
 		if (err < 0)
 			return err;
 
-		err = perf_stat_synthesize_config(is_pipe);
+		err = perf_stat_synthesize_config(&stat_config, is_pipe);
 		if (err < 0)
 			return err;
 	}
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 11/43] perf stat: Add struct perf_tool argument to perf_stat_synthesize_config
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
                   ` (9 preceding siblings ...)
  2018-08-30  6:32 ` [PATCH 10/43] perf stat: Add struct perf_stat_config argument to perf_stat_synthesize_config Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:26   ` [tip:perf/core] perf stat: Add 'struct perf_tool' argument to perf_stat_synthesize_config() tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 12/43] perf stat: Add struct perf_evlist argument to perf_stat_synthesize_config Jiri Olsa
                   ` (32 subsequent siblings)
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

So we can use the function outside stat command
with standard synthesize functions, that take
struct perf_tool* argument.

Link: http://lkml.kernel.org/n/tip-fwzsgvy78dkaij1dt6icb51i@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index d0d19a5ffa85..ae5029875e87 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -403,12 +403,13 @@ static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *inf
 }
 
 static int perf_stat_synthesize_config(struct perf_stat_config *config,
+				       struct perf_tool *tool,
 				       bool attrs)
 {
 	int err;
 
 	if (attrs) {
-		err = perf_event__synthesize_attrs(NULL, evsel_list,
+		err = perf_event__synthesize_attrs(tool, evsel_list,
 						   process_synthesized_event);
 		if (err < 0) {
 			pr_err("Couldn't synthesize attrs.\n");
@@ -416,12 +417,12 @@ static int perf_stat_synthesize_config(struct perf_stat_config *config,
 		}
 	}
 
-	err = perf_event__synthesize_extra_attr(NULL,
+	err = perf_event__synthesize_extra_attr(tool,
 						evsel_list,
 						process_synthesized_event,
 						attrs);
 
-	err = perf_event__synthesize_thread_map2(NULL, evsel_list->threads,
+	err = perf_event__synthesize_thread_map2(tool, evsel_list->threads,
 						process_synthesized_event,
 						NULL);
 	if (err < 0) {
@@ -429,14 +430,14 @@ static int perf_stat_synthesize_config(struct perf_stat_config *config,
 		return err;
 	}
 
-	err = perf_event__synthesize_cpu_map(NULL, evsel_list->cpus,
+	err = perf_event__synthesize_cpu_map(tool, evsel_list->cpus,
 					     process_synthesized_event, NULL);
 	if (err < 0) {
 		pr_err("Couldn't synthesize thread map.\n");
 		return err;
 	}
 
-	err = perf_event__synthesize_stat_config(NULL, config,
+	err = perf_event__synthesize_stat_config(tool, config,
 						 process_synthesized_event, NULL);
 	if (err < 0) {
 		pr_err("Couldn't synthesize config.\n");
@@ -607,7 +608,7 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
 		if (err < 0)
 			return err;
 
-		err = perf_stat_synthesize_config(&stat_config, is_pipe);
+		err = perf_stat_synthesize_config(&stat_config, NULL, is_pipe);
 		if (err < 0)
 			return err;
 	}
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 12/43] perf stat: Add struct perf_evlist argument to perf_stat_synthesize_config
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
                   ` (10 preceding siblings ...)
  2018-08-30  6:32 ` [PATCH 11/43] perf stat: Add struct perf_tool argument to perf_stat_synthesize_config Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:27   ` [tip:perf/core] perf stat: Add 'struct perf_evlist' argument to perf_stat_synthesize_config() tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 13/43] perf stat: Add perf_event__handler_t argument to perf_stat_synthesize_config Jiri Olsa
                   ` (31 subsequent siblings)
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

Getting rid of the evsel_list dependency, here in function
perf_stat_synthesize_config we are adding the evlist arg.

Link: http://lkml.kernel.org/n/tip-eehdn85xqcqf7jrafoqu2lfv@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index ae5029875e87..cb36344c25b7 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -404,12 +404,13 @@ static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *inf
 
 static int perf_stat_synthesize_config(struct perf_stat_config *config,
 				       struct perf_tool *tool,
+				       struct perf_evlist *evlist,
 				       bool attrs)
 {
 	int err;
 
 	if (attrs) {
-		err = perf_event__synthesize_attrs(tool, evsel_list,
+		err = perf_event__synthesize_attrs(tool, evlist,
 						   process_synthesized_event);
 		if (err < 0) {
 			pr_err("Couldn't synthesize attrs.\n");
@@ -417,12 +418,11 @@ static int perf_stat_synthesize_config(struct perf_stat_config *config,
 		}
 	}
 
-	err = perf_event__synthesize_extra_attr(tool,
-						evsel_list,
+	err = perf_event__synthesize_extra_attr(tool, evlist,
 						process_synthesized_event,
 						attrs);
 
-	err = perf_event__synthesize_thread_map2(tool, evsel_list->threads,
+	err = perf_event__synthesize_thread_map2(tool, evlist->threads,
 						process_synthesized_event,
 						NULL);
 	if (err < 0) {
@@ -430,7 +430,7 @@ static int perf_stat_synthesize_config(struct perf_stat_config *config,
 		return err;
 	}
 
-	err = perf_event__synthesize_cpu_map(tool, evsel_list->cpus,
+	err = perf_event__synthesize_cpu_map(tool, evlist->cpus,
 					     process_synthesized_event, NULL);
 	if (err < 0) {
 		pr_err("Couldn't synthesize thread map.\n");
@@ -608,7 +608,8 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
 		if (err < 0)
 			return err;
 
-		err = perf_stat_synthesize_config(&stat_config, NULL, is_pipe);
+		err = perf_stat_synthesize_config(&stat_config, NULL, evsel_list,
+						  is_pipe);
 		if (err < 0)
 			return err;
 	}
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 13/43] perf stat: Add perf_event__handler_t argument to perf_stat_synthesize_config
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
                   ` (11 preceding siblings ...)
  2018-08-30  6:32 ` [PATCH 12/43] perf stat: Add struct perf_evlist argument to perf_stat_synthesize_config Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:27   ` [tip:perf/core] perf stat: Add 'perf_event__handler_t' argument to perf_stat_synthesize_config() tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 14/43] perf stat: Move perf_stat_synthesize_config into stat.c Jiri Olsa
                   ` (30 subsequent siblings)
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

So it's completely independent and can be
used outside stat command.

Link: http://lkml.kernel.org/n/tip-eehdn85xqcqf7jrafoqu2lfv@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 17 +++++++----------
 1 file changed, 7 insertions(+), 10 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index cb36344c25b7..1171d4e00276 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -405,40 +405,37 @@ static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *inf
 static int perf_stat_synthesize_config(struct perf_stat_config *config,
 				       struct perf_tool *tool,
 				       struct perf_evlist *evlist,
+				       perf_event__handler_t process,
 				       bool attrs)
 {
 	int err;
 
 	if (attrs) {
-		err = perf_event__synthesize_attrs(tool, evlist,
-						   process_synthesized_event);
+		err = perf_event__synthesize_attrs(tool, evlist, process);
 		if (err < 0) {
 			pr_err("Couldn't synthesize attrs.\n");
 			return err;
 		}
 	}
 
-	err = perf_event__synthesize_extra_attr(tool, evlist,
-						process_synthesized_event,
+	err = perf_event__synthesize_extra_attr(tool, evlist, process,
 						attrs);
 
 	err = perf_event__synthesize_thread_map2(tool, evlist->threads,
-						process_synthesized_event,
-						NULL);
+						 process, NULL);
 	if (err < 0) {
 		pr_err("Couldn't synthesize thread map.\n");
 		return err;
 	}
 
 	err = perf_event__synthesize_cpu_map(tool, evlist->cpus,
-					     process_synthesized_event, NULL);
+					     process, NULL);
 	if (err < 0) {
 		pr_err("Couldn't synthesize thread map.\n");
 		return err;
 	}
 
-	err = perf_event__synthesize_stat_config(tool, config,
-						 process_synthesized_event, NULL);
+	err = perf_event__synthesize_stat_config(tool, config, process, NULL);
 	if (err < 0) {
 		pr_err("Couldn't synthesize config.\n");
 		return err;
@@ -609,7 +606,7 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
 			return err;
 
 		err = perf_stat_synthesize_config(&stat_config, NULL, evsel_list,
-						  is_pipe);
+						  process_synthesized_event, is_pipe);
 		if (err < 0)
 			return err;
 	}
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 14/43] perf stat: Move perf_stat_synthesize_config into stat.c
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
                   ` (12 preceding siblings ...)
  2018-08-30  6:32 ` [PATCH 13/43] perf stat: Add perf_event__handler_t argument to perf_stat_synthesize_config Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:28   ` [tip:perf/core] perf stat: Move perf_stat_synthesize_config() to stat.c tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 15/43] perf stat: Add perf_evlist__print_counters function Jiri Olsa
                   ` (29 subsequent siblings)
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

So it can be used globaly.

Link: http://lkml.kernel.org/n/tip-6iu57r6ts9f0m92hw7f8in1o@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 42 ---------------------------------------
 tools/perf/util/stat.c    | 42 +++++++++++++++++++++++++++++++++++++++
 tools/perf/util/stat.h    |  6 ++++++
 3 files changed, 48 insertions(+), 42 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 1171d4e00276..54768ec15dbc 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -402,48 +402,6 @@ static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *inf
 	workload_exec_errno = info->si_value.sival_int;
 }
 
-static int perf_stat_synthesize_config(struct perf_stat_config *config,
-				       struct perf_tool *tool,
-				       struct perf_evlist *evlist,
-				       perf_event__handler_t process,
-				       bool attrs)
-{
-	int err;
-
-	if (attrs) {
-		err = perf_event__synthesize_attrs(tool, evlist, process);
-		if (err < 0) {
-			pr_err("Couldn't synthesize attrs.\n");
-			return err;
-		}
-	}
-
-	err = perf_event__synthesize_extra_attr(tool, evlist, process,
-						attrs);
-
-	err = perf_event__synthesize_thread_map2(tool, evlist->threads,
-						 process, NULL);
-	if (err < 0) {
-		pr_err("Couldn't synthesize thread map.\n");
-		return err;
-	}
-
-	err = perf_event__synthesize_cpu_map(tool, evlist->cpus,
-					     process, NULL);
-	if (err < 0) {
-		pr_err("Couldn't synthesize thread map.\n");
-		return err;
-	}
-
-	err = perf_event__synthesize_stat_config(tool, config, process, NULL);
-	if (err < 0) {
-		pr_err("Couldn't synthesize config.\n");
-		return err;
-	}
-
-	return 0;
-}
-
 static bool perf_evsel__should_store_id(struct perf_evsel *counter)
 {
 	return STAT_RECORD || counter->attr.read_format & PERF_FORMAT_ID;
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index 3bd24255376a..5d3172bcc4ae 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -488,3 +488,45 @@ int create_perf_stat_counter(struct perf_evsel *evsel,
 
 	return perf_evsel__open_per_thread(evsel, evsel->threads);
 }
+
+int perf_stat_synthesize_config(struct perf_stat_config *config,
+				struct perf_tool *tool,
+				struct perf_evlist *evlist,
+				perf_event__handler_t process,
+				bool attrs)
+{
+	int err;
+
+	if (attrs) {
+		err = perf_event__synthesize_attrs(tool, evlist, process);
+		if (err < 0) {
+			pr_err("Couldn't synthesize attrs.\n");
+			return err;
+		}
+	}
+
+	err = perf_event__synthesize_extra_attr(tool, evlist, process,
+						attrs);
+
+	err = perf_event__synthesize_thread_map2(tool, evlist->threads,
+						 process, NULL);
+	if (err < 0) {
+		pr_err("Couldn't synthesize thread map.\n");
+		return err;
+	}
+
+	err = perf_event__synthesize_cpu_map(tool, evlist->cpus,
+					     process, NULL);
+	if (err < 0) {
+		pr_err("Couldn't synthesize thread map.\n");
+		return err;
+	}
+
+	err = perf_event__synthesize_stat_config(tool, config, process, NULL);
+	if (err < 0) {
+		pr_err("Couldn't synthesize config.\n");
+		return err;
+	}
+
+	return 0;
+}
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 8fb596641545..da6a706daecc 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -7,6 +7,7 @@
 #include "xyarray.h"
 #include "rblist.h"
 #include "perf.h"
+#include "event.h"
 
 struct stats {
 	double n, mean, M2;
@@ -179,4 +180,9 @@ size_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp);
 int create_perf_stat_counter(struct perf_evsel *evsel,
 			     struct perf_stat_config *config,
 			     struct target *target);
+int perf_stat_synthesize_config(struct perf_stat_config *config,
+				struct perf_tool *tool,
+				struct perf_evlist *evlist,
+				perf_event__handler_t process,
+				bool attrs);
 #endif
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 15/43] perf stat: Add perf_evlist__print_counters function
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
                   ` (13 preceding siblings ...)
  2018-08-30  6:32 ` [PATCH 14/43] perf stat: Move perf_stat_synthesize_config into stat.c Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:28   ` [tip:perf/core] perf stat: Introduce perf_evlist__print_counters() tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 16/43] perf stat: Move STAT_RECORD out of perf_evlist__print_counters Jiri Olsa
                   ` (28 subsequent siblings)
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

To be in charge of printing out the stat output. It will be
moved out of stat command in following patches.

Link: http://lkml.kernel.org/n/tip-girva61h4z5vjn9fclc4d2x9@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 54768ec15dbc..db11832bbdbc 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1692,7 +1692,10 @@ static void print_footer(void)
 			"the same PMU. Try reorganizing the group.\n");
 }
 
-static void print_counters(struct timespec *ts, int argc, const char **argv)
+static void
+perf_evlist__print_counters(struct perf_evlist *evlist,
+			    struct timespec *ts,
+			    int argc, const char **argv)
 {
 	int interval = stat_config.interval;
 	struct perf_evsel *counter;
@@ -1724,14 +1727,14 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)
 		print_aggr(prefix);
 		break;
 	case AGGR_THREAD:
-		evlist__for_each_entry(evsel_list, counter) {
+		evlist__for_each_entry(evlist, counter) {
 			if (is_duration_time(counter))
 				continue;
 			print_aggr_thread(counter, prefix);
 		}
 		break;
 	case AGGR_GLOBAL:
-		evlist__for_each_entry(evsel_list, counter) {
+		evlist__for_each_entry(evlist, counter) {
 			if (is_duration_time(counter))
 				continue;
 			print_counter_aggr(counter, prefix);
@@ -1743,7 +1746,7 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)
 		if (metric_only)
 			print_no_aggr_metric(prefix);
 		else {
-			evlist__for_each_entry(evsel_list, counter) {
+			evlist__for_each_entry(evlist, counter) {
 				if (is_duration_time(counter))
 					continue;
 				print_counter(counter, prefix);
@@ -1761,6 +1764,11 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)
 	fflush(stat_config.output);
 }
 
+static void print_counters(struct timespec *ts, int argc, const char **argv)
+{
+	perf_evlist__print_counters(evsel_list, ts, argc, argv);
+}
+
 static volatile int signr = -1;
 
 static void skip_signal(int signo)
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 16/43] perf stat: Move STAT_RECORD out of perf_evlist__print_counters
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
                   ` (14 preceding siblings ...)
  2018-08-30  6:32 ` [PATCH 15/43] perf stat: Add perf_evlist__print_counters function Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:29   ` [tip:perf/core] perf stat: Move STAT_RECORD out of perf_evlist__print_counters() tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 17/43] perf stat: Add stat_config argument to perf_evlist__print_counters Jiri Olsa
                   ` (27 subsequent siblings)
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

It's stat related and should stay in stat command.
The perf_evlist__print_counters function will be
moved out in following patches.

Link: http://lkml.kernel.org/n/tip-be5esxsl725gf6w717owbicp@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index db11832bbdbc..4ffbb6594eb6 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1701,10 +1701,6 @@ perf_evlist__print_counters(struct perf_evlist *evlist,
 	struct perf_evsel *counter;
 	char buf[64], *prefix = NULL;
 
-	/* Do not print anything if we record to the pipe. */
-	if (STAT_RECORD && perf_stat.data.is_pipe)
-		return;
-
 	if (interval)
 		print_interval(prefix = buf, ts);
 	else
@@ -1766,6 +1762,10 @@ perf_evlist__print_counters(struct perf_evlist *evlist,
 
 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;
+
 	perf_evlist__print_counters(evsel_list, ts, argc, argv);
 }
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 17/43] perf stat: Add stat_config argument to perf_evlist__print_counters
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
                   ` (15 preceding siblings ...)
  2018-08-30  6:32 ` [PATCH 16/43] perf stat: Move STAT_RECORD out of perf_evlist__print_counters Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:29   ` [tip:perf/core] perf stat: Add 'struct perf_stat_config' argument to perf_evlist__print_counters() tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 18/43] perf stat: Pass stat_config argument to local print functions Jiri Olsa
                   ` (26 subsequent siblings)
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

Adding stat_config argument perf_evlist__print_counters,
so the function could be moved out of stat command to
generic object in following patches.

Link: http://lkml.kernel.org/n/tip-spaw3m5jf1o6ycv39j57va1e@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 4ffbb6594eb6..f340641fe63a 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1694,10 +1694,11 @@ static void print_footer(void)
 
 static void
 perf_evlist__print_counters(struct perf_evlist *evlist,
+			    struct perf_stat_config *config,
 			    struct timespec *ts,
 			    int argc, const char **argv)
 {
-	int interval = stat_config.interval;
+	int interval = config->interval;
 	struct perf_evsel *counter;
 	char buf[64], *prefix = NULL;
 
@@ -1713,11 +1714,11 @@ perf_evlist__print_counters(struct perf_evlist *evlist,
 			print_metric_headers(prefix, false);
 		if (num_print_iv++ == 25)
 			num_print_iv = 0;
-		if (stat_config.aggr_mode == AGGR_GLOBAL && prefix)
-			fprintf(stat_config.output, "%s", prefix);
+		if (config->aggr_mode == AGGR_GLOBAL && prefix)
+			fprintf(config->output, "%s", prefix);
 	}
 
-	switch (stat_config.aggr_mode) {
+	switch (config->aggr_mode) {
 	case AGGR_CORE:
 	case AGGR_SOCKET:
 		print_aggr(prefix);
@@ -1736,7 +1737,7 @@ perf_evlist__print_counters(struct perf_evlist *evlist,
 			print_counter_aggr(counter, prefix);
 		}
 		if (metric_only)
-			fputc('\n', stat_config.output);
+			fputc('\n', config->output);
 		break;
 	case AGGR_NONE:
 		if (metric_only)
@@ -1757,7 +1758,7 @@ perf_evlist__print_counters(struct perf_evlist *evlist,
 	if (!interval && !csv_output)
 		print_footer();
 
-	fflush(stat_config.output);
+	fflush(config->output);
 }
 
 static void print_counters(struct timespec *ts, int argc, const char **argv)
@@ -1766,7 +1767,8 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)
 	if (STAT_RECORD && perf_stat.data.is_pipe)
 		return;
 
-	perf_evlist__print_counters(evsel_list, ts, argc, argv);
+	perf_evlist__print_counters(evsel_list, &stat_config,
+				    ts, argc, argv);
 }
 
 static volatile int signr = -1;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 18/43] perf stat: Pass stat_config argument to local print functions
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
                   ` (16 preceding siblings ...)
  2018-08-30  6:32 ` [PATCH 17/43] perf stat: Add stat_config argument to perf_evlist__print_counters Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:30   ` [tip:perf/core] perf stat: Pass 'struct perf_stat_config' " tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 19/43] perf stat: Pass stat_config argument to global " Jiri Olsa
                   ` (25 subsequent siblings)
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

Adding stat_config argument local print functions, so those
functions could be moved out of stat command to generic object
in following patches.

Link: http://lkml.kernel.org/n/tip-p1yrm9p91j87rx77eqzf5cfk@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 149 ++++++++++++++++++++------------------
 1 file changed, 80 insertions(+), 69 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index f340641fe63a..f56da22abccc 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -660,30 +660,33 @@ static int run_perf_stat(int argc, const char **argv, int run_idx)
 	return ret;
 }
 
-static void print_running(u64 run, u64 ena)
+static void print_running(struct perf_stat_config *config,
+			  u64 run, u64 ena)
 {
 	if (csv_output) {
-		fprintf(stat_config.output, "%s%" PRIu64 "%s%.2f",
+		fprintf(config->output, "%s%" PRIu64 "%s%.2f",
 					csv_sep,
 					run,
 					csv_sep,
 					ena ? 100.0 * run / ena : 100.0);
 	} else if (run != ena) {
-		fprintf(stat_config.output, "  (%.2f%%)", 100.0 * run / ena);
+		fprintf(config->output, "  (%.2f%%)", 100.0 * run / ena);
 	}
 }
 
-static void print_noise_pct(double total, double avg)
+static void print_noise_pct(struct perf_stat_config *config,
+			    double total, double avg)
 {
 	double pct = rel_stddev_stats(total, avg);
 
 	if (csv_output)
-		fprintf(stat_config.output, "%s%.2f%%", csv_sep, pct);
+		fprintf(config->output, "%s%.2f%%", csv_sep, pct);
 	else if (pct)
-		fprintf(stat_config.output, "  ( +-%6.2f%% )", pct);
+		fprintf(config->output, "  ( +-%6.2f%% )", pct);
 }
 
-static void print_noise(struct perf_evsel *evsel, double avg)
+static void print_noise(struct perf_stat_config *config,
+			struct perf_evsel *evsel, double avg)
 {
 	struct perf_stat_evsel *ps;
 
@@ -691,7 +694,7 @@ static void print_noise(struct perf_evsel *evsel, double avg)
 		return;
 
 	ps = evsel->stats;
-	print_noise_pct(stddev_stats(&ps->res_stats[0]), avg);
+	print_noise_pct(config, stddev_stats(&ps->res_stats[0]), avg);
 }
 
 static void aggr_printout(struct perf_evsel *evsel, int id, int nr)
@@ -987,13 +990,14 @@ static bool is_mixed_hw_group(struct perf_evsel *counter)
 	return false;
 }
 
-static void printout(int id, int nr, struct perf_evsel *counter, double uval,
+static void printout(struct perf_stat_config *config, int id, int nr,
+		     struct perf_evsel *counter, double uval,
 		     char *prefix, u64 run, u64 ena, double noise,
 		     struct runtime_stat *st)
 {
 	struct perf_stat_output_ctx out;
 	struct outstate os = {
-		.fh = stat_config.output,
+		.fh = config->output,
 		.prefix = prefix ? prefix : "",
 		.id = id,
 		.nr = nr,
@@ -1023,7 +1027,7 @@ static void printout(int id, int nr, struct perf_evsel *counter, double uval,
 		pm = print_metric_csv;
 		nl = new_line_csv;
 		os.nfields = 3;
-		os.nfields += aggr_fields[stat_config.aggr_mode];
+		os.nfields += aggr_fields[config->aggr_mode];
 		if (counter->cgrp)
 			os.nfields++;
 	}
@@ -1034,7 +1038,7 @@ static void printout(int id, int nr, struct perf_evsel *counter, double uval,
 		}
 		aggr_printout(counter, id, nr);
 
-		fprintf(stat_config.output, "%*s%s",
+		fprintf(config->output, "%*s%s",
 			csv_output ? 0 : 18,
 			counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
 			csv_sep);
@@ -1045,22 +1049,22 @@ static void printout(int id, int nr, struct perf_evsel *counter, double uval,
 				print_mixed_hw_group_error = 1;
 		}
 
-		fprintf(stat_config.output, "%-*s%s",
+		fprintf(config->output, "%-*s%s",
 			csv_output ? 0 : unit_width,
 			counter->unit, csv_sep);
 
-		fprintf(stat_config.output, "%*s",
+		fprintf(config->output, "%*s",
 			csv_output ? 0 : -25,
 			perf_evsel__name(counter));
 
 		if (counter->cgrp)
-			fprintf(stat_config.output, "%s%s",
+			fprintf(config->output, "%s%s",
 				csv_sep, counter->cgrp->name);
 
 		if (!csv_output)
 			pm(&os, NULL, NULL, "", 0);
-		print_noise(counter, noise);
-		print_running(run, ena);
+		print_noise(config, counter, noise);
+		print_running(config, run, ena);
 		if (csv_output)
 			pm(&os, NULL, NULL, "", 0);
 		return;
@@ -1075,16 +1079,16 @@ static void printout(int id, int nr, struct perf_evsel *counter, double uval,
 	out.force_header = false;
 
 	if (csv_output && !metric_only) {
-		print_noise(counter, noise);
-		print_running(run, ena);
+		print_noise(config, counter, noise);
+		print_running(config, run, ena);
 	}
 
 	perf_stat__print_shadow_stats(counter, uval,
 				first_shadow_cpu(counter, id),
 				&out, &metric_events, st);
 	if (!csv_output && !metric_only) {
-		print_noise(counter, noise);
-		print_running(run, ena);
+		print_noise(config, counter, noise);
+		print_running(config, run, ena);
 	}
 }
 
@@ -1211,9 +1215,10 @@ static void aggr_cb(struct perf_evsel *counter, void *data, bool first)
 	}
 }
 
-static void print_aggr(char *prefix)
+static void print_aggr(struct perf_stat_config *config,
+		       char *prefix)
 {
-	FILE *output = stat_config.output;
+	FILE *output = config->output;
 	struct perf_evsel *counter;
 	int s, id, nr;
 	double uval;
@@ -1256,8 +1261,8 @@ static void print_aggr(char *prefix)
 				fprintf(output, "%s", prefix);
 
 			uval = val * counter->scale;
-			printout(id, nr, counter, uval, prefix, run, ena, 1.0,
-				 &rt_stat);
+			printout(config, id, nr, counter, uval, prefix,
+				 run, ena, 1.0, &rt_stat);
 			if (!metric_only)
 				fputc('\n', output);
 		}
@@ -1320,9 +1325,10 @@ static struct perf_aggr_thread_value *sort_aggr_thread(
 	return buf;
 }
 
-static void print_aggr_thread(struct perf_evsel *counter, char *prefix)
+static void print_aggr_thread(struct perf_stat_config *config,
+			      struct perf_evsel *counter, char *prefix)
 {
-	FILE *output = stat_config.output;
+	FILE *output = config->output;
 	int nthreads = thread_map__nr(counter->threads);
 	int ncpus = cpu_map__nr(counter->cpus);
 	int thread, sorted_threads, id;
@@ -1339,12 +1345,12 @@ static void print_aggr_thread(struct perf_evsel *counter, char *prefix)
 			fprintf(output, "%s", prefix);
 
 		id = buf[thread].id;
-		if (stat_config.stats)
-			printout(id, 0, buf[thread].counter, buf[thread].uval,
+		if (config->stats)
+			printout(config, id, 0, buf[thread].counter, buf[thread].uval,
 				 prefix, buf[thread].run, buf[thread].ena, 1.0,
-				 &stat_config.stats[id]);
+				 &config->stats[id]);
 		else
-			printout(id, 0, buf[thread].counter, buf[thread].uval,
+			printout(config, id, 0, buf[thread].counter, buf[thread].uval,
 				 prefix, buf[thread].run, buf[thread].ena, 1.0,
 				 &rt_stat);
 		fputc('\n', output);
@@ -1372,9 +1378,10 @@ static void counter_aggr_cb(struct perf_evsel *counter, void *data,
  * Print out the results of a single counter:
  * aggregated counts in system-wide mode
  */
-static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
+static void print_counter_aggr(struct perf_stat_config *config,
+			       struct perf_evsel *counter, char *prefix)
 {
-	FILE *output = stat_config.output;
+	FILE *output = config->output;
 	double uval;
 	struct caggr_data cd = { .avg = 0.0 };
 
@@ -1385,7 +1392,7 @@ static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
 		fprintf(output, "%s", prefix);
 
 	uval = cd.avg * counter->scale;
-	printout(-1, 0, counter, uval, prefix, cd.avg_running, cd.avg_enabled,
+	printout(config, -1, 0, counter, uval, prefix, cd.avg_running, cd.avg_enabled,
 		 cd.avg, &rt_stat);
 	if (!metric_only)
 		fprintf(output, "\n");
@@ -1405,9 +1412,10 @@ static void counter_cb(struct perf_evsel *counter, void *data,
  * Print out the results of a single counter:
  * does not use aggregated count in system-wide
  */
-static void print_counter(struct perf_evsel *counter, char *prefix)
+static void print_counter(struct perf_stat_config *config,
+			  struct perf_evsel *counter, char *prefix)
 {
-	FILE *output = stat_config.output;
+	FILE *output = config->output;
 	u64 ena, run, val;
 	double uval;
 	int cpu;
@@ -1425,14 +1433,15 @@ static void print_counter(struct perf_evsel *counter, char *prefix)
 			fprintf(output, "%s", prefix);
 
 		uval = val * counter->scale;
-		printout(cpu, 0, counter, uval, prefix, run, ena, 1.0,
+		printout(config, cpu, 0, counter, uval, prefix, run, ena, 1.0,
 			 &rt_stat);
 
 		fputc('\n', output);
 	}
 }
 
-static void print_no_aggr_metric(char *prefix)
+static void print_no_aggr_metric(struct perf_stat_config *config,
+				 char *prefix)
 {
 	int cpu;
 	int nrcpus = 0;
@@ -1445,7 +1454,7 @@ static void print_no_aggr_metric(char *prefix)
 		bool first = true;
 
 		if (prefix)
-			fputs(prefix, stat_config.output);
+			fputs(prefix, config->output);
 		evlist__for_each_entry(evsel_list, counter) {
 			if (is_duration_time(counter))
 				continue;
@@ -1458,10 +1467,10 @@ static void print_no_aggr_metric(char *prefix)
 			run = perf_counts(counter->counts, cpu, 0)->run;
 
 			uval = val * counter->scale;
-			printout(cpu, 0, counter, uval, prefix, run, ena, 1.0,
+			printout(config, cpu, 0, counter, uval, prefix, run, ena, 1.0,
 				 &rt_stat);
 		}
-		fputc('\n', stat_config.output);
+		fputc('\n', config->output);
 	}
 }
 
@@ -1481,25 +1490,25 @@ static const char *aggr_header_csv[] = {
 	[AGGR_GLOBAL] 	=	""
 };
 
-static void print_metric_headers(const char *prefix, bool no_indent)
+static void print_metric_headers(struct perf_stat_config *config,
+				 const char *prefix, bool no_indent)
 {
 	struct perf_stat_output_ctx out;
 	struct perf_evsel *counter;
 	struct outstate os = {
-		.fh = stat_config.output
+		.fh = config->output
 	};
 
 	if (prefix)
-		fprintf(stat_config.output, "%s", prefix);
+		fprintf(config->output, "%s", prefix);
 
 	if (!csv_output && !no_indent)
-		fprintf(stat_config.output, "%*s",
-			aggr_header_lens[stat_config.aggr_mode], "");
+		fprintf(config->output, "%*s",
+			aggr_header_lens[config->aggr_mode], "");
 	if (csv_output) {
-		if (stat_config.interval)
-			fputs("time,", stat_config.output);
-		fputs(aggr_header_csv[stat_config.aggr_mode],
-			stat_config.output);
+		if (config->interval)
+			fputs("time,", config->output);
+		fputs(aggr_header_csv[config->aggr_mode], config->output);
 	}
 
 	/* Print metrics headers only */
@@ -1518,12 +1527,13 @@ static void print_metric_headers(const char *prefix, bool no_indent)
 					      &metric_events,
 					      &rt_stat);
 	}
-	fputc('\n', stat_config.output);
+	fputc('\n', config->output);
 }
 
-static void print_interval(char *prefix, struct timespec *ts)
+static void print_interval(struct perf_stat_config *config,
+			   char *prefix, struct timespec *ts)
 {
-	FILE *output = stat_config.output;
+	FILE *output = config->output;
 	static int num_print_interval;
 
 	if (interval_clear)
@@ -1532,7 +1542,7 @@ static void print_interval(char *prefix, struct timespec *ts)
 	sprintf(prefix, "%6lu.%09lu%s", ts->tv_sec, ts->tv_nsec, csv_sep);
 
 	if ((num_print_interval == 0 && !csv_output) || interval_clear) {
-		switch (stat_config.aggr_mode) {
+		switch (config->aggr_mode) {
 		case AGGR_SOCKET:
 			fprintf(output, "#           time socket cpus");
 			if (!metric_only)
@@ -1564,14 +1574,15 @@ static void print_interval(char *prefix, struct timespec *ts)
 	}
 
 	if ((num_print_interval == 0 || interval_clear) && metric_only)
-		print_metric_headers(" ", true);
+		print_metric_headers(config, " ", true);
 	if (++num_print_interval == 25)
 		num_print_interval = 0;
 }
 
-static void print_header(int argc, const char **argv)
+static void print_header(struct perf_stat_config *config,
+			 int argc, const char **argv)
 {
-	FILE *output = stat_config.output;
+	FILE *output = config->output;
 	int i;
 
 	fflush(stdout);
@@ -1639,10 +1650,10 @@ static double timeval2double(struct timeval *t)
 	return t->tv_sec + (double) t->tv_usec/USEC_PER_SEC;
 }
 
-static void print_footer(void)
+static void print_footer(struct perf_stat_config *config)
 {
 	double avg = avg_stats(&walltime_nsecs_stats) / NSEC_PER_SEC;
-	FILE *output = stat_config.output;
+	FILE *output = config->output;
 	int n;
 
 	if (!null_run)
@@ -1673,7 +1684,7 @@ static void print_footer(void)
 		fprintf(output, " %17.*f +- %.*f seconds time elapsed",
 			precision, avg, precision, sd);
 
-		print_noise_pct(sd, avg);
+		print_noise_pct(config, sd, avg);
 	}
 	fprintf(output, "\n\n");
 
@@ -1703,15 +1714,15 @@ perf_evlist__print_counters(struct perf_evlist *evlist,
 	char buf[64], *prefix = NULL;
 
 	if (interval)
-		print_interval(prefix = buf, ts);
+		print_interval(config, prefix = buf, ts);
 	else
-		print_header(argc, argv);
+		print_header(config, argc, argv);
 
 	if (metric_only) {
 		static int num_print_iv;
 
 		if (num_print_iv == 0 && !interval)
-			print_metric_headers(prefix, false);
+			print_metric_headers(config, prefix, false);
 		if (num_print_iv++ == 25)
 			num_print_iv = 0;
 		if (config->aggr_mode == AGGR_GLOBAL && prefix)
@@ -1721,32 +1732,32 @@ perf_evlist__print_counters(struct perf_evlist *evlist,
 	switch (config->aggr_mode) {
 	case AGGR_CORE:
 	case AGGR_SOCKET:
-		print_aggr(prefix);
+		print_aggr(config, prefix);
 		break;
 	case AGGR_THREAD:
 		evlist__for_each_entry(evlist, counter) {
 			if (is_duration_time(counter))
 				continue;
-			print_aggr_thread(counter, prefix);
+			print_aggr_thread(config, counter, prefix);
 		}
 		break;
 	case AGGR_GLOBAL:
 		evlist__for_each_entry(evlist, counter) {
 			if (is_duration_time(counter))
 				continue;
-			print_counter_aggr(counter, prefix);
+			print_counter_aggr(config, counter, prefix);
 		}
 		if (metric_only)
 			fputc('\n', config->output);
 		break;
 	case AGGR_NONE:
 		if (metric_only)
-			print_no_aggr_metric(prefix);
+			print_no_aggr_metric(config, prefix);
 		else {
 			evlist__for_each_entry(evlist, counter) {
 				if (is_duration_time(counter))
 					continue;
-				print_counter(counter, prefix);
+				print_counter(config, counter, prefix);
 			}
 		}
 		break;
@@ -1756,7 +1767,7 @@ perf_evlist__print_counters(struct perf_evlist *evlist,
 	}
 
 	if (!interval && !csv_output)
-		print_footer();
+		print_footer(config);
 
 	fflush(config->output);
 }
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 19/43] perf stat: Pass stat_config argument to global print functions
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
                   ` (17 preceding siblings ...)
  2018-08-30  6:32 ` [PATCH 18/43] perf stat: Pass stat_config argument to local print functions Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:30   ` [tip:perf/core] perf stat: Pass a 'struct perf_stat_config' " tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 20/43] perf stat: Move csv_* into struct perf_stat_config Jiri Olsa
                   ` (24 subsequent siblings)
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

Adding stat_config argument global print functions, so those
functions could be used out of the stat command code.

Link: http://lkml.kernel.org/n/tip-p1yrm9p91j87rx77eqzf5cfk@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-script.c   |   8 +-
 tools/perf/builtin-stat.c     |  74 +++++++++--------
 tools/perf/util/stat-shadow.c | 147 ++++++++++++++++++----------------
 tools/perf/util/stat.h        |   8 +-
 4 files changed, 131 insertions(+), 106 deletions(-)

diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index ba481d73f910..6176bae177c2 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -1544,7 +1544,8 @@ struct metric_ctx {
 	FILE 			*fp;
 };
 
-static void script_print_metric(void *ctx, const char *color,
+static void script_print_metric(struct perf_stat_config *config __maybe_unused,
+				void *ctx, const char *color,
 			        const char *fmt,
 			        const char *unit, double val)
 {
@@ -1562,7 +1563,8 @@ static void script_print_metric(void *ctx, const char *color,
 	fprintf(mctx->fp, " %s\n", unit);
 }
 
-static void script_new_line(void *ctx)
+static void script_new_line(struct perf_stat_config *config __maybe_unused,
+			    void *ctx)
 {
 	struct metric_ctx *mctx = ctx;
 
@@ -1608,7 +1610,7 @@ static void perf_sample__fprint_metric(struct perf_script *script,
 	evsel_script(evsel)->val = val;
 	if (evsel_script(evsel->leader)->gnum == evsel->leader->nr_members) {
 		for_each_group_member (ev2, evsel->leader) {
-			perf_stat__print_shadow_stats(ev2,
+			perf_stat__print_shadow_stats(&stat_config, ev2,
 						      evsel_script(ev2)->val,
 						      sample->cpu,
 						      &ctx,
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index f56da22abccc..7a3361308e61 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -697,11 +697,12 @@ static void print_noise(struct perf_stat_config *config,
 	print_noise_pct(config, stddev_stats(&ps->res_stats[0]), avg);
 }
 
-static void aggr_printout(struct perf_evsel *evsel, int id, int nr)
+static void aggr_printout(struct perf_stat_config *config,
+			  struct perf_evsel *evsel, int id, int nr)
 {
-	switch (stat_config.aggr_mode) {
+	switch (config->aggr_mode) {
 	case AGGR_CORE:
-		fprintf(stat_config.output, "S%d-C%*d%s%*d%s",
+		fprintf(config->output, "S%d-C%*d%s%*d%s",
 			cpu_map__id_to_socket(id),
 			csv_output ? 0 : -8,
 			cpu_map__id_to_cpu(id),
@@ -711,7 +712,7 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr)
 			csv_sep);
 		break;
 	case AGGR_SOCKET:
-		fprintf(stat_config.output, "S%*d%s%*d%s",
+		fprintf(config->output, "S%*d%s%*d%s",
 			csv_output ? 0 : -5,
 			id,
 			csv_sep,
@@ -720,12 +721,12 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr)
 			csv_sep);
 			break;
 	case AGGR_NONE:
-		fprintf(stat_config.output, "CPU%*d%s",
+		fprintf(config->output, "CPU%*d%s",
 			csv_output ? 0 : -4,
 			perf_evsel__cpus(evsel)->map[id], csv_sep);
 		break;
 	case AGGR_THREAD:
-		fprintf(stat_config.output, "%*s-%*d%s",
+		fprintf(config->output, "%*s-%*d%s",
 			csv_output ? 0 : 16,
 			thread_map__comm(evsel->threads, id),
 			csv_output ? 0 : -8,
@@ -750,24 +751,27 @@ struct outstate {
 
 #define METRIC_LEN  35
 
-static void new_line_std(void *ctx)
+static void new_line_std(struct perf_stat_config *config __maybe_unused,
+			 void *ctx)
 {
 	struct outstate *os = ctx;
 
 	os->newline = true;
 }
 
-static void do_new_line_std(struct outstate *os)
+static void do_new_line_std(struct perf_stat_config *config,
+			    struct outstate *os)
 {
 	fputc('\n', os->fh);
 	fputs(os->prefix, os->fh);
-	aggr_printout(os->evsel, os->id, os->nr);
-	if (stat_config.aggr_mode == AGGR_NONE)
+	aggr_printout(config, os->evsel, os->id, os->nr);
+	if (config->aggr_mode == AGGR_NONE)
 		fprintf(os->fh, "        ");
 	fprintf(os->fh, "                                                 ");
 }
 
-static void print_metric_std(void *ctx, const char *color, const char *fmt,
+static void print_metric_std(struct perf_stat_config *config,
+			     void *ctx, const char *color, const char *fmt,
 			     const char *unit, double val)
 {
 	struct outstate *os = ctx;
@@ -783,7 +787,7 @@ static void print_metric_std(void *ctx, const char *color, const char *fmt,
 	}
 
 	if (newline)
-		do_new_line_std(os);
+		do_new_line_std(config, os);
 
 	n = fprintf(out, " # ");
 	if (color)
@@ -793,7 +797,7 @@ static void print_metric_std(void *ctx, const char *color, const char *fmt,
 	fprintf(out, " %-*s", METRIC_LEN - n - 1, unit);
 }
 
-static void new_line_csv(void *ctx)
+static void new_line_csv(struct perf_stat_config *config, void *ctx)
 {
 	struct outstate *os = ctx;
 	int i;
@@ -801,12 +805,13 @@ static void new_line_csv(void *ctx)
 	fputc('\n', os->fh);
 	if (os->prefix)
 		fprintf(os->fh, "%s%s", os->prefix, csv_sep);
-	aggr_printout(os->evsel, os->id, os->nr);
+	aggr_printout(config, os->evsel, os->id, os->nr);
 	for (i = 0; i < os->nfields; i++)
 		fputs(csv_sep, os->fh);
 }
 
-static void print_metric_csv(void *ctx,
+static void print_metric_csv(struct perf_stat_config *config __maybe_unused,
+			     void *ctx,
 			     const char *color __maybe_unused,
 			     const char *fmt, const char *unit, double val)
 {
@@ -853,7 +858,8 @@ static const char *fixunit(char *buf, struct perf_evsel *evsel,
 	return unit;
 }
 
-static void print_metric_only(void *ctx, const char *color, const char *fmt,
+static void print_metric_only(struct perf_stat_config *config __maybe_unused,
+			      void *ctx, const char *color, const char *fmt,
 			      const char *unit, double val)
 {
 	struct outstate *os = ctx;
@@ -874,7 +880,8 @@ static void print_metric_only(void *ctx, const char *color, const char *fmt,
 	fprintf(out, "%*s ", mlen, str);
 }
 
-static void print_metric_only_csv(void *ctx, const char *color __maybe_unused,
+static void print_metric_only_csv(struct perf_stat_config *config __maybe_unused,
+				  void *ctx, const char *color __maybe_unused,
 				  const char *fmt,
 				  const char *unit, double val)
 {
@@ -894,11 +901,13 @@ static void print_metric_only_csv(void *ctx, const char *color __maybe_unused,
 	fprintf(out, "%s%s", vals, csv_sep);
 }
 
-static void new_line_metric(void *ctx __maybe_unused)
+static void new_line_metric(struct perf_stat_config *config __maybe_unused,
+			    void *ctx __maybe_unused)
 {
 }
 
-static void print_metric_header(void *ctx, const char *color __maybe_unused,
+static void print_metric_header(struct perf_stat_config *config __maybe_unused,
+				void *ctx, const char *color __maybe_unused,
 				const char *fmt __maybe_unused,
 				const char *unit, double val __maybe_unused)
 {
@@ -936,9 +945,10 @@ static int first_shadow_cpu(struct perf_evsel *evsel, int id)
 	return 0;
 }
 
-static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
+static void abs_printout(struct perf_stat_config *config,
+			 int id, int nr, struct perf_evsel *evsel, double avg)
 {
-	FILE *output = stat_config.output;
+	FILE *output = config->output;
 	double sc =  evsel->scale;
 	const char *fmt;
 
@@ -951,7 +961,7 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
 			fmt = floor(sc) != sc ? "%18.2f%s" : "%18.0f%s";
 	}
 
-	aggr_printout(evsel, id, nr);
+	aggr_printout(config, evsel, id, nr);
 
 	fprintf(output, fmt, avg, csv_sep);
 
@@ -1004,7 +1014,7 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 		.evsel = counter,
 	};
 	print_metric_t pm = print_metric_std;
-	void (*nl)(void *);
+	new_line_t nl;
 
 	if (metric_only) {
 		nl = new_line_metric;
@@ -1033,10 +1043,10 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 	}
 	if (run == 0 || ena == 0 || counter->counts->scaled == -1) {
 		if (metric_only) {
-			pm(&os, NULL, "", "", 0);
+			pm(config, &os, NULL, "", "", 0);
 			return;
 		}
-		aggr_printout(counter, id, nr);
+		aggr_printout(config, counter, id, nr);
 
 		fprintf(config->output, "%*s%s",
 			csv_output ? 0 : 18,
@@ -1062,16 +1072,16 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 				csv_sep, counter->cgrp->name);
 
 		if (!csv_output)
-			pm(&os, NULL, NULL, "", 0);
+			pm(config, &os, NULL, NULL, "", 0);
 		print_noise(config, counter, noise);
 		print_running(config, run, ena);
 		if (csv_output)
-			pm(&os, NULL, NULL, "", 0);
+			pm(config, &os, NULL, NULL, "", 0);
 		return;
 	}
 
 	if (!metric_only)
-		abs_printout(id, nr, counter, uval);
+		abs_printout(config, id, nr, counter, uval);
 
 	out.print_metric = pm;
 	out.new_line = nl;
@@ -1083,7 +1093,7 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 		print_running(config, run, ena);
 	}
 
-	perf_stat__print_shadow_stats(counter, uval,
+	perf_stat__print_shadow_stats(config, counter, uval,
 				first_shadow_cpu(counter, id),
 				&out, &metric_events, st);
 	if (!csv_output && !metric_only) {
@@ -1255,7 +1265,7 @@ static void print_aggr(struct perf_stat_config *config,
 			val = ad.val;
 			if (first && metric_only) {
 				first = false;
-				aggr_printout(counter, id, nr);
+				aggr_printout(config, counter, id, nr);
 			}
 			if (prefix && !metric_only)
 				fprintf(output, "%s", prefix);
@@ -1459,7 +1469,7 @@ static void print_no_aggr_metric(struct perf_stat_config *config,
 			if (is_duration_time(counter))
 				continue;
 			if (first) {
-				aggr_printout(counter, cpu, 0);
+				aggr_printout(config, counter, cpu, 0);
 				first = false;
 			}
 			val = perf_counts(counter->counts, cpu, 0)->val;
@@ -1521,7 +1531,7 @@ static void print_metric_headers(struct perf_stat_config *config,
 		out.new_line = new_line_metric;
 		out.force_header = true;
 		os.evsel = counter;
-		perf_stat__print_shadow_stats(counter, 0,
+		perf_stat__print_shadow_stats(config, counter, 0,
 					      0,
 					      &out,
 					      &metric_events,
diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c
index 99990f5f2512..8ad32763cfff 100644
--- a/tools/perf/util/stat-shadow.c
+++ b/tools/perf/util/stat-shadow.c
@@ -410,7 +410,8 @@ static double runtime_stat_n(struct runtime_stat *st,
 	return v->stats.n;
 }
 
-static void print_stalled_cycles_frontend(int cpu,
+static void print_stalled_cycles_frontend(struct perf_stat_config *config,
+					  int cpu,
 					  struct perf_evsel *evsel, double avg,
 					  struct perf_stat_output_ctx *out,
 					  struct runtime_stat *st)
@@ -427,13 +428,14 @@ static void print_stalled_cycles_frontend(int cpu,
 	color = get_ratio_color(GRC_STALLED_CYCLES_FE, ratio);
 
 	if (ratio)
-		out->print_metric(out->ctx, color, "%7.2f%%", "frontend cycles idle",
+		out->print_metric(config, out->ctx, color, "%7.2f%%", "frontend cycles idle",
 				  ratio);
 	else
-		out->print_metric(out->ctx, NULL, NULL, "frontend cycles idle", 0);
+		out->print_metric(config, out->ctx, NULL, NULL, "frontend cycles idle", 0);
 }
 
-static void print_stalled_cycles_backend(int cpu,
+static void print_stalled_cycles_backend(struct perf_stat_config *config,
+					 int cpu,
 					 struct perf_evsel *evsel, double avg,
 					 struct perf_stat_output_ctx *out,
 					 struct runtime_stat *st)
@@ -449,10 +451,11 @@ static void print_stalled_cycles_backend(int cpu,
 
 	color = get_ratio_color(GRC_STALLED_CYCLES_BE, ratio);
 
-	out->print_metric(out->ctx, color, "%7.2f%%", "backend cycles idle", ratio);
+	out->print_metric(config, out->ctx, color, "%7.2f%%", "backend cycles idle", ratio);
 }
 
-static void print_branch_misses(int cpu,
+static void print_branch_misses(struct perf_stat_config *config,
+				int cpu,
 				struct perf_evsel *evsel,
 				double avg,
 				struct perf_stat_output_ctx *out,
@@ -469,10 +472,11 @@ static void print_branch_misses(int cpu,
 
 	color = get_ratio_color(GRC_CACHE_MISSES, ratio);
 
-	out->print_metric(out->ctx, color, "%7.2f%%", "of all branches", ratio);
+	out->print_metric(config, out->ctx, color, "%7.2f%%", "of all branches", ratio);
 }
 
-static void print_l1_dcache_misses(int cpu,
+static void print_l1_dcache_misses(struct perf_stat_config *config,
+				   int cpu,
 				   struct perf_evsel *evsel,
 				   double avg,
 				   struct perf_stat_output_ctx *out,
@@ -490,10 +494,11 @@ static void print_l1_dcache_misses(int cpu,
 
 	color = get_ratio_color(GRC_CACHE_MISSES, ratio);
 
-	out->print_metric(out->ctx, color, "%7.2f%%", "of all L1-dcache hits", ratio);
+	out->print_metric(config, out->ctx, color, "%7.2f%%", "of all L1-dcache hits", ratio);
 }
 
-static void print_l1_icache_misses(int cpu,
+static void print_l1_icache_misses(struct perf_stat_config *config,
+				   int cpu,
 				   struct perf_evsel *evsel,
 				   double avg,
 				   struct perf_stat_output_ctx *out,
@@ -510,10 +515,11 @@ static void print_l1_icache_misses(int cpu,
 		ratio = avg / total * 100.0;
 
 	color = get_ratio_color(GRC_CACHE_MISSES, ratio);
-	out->print_metric(out->ctx, color, "%7.2f%%", "of all L1-icache hits", ratio);
+	out->print_metric(config, out->ctx, color, "%7.2f%%", "of all L1-icache hits", ratio);
 }
 
-static void print_dtlb_cache_misses(int cpu,
+static void print_dtlb_cache_misses(struct perf_stat_config *config,
+				    int cpu,
 				    struct perf_evsel *evsel,
 				    double avg,
 				    struct perf_stat_output_ctx *out,
@@ -529,10 +535,11 @@ static void print_dtlb_cache_misses(int cpu,
 		ratio = avg / total * 100.0;
 
 	color = get_ratio_color(GRC_CACHE_MISSES, ratio);
-	out->print_metric(out->ctx, color, "%7.2f%%", "of all dTLB cache hits", ratio);
+	out->print_metric(config, out->ctx, color, "%7.2f%%", "of all dTLB cache hits", ratio);
 }
 
-static void print_itlb_cache_misses(int cpu,
+static void print_itlb_cache_misses(struct perf_stat_config *config,
+				    int cpu,
 				    struct perf_evsel *evsel,
 				    double avg,
 				    struct perf_stat_output_ctx *out,
@@ -548,10 +555,11 @@ static void print_itlb_cache_misses(int cpu,
 		ratio = avg / total * 100.0;
 
 	color = get_ratio_color(GRC_CACHE_MISSES, ratio);
-	out->print_metric(out->ctx, color, "%7.2f%%", "of all iTLB cache hits", ratio);
+	out->print_metric(config, out->ctx, color, "%7.2f%%", "of all iTLB cache hits", ratio);
 }
 
-static void print_ll_cache_misses(int cpu,
+static void print_ll_cache_misses(struct perf_stat_config *config,
+				  int cpu,
 				  struct perf_evsel *evsel,
 				  double avg,
 				  struct perf_stat_output_ctx *out,
@@ -567,7 +575,7 @@ static void print_ll_cache_misses(int cpu,
 		ratio = avg / total * 100.0;
 
 	color = get_ratio_color(GRC_CACHE_MISSES, ratio);
-	out->print_metric(out->ctx, color, "%7.2f%%", "of all LL-cache hits", ratio);
+	out->print_metric(config, out->ctx, color, "%7.2f%%", "of all LL-cache hits", ratio);
 }
 
 /*
@@ -674,7 +682,8 @@ static double td_be_bound(int ctx, int cpu, struct runtime_stat *st)
 	return sanitize_val(1.0 - sum);
 }
 
-static void print_smi_cost(int cpu, struct perf_evsel *evsel,
+static void print_smi_cost(struct perf_stat_config *config,
+			   int cpu, struct perf_evsel *evsel,
 			   struct perf_stat_output_ctx *out,
 			   struct runtime_stat *st)
 {
@@ -694,11 +703,12 @@ static void print_smi_cost(int cpu, struct perf_evsel *evsel,
 
 	if (cost > 10)
 		color = PERF_COLOR_RED;
-	out->print_metric(out->ctx, color, "%8.1f%%", "SMI cycles%", cost);
-	out->print_metric(out->ctx, NULL, "%4.0f", "SMI#", smi_num);
+	out->print_metric(config, out->ctx, color, "%8.1f%%", "SMI cycles%", cost);
+	out->print_metric(config, out->ctx, NULL, "%4.0f", "SMI#", smi_num);
 }
 
-static void generic_metric(const char *metric_expr,
+static void generic_metric(struct perf_stat_config *config,
+			   const char *metric_expr,
 			   struct perf_evsel **metric_events,
 			   char *name,
 			   const char *metric_name,
@@ -737,20 +747,21 @@ static void generic_metric(const char *metric_expr,
 		const char *p = metric_expr;
 
 		if (expr__parse(&ratio, &pctx, &p) == 0)
-			print_metric(ctxp, NULL, "%8.1f",
+			print_metric(config, ctxp, NULL, "%8.1f",
 				metric_name ?
 				metric_name :
 				out->force_header ?  name : "",
 				ratio);
 		else
-			print_metric(ctxp, NULL, NULL,
+			print_metric(config, ctxp, NULL, NULL,
 				     out->force_header ?
 				     (metric_name ? metric_name : name) : "", 0);
 	} else
-		print_metric(ctxp, NULL, NULL, "", 0);
+		print_metric(config, ctxp, NULL, NULL, "", 0);
 }
 
-void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
+void perf_stat__print_shadow_stats(struct perf_stat_config *config,
+				   struct perf_evsel *evsel,
 				   double avg, int cpu,
 				   struct perf_stat_output_ctx *out,
 				   struct rblist *metric_events,
@@ -769,10 +780,10 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
 
 		if (total) {
 			ratio = avg / total;
-			print_metric(ctxp, NULL, "%7.2f ",
+			print_metric(config, ctxp, NULL, "%7.2f ",
 					"insn per cycle", ratio);
 		} else {
-			print_metric(ctxp, NULL, NULL, "insn per cycle", 0);
+			print_metric(config, ctxp, NULL, NULL, "insn per cycle", 0);
 		}
 
 		total = runtime_stat_avg(st, STAT_STALLED_CYCLES_FRONT,
@@ -783,20 +794,20 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
 						    ctx, cpu));
 
 		if (total && avg) {
-			out->new_line(ctxp);
+			out->new_line(config, ctxp);
 			ratio = total / avg;
-			print_metric(ctxp, NULL, "%7.2f ",
+			print_metric(config, ctxp, NULL, "%7.2f ",
 					"stalled cycles per insn",
 					ratio);
 		} else if (have_frontend_stalled) {
-			print_metric(ctxp, NULL, NULL,
+			print_metric(config, ctxp, NULL, NULL,
 				     "stalled cycles per insn", 0);
 		}
 	} else if (perf_evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES)) {
 		if (runtime_stat_n(st, STAT_BRANCHES, ctx, cpu) != 0)
-			print_branch_misses(cpu, evsel, avg, out, st);
+			print_branch_misses(config, cpu, evsel, avg, out, st);
 		else
-			print_metric(ctxp, NULL, NULL, "of all branches", 0);
+			print_metric(config, ctxp, NULL, NULL, "of all branches", 0);
 	} else if (
 		evsel->attr.type == PERF_TYPE_HW_CACHE &&
 		evsel->attr.config ==  ( PERF_COUNT_HW_CACHE_L1D |
@@ -804,9 +815,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
 					 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) {
 
 		if (runtime_stat_n(st, STAT_L1_DCACHE, ctx, cpu) != 0)
-			print_l1_dcache_misses(cpu, evsel, avg, out, st);
+			print_l1_dcache_misses(config, cpu, evsel, avg, out, st);
 		else
-			print_metric(ctxp, NULL, NULL, "of all L1-dcache hits", 0);
+			print_metric(config, ctxp, NULL, NULL, "of all L1-dcache hits", 0);
 	} else if (
 		evsel->attr.type == PERF_TYPE_HW_CACHE &&
 		evsel->attr.config ==  ( PERF_COUNT_HW_CACHE_L1I |
@@ -814,9 +825,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
 					 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) {
 
 		if (runtime_stat_n(st, STAT_L1_ICACHE, ctx, cpu) != 0)
-			print_l1_icache_misses(cpu, evsel, avg, out, st);
+			print_l1_icache_misses(config, cpu, evsel, avg, out, st);
 		else
-			print_metric(ctxp, NULL, NULL, "of all L1-icache hits", 0);
+			print_metric(config, ctxp, NULL, NULL, "of all L1-icache hits", 0);
 	} else if (
 		evsel->attr.type == PERF_TYPE_HW_CACHE &&
 		evsel->attr.config ==  ( PERF_COUNT_HW_CACHE_DTLB |
@@ -824,9 +835,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
 					 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) {
 
 		if (runtime_stat_n(st, STAT_DTLB_CACHE, ctx, cpu) != 0)
-			print_dtlb_cache_misses(cpu, evsel, avg, out, st);
+			print_dtlb_cache_misses(config, cpu, evsel, avg, out, st);
 		else
-			print_metric(ctxp, NULL, NULL, "of all dTLB cache hits", 0);
+			print_metric(config, ctxp, NULL, NULL, "of all dTLB cache hits", 0);
 	} else if (
 		evsel->attr.type == PERF_TYPE_HW_CACHE &&
 		evsel->attr.config ==  ( PERF_COUNT_HW_CACHE_ITLB |
@@ -834,9 +845,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
 					 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) {
 
 		if (runtime_stat_n(st, STAT_ITLB_CACHE, ctx, cpu) != 0)
-			print_itlb_cache_misses(cpu, evsel, avg, out, st);
+			print_itlb_cache_misses(config, cpu, evsel, avg, out, st);
 		else
-			print_metric(ctxp, NULL, NULL, "of all iTLB cache hits", 0);
+			print_metric(config, ctxp, NULL, NULL, "of all iTLB cache hits", 0);
 	} else if (
 		evsel->attr.type == PERF_TYPE_HW_CACHE &&
 		evsel->attr.config ==  ( PERF_COUNT_HW_CACHE_LL |
@@ -844,9 +855,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
 					 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) {
 
 		if (runtime_stat_n(st, STAT_LL_CACHE, ctx, cpu) != 0)
-			print_ll_cache_misses(cpu, evsel, avg, out, st);
+			print_ll_cache_misses(config, cpu, evsel, avg, out, st);
 		else
-			print_metric(ctxp, NULL, NULL, "of all LL-cache hits", 0);
+			print_metric(config, ctxp, NULL, NULL, "of all LL-cache hits", 0);
 	} else if (perf_evsel__match(evsel, HARDWARE, HW_CACHE_MISSES)) {
 		total = runtime_stat_avg(st, STAT_CACHEREFS, ctx, cpu);
 
@@ -854,32 +865,32 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
 			ratio = avg * 100 / total;
 
 		if (runtime_stat_n(st, STAT_CACHEREFS, ctx, cpu) != 0)
-			print_metric(ctxp, NULL, "%8.3f %%",
+			print_metric(config, ctxp, NULL, "%8.3f %%",
 				     "of all cache refs", ratio);
 		else
-			print_metric(ctxp, NULL, NULL, "of all cache refs", 0);
+			print_metric(config, ctxp, NULL, NULL, "of all cache refs", 0);
 	} else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) {
-		print_stalled_cycles_frontend(cpu, evsel, avg, out, st);
+		print_stalled_cycles_frontend(config, cpu, evsel, avg, out, st);
 	} else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_BACKEND)) {
-		print_stalled_cycles_backend(cpu, evsel, avg, out, st);
+		print_stalled_cycles_backend(config, cpu, evsel, avg, out, st);
 	} else if (perf_evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)) {
 		total = runtime_stat_avg(st, STAT_NSECS, 0, cpu);
 
 		if (total) {
 			ratio = avg / total;
-			print_metric(ctxp, NULL, "%8.3f", "GHz", ratio);
+			print_metric(config, ctxp, NULL, "%8.3f", "GHz", ratio);
 		} else {
-			print_metric(ctxp, NULL, NULL, "Ghz", 0);
+			print_metric(config, ctxp, NULL, NULL, "Ghz", 0);
 		}
 	} else if (perf_stat_evsel__is(evsel, CYCLES_IN_TX)) {
 		total = runtime_stat_avg(st, STAT_CYCLES, ctx, cpu);
 
 		if (total)
-			print_metric(ctxp, NULL,
+			print_metric(config, ctxp, NULL,
 					"%7.2f%%", "transactional cycles",
 					100.0 * (avg / total));
 		else
-			print_metric(ctxp, NULL, NULL, "transactional cycles",
+			print_metric(config, ctxp, NULL, NULL, "transactional cycles",
 				     0);
 	} else if (perf_stat_evsel__is(evsel, CYCLES_IN_TX_CP)) {
 		total = runtime_stat_avg(st, STAT_CYCLES, ctx, cpu);
@@ -888,10 +899,10 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
 		if (total2 < avg)
 			total2 = avg;
 		if (total)
-			print_metric(ctxp, NULL, "%7.2f%%", "aborted cycles",
+			print_metric(config, ctxp, NULL, "%7.2f%%", "aborted cycles",
 				100.0 * ((total2-avg) / total));
 		else
-			print_metric(ctxp, NULL, NULL, "aborted cycles", 0);
+			print_metric(config, ctxp, NULL, NULL, "aborted cycles", 0);
 	} else if (perf_stat_evsel__is(evsel, TRANSACTION_START)) {
 		total = runtime_stat_avg(st, STAT_CYCLES_IN_TX,
 					 ctx, cpu);
@@ -900,10 +911,10 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
 			ratio = total / avg;
 
 		if (runtime_stat_n(st, STAT_CYCLES_IN_TX, ctx, cpu) != 0)
-			print_metric(ctxp, NULL, "%8.0f",
+			print_metric(config, ctxp, NULL, "%8.0f",
 				     "cycles / transaction", ratio);
 		else
-			print_metric(ctxp, NULL, NULL, "cycles / transaction",
+			print_metric(config, ctxp, NULL, NULL, "cycles / transaction",
 				      0);
 	} else if (perf_stat_evsel__is(evsel, ELISION_START)) {
 		total = runtime_stat_avg(st, STAT_CYCLES_IN_TX,
@@ -912,33 +923,33 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
 		if (avg)
 			ratio = total / avg;
 
-		print_metric(ctxp, NULL, "%8.0f", "cycles / elision", ratio);
+		print_metric(config, ctxp, NULL, "%8.0f", "cycles / elision", ratio);
 	} else if (perf_evsel__is_clock(evsel)) {
 		if ((ratio = avg_stats(&walltime_nsecs_stats)) != 0)
-			print_metric(ctxp, NULL, "%8.3f", "CPUs utilized",
+			print_metric(config, ctxp, NULL, "%8.3f", "CPUs utilized",
 				     avg / (ratio * evsel->scale));
 		else
-			print_metric(ctxp, NULL, NULL, "CPUs utilized", 0);
+			print_metric(config, ctxp, NULL, NULL, "CPUs utilized", 0);
 	} else if (perf_stat_evsel__is(evsel, TOPDOWN_FETCH_BUBBLES)) {
 		double fe_bound = td_fe_bound(ctx, cpu, st);
 
 		if (fe_bound > 0.2)
 			color = PERF_COLOR_RED;
-		print_metric(ctxp, color, "%8.1f%%", "frontend bound",
+		print_metric(config, ctxp, color, "%8.1f%%", "frontend bound",
 				fe_bound * 100.);
 	} else if (perf_stat_evsel__is(evsel, TOPDOWN_SLOTS_RETIRED)) {
 		double retiring = td_retiring(ctx, cpu, st);
 
 		if (retiring > 0.7)
 			color = PERF_COLOR_GREEN;
-		print_metric(ctxp, color, "%8.1f%%", "retiring",
+		print_metric(config, ctxp, color, "%8.1f%%", "retiring",
 				retiring * 100.);
 	} else if (perf_stat_evsel__is(evsel, TOPDOWN_RECOVERY_BUBBLES)) {
 		double bad_spec = td_bad_spec(ctx, cpu, st);
 
 		if (bad_spec > 0.1)
 			color = PERF_COLOR_RED;
-		print_metric(ctxp, color, "%8.1f%%", "bad speculation",
+		print_metric(config, ctxp, color, "%8.1f%%", "bad speculation",
 				bad_spec * 100.);
 	} else if (perf_stat_evsel__is(evsel, TOPDOWN_SLOTS_ISSUED)) {
 		double be_bound = td_be_bound(ctx, cpu, st);
@@ -955,12 +966,12 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
 		if (be_bound > 0.2)
 			color = PERF_COLOR_RED;
 		if (td_total_slots(ctx, cpu, st) > 0)
-			print_metric(ctxp, color, "%8.1f%%", name,
+			print_metric(config, ctxp, color, "%8.1f%%", name,
 					be_bound * 100.);
 		else
-			print_metric(ctxp, NULL, NULL, name, 0);
+			print_metric(config, ctxp, NULL, NULL, name, 0);
 	} else if (evsel->metric_expr) {
-		generic_metric(evsel->metric_expr, evsel->metric_events, evsel->name,
+		generic_metric(config, evsel->metric_expr, evsel->metric_events, evsel->name,
 				evsel->metric_name, avg, cpu, out, st);
 	} else if (runtime_stat_n(st, STAT_NSECS, 0, cpu) != 0) {
 		char unit = 'M';
@@ -975,9 +986,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
 			unit = 'K';
 		}
 		snprintf(unit_buf, sizeof(unit_buf), "%c/sec", unit);
-		print_metric(ctxp, NULL, "%8.3f", unit_buf, ratio);
+		print_metric(config, ctxp, NULL, "%8.3f", unit_buf, ratio);
 	} else if (perf_stat_evsel__is(evsel, SMI_NUM)) {
-		print_smi_cost(cpu, evsel, out, st);
+		print_smi_cost(config, cpu, evsel, out, st);
 	} else {
 		num = 0;
 	}
@@ -987,12 +998,12 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
 
 		list_for_each_entry (mexp, &me->head, nd) {
 			if (num++ > 0)
-				out->new_line(ctxp);
-			generic_metric(mexp->metric_expr, mexp->metric_events,
+				out->new_line(config, ctxp);
+			generic_metric(config, mexp->metric_expr, mexp->metric_events,
 					evsel->name, mexp->metric_name,
 					avg, cpu, out, st);
 		}
 	}
 	if (num == 0)
-		print_metric(ctxp, NULL, NULL, NULL, 0);
+		print_metric(config, ctxp, NULL, NULL, NULL, 0);
 }
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index da6a706daecc..dffcf2110706 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -135,9 +135,10 @@ bool __perf_evsel_stat__is(struct perf_evsel *evsel,
 extern struct runtime_stat rt_stat;
 extern struct stats walltime_nsecs_stats;
 
-typedef void (*print_metric_t)(void *ctx, const char *color, const char *unit,
+typedef void (*print_metric_t)(struct perf_stat_config *config,
+			       void *ctx, const char *color, const char *unit,
 			       const char *fmt, double val);
-typedef void (*new_line_t )(void *ctx);
+typedef void (*new_line_t)(struct perf_stat_config *config, void *ctx);
 
 void runtime_stat__init(struct runtime_stat *st);
 void runtime_stat__exit(struct runtime_stat *st);
@@ -153,7 +154,8 @@ struct perf_stat_output_ctx {
 	bool force_header;
 };
 
-void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
+void perf_stat__print_shadow_stats(struct perf_stat_config *config,
+				   struct perf_evsel *evsel,
 				   double avg, int cpu,
 				   struct perf_stat_output_ctx *out,
 				   struct rblist *metric_events,
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 20/43] perf stat: Move csv_* into struct perf_stat_config
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
                   ` (18 preceding siblings ...)
  2018-08-30  6:32 ` [PATCH 19/43] perf stat: Pass stat_config argument to global " Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:31   ` [tip:perf/core] perf stat: Move csv_* to 'struct perf_stat_config' tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 21/43] perf stat: Move interval_clear into struct perf_stat_config Jiri Olsa
                   ` (23 subsequent siblings)
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

Moving static csv_* fields into struct perf_stat_config,
so it can be passed around and used outside stat command.

Link: http://lkml.kernel.org/n/tip-md7htmdsje3od38k86do4899@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 114 +++++++++++++++++++-------------------
 tools/perf/util/stat.h    |   2 +
 2 files changed, 58 insertions(+), 58 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 7a3361308e61..4c29e5065e02 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -157,8 +157,6 @@ static bool			smi_cost			= false;
 static bool			smi_reset			= false;
 static bool			big_num				=  true;
 static int			big_num_opt			=  -1;
-static const char		*csv_sep			= NULL;
-static bool			csv_output			= false;
 static bool			group				= false;
 static const char		*pre_cmd			= NULL;
 static const char		*post_cmd			= NULL;
@@ -663,11 +661,11 @@ static int run_perf_stat(int argc, const char **argv, int run_idx)
 static void print_running(struct perf_stat_config *config,
 			  u64 run, u64 ena)
 {
-	if (csv_output) {
+	if (config->csv_output) {
 		fprintf(config->output, "%s%" PRIu64 "%s%.2f",
-					csv_sep,
+					config->csv_sep,
 					run,
-					csv_sep,
+					config->csv_sep,
 					ena ? 100.0 * run / ena : 100.0);
 	} else if (run != ena) {
 		fprintf(config->output, "  (%.2f%%)", 100.0 * run / ena);
@@ -679,8 +677,8 @@ static void print_noise_pct(struct perf_stat_config *config,
 {
 	double pct = rel_stddev_stats(total, avg);
 
-	if (csv_output)
-		fprintf(config->output, "%s%.2f%%", csv_sep, pct);
+	if (config->csv_output)
+		fprintf(config->output, "%s%.2f%%", config->csv_sep, pct);
 	else if (pct)
 		fprintf(config->output, "  ( +-%6.2f%% )", pct);
 }
@@ -704,34 +702,34 @@ static void aggr_printout(struct perf_stat_config *config,
 	case AGGR_CORE:
 		fprintf(config->output, "S%d-C%*d%s%*d%s",
 			cpu_map__id_to_socket(id),
-			csv_output ? 0 : -8,
+			config->csv_output ? 0 : -8,
 			cpu_map__id_to_cpu(id),
-			csv_sep,
-			csv_output ? 0 : 4,
+			config->csv_sep,
+			config->csv_output ? 0 : 4,
 			nr,
-			csv_sep);
+			config->csv_sep);
 		break;
 	case AGGR_SOCKET:
 		fprintf(config->output, "S%*d%s%*d%s",
-			csv_output ? 0 : -5,
+			config->csv_output ? 0 : -5,
 			id,
-			csv_sep,
-			csv_output ? 0 : 4,
+			config->csv_sep,
+			config->csv_output ? 0 : 4,
 			nr,
-			csv_sep);
+			config->csv_sep);
 			break;
 	case AGGR_NONE:
 		fprintf(config->output, "CPU%*d%s",
-			csv_output ? 0 : -4,
-			perf_evsel__cpus(evsel)->map[id], csv_sep);
+			config->csv_output ? 0 : -4,
+			perf_evsel__cpus(evsel)->map[id], config->csv_sep);
 		break;
 	case AGGR_THREAD:
 		fprintf(config->output, "%*s-%*d%s",
-			csv_output ? 0 : 16,
+			config->csv_output ? 0 : 16,
 			thread_map__comm(evsel->threads, id),
-			csv_output ? 0 : -8,
+			config->csv_output ? 0 : -8,
 			thread_map__pid(evsel->threads, id),
-			csv_sep);
+			config->csv_sep);
 		break;
 	case AGGR_GLOBAL:
 	case AGGR_UNSET:
@@ -804,10 +802,10 @@ static void new_line_csv(struct perf_stat_config *config, void *ctx)
 
 	fputc('\n', os->fh);
 	if (os->prefix)
-		fprintf(os->fh, "%s%s", os->prefix, csv_sep);
+		fprintf(os->fh, "%s%s", os->prefix, config->csv_sep);
 	aggr_printout(config, os->evsel, os->id, os->nr);
 	for (i = 0; i < os->nfields; i++)
-		fputs(csv_sep, os->fh);
+		fputs(config->csv_sep, os->fh);
 }
 
 static void print_metric_csv(struct perf_stat_config *config __maybe_unused,
@@ -820,7 +818,7 @@ static void print_metric_csv(struct perf_stat_config *config __maybe_unused,
 	char buf[64], *vals, *ends;
 
 	if (unit == NULL || fmt == NULL) {
-		fprintf(out, "%s%s", csv_sep, csv_sep);
+		fprintf(out, "%s%s", config->csv_sep, config->csv_sep);
 		return;
 	}
 	snprintf(buf, sizeof(buf), fmt, val);
@@ -830,7 +828,7 @@ static void print_metric_csv(struct perf_stat_config *config __maybe_unused,
 	*ends = 0;
 	while (isspace(*unit))
 		unit++;
-	fprintf(out, "%s%s%s%s", csv_sep, vals, csv_sep, unit);
+	fprintf(out, "%s%s%s%s", config->csv_sep, vals, config->csv_sep, unit);
 }
 
 /* Filter out some columns that don't work well in metrics only mode */
@@ -898,7 +896,7 @@ static void print_metric_only_csv(struct perf_stat_config *config __maybe_unused
 	while (isdigit(*ends) || *ends == '.')
 		ends++;
 	*ends = 0;
-	fprintf(out, "%s%s", vals, csv_sep);
+	fprintf(out, "%s%s", vals, config->csv_sep);
 }
 
 static void new_line_metric(struct perf_stat_config *config __maybe_unused,
@@ -917,8 +915,8 @@ static void print_metric_header(struct perf_stat_config *config __maybe_unused,
 	if (!valid_only_metric(unit))
 		return;
 	unit = fixunit(tbuf, os->evsel, unit);
-	if (csv_output)
-		fprintf(os->fh, "%s%s", unit, csv_sep);
+	if (config->csv_output)
+		fprintf(os->fh, "%s%s", unit, config->csv_sep);
 	else
 		fprintf(os->fh, "%*s ", metric_only_len, unit);
 }
@@ -952,7 +950,7 @@ static void abs_printout(struct perf_stat_config *config,
 	double sc =  evsel->scale;
 	const char *fmt;
 
-	if (csv_output) {
+	if (config->csv_output) {
 		fmt = floor(sc) != sc ?  "%.2f%s" : "%.0f%s";
 	} else {
 		if (big_num)
@@ -963,17 +961,17 @@ static void abs_printout(struct perf_stat_config *config,
 
 	aggr_printout(config, evsel, id, nr);
 
-	fprintf(output, fmt, avg, csv_sep);
+	fprintf(output, fmt, avg, config->csv_sep);
 
 	if (evsel->unit)
 		fprintf(output, "%-*s%s",
-			csv_output ? 0 : unit_width,
-			evsel->unit, csv_sep);
+			config->csv_output ? 0 : unit_width,
+			evsel->unit, config->csv_sep);
 
-	fprintf(output, "%-*s", csv_output ? 0 : 25, perf_evsel__name(evsel));
+	fprintf(output, "%-*s", config->csv_output ? 0 : 25, perf_evsel__name(evsel));
 
 	if (evsel->cgrp)
-		fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
+		fprintf(output, "%s%s", config->csv_sep, evsel->cgrp->name);
 }
 
 static bool is_mixed_hw_group(struct perf_evsel *counter)
@@ -1018,14 +1016,14 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 
 	if (metric_only) {
 		nl = new_line_metric;
-		if (csv_output)
+		if (config->csv_output)
 			pm = print_metric_only_csv;
 		else
 			pm = print_metric_only;
 	} else
 		nl = new_line_std;
 
-	if (csv_output && !metric_only) {
+	if (config->csv_output && !metric_only) {
 		static int aggr_fields[] = {
 			[AGGR_GLOBAL] = 0,
 			[AGGR_THREAD] = 1,
@@ -1049,9 +1047,9 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 		aggr_printout(config, counter, id, nr);
 
 		fprintf(config->output, "%*s%s",
-			csv_output ? 0 : 18,
+			config->csv_output ? 0 : 18,
 			counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
-			csv_sep);
+			config->csv_sep);
 
 		if (counter->supported) {
 			print_free_counters_hint = 1;
@@ -1060,22 +1058,22 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 		}
 
 		fprintf(config->output, "%-*s%s",
-			csv_output ? 0 : unit_width,
-			counter->unit, csv_sep);
+			config->csv_output ? 0 : unit_width,
+			counter->unit, config->csv_sep);
 
 		fprintf(config->output, "%*s",
-			csv_output ? 0 : -25,
+			config->csv_output ? 0 : -25,
 			perf_evsel__name(counter));
 
 		if (counter->cgrp)
 			fprintf(config->output, "%s%s",
-				csv_sep, counter->cgrp->name);
+				config->csv_sep, counter->cgrp->name);
 
-		if (!csv_output)
+		if (!config->csv_output)
 			pm(config, &os, NULL, NULL, "", 0);
 		print_noise(config, counter, noise);
 		print_running(config, run, ena);
-		if (csv_output)
+		if (config->csv_output)
 			pm(config, &os, NULL, NULL, "", 0);
 		return;
 	}
@@ -1088,7 +1086,7 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 	out.ctx = &os;
 	out.force_header = false;
 
-	if (csv_output && !metric_only) {
+	if (config->csv_output && !metric_only) {
 		print_noise(config, counter, noise);
 		print_running(config, run, ena);
 	}
@@ -1096,7 +1094,7 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 	perf_stat__print_shadow_stats(config, counter, uval,
 				first_shadow_cpu(counter, id),
 				&out, &metric_events, st);
-	if (!csv_output && !metric_only) {
+	if (!config->csv_output && !metric_only) {
 		print_noise(config, counter, noise);
 		print_running(config, run, ena);
 	}
@@ -1512,10 +1510,10 @@ static void print_metric_headers(struct perf_stat_config *config,
 	if (prefix)
 		fprintf(config->output, "%s", prefix);
 
-	if (!csv_output && !no_indent)
+	if (!config->csv_output && !no_indent)
 		fprintf(config->output, "%*s",
 			aggr_header_lens[config->aggr_mode], "");
-	if (csv_output) {
+	if (config->csv_output) {
 		if (config->interval)
 			fputs("time,", config->output);
 		fputs(aggr_header_csv[config->aggr_mode], config->output);
@@ -1549,9 +1547,9 @@ static void print_interval(struct perf_stat_config *config,
 	if (interval_clear)
 		puts(CONSOLE_CLEAR);
 
-	sprintf(prefix, "%6lu.%09lu%s", ts->tv_sec, ts->tv_nsec, csv_sep);
+	sprintf(prefix, "%6lu.%09lu%s", ts->tv_sec, ts->tv_nsec, config->csv_sep);
 
-	if ((num_print_interval == 0 && !csv_output) || interval_clear) {
+	if ((num_print_interval == 0 && !config->csv_output) || interval_clear) {
 		switch (config->aggr_mode) {
 		case AGGR_SOCKET:
 			fprintf(output, "#           time socket cpus");
@@ -1597,7 +1595,7 @@ static void print_header(struct perf_stat_config *config,
 
 	fflush(stdout);
 
-	if (!csv_output) {
+	if (!config->csv_output) {
 		fprintf(output, "\n");
 		fprintf(output, " Performance counter stats for ");
 		if (target.system_wide)
@@ -1776,7 +1774,7 @@ perf_evlist__print_counters(struct perf_evlist *evlist,
 		break;
 	}
 
-	if (!interval && !csv_output)
+	if (!interval && !config->csv_output)
 		print_footer(config);
 
 	fflush(config->output);
@@ -1896,7 +1894,7 @@ static const struct option stat_options[] = {
 	OPT_SET_UINT('A', "no-aggr", &stat_config.aggr_mode,
 		    "disable CPU count aggregation", AGGR_NONE),
 	OPT_BOOLEAN(0, "no-merge", &no_merge, "Do not merge identical named events"),
-	OPT_STRING('x', "field-separator", &csv_sep, "separator",
+	OPT_STRING('x', "field-separator", &stat_config.csv_sep, "separator",
 		   "print counts with custom separator"),
 	OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
 		     "monitor event in cgroup name only", parse_cgroups),
@@ -2749,12 +2747,12 @@ int cmd_stat(int argc, const char **argv)
 	perf_stat__collect_metric_expr(evsel_list);
 	perf_stat__init_shadow_stats();
 
-	if (csv_sep) {
-		csv_output = true;
-		if (!strcmp(csv_sep, "\\t"))
-			csv_sep = "\t";
+	if (stat_config.csv_sep) {
+		stat_config.csv_output = true;
+		if (!strcmp(stat_config.csv_sep, "\\t"))
+			stat_config.csv_sep = "\t";
 	} else
-		csv_sep = DEFAULT_SEPARATOR;
+		stat_config.csv_sep = DEFAULT_SEPARATOR;
 
 	if (argc && !strncmp(argv[0], "rec", 3)) {
 		argc = __cmd_record(argc, argv);
@@ -2827,7 +2825,7 @@ int cmd_stat(int argc, const char **argv)
 	/*
 	 * let the spreadsheet do the pretty-printing
 	 */
-	if (csv_output) {
+	if (stat_config.csv_output) {
 		/* User explicitly passed -B? */
 		if (big_num_opt == 1) {
 			fprintf(stderr, "-B option not supported with -x\n");
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index dffcf2110706..18546d8b0279 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -91,6 +91,7 @@ struct perf_stat_config {
 	bool			 scale;
 	bool			 no_inherit;
 	bool			 identifier;
+	bool			 csv_output;
 	FILE			*output;
 	unsigned int		 interval;
 	unsigned int		 timeout;
@@ -98,6 +99,7 @@ struct perf_stat_config {
 	int			 times;
 	struct runtime_stat	*stats;
 	int			 stats_num;
+	const char		*csv_sep;
 };
 
 void update_stats(struct stats *stats, u64 val);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 21/43] perf stat: Move interval_clear into struct perf_stat_config
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
                   ` (19 preceding siblings ...)
  2018-08-30  6:32 ` [PATCH 20/43] perf stat: Move csv_* into struct perf_stat_config Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:31   ` [tip:perf/core] perf stat: Move 'interval_clear' to 'struct perf_stat_config' tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 22/43] perf stat: Move metric_only into struct perf_stat_config Jiri Olsa
                   ` (22 subsequent siblings)
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

Moving static interval_clear into struct perf_stat_config,
so it can be passed around and used outside stat command.

Link: http://lkml.kernel.org/n/tip-jvas3d3b4t0jn3bdrnm0ek2p@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 9 ++++-----
 tools/perf/util/stat.h    | 1 +
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 4c29e5065e02..89297ab77d21 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -172,7 +172,6 @@ static struct cpu_map		*aggr_map;
 static aggr_get_id_t		aggr_get_id;
 static bool			append_file;
 static bool			interval_count;
-static bool			interval_clear;
 static const char		*output_name;
 static int			output_fd;
 static int			print_free_counters_hint;
@@ -1544,12 +1543,12 @@ static void print_interval(struct perf_stat_config *config,
 	FILE *output = config->output;
 	static int num_print_interval;
 
-	if (interval_clear)
+	if (config->interval_clear)
 		puts(CONSOLE_CLEAR);
 
 	sprintf(prefix, "%6lu.%09lu%s", ts->tv_sec, ts->tv_nsec, config->csv_sep);
 
-	if ((num_print_interval == 0 && !config->csv_output) || interval_clear) {
+	if ((num_print_interval == 0 && !config->csv_output) || config->interval_clear) {
 		switch (config->aggr_mode) {
 		case AGGR_SOCKET:
 			fprintf(output, "#           time socket cpus");
@@ -1581,7 +1580,7 @@ static void print_interval(struct perf_stat_config *config,
 		}
 	}
 
-	if ((num_print_interval == 0 || interval_clear) && metric_only)
+	if ((num_print_interval == 0 || config->interval_clear) && metric_only)
 		print_metric_headers(config, " ", true);
 	if (++num_print_interval == 25)
 		num_print_interval = 0;
@@ -1911,7 +1910,7 @@ static const struct option stat_options[] = {
 		    "(overhead is possible for values <= 100ms)"),
 	OPT_INTEGER(0, "interval-count", &stat_config.times,
 		    "print counts for fixed number of times"),
-	OPT_BOOLEAN(0, "interval-clear", &interval_clear,
+	OPT_BOOLEAN(0, "interval-clear", &stat_config.interval_clear,
 		    "clear screen in between new interval"),
 	OPT_UINTEGER(0, "timeout", &stat_config.timeout,
 		    "stop workload and print counts after a timeout period in ms (>= 10ms)"),
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 18546d8b0279..470ab37601be 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -92,6 +92,7 @@ struct perf_stat_config {
 	bool			 no_inherit;
 	bool			 identifier;
 	bool			 csv_output;
+	bool			 interval_clear;
 	FILE			*output;
 	unsigned int		 interval;
 	unsigned int		 timeout;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 22/43] perf stat: Move metric_only into struct perf_stat_config
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
                   ` (20 preceding siblings ...)
  2018-08-30  6:32 ` [PATCH 21/43] perf stat: Move interval_clear into struct perf_stat_config Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:32   ` [tip:perf/core] perf stat: Move 'metric_only' to 'struct perf_stat_config' tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 23/43] perf stat: Move unit_width into struct perf_stat_config Jiri Olsa
                   ` (21 subsequent siblings)
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

Moving static metric_only into struct perf_stat_config,
so it can be passed around and used outside stat command.

Link: http://lkml.kernel.org/n/tip-tevvpgyi3o7ok34nx0oi05gu@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 29 ++++++++++++++++-------------
 tools/perf/util/stat.h    |  1 +
 2 files changed, 17 insertions(+), 13 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 89297ab77d21..397cb4f28d7f 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -163,7 +163,6 @@ static const char		*post_cmd			= NULL;
 static bool			sync_run			= false;
 static unsigned int		unit_width			= 4; /* strlen("unit") */
 static bool			forever				= false;
-static bool			metric_only			= false;
 static bool			force_metric_only		= false;
 static bool			no_merge			= false;
 static bool			walltime_run_table		= false;
@@ -1013,7 +1012,7 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 	print_metric_t pm = print_metric_std;
 	new_line_t nl;
 
-	if (metric_only) {
+	if (config->metric_only) {
 		nl = new_line_metric;
 		if (config->csv_output)
 			pm = print_metric_only_csv;
@@ -1022,7 +1021,7 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 	} else
 		nl = new_line_std;
 
-	if (config->csv_output && !metric_only) {
+	if (config->csv_output && !config->metric_only) {
 		static int aggr_fields[] = {
 			[AGGR_GLOBAL] = 0,
 			[AGGR_THREAD] = 1,
@@ -1039,7 +1038,7 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 			os.nfields++;
 	}
 	if (run == 0 || ena == 0 || counter->counts->scaled == -1) {
-		if (metric_only) {
+		if (config->metric_only) {
 			pm(config, &os, NULL, "", "", 0);
 			return;
 		}
@@ -1077,7 +1076,7 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 		return;
 	}
 
-	if (!metric_only)
+	if (!config->metric_only)
 		abs_printout(config, id, nr, counter, uval);
 
 	out.print_metric = pm;
@@ -1085,7 +1084,7 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 	out.ctx = &os;
 	out.force_header = false;
 
-	if (config->csv_output && !metric_only) {
+	if (config->csv_output && !config->metric_only) {
 		print_noise(config, counter, noise);
 		print_running(config, run, ena);
 	}
@@ -1093,7 +1092,7 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 	perf_stat__print_shadow_stats(config, counter, uval,
 				first_shadow_cpu(counter, id),
 				&out, &metric_events, st);
-	if (!config->csv_output && !metric_only) {
+	if (!config->csv_output && !config->metric_only) {
 		print_noise(config, counter, noise);
 		print_running(config, run, ena);
 	}
@@ -1225,6 +1224,7 @@ static void aggr_cb(struct perf_evsel *counter, void *data, bool first)
 static void print_aggr(struct perf_stat_config *config,
 		       char *prefix)
 {
+	bool metric_only = config->metric_only;
 	FILE *output = config->output;
 	struct perf_evsel *counter;
 	int s, id, nr;
@@ -1388,6 +1388,7 @@ static void counter_aggr_cb(struct perf_evsel *counter, void *data,
 static void print_counter_aggr(struct perf_stat_config *config,
 			       struct perf_evsel *counter, char *prefix)
 {
+	bool metric_only = config->metric_only;
 	FILE *output = config->output;
 	double uval;
 	struct caggr_data cd = { .avg = 0.0 };
@@ -1540,6 +1541,7 @@ static void print_metric_headers(struct perf_stat_config *config,
 static void print_interval(struct perf_stat_config *config,
 			   char *prefix, struct timespec *ts)
 {
+	bool metric_only = config->metric_only;
 	FILE *output = config->output;
 	static int num_print_interval;
 
@@ -1716,6 +1718,7 @@ perf_evlist__print_counters(struct perf_evlist *evlist,
 			    struct timespec *ts,
 			    int argc, const char **argv)
 {
+	bool metric_only = config->metric_only;
 	int interval = config->interval;
 	struct perf_evsel *counter;
 	char buf[64], *prefix = NULL;
@@ -1843,7 +1846,7 @@ static int enable_metric_only(const struct option *opt __maybe_unused,
 			      const char *s __maybe_unused, int unset)
 {
 	force_metric_only = true;
-	metric_only = !unset;
+	stat_config.metric_only = !unset;
 	return 0;
 }
 
@@ -1922,7 +1925,7 @@ static const struct option stat_options[] = {
 		     "aggregate counts per thread", AGGR_THREAD),
 	OPT_UINTEGER('D', "delay", &stat_config.initial_delay,
 		     "ms to wait before starting measurement after program start"),
-	OPT_CALLBACK_NOOPT(0, "metric-only", &metric_only, NULL,
+	OPT_CALLBACK_NOOPT(0, "metric-only", &stat_config.metric_only, NULL,
 			"Only print computed metrics. No raw values", enable_metric_only),
 	OPT_BOOLEAN(0, "topdown", &topdown_run,
 			"measure topdown level 1 statistics"),
@@ -2345,7 +2348,7 @@ static int add_default_attributes(void)
 		if (pmu_have_event("msr", "aperf") &&
 		    pmu_have_event("msr", "smi")) {
 			if (!force_metric_only)
-				metric_only = true;
+				stat_config.metric_only = true;
 			err = parse_events(evsel_list, smi_cost_attrs, &errinfo);
 		} else {
 			fprintf(stderr, "To measure SMI cost, it needs "
@@ -2376,7 +2379,7 @@ static int add_default_attributes(void)
 		}
 
 		if (!force_metric_only)
-			metric_only = true;
+			stat_config.metric_only = true;
 		if (topdown_filter_events(topdown_attrs, &str,
 				arch_topdown_check_group(&warn)) < 0) {
 			pr_err("Out of memory\n");
@@ -2776,12 +2779,12 @@ int cmd_stat(int argc, const char **argv)
 		goto out;
 	}
 
-	if (metric_only && stat_config.aggr_mode == AGGR_THREAD) {
+	if (stat_config.metric_only && stat_config.aggr_mode == AGGR_THREAD) {
 		fprintf(stderr, "--metric-only is not supported with --per-thread\n");
 		goto out;
 	}
 
-	if (metric_only && run_count > 1) {
+	if (stat_config.metric_only && run_count > 1) {
 		fprintf(stderr, "--metric-only is not supported with -r\n");
 		goto out;
 	}
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 470ab37601be..da838182b99c 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -93,6 +93,7 @@ struct perf_stat_config {
 	bool			 identifier;
 	bool			 csv_output;
 	bool			 interval_clear;
+	bool			 metric_only;
 	FILE			*output;
 	unsigned int		 interval;
 	unsigned int		 timeout;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 23/43] perf stat: Move unit_width into struct perf_stat_config
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
                   ` (21 preceding siblings ...)
  2018-08-30  6:32 ` [PATCH 22/43] perf stat: Move metric_only into struct perf_stat_config Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:33   ` [tip:perf/core] perf stat: Move 'unit_width' to 'struct perf_stat_config' tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 24/43] perf stat: Add target argument to perf_evlist__print_counters Jiri Olsa
                   ` (20 subsequent siblings)
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

Moving static unit_width into struct perf_stat_config,
so it can be passed around and used outside stat command.

Link: http://lkml.kernel.org/n/tip-wmmgzikkzqx4k5mqz7xld903@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 11 ++++++-----
 tools/perf/util/stat.h    |  1 +
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 397cb4f28d7f..24171aa6c41f 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -161,7 +161,6 @@ static bool			group				= false;
 static const char		*pre_cmd			= NULL;
 static const char		*post_cmd			= NULL;
 static bool			sync_run			= false;
-static unsigned int		unit_width			= 4; /* strlen("unit") */
 static bool			forever				= false;
 static bool			force_metric_only		= false;
 static bool			no_merge			= false;
@@ -200,6 +199,7 @@ static volatile int done = 0;
 static struct perf_stat_config stat_config = {
 	.aggr_mode	= AGGR_GLOBAL,
 	.scale		= true,
+	.unit_width	= 4, /* strlen("unit") */
 };
 
 static bool is_duration_time(struct perf_evsel *evsel)
@@ -524,8 +524,8 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
 		counter->supported = true;
 
 		l = strlen(counter->unit);
-		if (l > unit_width)
-			unit_width = l;
+		if (l > stat_config.unit_width)
+			stat_config.unit_width = l;
 
 		if (perf_evsel__should_store_id(counter) &&
 		    perf_evsel__store_ids(counter, evsel_list))
@@ -963,7 +963,7 @@ static void abs_printout(struct perf_stat_config *config,
 
 	if (evsel->unit)
 		fprintf(output, "%-*s%s",
-			config->csv_output ? 0 : unit_width,
+			config->csv_output ? 0 : config->unit_width,
 			evsel->unit, config->csv_sep);
 
 	fprintf(output, "%-*s", config->csv_output ? 0 : 25, perf_evsel__name(evsel));
@@ -1056,7 +1056,7 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 		}
 
 		fprintf(config->output, "%-*s%s",
-			config->csv_output ? 0 : unit_width,
+			config->csv_output ? 0 : config->unit_width,
 			counter->unit, config->csv_sep);
 
 		fprintf(config->output, "%*s",
@@ -1542,6 +1542,7 @@ static void print_interval(struct perf_stat_config *config,
 			   char *prefix, struct timespec *ts)
 {
 	bool metric_only = config->metric_only;
+	unsigned int unit_width = config->unit_width;
 	FILE *output = config->output;
 	static int num_print_interval;
 
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index da838182b99c..2dc66e0ba4b8 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -98,6 +98,7 @@ struct perf_stat_config {
 	unsigned int		 interval;
 	unsigned int		 timeout;
 	unsigned int		 initial_delay;
+	unsigned int		 unit_width;
 	int			 times;
 	struct runtime_stat	*stats;
 	int			 stats_num;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 24/43] perf stat: Add target argument to perf_evlist__print_counters
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
                   ` (22 preceding siblings ...)
  2018-08-30  6:32 ` [PATCH 23/43] perf stat: Move unit_width into struct perf_stat_config Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:33   ` [tip:perf/core] perf stat: Add 'target' argument to perf_evlist__print_counters() tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 25/43] perf stat: Pass evlist argument to print functions Jiri Olsa
                   ` (19 subsequent siblings)
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

Adding 'struct target' argument to perf_evlist__print_counters,
so the function does not depend on stat command object local
target and can be moved out.

Link: http://lkml.kernel.org/n/tip-fxhirh8l1b9i0ozb6j69umd1@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 20 +++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 24171aa6c41f..528f85146b59 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1590,6 +1590,7 @@ static void print_interval(struct perf_stat_config *config,
 }
 
 static void print_header(struct perf_stat_config *config,
+			 struct target *_target,
 			 int argc, const char **argv)
 {
 	FILE *output = config->output;
@@ -1600,18 +1601,18 @@ static void print_header(struct perf_stat_config *config,
 	if (!config->csv_output) {
 		fprintf(output, "\n");
 		fprintf(output, " Performance counter stats for ");
-		if (target.system_wide)
+		if (_target->system_wide)
 			fprintf(output, "\'system wide");
-		else if (target.cpu_list)
-			fprintf(output, "\'CPU(s) %s", target.cpu_list);
-		else if (!target__has_task(&target)) {
+		else if (_target->cpu_list)
+			fprintf(output, "\'CPU(s) %s", _target->cpu_list);
+		else if (!target__has_task(_target)) {
 			fprintf(output, "\'%s", argv ? argv[0] : "pipe");
 			for (i = 1; argv && (i < argc); i++)
 				fprintf(output, " %s", argv[i]);
-		} else if (target.pid)
-			fprintf(output, "process id \'%s", target.pid);
+		} else if (_target->pid)
+			fprintf(output, "process id \'%s", _target->pid);
 		else
-			fprintf(output, "thread id \'%s", target.tid);
+			fprintf(output, "thread id \'%s", _target->tid);
 
 		fprintf(output, "\'");
 		if (run_count > 1)
@@ -1716,6 +1717,7 @@ static void print_footer(struct perf_stat_config *config)
 static void
 perf_evlist__print_counters(struct perf_evlist *evlist,
 			    struct perf_stat_config *config,
+			    struct target *_target,
 			    struct timespec *ts,
 			    int argc, const char **argv)
 {
@@ -1727,7 +1729,7 @@ perf_evlist__print_counters(struct perf_evlist *evlist,
 	if (interval)
 		print_interval(config, prefix = buf, ts);
 	else
-		print_header(config, argc, argv);
+		print_header(config, _target, argc, argv);
 
 	if (metric_only) {
 		static int num_print_iv;
@@ -1789,7 +1791,7 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)
 	if (STAT_RECORD && perf_stat.data.is_pipe)
 		return;
 
-	perf_evlist__print_counters(evsel_list, &stat_config,
+	perf_evlist__print_counters(evsel_list, &stat_config, &target,
 				    ts, argc, argv);
 }
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 25/43] perf stat: Pass evlist argument to print functions
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
                   ` (23 preceding siblings ...)
  2018-08-30  6:32 ` [PATCH 24/43] perf stat: Add target argument to perf_evlist__print_counters Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:34   ` [tip:perf/core] perf stat: Pass 'evlist' " tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 26/43] perf stat: Use evsel->evlist instead of evsel_list in collect_all_aliases Jiri Olsa
                   ` (18 subsequent siblings)
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

Adding evlist argument to print functions to get
rid of the evsel_list dependency.

Link: http://lkml.kernel.org/n/tip-wema3fc7ibju89vom0p4pc4a@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 22 +++++++++++++---------
 1 file changed, 13 insertions(+), 9 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 528f85146b59..46181ac492c5 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1222,6 +1222,7 @@ static void aggr_cb(struct perf_evsel *counter, void *data, bool first)
 }
 
 static void print_aggr(struct perf_stat_config *config,
+		       struct perf_evlist *evlist,
 		       char *prefix)
 {
 	bool metric_only = config->metric_only;
@@ -1248,7 +1249,7 @@ static void print_aggr(struct perf_stat_config *config,
 
 		ad.id = id = aggr_map->map[s];
 		first = true;
-		evlist__for_each_entry(evsel_list, counter) {
+		evlist__for_each_entry(evlist, counter) {
 			if (is_duration_time(counter))
 				continue;
 
@@ -1449,6 +1450,7 @@ static void print_counter(struct perf_stat_config *config,
 }
 
 static void print_no_aggr_metric(struct perf_stat_config *config,
+				 struct perf_evlist *evlist,
 				 char *prefix)
 {
 	int cpu;
@@ -1457,13 +1459,13 @@ static void print_no_aggr_metric(struct perf_stat_config *config,
 	u64 ena, run, val;
 	double uval;
 
-	nrcpus = evsel_list->cpus->nr;
+	nrcpus = evlist->cpus->nr;
 	for (cpu = 0; cpu < nrcpus; cpu++) {
 		bool first = true;
 
 		if (prefix)
 			fputs(prefix, config->output);
-		evlist__for_each_entry(evsel_list, counter) {
+		evlist__for_each_entry(evlist, counter) {
 			if (is_duration_time(counter))
 				continue;
 			if (first) {
@@ -1499,6 +1501,7 @@ static const char *aggr_header_csv[] = {
 };
 
 static void print_metric_headers(struct perf_stat_config *config,
+				 struct perf_evlist *evlist,
 				 const char *prefix, bool no_indent)
 {
 	struct perf_stat_output_ctx out;
@@ -1520,7 +1523,7 @@ static void print_metric_headers(struct perf_stat_config *config,
 	}
 
 	/* Print metrics headers only */
-	evlist__for_each_entry(evsel_list, counter) {
+	evlist__for_each_entry(evlist, counter) {
 		if (is_duration_time(counter))
 			continue;
 		os.evsel = counter;
@@ -1539,6 +1542,7 @@ static void print_metric_headers(struct perf_stat_config *config,
 }
 
 static void print_interval(struct perf_stat_config *config,
+			   struct perf_evlist *evlist,
 			   char *prefix, struct timespec *ts)
 {
 	bool metric_only = config->metric_only;
@@ -1584,7 +1588,7 @@ static void print_interval(struct perf_stat_config *config,
 	}
 
 	if ((num_print_interval == 0 || config->interval_clear) && metric_only)
-		print_metric_headers(config, " ", true);
+		print_metric_headers(config, evlist, " ", true);
 	if (++num_print_interval == 25)
 		num_print_interval = 0;
 }
@@ -1727,7 +1731,7 @@ perf_evlist__print_counters(struct perf_evlist *evlist,
 	char buf[64], *prefix = NULL;
 
 	if (interval)
-		print_interval(config, prefix = buf, ts);
+		print_interval(config, evlist, prefix = buf, ts);
 	else
 		print_header(config, _target, argc, argv);
 
@@ -1735,7 +1739,7 @@ perf_evlist__print_counters(struct perf_evlist *evlist,
 		static int num_print_iv;
 
 		if (num_print_iv == 0 && !interval)
-			print_metric_headers(config, prefix, false);
+			print_metric_headers(config, evlist, prefix, false);
 		if (num_print_iv++ == 25)
 			num_print_iv = 0;
 		if (config->aggr_mode == AGGR_GLOBAL && prefix)
@@ -1745,7 +1749,7 @@ perf_evlist__print_counters(struct perf_evlist *evlist,
 	switch (config->aggr_mode) {
 	case AGGR_CORE:
 	case AGGR_SOCKET:
-		print_aggr(config, prefix);
+		print_aggr(config, evlist, prefix);
 		break;
 	case AGGR_THREAD:
 		evlist__for_each_entry(evlist, counter) {
@@ -1765,7 +1769,7 @@ perf_evlist__print_counters(struct perf_evlist *evlist,
 		break;
 	case AGGR_NONE:
 		if (metric_only)
-			print_no_aggr_metric(config, prefix);
+			print_no_aggr_metric(config, evlist, prefix);
 		else {
 			evlist__for_each_entry(evlist, counter) {
 				if (is_duration_time(counter))
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 26/43] perf stat: Use evsel->evlist instead of evsel_list in collect_all_aliases
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
                   ` (24 preceding siblings ...)
  2018-08-30  6:32 ` [PATCH 25/43] perf stat: Pass evlist argument to print functions Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:34   ` [tip:perf/core] perf stat: Use 'evsel->evlist' instead of 'evsel_list' in collect_all_aliases() tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 27/43] perf stat: Move run_count into struct perf_stat_config Jiri Olsa
                   ` (17 subsequent siblings)
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

Using evsel->evlist instead of evsel_list in collect_all_aliases,
to rid of the evsel_list dependency.

Link: http://lkml.kernel.org/n/tip-lx03c5czf6iixgd0gyaws2hk@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 46181ac492c5..11741f3a8342 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1154,10 +1154,11 @@ static void collect_all_aliases(struct perf_evsel *counter,
 				       bool first),
 			    void *data)
 {
+	struct perf_evlist *evlist = counter->evlist;
 	struct perf_evsel *alias;
 
-	alias = list_prepare_entry(counter, &(evsel_list->entries), node);
-	list_for_each_entry_continue (alias, &evsel_list->entries, node) {
+	alias = list_prepare_entry(counter, &(evlist->entries), node);
+	list_for_each_entry_continue (alias, &evlist->entries, node) {
 		if (strcmp(perf_evsel__name(alias), perf_evsel__name(counter)) ||
 		    alias->scale != counter->scale ||
 		    alias->cgrp != counter->cgrp ||
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 27/43] perf stat: Move run_count into struct perf_stat_config
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
                   ` (25 preceding siblings ...)
  2018-08-30  6:32 ` [PATCH 26/43] perf stat: Use evsel->evlist instead of evsel_list in collect_all_aliases Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:35   ` [tip:perf/core] perf stat: Move 'run_count' to 'struct perf_stat_config' tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 28/43] perf stat: Move metric_only_len into struct perf_stat_config Jiri Olsa
                   ` (16 subsequent siblings)
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

Moving static run_count into struct perf_stat_config,
so it can be passed around and used outside stat command.

Link: http://lkml.kernel.org/n/tip-wmmgzikkzqx4k5mqz7xld903@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 39 ++++++++++++++++++++-------------------
 tools/perf/util/stat.h    |  1 +
 2 files changed, 21 insertions(+), 19 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 11741f3a8342..1276596840c9 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -147,7 +147,6 @@ typedef int (*aggr_get_id_t)(struct cpu_map *m, int cpu);
 
 #define METRIC_ONLY_LEN 20
 
-static int			run_count			=  1;
 static volatile pid_t		child_pid			= -1;
 static bool			null_run			=  false;
 static int			detailed_run			=  0;
@@ -200,6 +199,7 @@ static struct perf_stat_config stat_config = {
 	.aggr_mode	= AGGR_GLOBAL,
 	.scale		= true,
 	.unit_width	= 4, /* strlen("unit") */
+	.run_count	= 1,
 };
 
 static bool is_duration_time(struct perf_evsel *evsel)
@@ -686,7 +686,7 @@ static void print_noise(struct perf_stat_config *config,
 {
 	struct perf_stat_evsel *ps;
 
-	if (run_count == 1)
+	if (config->run_count == 1)
 		return;
 
 	ps = evsel->stats;
@@ -1620,8 +1620,8 @@ static void print_header(struct perf_stat_config *config,
 			fprintf(output, "thread id \'%s", _target->tid);
 
 		fprintf(output, "\'");
-		if (run_count > 1)
-			fprintf(output, " (%d runs)", run_count);
+		if (config->run_count > 1)
+			fprintf(output, " (%d runs)", config->run_count);
 		fprintf(output, ":\n\n");
 	}
 }
@@ -1634,7 +1634,8 @@ static int get_precision(double num)
 	return lround(ceil(-log10(num)));
 }
 
-static void print_table(FILE *output, int precision, double avg)
+static void print_table(struct perf_stat_config *config,
+			FILE *output, int precision, double avg)
 {
 	char tmp[64];
 	int idx, indent = 0;
@@ -1645,7 +1646,7 @@ static void print_table(FILE *output, int precision, double avg)
 
 	fprintf(output, "%*s# Table of individual measurements:\n", indent, "");
 
-	for (idx = 0; idx < run_count; idx++) {
+	for (idx = 0; idx < config->run_count; idx++) {
 		double run = (double) walltime_run[idx] / NSEC_PER_SEC;
 		int h, n = 1 + abs((int) (100.0 * (run - avg)/run) / 5);
 
@@ -1675,7 +1676,7 @@ static void print_footer(struct perf_stat_config *config)
 	if (!null_run)
 		fprintf(output, "\n");
 
-	if (run_count == 1) {
+	if (config->run_count == 1) {
 		fprintf(output, " %17.9f seconds time elapsed", avg);
 
 		if (ru_display) {
@@ -1695,7 +1696,7 @@ static void print_footer(struct perf_stat_config *config)
 		int precision = get_precision(sd) + 2;
 
 		if (walltime_run_table)
-			print_table(output, precision, avg);
+			print_table(config, output, precision, avg);
 
 		fprintf(output, " %17.*f +- %.*f seconds time elapsed",
 			precision, avg, precision, sd);
@@ -1886,7 +1887,7 @@ static const struct option stat_options[] = {
 	OPT_BOOLEAN('c', "scale", &stat_config.scale, "scale/normalize counters"),
 	OPT_INCR('v', "verbose", &verbose,
 		    "be more verbose (show counter open errors, etc)"),
-	OPT_INTEGER('r', "repeat", &run_count,
+	OPT_INTEGER('r', "repeat", &stat_config.run_count,
 		    "repeat command and print average + stddev (max: 100, forever: 0)"),
 	OPT_BOOLEAN(0, "table", &walltime_run_table,
 		    "display details about each run (only with -r option)"),
@@ -2484,7 +2485,7 @@ static int __cmd_record(int argc, const char **argv)
 	if (output_name)
 		data->file.path = output_name;
 
-	if (run_count != 1 || forever) {
+	if (stat_config.run_count != 1 || forever) {
 		pr_err("Cannot use -r option with perf stat record.\n");
 		return -1;
 	}
@@ -2792,12 +2793,12 @@ int cmd_stat(int argc, const char **argv)
 		goto out;
 	}
 
-	if (stat_config.metric_only && run_count > 1) {
+	if (stat_config.metric_only && stat_config.run_count > 1) {
 		fprintf(stderr, "--metric-only is not supported with -r\n");
 		goto out;
 	}
 
-	if (walltime_run_table && run_count <= 1) {
+	if (walltime_run_table && stat_config.run_count <= 1) {
 		fprintf(stderr, "--table is only supported with -r\n");
 		parse_options_usage(stat_usage, stat_options, "r", 1);
 		parse_options_usage(NULL, stat_options, "table", 0);
@@ -2853,20 +2854,20 @@ int cmd_stat(int argc, const char **argv)
 	 * Display user/system times only for single
 	 * run and when there's specified tracee.
 	 */
-	if ((run_count == 1) && target__none(&target))
+	if ((stat_config.run_count == 1) && target__none(&target))
 		ru_display = true;
 
-	if (run_count < 0) {
+	if (stat_config.run_count < 0) {
 		pr_err("Run count must be a positive number\n");
 		parse_options_usage(stat_usage, stat_options, "r", 1);
 		goto out;
-	} else if (run_count == 0) {
+	} else if (stat_config.run_count == 0) {
 		forever = true;
-		run_count = 1;
+		stat_config.run_count = 1;
 	}
 
 	if (walltime_run_table) {
-		walltime_run = zalloc(run_count * sizeof(walltime_run[0]));
+		walltime_run = zalloc(stat_config.run_count * sizeof(walltime_run[0]));
 		if (!walltime_run) {
 			pr_err("failed to setup -r option");
 			goto out;
@@ -2994,8 +2995,8 @@ int cmd_stat(int argc, const char **argv)
 	signal(SIGABRT, skip_signal);
 
 	status = 0;
-	for (run_idx = 0; forever || run_idx < run_count; run_idx++) {
-		if (run_count != 1 && verbose > 0)
+	for (run_idx = 0; forever || run_idx < stat_config.run_count; run_idx++) {
+		if (stat_config.run_count != 1 && verbose > 0)
 			fprintf(output, "[ perf stat: executing run #%d ... ]\n",
 				run_idx + 1);
 
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 2dc66e0ba4b8..351a36f5f5b0 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -100,6 +100,7 @@ struct perf_stat_config {
 	unsigned int		 initial_delay;
 	unsigned int		 unit_width;
 	int			 times;
+	int			 run_count;
 	struct runtime_stat	*stats;
 	int			 stats_num;
 	const char		*csv_sep;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 28/43] perf stat: Move metric_only_len into struct perf_stat_config
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
                   ` (26 preceding siblings ...)
  2018-08-30  6:32 ` [PATCH 27/43] perf stat: Move run_count into struct perf_stat_config Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:35   ` [tip:perf/core] perf stat: Move 'metric_only_len' to 'struct perf_stat_config' tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 29/43] perf stat: Pass stat_config to first_shadow_cpu Jiri Olsa
                   ` (15 subsequent siblings)
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

Moving static metric_only_len into struct perf_stat_config,
so it can be passed around and used outside stat command.

Link: http://lkml.kernel.org/n/tip-brq3qbbb9262ks5f6w8zjm24@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 10 +++++-----
 tools/perf/util/stat.h    |  1 +
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 1276596840c9..e96cef526ef0 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -176,7 +176,6 @@ static int			print_mixed_hw_group_error;
 static u64			*walltime_run;
 static bool			ru_display			= false;
 static struct rusage		ru_data;
-static unsigned int		metric_only_len			= METRIC_ONLY_LEN;
 
 struct perf_stat {
 	bool			 record;
@@ -200,6 +199,7 @@ static struct perf_stat_config stat_config = {
 	.scale		= true,
 	.unit_width	= 4, /* strlen("unit") */
 	.run_count	= 1,
+	.metric_only_len = METRIC_ONLY_LEN,
 };
 
 static bool is_duration_time(struct perf_evsel *evsel)
@@ -854,14 +854,14 @@ static const char *fixunit(char *buf, struct perf_evsel *evsel,
 	return unit;
 }
 
-static void print_metric_only(struct perf_stat_config *config __maybe_unused,
+static void print_metric_only(struct perf_stat_config *config,
 			      void *ctx, const char *color, const char *fmt,
 			      const char *unit, double val)
 {
 	struct outstate *os = ctx;
 	FILE *out = os->fh;
 	char buf[1024], str[1024];
-	unsigned mlen = metric_only_len;
+	unsigned mlen = config->metric_only_len;
 
 	if (!valid_only_metric(unit))
 		return;
@@ -902,7 +902,7 @@ static void new_line_metric(struct perf_stat_config *config __maybe_unused,
 {
 }
 
-static void print_metric_header(struct perf_stat_config *config __maybe_unused,
+static void print_metric_header(struct perf_stat_config *config,
 				void *ctx, const char *color __maybe_unused,
 				const char *fmt __maybe_unused,
 				const char *unit, double val __maybe_unused)
@@ -916,7 +916,7 @@ static void print_metric_header(struct perf_stat_config *config __maybe_unused,
 	if (config->csv_output)
 		fprintf(os->fh, "%s%s", unit, config->csv_sep);
 	else
-		fprintf(os->fh, "%*s ", metric_only_len, unit);
+		fprintf(os->fh, "%*s ", config->metric_only_len, unit);
 }
 
 static int first_shadow_cpu(struct perf_evsel *evsel, int id)
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 351a36f5f5b0..e70e6d93ee1b 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -99,6 +99,7 @@ struct perf_stat_config {
 	unsigned int		 timeout;
 	unsigned int		 initial_delay;
 	unsigned int		 unit_width;
+	unsigned int		 metric_only_len;
 	int			 times;
 	int			 run_count;
 	struct runtime_stat	*stats;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 29/43] perf stat: Pass stat_config to first_shadow_cpu
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
                   ` (27 preceding siblings ...)
  2018-08-30  6:32 ` [PATCH 28/43] perf stat: Move metric_only_len into struct perf_stat_config Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:36   ` [tip:perf/core] perf stat: Pass 'struct perf_stat_config' to first_shadow_cpu() tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 30/43] perf stat: Pass evlist to aggr_update_shadow Jiri Olsa
                   ` (14 subsequent siblings)
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

Passing stat_config to first_shadow_cpu, so the function
does not depend on stat command object local stat_config
and can be moved out.

Link: http://lkml.kernel.org/n/tip-x9gryrm7evfb3uybq2pxcix6@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index e96cef526ef0..f5ac6545af34 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -919,17 +919,18 @@ static void print_metric_header(struct perf_stat_config *config,
 		fprintf(os->fh, "%*s ", config->metric_only_len, unit);
 }
 
-static int first_shadow_cpu(struct perf_evsel *evsel, int id)
+static int first_shadow_cpu(struct perf_stat_config *config,
+			    struct perf_evsel *evsel, int id)
 {
 	int i;
 
 	if (!aggr_get_id)
 		return 0;
 
-	if (stat_config.aggr_mode == AGGR_NONE)
+	if (config->aggr_mode == AGGR_NONE)
 		return id;
 
-	if (stat_config.aggr_mode == AGGR_GLOBAL)
+	if (config->aggr_mode == AGGR_GLOBAL)
 		return 0;
 
 	for (i = 0; i < perf_evsel__nr_cpus(evsel); i++) {
@@ -1090,7 +1091,7 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 	}
 
 	perf_stat__print_shadow_stats(config, counter, uval,
-				first_shadow_cpu(counter, id),
+				first_shadow_cpu(config, counter, id),
 				&out, &metric_events, st);
 	if (!config->csv_output && !config->metric_only) {
 		print_noise(config, counter, noise);
@@ -1098,7 +1099,7 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 	}
 }
 
-static void aggr_update_shadow(void)
+static void aggr_update_shadow(struct perf_stat_config *config)
 {
 	int cpu, s2, id, s;
 	u64 val;
@@ -1115,7 +1116,7 @@ static void aggr_update_shadow(void)
 				val += perf_counts(counter->counts, cpu, 0)->val;
 			}
 			perf_stat__update_shadow_stats(counter, val,
-					first_shadow_cpu(counter, id),
+					first_shadow_cpu(config, counter, id),
 					&rt_stat);
 		}
 	}
@@ -1237,7 +1238,7 @@ static void print_aggr(struct perf_stat_config *config,
 	if (!(aggr_map || aggr_get_id))
 		return;
 
-	aggr_update_shadow();
+	aggr_update_shadow(config);
 
 	/*
 	 * With metric_only everything is on a single line.
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 30/43] perf stat: Pass evlist to aggr_update_shadow
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
                   ` (28 preceding siblings ...)
  2018-08-30  6:32 ` [PATCH 29/43] perf stat: Pass stat_config to first_shadow_cpu Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:37   ` [tip:perf/core] perf stat: Pass 'evlist' to aggr_update_shadow() tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 31/43] perf stat: Add walltime_nsecs_stats pointer into struct perf_stat_config Jiri Olsa
                   ` (13 subsequent siblings)
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

Passing evlist to aggr_update_shadow,
to rid of the evsel_list dependency.

Link: http://lkml.kernel.org/n/tip-4xhx9wz6e4gua5q40dpj235y@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index f5ac6545af34..2711d8f6e4b8 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1099,7 +1099,8 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 	}
 }
 
-static void aggr_update_shadow(struct perf_stat_config *config)
+static void aggr_update_shadow(struct perf_stat_config *config,
+			       struct perf_evlist *evlist)
 {
 	int cpu, s2, id, s;
 	u64 val;
@@ -1107,7 +1108,7 @@ static void aggr_update_shadow(struct perf_stat_config *config)
 
 	for (s = 0; s < aggr_map->nr; s++) {
 		id = aggr_map->map[s];
-		evlist__for_each_entry(evsel_list, counter) {
+		evlist__for_each_entry(evlist, counter) {
 			val = 0;
 			for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
 				s2 = aggr_get_id(evsel_list->cpus, cpu);
@@ -1238,7 +1239,7 @@ static void print_aggr(struct perf_stat_config *config,
 	if (!(aggr_map || aggr_get_id))
 		return;
 
-	aggr_update_shadow(config);
+	aggr_update_shadow(config, evlist);
 
 	/*
 	 * With metric_only everything is on a single line.
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 31/43] perf stat: Add walltime_nsecs_stats pointer into struct perf_stat_config
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
                   ` (29 preceding siblings ...)
  2018-08-30  6:32 ` [PATCH 30/43] perf stat: Pass evlist to aggr_update_shadow Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:37   ` [tip:perf/core] perf stat: Add 'walltime_nsecs_stats' pointer to 'struct perf_stat_config' tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 32/43] perf stat: Move null_run into struct perf_stat_config Jiri Olsa
                   ` (12 subsequent siblings)
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

Adding walltime_nsecs_stats pointer into struct perf_stat_config,
so it can be passed around and used outside stat command.

It's initialized to point to stat's walltime_nsecs_stats value.

Link: http://lkml.kernel.org/n/tip-oxi6iqsmux5m4hmk8k1rwch4@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 15 ++++++++-------
 tools/perf/util/stat.h    |  1 +
 2 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 2711d8f6e4b8..381549a989b4 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -195,11 +195,12 @@ static struct perf_stat		perf_stat;
 static volatile int done = 0;
 
 static struct perf_stat_config stat_config = {
-	.aggr_mode	= AGGR_GLOBAL,
-	.scale		= true,
-	.unit_width	= 4, /* strlen("unit") */
-	.run_count	= 1,
-	.metric_only_len = METRIC_ONLY_LEN,
+	.aggr_mode		= AGGR_GLOBAL,
+	.scale			= true,
+	.unit_width		= 4, /* strlen("unit") */
+	.run_count		= 1,
+	.metric_only_len	= METRIC_ONLY_LEN,
+	.walltime_nsecs_stats	= &walltime_nsecs_stats,
 };
 
 static bool is_duration_time(struct perf_evsel *evsel)
@@ -1671,7 +1672,7 @@ static double timeval2double(struct timeval *t)
 
 static void print_footer(struct perf_stat_config *config)
 {
-	double avg = avg_stats(&walltime_nsecs_stats) / NSEC_PER_SEC;
+	double avg = avg_stats(config->walltime_nsecs_stats) / NSEC_PER_SEC;
 	FILE *output = config->output;
 	int n;
 
@@ -1690,7 +1691,7 @@ static void print_footer(struct perf_stat_config *config)
 			fprintf(output, " %17.9f seconds sys\n", ru_stime);
 		}
 	} else {
-		double sd = stddev_stats(&walltime_nsecs_stats) / NSEC_PER_SEC;
+		double sd = stddev_stats(config->walltime_nsecs_stats) / NSEC_PER_SEC;
 		/*
 		 * Display at most 2 more significant
 		 * digits than the stddev inaccuracy.
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index e70e6d93ee1b..35550e3efd81 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -105,6 +105,7 @@ struct perf_stat_config {
 	struct runtime_stat	*stats;
 	int			 stats_num;
 	const char		*csv_sep;
+	struct stats		*walltime_nsecs_stats;
 };
 
 void update_stats(struct stats *stats, u64 val);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 32/43] perf stat: Move null_run into struct perf_stat_config
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
                   ` (30 preceding siblings ...)
  2018-08-30  6:32 ` [PATCH 31/43] perf stat: Add walltime_nsecs_stats pointer into struct perf_stat_config Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:38   ` [tip:perf/core] perf stat: Move 'null_run' to 'struct perf_stat_config' tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 33/43] perf stat: Move print_free_counters_hint into struct perf_stat_config Jiri Olsa
                   ` (11 subsequent siblings)
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

Move static null_run into struct perf_stat_config,
so it can be passed around and used outside stat command.

Link: http://lkml.kernel.org/n/tip-cclahp2w949g9eg2ryl8ibd4@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 7 +++----
 tools/perf/util/stat.h    | 1 +
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 381549a989b4..844c755564e3 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -148,7 +148,6 @@ typedef int (*aggr_get_id_t)(struct cpu_map *m, int cpu);
 #define METRIC_ONLY_LEN 20
 
 static volatile pid_t		child_pid			= -1;
-static bool			null_run			=  false;
 static int			detailed_run			=  0;
 static bool			transaction_run;
 static bool			topdown_run			= false;
@@ -1676,7 +1675,7 @@ static void print_footer(struct perf_stat_config *config)
 	FILE *output = config->output;
 	int n;
 
-	if (!null_run)
+	if (!config->null_run)
 		fprintf(output, "\n");
 
 	if (config->run_count == 1) {
@@ -1894,7 +1893,7 @@ static const struct option stat_options[] = {
 		    "repeat command and print average + stddev (max: 100, forever: 0)"),
 	OPT_BOOLEAN(0, "table", &walltime_run_table,
 		    "display details about each run (only with -r option)"),
-	OPT_BOOLEAN('n', "null", &null_run,
+	OPT_BOOLEAN('n', "null", &stat_config.null_run,
 		    "null run - dont start any counters"),
 	OPT_INCR('d', "detailed", &detailed_run,
 		    "detailed run - start a lot of events"),
@@ -2309,7 +2308,7 @@ static int add_default_attributes(void)
 	struct parse_events_error errinfo;
 
 	/* Set attrs if no event is selected and !null_run: */
-	if (null_run)
+	if (stat_config.null_run)
 		return 0;
 
 	if (transaction_run) {
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 35550e3efd81..c198926c0e27 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -94,6 +94,7 @@ struct perf_stat_config {
 	bool			 csv_output;
 	bool			 interval_clear;
 	bool			 metric_only;
+	bool			 null_run;
 	FILE			*output;
 	unsigned int		 interval;
 	unsigned int		 timeout;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 33/43] perf stat: Move print_free_counters_hint into struct perf_stat_config
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
                   ` (31 preceding siblings ...)
  2018-08-30  6:32 ` [PATCH 32/43] perf stat: Move null_run into struct perf_stat_config Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:38   ` [tip:perf/core] perf stat: Move 'print_free_counters_hint' to 'struct perf_stat_config' tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 34/43] perf stat: Move print_mixed_hw_group_error into struct perf_stat_config Jiri Olsa
                   ` (10 subsequent siblings)
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

Moving print_free_counters_hint into struct perf_stat_config,
so it can be passed around and used outside stat command.

Link: http://lkml.kernel.org/n/tip-ksfkhgwoquxqrlryz8se3hen@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 5 ++---
 tools/perf/util/stat.h    | 1 +
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 844c755564e3..8748bb5e5403 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -170,7 +170,6 @@ static bool			append_file;
 static bool			interval_count;
 static const char		*output_name;
 static int			output_fd;
-static int			print_free_counters_hint;
 static int			print_mixed_hw_group_error;
 static u64			*walltime_run;
 static bool			ru_display			= false;
@@ -1051,7 +1050,7 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 			config->csv_sep);
 
 		if (counter->supported) {
-			print_free_counters_hint = 1;
+			config->print_free_counters_hint = 1;
 			if (is_mixed_hw_group(counter))
 				print_mixed_hw_group_error = 1;
 		}
@@ -1707,7 +1706,7 @@ static void print_footer(struct perf_stat_config *config)
 	}
 	fprintf(output, "\n\n");
 
-	if (print_free_counters_hint &&
+	if (config->print_free_counters_hint &&
 	    sysctl__read_int("kernel/nmi_watchdog", &n) >= 0 &&
 	    n > 0)
 		fprintf(output,
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index c198926c0e27..8cad17363e90 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -103,6 +103,7 @@ struct perf_stat_config {
 	unsigned int		 metric_only_len;
 	int			 times;
 	int			 run_count;
+	int			 print_free_counters_hint;
 	struct runtime_stat	*stats;
 	int			 stats_num;
 	const char		*csv_sep;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 34/43] perf stat: Move print_mixed_hw_group_error into struct perf_stat_config
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
                   ` (32 preceding siblings ...)
  2018-08-30  6:32 ` [PATCH 33/43] perf stat: Move print_free_counters_hint into struct perf_stat_config Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:39   ` [tip:perf/core] perf stat: Move 'print_mixed_hw_group_error' to 'struct perf_stat_config' tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 35/43] perf stat: Move ru_* data into struct perf_stat_config Jiri Olsa
                   ` (9 subsequent siblings)
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

Moving print_mixed_hw_group_error into struct perf_stat_config,
so it can be passed around and used outside stat command.

Link: http://lkml.kernel.org/n/tip-oz7f6n54ui1eilo9b67n0kk9@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 5 ++---
 tools/perf/util/stat.h    | 1 +
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 8748bb5e5403..f61c2dc8c7e8 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -170,7 +170,6 @@ static bool			append_file;
 static bool			interval_count;
 static const char		*output_name;
 static int			output_fd;
-static int			print_mixed_hw_group_error;
 static u64			*walltime_run;
 static bool			ru_display			= false;
 static struct rusage		ru_data;
@@ -1052,7 +1051,7 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 		if (counter->supported) {
 			config->print_free_counters_hint = 1;
 			if (is_mixed_hw_group(counter))
-				print_mixed_hw_group_error = 1;
+				config->print_mixed_hw_group_error = 1;
 		}
 
 		fprintf(config->output, "%-*s%s",
@@ -1715,7 +1714,7 @@ static void print_footer(struct perf_stat_config *config)
 "	perf stat ...\n"
 "	echo 1 > /proc/sys/kernel/nmi_watchdog\n");
 
-	if (print_mixed_hw_group_error)
+	if (config->print_mixed_hw_group_error)
 		fprintf(output,
 			"The events in group usually have to be from "
 			"the same PMU. Try reorganizing the group.\n");
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 8cad17363e90..6fb4dac26ccc 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -104,6 +104,7 @@ struct perf_stat_config {
 	int			 times;
 	int			 run_count;
 	int			 print_free_counters_hint;
+	int			 print_mixed_hw_group_error;
 	struct runtime_stat	*stats;
 	int			 stats_num;
 	const char		*csv_sep;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 35/43] perf stat: Move ru_* data into struct perf_stat_config
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
                   ` (33 preceding siblings ...)
  2018-08-30  6:32 ` [PATCH 34/43] perf stat: Move print_mixed_hw_group_error into struct perf_stat_config Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:39   ` [tip:perf/core] perf stat: Move ru_* data to 'struct perf_stat_config' tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 36/43] perf stat: Move *_aggr_* data into struct perf_stat_config Jiri Olsa
                   ` (8 subsequent siblings)
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

Moving ru_* data into struct perf_stat_config,
so it can be passed around and used outside stat command.

Link: http://lkml.kernel.org/n/tip-laaz6pbi1x4hicadbvf9ed9s@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 12 +++++-------
 tools/perf/util/stat.h    |  6 ++++++
 2 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index f61c2dc8c7e8..942ebfd8ef2e 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -171,8 +171,6 @@ static bool			interval_count;
 static const char		*output_name;
 static int			output_fd;
 static u64			*walltime_run;
-static bool			ru_display			= false;
-static struct rusage		ru_data;
 
 struct perf_stat {
 	bool			 record;
@@ -583,7 +581,7 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
 					break;
 			}
 		}
-		wait4(child_pid, &status, 0, &ru_data);
+		wait4(child_pid, &status, 0, &stat_config.ru_data);
 
 		if (workload_exec_errno) {
 			const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg));
@@ -1679,9 +1677,9 @@ static void print_footer(struct perf_stat_config *config)
 	if (config->run_count == 1) {
 		fprintf(output, " %17.9f seconds time elapsed", avg);
 
-		if (ru_display) {
-			double ru_utime = timeval2double(&ru_data.ru_utime);
-			double ru_stime = timeval2double(&ru_data.ru_stime);
+		if (config->ru_display) {
+			double ru_utime = timeval2double(&config->ru_data.ru_utime);
+			double ru_stime = timeval2double(&config->ru_data.ru_stime);
 
 			fprintf(output, "\n\n");
 			fprintf(output, " %17.9f seconds user\n", ru_utime);
@@ -2855,7 +2853,7 @@ int cmd_stat(int argc, const char **argv)
 	 * run and when there's specified tracee.
 	 */
 	if ((stat_config.run_count == 1) && target__none(&target))
-		ru_display = true;
+		stat_config.ru_display = true;
 
 	if (stat_config.run_count < 0) {
 		pr_err("Run count must be a positive number\n");
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 6fb4dac26ccc..1fd0b7e196c6 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -4,6 +4,10 @@
 
 #include <linux/types.h>
 #include <stdio.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
 #include "xyarray.h"
 #include "rblist.h"
 #include "perf.h"
@@ -95,6 +99,7 @@ struct perf_stat_config {
 	bool			 interval_clear;
 	bool			 metric_only;
 	bool			 null_run;
+	bool			 ru_display;
 	FILE			*output;
 	unsigned int		 interval;
 	unsigned int		 timeout;
@@ -109,6 +114,7 @@ struct perf_stat_config {
 	int			 stats_num;
 	const char		*csv_sep;
 	struct stats		*walltime_nsecs_stats;
+	struct rusage		 ru_data;
 };
 
 void update_stats(struct stats *stats, u64 val);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 36/43] perf stat: Move *_aggr_* data into struct perf_stat_config
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
                   ` (34 preceding siblings ...)
  2018-08-30  6:32 ` [PATCH 35/43] perf stat: Move ru_* data into struct perf_stat_config Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:40   ` [tip:perf/core] perf stat: Move *_aggr_* data to 'struct perf_stat_config' tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 37/43] perf stat: Do not use glovab evsel_list in print functions Jiri Olsa
                   ` (7 subsequent siblings)
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

Moving *_aggr_* data into struct perf_stat_config,
so it can be passed around and used outside stat command.

Link: http://lkml.kernel.org/n/tip-3z70bag45oyahf06loz984uo@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 112 ++++++++++++++++++++------------------
 tools/perf/util/stat.h    |   6 ++
 2 files changed, 64 insertions(+), 54 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 942ebfd8ef2e..2f606f76b66a 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -143,8 +143,6 @@ static struct target target = {
 	.uid	= UINT_MAX,
 };
 
-typedef int (*aggr_get_id_t)(struct cpu_map *m, int cpu);
-
 #define METRIC_ONLY_LEN 20
 
 static volatile pid_t		child_pid			= -1;
@@ -164,8 +162,6 @@ static bool			force_metric_only		= false;
 static bool			no_merge			= false;
 static bool			walltime_run_table		= false;
 static struct timespec		ref_time;
-static struct cpu_map		*aggr_map;
-static aggr_get_id_t		aggr_get_id;
 static bool			append_file;
 static bool			interval_count;
 static const char		*output_name;
@@ -920,7 +916,7 @@ static int first_shadow_cpu(struct perf_stat_config *config,
 {
 	int i;
 
-	if (!aggr_get_id)
+	if (!config->aggr_get_id)
 		return 0;
 
 	if (config->aggr_mode == AGGR_NONE)
@@ -932,7 +928,7 @@ static int first_shadow_cpu(struct perf_stat_config *config,
 	for (i = 0; i < perf_evsel__nr_cpus(evsel); i++) {
 		int cpu2 = perf_evsel__cpus(evsel)->map[i];
 
-		if (aggr_get_id(evsel_list->cpus, cpu2) == id)
+		if (config->aggr_get_id(config, evsel_list->cpus, cpu2) == id)
 			return cpu2;
 	}
 	return 0;
@@ -1102,12 +1098,12 @@ static void aggr_update_shadow(struct perf_stat_config *config,
 	u64 val;
 	struct perf_evsel *counter;
 
-	for (s = 0; s < aggr_map->nr; s++) {
-		id = aggr_map->map[s];
+	for (s = 0; s < config->aggr_map->nr; s++) {
+		id = config->aggr_map->map[s];
 		evlist__for_each_entry(evlist, counter) {
 			val = 0;
 			for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
-				s2 = aggr_get_id(evsel_list->cpus, cpu);
+				s2 = config->aggr_get_id(config, evsel_list->cpus, cpu);
 				if (s2 != id)
 					continue;
 				val += perf_counts(counter->counts, cpu, 0)->val;
@@ -1147,8 +1143,8 @@ static void uniquify_event_name(struct perf_evsel *counter)
 	counter->uniquified_name = true;
 }
 
-static void collect_all_aliases(struct perf_evsel *counter,
-			    void (*cb)(struct perf_evsel *counter, void *data,
+static void collect_all_aliases(struct perf_stat_config *config, struct perf_evsel *counter,
+			    void (*cb)(struct perf_stat_config *config, struct perf_evsel *counter, void *data,
 				       bool first),
 			    void *data)
 {
@@ -1164,22 +1160,22 @@ static void collect_all_aliases(struct perf_evsel *counter,
 		    perf_evsel__is_clock(alias) != perf_evsel__is_clock(counter))
 			break;
 		alias->merged_stat = true;
-		cb(alias, data, false);
+		cb(config, alias, data, false);
 	}
 }
 
-static bool collect_data(struct perf_evsel *counter,
-			    void (*cb)(struct perf_evsel *counter, void *data,
+static bool collect_data(struct perf_stat_config *config, struct perf_evsel *counter,
+			    void (*cb)(struct perf_stat_config *config, struct perf_evsel *counter, void *data,
 				       bool first),
 			    void *data)
 {
 	if (counter->merged_stat)
 		return false;
-	cb(counter, data, true);
+	cb(config, counter, data, true);
 	if (no_merge)
 		uniquify_event_name(counter);
 	else if (counter->auto_merge_stats)
-		collect_all_aliases(counter, cb, data);
+		collect_all_aliases(config, counter, cb, data);
 	return true;
 }
 
@@ -1190,7 +1186,8 @@ struct aggr_data {
 	int cpu;
 };
 
-static void aggr_cb(struct perf_evsel *counter, void *data, bool first)
+static void aggr_cb(struct perf_stat_config *config,
+		    struct perf_evsel *counter, void *data, bool first)
 {
 	struct aggr_data *ad = data;
 	int cpu, s2;
@@ -1198,7 +1195,7 @@ static void aggr_cb(struct perf_evsel *counter, void *data, bool first)
 	for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
 		struct perf_counts_values *counts;
 
-		s2 = aggr_get_id(perf_evsel__cpus(counter), cpu);
+		s2 = config->aggr_get_id(config, perf_evsel__cpus(counter), cpu);
 		if (s2 != ad->id)
 			continue;
 		if (first)
@@ -1232,7 +1229,7 @@ static void print_aggr(struct perf_stat_config *config,
 	u64 ena, run, val;
 	bool first;
 
-	if (!(aggr_map || aggr_get_id))
+	if (!(config->aggr_map || config->aggr_get_id))
 		return;
 
 	aggr_update_shadow(config, evlist);
@@ -1241,12 +1238,12 @@ static void print_aggr(struct perf_stat_config *config,
 	 * With metric_only everything is on a single line.
 	 * Without each counter has its own line.
 	 */
-	for (s = 0; s < aggr_map->nr; s++) {
+	for (s = 0; s < config->aggr_map->nr; s++) {
 		struct aggr_data ad;
 		if (prefix && metric_only)
 			fprintf(output, "%s", prefix);
 
-		ad.id = id = aggr_map->map[s];
+		ad.id = id = config->aggr_map->map[s];
 		first = true;
 		evlist__for_each_entry(evlist, counter) {
 			if (is_duration_time(counter))
@@ -1254,7 +1251,7 @@ static void print_aggr(struct perf_stat_config *config,
 
 			ad.val = ad.ena = ad.run = 0;
 			ad.nr = 0;
-			if (!collect_data(counter, aggr_cb, &ad))
+			if (!collect_data(config, counter, aggr_cb, &ad))
 				continue;
 			nr = ad.nr;
 			ena = ad.ena;
@@ -1370,7 +1367,8 @@ struct caggr_data {
 	double avg, avg_enabled, avg_running;
 };
 
-static void counter_aggr_cb(struct perf_evsel *counter, void *data,
+static void counter_aggr_cb(struct perf_stat_config *config __maybe_unused,
+			    struct perf_evsel *counter, void *data,
 			    bool first __maybe_unused)
 {
 	struct caggr_data *cd = data;
@@ -1393,7 +1391,7 @@ static void print_counter_aggr(struct perf_stat_config *config,
 	double uval;
 	struct caggr_data cd = { .avg = 0.0 };
 
-	if (!collect_data(counter, counter_aggr_cb, &cd))
+	if (!collect_data(config, counter, counter_aggr_cb, &cd))
 		return;
 
 	if (prefix && !metric_only)
@@ -1406,7 +1404,8 @@ static void print_counter_aggr(struct perf_stat_config *config,
 		fprintf(output, "\n");
 }
 
-static void counter_cb(struct perf_evsel *counter, void *data,
+static void counter_cb(struct perf_stat_config *config __maybe_unused,
+		       struct perf_evsel *counter, void *data,
 		       bool first __maybe_unused)
 {
 	struct aggr_data *ad = data;
@@ -1431,7 +1430,7 @@ static void print_counter(struct perf_stat_config *config,
 	for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
 		struct aggr_data ad = { .cpu = cpu };
 
-		if (!collect_data(counter, counter_cb, &ad))
+		if (!collect_data(config, counter, counter_cb, &ad))
 			return;
 		val = ad.val;
 		ena = ad.ena;
@@ -1944,12 +1943,14 @@ static const struct option stat_options[] = {
 	OPT_END()
 };
 
-static int perf_stat__get_socket(struct cpu_map *map, int cpu)
+static int perf_stat__get_socket(struct perf_stat_config *config __maybe_unused,
+				 struct cpu_map *map, int cpu)
 {
 	return cpu_map__get_socket(map, cpu, NULL);
 }
 
-static int perf_stat__get_core(struct cpu_map *map, int cpu)
+static int perf_stat__get_core(struct perf_stat_config *config __maybe_unused,
+			       struct cpu_map *map, int cpu)
 {
 	return cpu_map__get_core(map, cpu, NULL);
 }
@@ -1966,9 +1967,8 @@ static int cpu_map__get_max(struct cpu_map *map)
 	return max;
 }
 
-static struct cpu_map *cpus_aggr_map;
-
-static int perf_stat__get_aggr(aggr_get_id_t get_id, struct cpu_map *map, int idx)
+static int perf_stat__get_aggr(struct perf_stat_config *config,
+			       aggr_get_id_t get_id, struct cpu_map *map, int idx)
 {
 	int cpu;
 
@@ -1977,20 +1977,22 @@ static int perf_stat__get_aggr(aggr_get_id_t get_id, struct cpu_map *map, int id
 
 	cpu = map->map[idx];
 
-	if (cpus_aggr_map->map[cpu] == -1)
-		cpus_aggr_map->map[cpu] = get_id(map, idx);
+	if (config->cpus_aggr_map->map[cpu] == -1)
+		config->cpus_aggr_map->map[cpu] = get_id(config, map, idx);
 
-	return cpus_aggr_map->map[cpu];
+	return config->cpus_aggr_map->map[cpu];
 }
 
-static int perf_stat__get_socket_cached(struct cpu_map *map, int idx)
+static int perf_stat__get_socket_cached(struct perf_stat_config *config,
+					struct cpu_map *map, int idx)
 {
-	return perf_stat__get_aggr(perf_stat__get_socket, map, idx);
+	return perf_stat__get_aggr(config, perf_stat__get_socket, map, idx);
 }
 
-static int perf_stat__get_core_cached(struct cpu_map *map, int idx)
+static int perf_stat__get_core_cached(struct perf_stat_config *config,
+				      struct cpu_map *map, int idx)
 {
-	return perf_stat__get_aggr(perf_stat__get_core, map, idx);
+	return perf_stat__get_aggr(config, perf_stat__get_core, map, idx);
 }
 
 static int perf_stat_init_aggr_mode(void)
@@ -1999,18 +2001,18 @@ static int perf_stat_init_aggr_mode(void)
 
 	switch (stat_config.aggr_mode) {
 	case AGGR_SOCKET:
-		if (cpu_map__build_socket_map(evsel_list->cpus, &aggr_map)) {
+		if (cpu_map__build_socket_map(evsel_list->cpus, &stat_config.aggr_map)) {
 			perror("cannot build socket map");
 			return -1;
 		}
-		aggr_get_id = perf_stat__get_socket_cached;
+		stat_config.aggr_get_id = perf_stat__get_socket_cached;
 		break;
 	case AGGR_CORE:
-		if (cpu_map__build_core_map(evsel_list->cpus, &aggr_map)) {
+		if (cpu_map__build_core_map(evsel_list->cpus, &stat_config.aggr_map)) {
 			perror("cannot build core map");
 			return -1;
 		}
-		aggr_get_id = perf_stat__get_core_cached;
+		stat_config.aggr_get_id = perf_stat__get_core_cached;
 		break;
 	case AGGR_NONE:
 	case AGGR_GLOBAL:
@@ -2026,16 +2028,16 @@ static int perf_stat_init_aggr_mode(void)
 	 * the aggregation translate cpumap.
 	 */
 	nr = cpu_map__get_max(evsel_list->cpus);
-	cpus_aggr_map = cpu_map__empty_new(nr + 1);
-	return cpus_aggr_map ? 0 : -ENOMEM;
+	stat_config.cpus_aggr_map = cpu_map__empty_new(nr + 1);
+	return stat_config.cpus_aggr_map ? 0 : -ENOMEM;
 }
 
 static void perf_stat__exit_aggr_mode(void)
 {
-	cpu_map__put(aggr_map);
-	cpu_map__put(cpus_aggr_map);
-	aggr_map = NULL;
-	cpus_aggr_map = NULL;
+	cpu_map__put(stat_config.aggr_map);
+	cpu_map__put(stat_config.cpus_aggr_map);
+	stat_config.aggr_map = NULL;
+	stat_config.cpus_aggr_map = NULL;
 }
 
 static inline int perf_env__get_cpu(struct perf_env *env, struct cpu_map *map, int idx)
@@ -2093,12 +2095,14 @@ static int perf_env__build_core_map(struct perf_env *env, struct cpu_map *cpus,
 	return cpu_map__build_map(cpus, corep, perf_env__get_core, env);
 }
 
-static int perf_stat__get_socket_file(struct cpu_map *map, int idx)
+static int perf_stat__get_socket_file(struct perf_stat_config *config __maybe_unused,
+				      struct cpu_map *map, int idx)
 {
 	return perf_env__get_socket(map, idx, &perf_stat.session->header.env);
 }
 
-static int perf_stat__get_core_file(struct cpu_map *map, int idx)
+static int perf_stat__get_core_file(struct perf_stat_config *config __maybe_unused,
+				    struct cpu_map *map, int idx)
 {
 	return perf_env__get_core(map, idx, &perf_stat.session->header.env);
 }
@@ -2109,18 +2113,18 @@ static int perf_stat_init_aggr_mode_file(struct perf_stat *st)
 
 	switch (stat_config.aggr_mode) {
 	case AGGR_SOCKET:
-		if (perf_env__build_socket_map(env, evsel_list->cpus, &aggr_map)) {
+		if (perf_env__build_socket_map(env, evsel_list->cpus, &stat_config.aggr_map)) {
 			perror("cannot build socket map");
 			return -1;
 		}
-		aggr_get_id = perf_stat__get_socket_file;
+		stat_config.aggr_get_id = perf_stat__get_socket_file;
 		break;
 	case AGGR_CORE:
-		if (perf_env__build_core_map(env, evsel_list->cpus, &aggr_map)) {
+		if (perf_env__build_core_map(env, evsel_list->cpus, &stat_config.aggr_map)) {
 			perror("cannot build core map");
 			return -1;
 		}
-		aggr_get_id = perf_stat__get_core_file;
+		stat_config.aggr_get_id = perf_stat__get_core_file;
 		break;
 	case AGGR_NONE:
 	case AGGR_GLOBAL:
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 1fd0b7e196c6..be202b066e62 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -90,6 +90,9 @@ struct runtime_stat {
 	struct rblist value_list;
 };
 
+typedef int (*aggr_get_id_t)(struct perf_stat_config *config,
+			     struct cpu_map *m, int cpu);
+
 struct perf_stat_config {
 	enum aggr_mode		 aggr_mode;
 	bool			 scale;
@@ -115,6 +118,9 @@ struct perf_stat_config {
 	const char		*csv_sep;
 	struct stats		*walltime_nsecs_stats;
 	struct rusage		 ru_data;
+	struct cpu_map		*aggr_map;
+	aggr_get_id_t		 aggr_get_id;
+	struct cpu_map		*cpus_aggr_map;
 };
 
 void update_stats(struct stats *stats, u64 val);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 37/43] perf stat: Do not use glovab evsel_list in print functions
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
                   ` (35 preceding siblings ...)
  2018-08-30  6:32 ` [PATCH 36/43] perf stat: Move *_aggr_* data into struct perf_stat_config Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:40   ` [tip:perf/core] perf stat: Do not use the global 'evsel_list' " tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 38/43] perf stat: Move big_num data into struct perf_stat_config Jiri Olsa
                   ` (6 subsequent siblings)
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

Getting rid of the evsel_list dependency, here we can
use the evlist pointer from the event.

Link: http://lkml.kernel.org/n/tip-wpuv5hoprhgljvo3k0ngprsz@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 2f606f76b66a..445673f688de 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -914,6 +914,7 @@ static void print_metric_header(struct perf_stat_config *config,
 static int first_shadow_cpu(struct perf_stat_config *config,
 			    struct perf_evsel *evsel, int id)
 {
+	struct perf_evlist *evlist = evsel->evlist;
 	int i;
 
 	if (!config->aggr_get_id)
@@ -928,7 +929,7 @@ static int first_shadow_cpu(struct perf_stat_config *config,
 	for (i = 0; i < perf_evsel__nr_cpus(evsel); i++) {
 		int cpu2 = perf_evsel__cpus(evsel)->map[i];
 
-		if (config->aggr_get_id(config, evsel_list->cpus, cpu2) == id)
+		if (config->aggr_get_id(config, evlist->cpus, cpu2) == id)
 			return cpu2;
 	}
 	return 0;
@@ -1103,7 +1104,7 @@ static void aggr_update_shadow(struct perf_stat_config *config,
 		evlist__for_each_entry(evlist, counter) {
 			val = 0;
 			for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
-				s2 = config->aggr_get_id(config, evsel_list->cpus, cpu);
+				s2 = config->aggr_get_id(config, evlist->cpus, cpu);
 				if (s2 != id)
 					continue;
 				val += perf_counts(counter->counts, cpu, 0)->val;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 38/43] perf stat: Move big_num data into struct perf_stat_config
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
                   ` (36 preceding siblings ...)
  2018-08-30  6:32 ` [PATCH 37/43] perf stat: Do not use glovab evsel_list in print functions Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:41   ` [tip:perf/core] perf stat: Move 'big_num' data to 'struct perf_stat_config' tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 39/43] perf stat: Move no_merge data into struct perf_stat_config Jiri Olsa
                   ` (5 subsequent siblings)
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

Moving static big_num into struct perf_stat_config,
so it can be passed around and used outside stat command.

Link: http://lkml.kernel.org/n/tip-3z70bag45oyahf06loz984uo@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 8 ++++----
 tools/perf/util/stat.h    | 1 +
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 445673f688de..8ca85017a973 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -151,7 +151,6 @@ static bool			transaction_run;
 static bool			topdown_run			= false;
 static bool			smi_cost			= false;
 static bool			smi_reset			= false;
-static bool			big_num				=  true;
 static int			big_num_opt			=  -1;
 static bool			group				= false;
 static const char		*pre_cmd			= NULL;
@@ -192,6 +191,7 @@ static struct perf_stat_config stat_config = {
 	.run_count		= 1,
 	.metric_only_len	= METRIC_ONLY_LEN,
 	.walltime_nsecs_stats	= &walltime_nsecs_stats,
+	.big_num		= true,
 };
 
 static bool is_duration_time(struct perf_evsel *evsel)
@@ -945,7 +945,7 @@ static void abs_printout(struct perf_stat_config *config,
 	if (config->csv_output) {
 		fmt = floor(sc) != sc ?  "%.2f%s" : "%.0f%s";
 	} else {
-		if (big_num)
+		if (config->big_num)
 			fmt = floor(sc) != sc ? "%'18.2f%s" : "%'18.0f%s";
 		else
 			fmt = floor(sc) != sc ? "%18.2f%s" : "%18.0f%s";
@@ -2847,9 +2847,9 @@ int cmd_stat(int argc, const char **argv)
 			parse_options_usage(NULL, stat_options, "x", 1);
 			goto out;
 		} else /* Nope, so disable big number formatting */
-			big_num = false;
+			stat_config.big_num = false;
 	} else if (big_num_opt == 0) /* User passed --no-big-num */
-		big_num = false;
+		stat_config.big_num = false;
 
 	setup_system_wide(argc);
 
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index be202b066e62..843672214cca 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -103,6 +103,7 @@ struct perf_stat_config {
 	bool			 metric_only;
 	bool			 null_run;
 	bool			 ru_display;
+	bool			 big_num;
 	FILE			*output;
 	unsigned int		 interval;
 	unsigned int		 timeout;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 39/43] perf stat: Move no_merge data into struct perf_stat_config
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
                   ` (37 preceding siblings ...)
  2018-08-30  6:32 ` [PATCH 38/43] perf stat: Move big_num data into struct perf_stat_config Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:42   ` [tip:perf/core] perf stat: Move 'no_merge' data to 'struct perf_stat_config' tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 40/43] perf stat: Propagate struct target arg to sort_aggr_thread Jiri Olsa
                   ` (4 subsequent siblings)
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

Moving static no_merge into struct perf_stat_config, so
it can be passed around and used outside stat command.

Link: http://lkml.kernel.org/n/tip-d8iqln0d16fvrbqyf9polv6h@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 5 ++---
 tools/perf/util/stat.h    | 1 +
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 8ca85017a973..c4df076f1e54 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -158,7 +158,6 @@ static const char		*post_cmd			= NULL;
 static bool			sync_run			= false;
 static bool			forever				= false;
 static bool			force_metric_only		= false;
-static bool			no_merge			= false;
 static bool			walltime_run_table		= false;
 static struct timespec		ref_time;
 static bool			append_file;
@@ -1173,7 +1172,7 @@ static bool collect_data(struct perf_stat_config *config, struct perf_evsel *cou
 	if (counter->merged_stat)
 		return false;
 	cb(config, counter, data, true);
-	if (no_merge)
+	if (config->no_merge)
 		uniquify_event_name(counter);
 	else if (counter->auto_merge_stats)
 		collect_all_aliases(config, counter, cb, data);
@@ -1902,7 +1901,7 @@ static const struct option stat_options[] = {
 		    "list of cpus to monitor in system-wide"),
 	OPT_SET_UINT('A', "no-aggr", &stat_config.aggr_mode,
 		    "disable CPU count aggregation", AGGR_NONE),
-	OPT_BOOLEAN(0, "no-merge", &no_merge, "Do not merge identical named events"),
+	OPT_BOOLEAN(0, "no-merge", &stat_config.no_merge, "Do not merge identical named events"),
 	OPT_STRING('x', "field-separator", &stat_config.csv_sep, "separator",
 		   "print counts with custom separator"),
 	OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 843672214cca..0758107fe56f 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -104,6 +104,7 @@ struct perf_stat_config {
 	bool			 null_run;
 	bool			 ru_display;
 	bool			 big_num;
+	bool			 no_merge;
 	FILE			*output;
 	unsigned int		 interval;
 	unsigned int		 timeout;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 40/43] perf stat: Propagate struct target arg to sort_aggr_thread
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
                   ` (38 preceding siblings ...)
  2018-08-30  6:32 ` [PATCH 39/43] perf stat: Move no_merge data into struct perf_stat_config Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:42   ` [tip:perf/core] perf stat: Propagate 'struct target' arg to sort_aggr_thread() tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 41/43] perf stat: Move walltime_* data into struct perf_stat_config Jiri Olsa
                   ` (3 subsequent siblings)
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

Propagate struct target arg to sort_aggr_thread
so the function does not depend on stat command object
local target and can be moved out.

Link: http://lkml.kernel.org/n/tip-1q2zv8p9pwa3vddh2js3s9fo@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index c4df076f1e54..486b0cf7818d 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1284,7 +1284,8 @@ static int cmp_val(const void *a, const void *b)
 static struct perf_aggr_thread_value *sort_aggr_thread(
 					struct perf_evsel *counter,
 					int nthreads, int ncpus,
-					int *ret)
+					int *ret,
+					struct target *_target)
 {
 	int cpu, thread, i = 0;
 	double uval;
@@ -1309,7 +1310,7 @@ static struct perf_aggr_thread_value *sort_aggr_thread(
 		 * Skip value 0 when enabling --per-thread globally,
 		 * otherwise too many 0 output.
 		 */
-		if (uval == 0.0 && target__has_per_thread(&target))
+		if (uval == 0.0 && target__has_per_thread(_target))
 			continue;
 
 		buf[i].counter = counter;
@@ -1330,6 +1331,7 @@ static struct perf_aggr_thread_value *sort_aggr_thread(
 }
 
 static void print_aggr_thread(struct perf_stat_config *config,
+			      struct target *_target,
 			      struct perf_evsel *counter, char *prefix)
 {
 	FILE *output = config->output;
@@ -1338,7 +1340,7 @@ static void print_aggr_thread(struct perf_stat_config *config,
 	int thread, sorted_threads, id;
 	struct perf_aggr_thread_value *buf;
 
-	buf = sort_aggr_thread(counter, nthreads, ncpus, &sorted_threads);
+	buf = sort_aggr_thread(counter, nthreads, ncpus, &sorted_threads, _target);
 	if (!buf) {
 		perror("cannot sort aggr thread");
 		return;
@@ -1754,7 +1756,7 @@ perf_evlist__print_counters(struct perf_evlist *evlist,
 		evlist__for_each_entry(evlist, counter) {
 			if (is_duration_time(counter))
 				continue;
-			print_aggr_thread(config, counter, prefix);
+			print_aggr_thread(config, _target, counter, prefix);
 		}
 		break;
 	case AGGR_GLOBAL:
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 41/43] perf stat: Move walltime_* data into struct perf_stat_config
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
                   ` (39 preceding siblings ...)
  2018-08-30  6:32 ` [PATCH 40/43] perf stat: Propagate struct target arg to sort_aggr_thread Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:43   ` [tip:perf/core] perf stat: Move 'walltime_*' data to 'struct perf_stat_config' tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 42/43] perf stat: Move metric_events into struct perf_stat_config Jiri Olsa
                   ` (2 subsequent siblings)
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

Moving static walltime_* data into struct perf_stat_config,
so it can be passed around and used outside stat command.

Link: http://lkml.kernel.org/n/tip-ymexory86fsla7n1yvy8tqfa@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 22 ++++++++++------------
 tools/perf/util/stat.h    |  2 ++
 2 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 486b0cf7818d..8a4979748cbb 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -158,13 +158,11 @@ static const char		*post_cmd			= NULL;
 static bool			sync_run			= false;
 static bool			forever				= false;
 static bool			force_metric_only		= false;
-static bool			walltime_run_table		= false;
 static struct timespec		ref_time;
 static bool			append_file;
 static bool			interval_count;
 static const char		*output_name;
 static int			output_fd;
-static u64			*walltime_run;
 
 struct perf_stat {
 	bool			 record;
@@ -604,8 +602,8 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
 
 	t1 = rdclock();
 
-	if (walltime_run_table)
-		walltime_run[run_idx] = t1 - t0;
+	if (stat_config.walltime_run_table)
+		stat_config.walltime_run[run_idx] = t1 - t0;
 
 	update_stats(&walltime_nsecs_stats, t1 - t0);
 
@@ -1646,7 +1644,7 @@ static void print_table(struct perf_stat_config *config,
 	fprintf(output, "%*s# Table of individual measurements:\n", indent, "");
 
 	for (idx = 0; idx < config->run_count; idx++) {
-		double run = (double) walltime_run[idx] / NSEC_PER_SEC;
+		double run = (double) config->walltime_run[idx] / NSEC_PER_SEC;
 		int h, n = 1 + abs((int) (100.0 * (run - avg)/run) / 5);
 
 		fprintf(output, " %17.*f (%+.*f) ",
@@ -1694,7 +1692,7 @@ static void print_footer(struct perf_stat_config *config)
 		 */
 		int precision = get_precision(sd) + 2;
 
-		if (walltime_run_table)
+		if (config->walltime_run_table)
 			print_table(config, output, precision, avg);
 
 		fprintf(output, " %17.*f +- %.*f seconds time elapsed",
@@ -1888,7 +1886,7 @@ static const struct option stat_options[] = {
 		    "be more verbose (show counter open errors, etc)"),
 	OPT_INTEGER('r', "repeat", &stat_config.run_count,
 		    "repeat command and print average + stddev (max: 100, forever: 0)"),
-	OPT_BOOLEAN(0, "table", &walltime_run_table,
+	OPT_BOOLEAN(0, "table", &stat_config.walltime_run_table,
 		    "display details about each run (only with -r option)"),
 	OPT_BOOLEAN('n', "null", &stat_config.null_run,
 		    "null run - dont start any counters"),
@@ -2802,7 +2800,7 @@ int cmd_stat(int argc, const char **argv)
 		goto out;
 	}
 
-	if (walltime_run_table && stat_config.run_count <= 1) {
+	if (stat_config.walltime_run_table && stat_config.run_count <= 1) {
 		fprintf(stderr, "--table is only supported with -r\n");
 		parse_options_usage(stat_usage, stat_options, "r", 1);
 		parse_options_usage(NULL, stat_options, "table", 0);
@@ -2870,9 +2868,9 @@ int cmd_stat(int argc, const char **argv)
 		stat_config.run_count = 1;
 	}
 
-	if (walltime_run_table) {
-		walltime_run = zalloc(stat_config.run_count * sizeof(walltime_run[0]));
-		if (!walltime_run) {
+	if (stat_config.walltime_run_table) {
+		stat_config.walltime_run = zalloc(stat_config.run_count * sizeof(stat_config.walltime_run[0]));
+		if (!stat_config.walltime_run) {
 			pr_err("failed to setup -r option");
 			goto out;
 		}
@@ -3052,7 +3050,7 @@ int cmd_stat(int argc, const char **argv)
 	perf_stat__exit_aggr_mode();
 	perf_evlist__free_stats(evsel_list);
 out:
-	free(walltime_run);
+	free(stat_config.walltime_run);
 
 	if (smi_cost && smi_reset)
 		sysfs__write_int(FREEZE_ON_SMI_PATH, 0);
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 0758107fe56f..5193cbf6e4c6 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -105,6 +105,7 @@ struct perf_stat_config {
 	bool			 ru_display;
 	bool			 big_num;
 	bool			 no_merge;
+	bool			 walltime_run_table;
 	FILE			*output;
 	unsigned int		 interval;
 	unsigned int		 timeout;
@@ -123,6 +124,7 @@ struct perf_stat_config {
 	struct cpu_map		*aggr_map;
 	aggr_get_id_t		 aggr_get_id;
 	struct cpu_map		*cpus_aggr_map;
+	u64			*walltime_run;
 };
 
 void update_stats(struct stats *stats, u64 val);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 42/43] perf stat: Move metric_events into struct perf_stat_config
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
                   ` (40 preceding siblings ...)
  2018-08-30  6:32 ` [PATCH 41/43] perf stat: Move walltime_* data into struct perf_stat_config Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:43   ` [tip:perf/core] perf stat: Move 'metric_events' to 'struct perf_stat_config' tip-bot for Jiri Olsa
  2018-08-30  6:32 ` [PATCH 43/43] perf stat: Move display functions into stat-display.c Jiri Olsa
  2018-08-30 17:54 ` [PATCH 00/43] perf stat: Make some of the stat code generic Arnaldo Carvalho de Melo
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

Moving static metric_events into struct perf_stat_config,
so it can be passed around and used outside stat command.

Link: http://lkml.kernel.org/n/tip-3yq5yfji3xlcp2khtioegmpp@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 10 ++++------
 tools/perf/util/stat.h    |  1 +
 2 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 8a4979748cbb..f4ddedc8619b 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -137,8 +137,6 @@ static const char *smi_cost_attrs = {
 
 static struct perf_evlist	*evsel_list;
 
-static struct rblist		 metric_events;
-
 static struct target target = {
 	.uid	= UINT_MAX,
 };
@@ -1082,7 +1080,7 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 
 	perf_stat__print_shadow_stats(config, counter, uval,
 				first_shadow_cpu(config, counter, id),
-				&out, &metric_events, st);
+				&out, &config->metric_events, st);
 	if (!config->csv_output && !config->metric_only) {
 		print_noise(config, counter, noise);
 		print_running(config, run, ena);
@@ -1533,7 +1531,7 @@ static void print_metric_headers(struct perf_stat_config *config,
 		perf_stat__print_shadow_stats(config, counter, 0,
 					      0,
 					      &out,
-					      &metric_events,
+					      &config->metric_events,
 					      &rt_stat);
 	}
 	fputc('\n', config->output);
@@ -1860,7 +1858,7 @@ static int parse_metric_groups(const struct option *opt,
 			       const char *str,
 			       int unset __maybe_unused)
 {
-	return metricgroup__parse_groups(opt, str, &metric_events);
+	return metricgroup__parse_groups(opt, str, &stat_config.metric_events);
 }
 
 static const struct option stat_options[] = {
@@ -2321,7 +2319,7 @@ static int add_default_attributes(void)
 			struct option opt = { .value = &evsel_list };
 
 			return metricgroup__parse_groups(&opt, "transaction",
-							 &metric_events);
+							 &stat_config.metric_events);
 		}
 
 		if (pmu_have_event("cpu", "cycles-ct") &&
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 5193cbf6e4c6..8d3354e21e19 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -125,6 +125,7 @@ struct perf_stat_config {
 	aggr_get_id_t		 aggr_get_id;
 	struct cpu_map		*cpus_aggr_map;
 	u64			*walltime_run;
+	struct rblist		 metric_events;
 };
 
 void update_stats(struct stats *stats, u64 val);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [PATCH 43/43] perf stat: Move display functions into stat-display.c
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
                   ` (41 preceding siblings ...)
  2018-08-30  6:32 ` [PATCH 42/43] perf stat: Move metric_events into struct perf_stat_config Jiri Olsa
@ 2018-08-30  6:32 ` Jiri Olsa
  2018-09-06 13:44   ` [tip:perf/core] perf stat: Move the display functions to stat-display.c tip-bot for Jiri Olsa
  2018-08-30 17:54 ` [PATCH 00/43] perf stat: Make some of the stat code generic Arnaldo Carvalho de Melo
  43 siblings, 1 reply; 88+ messages in thread
From: Jiri Olsa @ 2018-08-30  6:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

Moving perf_evlist__print_counters function with all its
dependency functions to stat-display.c object.

Link: http://lkml.kernel.org/n/tip-illv2t5x1amh8z506nxp7z7b@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c      | 1150 -------------------------------
 tools/perf/util/Build          |    1 +
 tools/perf/util/stat-display.c | 1166 ++++++++++++++++++++++++++++++++
 tools/perf/util/stat.h         |    6 +
 4 files changed, 1173 insertions(+), 1150 deletions(-)
 create mode 100644 tools/perf/util/stat-display.c

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index f4ddedc8619b..0b0e3961d511 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -88,8 +88,6 @@
 #include "sane_ctype.h"
 
 #define DEFAULT_SEPARATOR	" "
-#define CNTR_NOT_SUPPORTED	"<not supported>"
-#define CNTR_NOT_COUNTED	"<not counted>"
 #define FREEZE_ON_SMI_PATH	"devices/cpu/freeze_on_smi"
 
 static void print_counters(struct timespec *ts, int argc, const char **argv);
@@ -189,11 +187,6 @@ static struct perf_stat_config stat_config = {
 	.big_num		= true,
 };
 
-static bool is_duration_time(struct perf_evsel *evsel)
-{
-	return !strcmp(evsel->name, "duration_time");
-}
-
 static inline void diff_timespec(struct timespec *r, struct timespec *a,
 				 struct timespec *b)
 {
@@ -643,1149 +636,6 @@ static int run_perf_stat(int argc, const char **argv, int run_idx)
 	return ret;
 }
 
-static void print_running(struct perf_stat_config *config,
-			  u64 run, u64 ena)
-{
-	if (config->csv_output) {
-		fprintf(config->output, "%s%" PRIu64 "%s%.2f",
-					config->csv_sep,
-					run,
-					config->csv_sep,
-					ena ? 100.0 * run / ena : 100.0);
-	} else if (run != ena) {
-		fprintf(config->output, "  (%.2f%%)", 100.0 * run / ena);
-	}
-}
-
-static void print_noise_pct(struct perf_stat_config *config,
-			    double total, double avg)
-{
-	double pct = rel_stddev_stats(total, avg);
-
-	if (config->csv_output)
-		fprintf(config->output, "%s%.2f%%", config->csv_sep, pct);
-	else if (pct)
-		fprintf(config->output, "  ( +-%6.2f%% )", pct);
-}
-
-static void print_noise(struct perf_stat_config *config,
-			struct perf_evsel *evsel, double avg)
-{
-	struct perf_stat_evsel *ps;
-
-	if (config->run_count == 1)
-		return;
-
-	ps = evsel->stats;
-	print_noise_pct(config, stddev_stats(&ps->res_stats[0]), avg);
-}
-
-static void aggr_printout(struct perf_stat_config *config,
-			  struct perf_evsel *evsel, int id, int nr)
-{
-	switch (config->aggr_mode) {
-	case AGGR_CORE:
-		fprintf(config->output, "S%d-C%*d%s%*d%s",
-			cpu_map__id_to_socket(id),
-			config->csv_output ? 0 : -8,
-			cpu_map__id_to_cpu(id),
-			config->csv_sep,
-			config->csv_output ? 0 : 4,
-			nr,
-			config->csv_sep);
-		break;
-	case AGGR_SOCKET:
-		fprintf(config->output, "S%*d%s%*d%s",
-			config->csv_output ? 0 : -5,
-			id,
-			config->csv_sep,
-			config->csv_output ? 0 : 4,
-			nr,
-			config->csv_sep);
-			break;
-	case AGGR_NONE:
-		fprintf(config->output, "CPU%*d%s",
-			config->csv_output ? 0 : -4,
-			perf_evsel__cpus(evsel)->map[id], config->csv_sep);
-		break;
-	case AGGR_THREAD:
-		fprintf(config->output, "%*s-%*d%s",
-			config->csv_output ? 0 : 16,
-			thread_map__comm(evsel->threads, id),
-			config->csv_output ? 0 : -8,
-			thread_map__pid(evsel->threads, id),
-			config->csv_sep);
-		break;
-	case AGGR_GLOBAL:
-	case AGGR_UNSET:
-	default:
-		break;
-	}
-}
-
-struct outstate {
-	FILE *fh;
-	bool newline;
-	const char *prefix;
-	int  nfields;
-	int  id, nr;
-	struct perf_evsel *evsel;
-};
-
-#define METRIC_LEN  35
-
-static void new_line_std(struct perf_stat_config *config __maybe_unused,
-			 void *ctx)
-{
-	struct outstate *os = ctx;
-
-	os->newline = true;
-}
-
-static void do_new_line_std(struct perf_stat_config *config,
-			    struct outstate *os)
-{
-	fputc('\n', os->fh);
-	fputs(os->prefix, os->fh);
-	aggr_printout(config, os->evsel, os->id, os->nr);
-	if (config->aggr_mode == AGGR_NONE)
-		fprintf(os->fh, "        ");
-	fprintf(os->fh, "                                                 ");
-}
-
-static void print_metric_std(struct perf_stat_config *config,
-			     void *ctx, const char *color, const char *fmt,
-			     const char *unit, double val)
-{
-	struct outstate *os = ctx;
-	FILE *out = os->fh;
-	int n;
-	bool newline = os->newline;
-
-	os->newline = false;
-
-	if (unit == NULL || fmt == NULL) {
-		fprintf(out, "%-*s", METRIC_LEN, "");
-		return;
-	}
-
-	if (newline)
-		do_new_line_std(config, os);
-
-	n = fprintf(out, " # ");
-	if (color)
-		n += color_fprintf(out, color, fmt, val);
-	else
-		n += fprintf(out, fmt, val);
-	fprintf(out, " %-*s", METRIC_LEN - n - 1, unit);
-}
-
-static void new_line_csv(struct perf_stat_config *config, void *ctx)
-{
-	struct outstate *os = ctx;
-	int i;
-
-	fputc('\n', os->fh);
-	if (os->prefix)
-		fprintf(os->fh, "%s%s", os->prefix, config->csv_sep);
-	aggr_printout(config, os->evsel, os->id, os->nr);
-	for (i = 0; i < os->nfields; i++)
-		fputs(config->csv_sep, os->fh);
-}
-
-static void print_metric_csv(struct perf_stat_config *config __maybe_unused,
-			     void *ctx,
-			     const char *color __maybe_unused,
-			     const char *fmt, const char *unit, double val)
-{
-	struct outstate *os = ctx;
-	FILE *out = os->fh;
-	char buf[64], *vals, *ends;
-
-	if (unit == NULL || fmt == NULL) {
-		fprintf(out, "%s%s", config->csv_sep, config->csv_sep);
-		return;
-	}
-	snprintf(buf, sizeof(buf), fmt, val);
-	ends = vals = ltrim(buf);
-	while (isdigit(*ends) || *ends == '.')
-		ends++;
-	*ends = 0;
-	while (isspace(*unit))
-		unit++;
-	fprintf(out, "%s%s%s%s", config->csv_sep, vals, config->csv_sep, unit);
-}
-
-/* Filter out some columns that don't work well in metrics only mode */
-
-static bool valid_only_metric(const char *unit)
-{
-	if (!unit)
-		return false;
-	if (strstr(unit, "/sec") ||
-	    strstr(unit, "hz") ||
-	    strstr(unit, "Hz") ||
-	    strstr(unit, "CPUs utilized"))
-		return false;
-	return true;
-}
-
-static const char *fixunit(char *buf, struct perf_evsel *evsel,
-			   const char *unit)
-{
-	if (!strncmp(unit, "of all", 6)) {
-		snprintf(buf, 1024, "%s %s", perf_evsel__name(evsel),
-			 unit);
-		return buf;
-	}
-	return unit;
-}
-
-static void print_metric_only(struct perf_stat_config *config,
-			      void *ctx, const char *color, const char *fmt,
-			      const char *unit, double val)
-{
-	struct outstate *os = ctx;
-	FILE *out = os->fh;
-	char buf[1024], str[1024];
-	unsigned mlen = config->metric_only_len;
-
-	if (!valid_only_metric(unit))
-		return;
-	unit = fixunit(buf, os->evsel, unit);
-	if (mlen < strlen(unit))
-		mlen = strlen(unit) + 1;
-
-	if (color)
-		mlen += strlen(color) + sizeof(PERF_COLOR_RESET) - 1;
-
-	color_snprintf(str, sizeof(str), color ?: "", fmt, val);
-	fprintf(out, "%*s ", mlen, str);
-}
-
-static void print_metric_only_csv(struct perf_stat_config *config __maybe_unused,
-				  void *ctx, const char *color __maybe_unused,
-				  const char *fmt,
-				  const char *unit, double val)
-{
-	struct outstate *os = ctx;
-	FILE *out = os->fh;
-	char buf[64], *vals, *ends;
-	char tbuf[1024];
-
-	if (!valid_only_metric(unit))
-		return;
-	unit = fixunit(tbuf, os->evsel, unit);
-	snprintf(buf, sizeof buf, fmt, val);
-	ends = vals = ltrim(buf);
-	while (isdigit(*ends) || *ends == '.')
-		ends++;
-	*ends = 0;
-	fprintf(out, "%s%s", vals, config->csv_sep);
-}
-
-static void new_line_metric(struct perf_stat_config *config __maybe_unused,
-			    void *ctx __maybe_unused)
-{
-}
-
-static void print_metric_header(struct perf_stat_config *config,
-				void *ctx, const char *color __maybe_unused,
-				const char *fmt __maybe_unused,
-				const char *unit, double val __maybe_unused)
-{
-	struct outstate *os = ctx;
-	char tbuf[1024];
-
-	if (!valid_only_metric(unit))
-		return;
-	unit = fixunit(tbuf, os->evsel, unit);
-	if (config->csv_output)
-		fprintf(os->fh, "%s%s", unit, config->csv_sep);
-	else
-		fprintf(os->fh, "%*s ", config->metric_only_len, unit);
-}
-
-static int first_shadow_cpu(struct perf_stat_config *config,
-			    struct perf_evsel *evsel, int id)
-{
-	struct perf_evlist *evlist = evsel->evlist;
-	int i;
-
-	if (!config->aggr_get_id)
-		return 0;
-
-	if (config->aggr_mode == AGGR_NONE)
-		return id;
-
-	if (config->aggr_mode == AGGR_GLOBAL)
-		return 0;
-
-	for (i = 0; i < perf_evsel__nr_cpus(evsel); i++) {
-		int cpu2 = perf_evsel__cpus(evsel)->map[i];
-
-		if (config->aggr_get_id(config, evlist->cpus, cpu2) == id)
-			return cpu2;
-	}
-	return 0;
-}
-
-static void abs_printout(struct perf_stat_config *config,
-			 int id, int nr, struct perf_evsel *evsel, double avg)
-{
-	FILE *output = config->output;
-	double sc =  evsel->scale;
-	const char *fmt;
-
-	if (config->csv_output) {
-		fmt = floor(sc) != sc ?  "%.2f%s" : "%.0f%s";
-	} else {
-		if (config->big_num)
-			fmt = floor(sc) != sc ? "%'18.2f%s" : "%'18.0f%s";
-		else
-			fmt = floor(sc) != sc ? "%18.2f%s" : "%18.0f%s";
-	}
-
-	aggr_printout(config, evsel, id, nr);
-
-	fprintf(output, fmt, avg, config->csv_sep);
-
-	if (evsel->unit)
-		fprintf(output, "%-*s%s",
-			config->csv_output ? 0 : config->unit_width,
-			evsel->unit, config->csv_sep);
-
-	fprintf(output, "%-*s", config->csv_output ? 0 : 25, perf_evsel__name(evsel));
-
-	if (evsel->cgrp)
-		fprintf(output, "%s%s", config->csv_sep, evsel->cgrp->name);
-}
-
-static bool is_mixed_hw_group(struct perf_evsel *counter)
-{
-	struct perf_evlist *evlist = counter->evlist;
-	u32 pmu_type = counter->attr.type;
-	struct perf_evsel *pos;
-
-	if (counter->nr_members < 2)
-		return false;
-
-	evlist__for_each_entry(evlist, pos) {
-		/* software events can be part of any hardware group */
-		if (pos->attr.type == PERF_TYPE_SOFTWARE)
-			continue;
-		if (pmu_type == PERF_TYPE_SOFTWARE) {
-			pmu_type = pos->attr.type;
-			continue;
-		}
-		if (pmu_type != pos->attr.type)
-			return true;
-	}
-
-	return false;
-}
-
-static void printout(struct perf_stat_config *config, int id, int nr,
-		     struct perf_evsel *counter, double uval,
-		     char *prefix, u64 run, u64 ena, double noise,
-		     struct runtime_stat *st)
-{
-	struct perf_stat_output_ctx out;
-	struct outstate os = {
-		.fh = config->output,
-		.prefix = prefix ? prefix : "",
-		.id = id,
-		.nr = nr,
-		.evsel = counter,
-	};
-	print_metric_t pm = print_metric_std;
-	new_line_t nl;
-
-	if (config->metric_only) {
-		nl = new_line_metric;
-		if (config->csv_output)
-			pm = print_metric_only_csv;
-		else
-			pm = print_metric_only;
-	} else
-		nl = new_line_std;
-
-	if (config->csv_output && !config->metric_only) {
-		static int aggr_fields[] = {
-			[AGGR_GLOBAL] = 0,
-			[AGGR_THREAD] = 1,
-			[AGGR_NONE] = 1,
-			[AGGR_SOCKET] = 2,
-			[AGGR_CORE] = 2,
-		};
-
-		pm = print_metric_csv;
-		nl = new_line_csv;
-		os.nfields = 3;
-		os.nfields += aggr_fields[config->aggr_mode];
-		if (counter->cgrp)
-			os.nfields++;
-	}
-	if (run == 0 || ena == 0 || counter->counts->scaled == -1) {
-		if (config->metric_only) {
-			pm(config, &os, NULL, "", "", 0);
-			return;
-		}
-		aggr_printout(config, counter, id, nr);
-
-		fprintf(config->output, "%*s%s",
-			config->csv_output ? 0 : 18,
-			counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
-			config->csv_sep);
-
-		if (counter->supported) {
-			config->print_free_counters_hint = 1;
-			if (is_mixed_hw_group(counter))
-				config->print_mixed_hw_group_error = 1;
-		}
-
-		fprintf(config->output, "%-*s%s",
-			config->csv_output ? 0 : config->unit_width,
-			counter->unit, config->csv_sep);
-
-		fprintf(config->output, "%*s",
-			config->csv_output ? 0 : -25,
-			perf_evsel__name(counter));
-
-		if (counter->cgrp)
-			fprintf(config->output, "%s%s",
-				config->csv_sep, counter->cgrp->name);
-
-		if (!config->csv_output)
-			pm(config, &os, NULL, NULL, "", 0);
-		print_noise(config, counter, noise);
-		print_running(config, run, ena);
-		if (config->csv_output)
-			pm(config, &os, NULL, NULL, "", 0);
-		return;
-	}
-
-	if (!config->metric_only)
-		abs_printout(config, id, nr, counter, uval);
-
-	out.print_metric = pm;
-	out.new_line = nl;
-	out.ctx = &os;
-	out.force_header = false;
-
-	if (config->csv_output && !config->metric_only) {
-		print_noise(config, counter, noise);
-		print_running(config, run, ena);
-	}
-
-	perf_stat__print_shadow_stats(config, counter, uval,
-				first_shadow_cpu(config, counter, id),
-				&out, &config->metric_events, st);
-	if (!config->csv_output && !config->metric_only) {
-		print_noise(config, counter, noise);
-		print_running(config, run, ena);
-	}
-}
-
-static void aggr_update_shadow(struct perf_stat_config *config,
-			       struct perf_evlist *evlist)
-{
-	int cpu, s2, id, s;
-	u64 val;
-	struct perf_evsel *counter;
-
-	for (s = 0; s < config->aggr_map->nr; s++) {
-		id = config->aggr_map->map[s];
-		evlist__for_each_entry(evlist, counter) {
-			val = 0;
-			for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
-				s2 = config->aggr_get_id(config, evlist->cpus, cpu);
-				if (s2 != id)
-					continue;
-				val += perf_counts(counter->counts, cpu, 0)->val;
-			}
-			perf_stat__update_shadow_stats(counter, val,
-					first_shadow_cpu(config, counter, id),
-					&rt_stat);
-		}
-	}
-}
-
-static void uniquify_event_name(struct perf_evsel *counter)
-{
-	char *new_name;
-	char *config;
-
-	if (counter->uniquified_name ||
-	    !counter->pmu_name || !strncmp(counter->name, counter->pmu_name,
-					   strlen(counter->pmu_name)))
-		return;
-
-	config = strchr(counter->name, '/');
-	if (config) {
-		if (asprintf(&new_name,
-			     "%s%s", counter->pmu_name, config) > 0) {
-			free(counter->name);
-			counter->name = new_name;
-		}
-	} else {
-		if (asprintf(&new_name,
-			     "%s [%s]", counter->name, counter->pmu_name) > 0) {
-			free(counter->name);
-			counter->name = new_name;
-		}
-	}
-
-	counter->uniquified_name = true;
-}
-
-static void collect_all_aliases(struct perf_stat_config *config, struct perf_evsel *counter,
-			    void (*cb)(struct perf_stat_config *config, struct perf_evsel *counter, void *data,
-				       bool first),
-			    void *data)
-{
-	struct perf_evlist *evlist = counter->evlist;
-	struct perf_evsel *alias;
-
-	alias = list_prepare_entry(counter, &(evlist->entries), node);
-	list_for_each_entry_continue (alias, &evlist->entries, node) {
-		if (strcmp(perf_evsel__name(alias), perf_evsel__name(counter)) ||
-		    alias->scale != counter->scale ||
-		    alias->cgrp != counter->cgrp ||
-		    strcmp(alias->unit, counter->unit) ||
-		    perf_evsel__is_clock(alias) != perf_evsel__is_clock(counter))
-			break;
-		alias->merged_stat = true;
-		cb(config, alias, data, false);
-	}
-}
-
-static bool collect_data(struct perf_stat_config *config, struct perf_evsel *counter,
-			    void (*cb)(struct perf_stat_config *config, struct perf_evsel *counter, void *data,
-				       bool first),
-			    void *data)
-{
-	if (counter->merged_stat)
-		return false;
-	cb(config, counter, data, true);
-	if (config->no_merge)
-		uniquify_event_name(counter);
-	else if (counter->auto_merge_stats)
-		collect_all_aliases(config, counter, cb, data);
-	return true;
-}
-
-struct aggr_data {
-	u64 ena, run, val;
-	int id;
-	int nr;
-	int cpu;
-};
-
-static void aggr_cb(struct perf_stat_config *config,
-		    struct perf_evsel *counter, void *data, bool first)
-{
-	struct aggr_data *ad = data;
-	int cpu, s2;
-
-	for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
-		struct perf_counts_values *counts;
-
-		s2 = config->aggr_get_id(config, perf_evsel__cpus(counter), cpu);
-		if (s2 != ad->id)
-			continue;
-		if (first)
-			ad->nr++;
-		counts = perf_counts(counter->counts, cpu, 0);
-		/*
-		 * When any result is bad, make them all to give
-		 * consistent output in interval mode.
-		 */
-		if (counts->ena == 0 || counts->run == 0 ||
-		    counter->counts->scaled == -1) {
-			ad->ena = 0;
-			ad->run = 0;
-			break;
-		}
-		ad->val += counts->val;
-		ad->ena += counts->ena;
-		ad->run += counts->run;
-	}
-}
-
-static void print_aggr(struct perf_stat_config *config,
-		       struct perf_evlist *evlist,
-		       char *prefix)
-{
-	bool metric_only = config->metric_only;
-	FILE *output = config->output;
-	struct perf_evsel *counter;
-	int s, id, nr;
-	double uval;
-	u64 ena, run, val;
-	bool first;
-
-	if (!(config->aggr_map || config->aggr_get_id))
-		return;
-
-	aggr_update_shadow(config, evlist);
-
-	/*
-	 * With metric_only everything is on a single line.
-	 * Without each counter has its own line.
-	 */
-	for (s = 0; s < config->aggr_map->nr; s++) {
-		struct aggr_data ad;
-		if (prefix && metric_only)
-			fprintf(output, "%s", prefix);
-
-		ad.id = id = config->aggr_map->map[s];
-		first = true;
-		evlist__for_each_entry(evlist, counter) {
-			if (is_duration_time(counter))
-				continue;
-
-			ad.val = ad.ena = ad.run = 0;
-			ad.nr = 0;
-			if (!collect_data(config, counter, aggr_cb, &ad))
-				continue;
-			nr = ad.nr;
-			ena = ad.ena;
-			run = ad.run;
-			val = ad.val;
-			if (first && metric_only) {
-				first = false;
-				aggr_printout(config, counter, id, nr);
-			}
-			if (prefix && !metric_only)
-				fprintf(output, "%s", prefix);
-
-			uval = val * counter->scale;
-			printout(config, id, nr, counter, uval, prefix,
-				 run, ena, 1.0, &rt_stat);
-			if (!metric_only)
-				fputc('\n', output);
-		}
-		if (metric_only)
-			fputc('\n', output);
-	}
-}
-
-static int cmp_val(const void *a, const void *b)
-{
-	return ((struct perf_aggr_thread_value *)b)->val -
-		((struct perf_aggr_thread_value *)a)->val;
-}
-
-static struct perf_aggr_thread_value *sort_aggr_thread(
-					struct perf_evsel *counter,
-					int nthreads, int ncpus,
-					int *ret,
-					struct target *_target)
-{
-	int cpu, thread, i = 0;
-	double uval;
-	struct perf_aggr_thread_value *buf;
-
-	buf = calloc(nthreads, sizeof(struct perf_aggr_thread_value));
-	if (!buf)
-		return NULL;
-
-	for (thread = 0; thread < nthreads; thread++) {
-		u64 ena = 0, run = 0, val = 0;
-
-		for (cpu = 0; cpu < ncpus; cpu++) {
-			val += perf_counts(counter->counts, cpu, thread)->val;
-			ena += perf_counts(counter->counts, cpu, thread)->ena;
-			run += perf_counts(counter->counts, cpu, thread)->run;
-		}
-
-		uval = val * counter->scale;
-
-		/*
-		 * Skip value 0 when enabling --per-thread globally,
-		 * otherwise too many 0 output.
-		 */
-		if (uval == 0.0 && target__has_per_thread(_target))
-			continue;
-
-		buf[i].counter = counter;
-		buf[i].id = thread;
-		buf[i].uval = uval;
-		buf[i].val = val;
-		buf[i].run = run;
-		buf[i].ena = ena;
-		i++;
-	}
-
-	qsort(buf, i, sizeof(struct perf_aggr_thread_value), cmp_val);
-
-	if (ret)
-		*ret = i;
-
-	return buf;
-}
-
-static void print_aggr_thread(struct perf_stat_config *config,
-			      struct target *_target,
-			      struct perf_evsel *counter, char *prefix)
-{
-	FILE *output = config->output;
-	int nthreads = thread_map__nr(counter->threads);
-	int ncpus = cpu_map__nr(counter->cpus);
-	int thread, sorted_threads, id;
-	struct perf_aggr_thread_value *buf;
-
-	buf = sort_aggr_thread(counter, nthreads, ncpus, &sorted_threads, _target);
-	if (!buf) {
-		perror("cannot sort aggr thread");
-		return;
-	}
-
-	for (thread = 0; thread < sorted_threads; thread++) {
-		if (prefix)
-			fprintf(output, "%s", prefix);
-
-		id = buf[thread].id;
-		if (config->stats)
-			printout(config, id, 0, buf[thread].counter, buf[thread].uval,
-				 prefix, buf[thread].run, buf[thread].ena, 1.0,
-				 &config->stats[id]);
-		else
-			printout(config, id, 0, buf[thread].counter, buf[thread].uval,
-				 prefix, buf[thread].run, buf[thread].ena, 1.0,
-				 &rt_stat);
-		fputc('\n', output);
-	}
-
-	free(buf);
-}
-
-struct caggr_data {
-	double avg, avg_enabled, avg_running;
-};
-
-static void counter_aggr_cb(struct perf_stat_config *config __maybe_unused,
-			    struct perf_evsel *counter, void *data,
-			    bool first __maybe_unused)
-{
-	struct caggr_data *cd = data;
-	struct perf_stat_evsel *ps = counter->stats;
-
-	cd->avg += avg_stats(&ps->res_stats[0]);
-	cd->avg_enabled += avg_stats(&ps->res_stats[1]);
-	cd->avg_running += avg_stats(&ps->res_stats[2]);
-}
-
-/*
- * Print out the results of a single counter:
- * aggregated counts in system-wide mode
- */
-static void print_counter_aggr(struct perf_stat_config *config,
-			       struct perf_evsel *counter, char *prefix)
-{
-	bool metric_only = config->metric_only;
-	FILE *output = config->output;
-	double uval;
-	struct caggr_data cd = { .avg = 0.0 };
-
-	if (!collect_data(config, counter, counter_aggr_cb, &cd))
-		return;
-
-	if (prefix && !metric_only)
-		fprintf(output, "%s", prefix);
-
-	uval = cd.avg * counter->scale;
-	printout(config, -1, 0, counter, uval, prefix, cd.avg_running, cd.avg_enabled,
-		 cd.avg, &rt_stat);
-	if (!metric_only)
-		fprintf(output, "\n");
-}
-
-static void counter_cb(struct perf_stat_config *config __maybe_unused,
-		       struct perf_evsel *counter, void *data,
-		       bool first __maybe_unused)
-{
-	struct aggr_data *ad = data;
-
-	ad->val += perf_counts(counter->counts, ad->cpu, 0)->val;
-	ad->ena += perf_counts(counter->counts, ad->cpu, 0)->ena;
-	ad->run += perf_counts(counter->counts, ad->cpu, 0)->run;
-}
-
-/*
- * Print out the results of a single counter:
- * does not use aggregated count in system-wide
- */
-static void print_counter(struct perf_stat_config *config,
-			  struct perf_evsel *counter, char *prefix)
-{
-	FILE *output = config->output;
-	u64 ena, run, val;
-	double uval;
-	int cpu;
-
-	for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
-		struct aggr_data ad = { .cpu = cpu };
-
-		if (!collect_data(config, counter, counter_cb, &ad))
-			return;
-		val = ad.val;
-		ena = ad.ena;
-		run = ad.run;
-
-		if (prefix)
-			fprintf(output, "%s", prefix);
-
-		uval = val * counter->scale;
-		printout(config, cpu, 0, counter, uval, prefix, run, ena, 1.0,
-			 &rt_stat);
-
-		fputc('\n', output);
-	}
-}
-
-static void print_no_aggr_metric(struct perf_stat_config *config,
-				 struct perf_evlist *evlist,
-				 char *prefix)
-{
-	int cpu;
-	int nrcpus = 0;
-	struct perf_evsel *counter;
-	u64 ena, run, val;
-	double uval;
-
-	nrcpus = evlist->cpus->nr;
-	for (cpu = 0; cpu < nrcpus; cpu++) {
-		bool first = true;
-
-		if (prefix)
-			fputs(prefix, config->output);
-		evlist__for_each_entry(evlist, counter) {
-			if (is_duration_time(counter))
-				continue;
-			if (first) {
-				aggr_printout(config, counter, cpu, 0);
-				first = false;
-			}
-			val = perf_counts(counter->counts, cpu, 0)->val;
-			ena = perf_counts(counter->counts, cpu, 0)->ena;
-			run = perf_counts(counter->counts, cpu, 0)->run;
-
-			uval = val * counter->scale;
-			printout(config, cpu, 0, counter, uval, prefix, run, ena, 1.0,
-				 &rt_stat);
-		}
-		fputc('\n', config->output);
-	}
-}
-
-static int aggr_header_lens[] = {
-	[AGGR_CORE] = 18,
-	[AGGR_SOCKET] = 12,
-	[AGGR_NONE] = 6,
-	[AGGR_THREAD] = 24,
-	[AGGR_GLOBAL] = 0,
-};
-
-static const char *aggr_header_csv[] = {
-	[AGGR_CORE] 	= 	"core,cpus,",
-	[AGGR_SOCKET] 	= 	"socket,cpus",
-	[AGGR_NONE] 	= 	"cpu,",
-	[AGGR_THREAD] 	= 	"comm-pid,",
-	[AGGR_GLOBAL] 	=	""
-};
-
-static void print_metric_headers(struct perf_stat_config *config,
-				 struct perf_evlist *evlist,
-				 const char *prefix, bool no_indent)
-{
-	struct perf_stat_output_ctx out;
-	struct perf_evsel *counter;
-	struct outstate os = {
-		.fh = config->output
-	};
-
-	if (prefix)
-		fprintf(config->output, "%s", prefix);
-
-	if (!config->csv_output && !no_indent)
-		fprintf(config->output, "%*s",
-			aggr_header_lens[config->aggr_mode], "");
-	if (config->csv_output) {
-		if (config->interval)
-			fputs("time,", config->output);
-		fputs(aggr_header_csv[config->aggr_mode], config->output);
-	}
-
-	/* Print metrics headers only */
-	evlist__for_each_entry(evlist, counter) {
-		if (is_duration_time(counter))
-			continue;
-		os.evsel = counter;
-		out.ctx = &os;
-		out.print_metric = print_metric_header;
-		out.new_line = new_line_metric;
-		out.force_header = true;
-		os.evsel = counter;
-		perf_stat__print_shadow_stats(config, counter, 0,
-					      0,
-					      &out,
-					      &config->metric_events,
-					      &rt_stat);
-	}
-	fputc('\n', config->output);
-}
-
-static void print_interval(struct perf_stat_config *config,
-			   struct perf_evlist *evlist,
-			   char *prefix, struct timespec *ts)
-{
-	bool metric_only = config->metric_only;
-	unsigned int unit_width = config->unit_width;
-	FILE *output = config->output;
-	static int num_print_interval;
-
-	if (config->interval_clear)
-		puts(CONSOLE_CLEAR);
-
-	sprintf(prefix, "%6lu.%09lu%s", ts->tv_sec, ts->tv_nsec, config->csv_sep);
-
-	if ((num_print_interval == 0 && !config->csv_output) || config->interval_clear) {
-		switch (config->aggr_mode) {
-		case AGGR_SOCKET:
-			fprintf(output, "#           time socket cpus");
-			if (!metric_only)
-				fprintf(output, "             counts %*s events\n", unit_width, "unit");
-			break;
-		case AGGR_CORE:
-			fprintf(output, "#           time core         cpus");
-			if (!metric_only)
-				fprintf(output, "             counts %*s events\n", unit_width, "unit");
-			break;
-		case AGGR_NONE:
-			fprintf(output, "#           time CPU    ");
-			if (!metric_only)
-				fprintf(output, "                counts %*s events\n", unit_width, "unit");
-			break;
-		case AGGR_THREAD:
-			fprintf(output, "#           time             comm-pid");
-			if (!metric_only)
-				fprintf(output, "                  counts %*s events\n", unit_width, "unit");
-			break;
-		case AGGR_GLOBAL:
-		default:
-			fprintf(output, "#           time");
-			if (!metric_only)
-				fprintf(output, "             counts %*s events\n", unit_width, "unit");
-		case AGGR_UNSET:
-			break;
-		}
-	}
-
-	if ((num_print_interval == 0 || config->interval_clear) && metric_only)
-		print_metric_headers(config, evlist, " ", true);
-	if (++num_print_interval == 25)
-		num_print_interval = 0;
-}
-
-static void print_header(struct perf_stat_config *config,
-			 struct target *_target,
-			 int argc, const char **argv)
-{
-	FILE *output = config->output;
-	int i;
-
-	fflush(stdout);
-
-	if (!config->csv_output) {
-		fprintf(output, "\n");
-		fprintf(output, " Performance counter stats for ");
-		if (_target->system_wide)
-			fprintf(output, "\'system wide");
-		else if (_target->cpu_list)
-			fprintf(output, "\'CPU(s) %s", _target->cpu_list);
-		else if (!target__has_task(_target)) {
-			fprintf(output, "\'%s", argv ? argv[0] : "pipe");
-			for (i = 1; argv && (i < argc); i++)
-				fprintf(output, " %s", argv[i]);
-		} else if (_target->pid)
-			fprintf(output, "process id \'%s", _target->pid);
-		else
-			fprintf(output, "thread id \'%s", _target->tid);
-
-		fprintf(output, "\'");
-		if (config->run_count > 1)
-			fprintf(output, " (%d runs)", config->run_count);
-		fprintf(output, ":\n\n");
-	}
-}
-
-static int get_precision(double num)
-{
-	if (num > 1)
-		return 0;
-
-	return lround(ceil(-log10(num)));
-}
-
-static void print_table(struct perf_stat_config *config,
-			FILE *output, int precision, double avg)
-{
-	char tmp[64];
-	int idx, indent = 0;
-
-	scnprintf(tmp, 64, " %17.*f", precision, avg);
-	while (tmp[indent] == ' ')
-		indent++;
-
-	fprintf(output, "%*s# Table of individual measurements:\n", indent, "");
-
-	for (idx = 0; idx < config->run_count; idx++) {
-		double run = (double) config->walltime_run[idx] / NSEC_PER_SEC;
-		int h, n = 1 + abs((int) (100.0 * (run - avg)/run) / 5);
-
-		fprintf(output, " %17.*f (%+.*f) ",
-			precision, run, precision, run - avg);
-
-		for (h = 0; h < n; h++)
-			fprintf(output, "#");
-
-		fprintf(output, "\n");
-	}
-
-	fprintf(output, "\n%*s# Final result:\n", indent, "");
-}
-
-static double timeval2double(struct timeval *t)
-{
-	return t->tv_sec + (double) t->tv_usec/USEC_PER_SEC;
-}
-
-static void print_footer(struct perf_stat_config *config)
-{
-	double avg = avg_stats(config->walltime_nsecs_stats) / NSEC_PER_SEC;
-	FILE *output = config->output;
-	int n;
-
-	if (!config->null_run)
-		fprintf(output, "\n");
-
-	if (config->run_count == 1) {
-		fprintf(output, " %17.9f seconds time elapsed", avg);
-
-		if (config->ru_display) {
-			double ru_utime = timeval2double(&config->ru_data.ru_utime);
-			double ru_stime = timeval2double(&config->ru_data.ru_stime);
-
-			fprintf(output, "\n\n");
-			fprintf(output, " %17.9f seconds user\n", ru_utime);
-			fprintf(output, " %17.9f seconds sys\n", ru_stime);
-		}
-	} else {
-		double sd = stddev_stats(config->walltime_nsecs_stats) / NSEC_PER_SEC;
-		/*
-		 * Display at most 2 more significant
-		 * digits than the stddev inaccuracy.
-		 */
-		int precision = get_precision(sd) + 2;
-
-		if (config->walltime_run_table)
-			print_table(config, output, precision, avg);
-
-		fprintf(output, " %17.*f +- %.*f seconds time elapsed",
-			precision, avg, precision, sd);
-
-		print_noise_pct(config, sd, avg);
-	}
-	fprintf(output, "\n\n");
-
-	if (config->print_free_counters_hint &&
-	    sysctl__read_int("kernel/nmi_watchdog", &n) >= 0 &&
-	    n > 0)
-		fprintf(output,
-"Some events weren't counted. Try disabling the NMI watchdog:\n"
-"	echo 0 > /proc/sys/kernel/nmi_watchdog\n"
-"	perf stat ...\n"
-"	echo 1 > /proc/sys/kernel/nmi_watchdog\n");
-
-	if (config->print_mixed_hw_group_error)
-		fprintf(output,
-			"The events in group usually have to be from "
-			"the same PMU. Try reorganizing the group.\n");
-}
-
-static void
-perf_evlist__print_counters(struct perf_evlist *evlist,
-			    struct perf_stat_config *config,
-			    struct target *_target,
-			    struct timespec *ts,
-			    int argc, const char **argv)
-{
-	bool metric_only = config->metric_only;
-	int interval = config->interval;
-	struct perf_evsel *counter;
-	char buf[64], *prefix = NULL;
-
-	if (interval)
-		print_interval(config, evlist, prefix = buf, ts);
-	else
-		print_header(config, _target, argc, argv);
-
-	if (metric_only) {
-		static int num_print_iv;
-
-		if (num_print_iv == 0 && !interval)
-			print_metric_headers(config, evlist, prefix, false);
-		if (num_print_iv++ == 25)
-			num_print_iv = 0;
-		if (config->aggr_mode == AGGR_GLOBAL && prefix)
-			fprintf(config->output, "%s", prefix);
-	}
-
-	switch (config->aggr_mode) {
-	case AGGR_CORE:
-	case AGGR_SOCKET:
-		print_aggr(config, evlist, prefix);
-		break;
-	case AGGR_THREAD:
-		evlist__for_each_entry(evlist, counter) {
-			if (is_duration_time(counter))
-				continue;
-			print_aggr_thread(config, _target, counter, prefix);
-		}
-		break;
-	case AGGR_GLOBAL:
-		evlist__for_each_entry(evlist, counter) {
-			if (is_duration_time(counter))
-				continue;
-			print_counter_aggr(config, counter, prefix);
-		}
-		if (metric_only)
-			fputc('\n', config->output);
-		break;
-	case AGGR_NONE:
-		if (metric_only)
-			print_no_aggr_metric(config, evlist, prefix);
-		else {
-			evlist__for_each_entry(evlist, counter) {
-				if (is_duration_time(counter))
-					continue;
-				print_counter(config, counter, prefix);
-			}
-		}
-		break;
-	case AGGR_UNSET:
-	default:
-		break;
-	}
-
-	if (!interval && !config->csv_output)
-		print_footer(config);
-
-	fflush(config->output);
-}
-
 static void print_counters(struct timespec *ts, int argc, const char **argv)
 {
 	/* Do not print anything if we record to the pipe. */
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 7efe15b9618d..ecd9f9ceda77 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -73,6 +73,7 @@ libperf-y += vdso.o
 libperf-y += counts.o
 libperf-y += stat.o
 libperf-y += stat-shadow.o
+libperf-y += stat-display.o
 libperf-y += record.o
 libperf-y += srcline.o
 libperf-y += data.o
diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c
new file mode 100644
index 000000000000..e7b4c44ebb62
--- /dev/null
+++ b/tools/perf/util/stat-display.c
@@ -0,0 +1,1166 @@
+#include <stdio.h>
+#include <inttypes.h>
+#include <linux/time64.h>
+#include <math.h>
+#include "evlist.h"
+#include "evsel.h"
+#include "stat.h"
+#include "top.h"
+#include "thread_map.h"
+#include "cpumap.h"
+#include "string2.h"
+#include "sane_ctype.h"
+#include "cgroup.h"
+#include <math.h>
+#include <api/fs/fs.h>
+
+#define CNTR_NOT_SUPPORTED	"<not supported>"
+#define CNTR_NOT_COUNTED	"<not counted>"
+
+static bool is_duration_time(struct perf_evsel *evsel)
+{
+	return !strcmp(evsel->name, "duration_time");
+}
+
+static void print_running(struct perf_stat_config *config,
+			  u64 run, u64 ena)
+{
+	if (config->csv_output) {
+		fprintf(config->output, "%s%" PRIu64 "%s%.2f",
+					config->csv_sep,
+					run,
+					config->csv_sep,
+					ena ? 100.0 * run / ena : 100.0);
+	} else if (run != ena) {
+		fprintf(config->output, "  (%.2f%%)", 100.0 * run / ena);
+	}
+}
+
+static void print_noise_pct(struct perf_stat_config *config,
+			    double total, double avg)
+{
+	double pct = rel_stddev_stats(total, avg);
+
+	if (config->csv_output)
+		fprintf(config->output, "%s%.2f%%", config->csv_sep, pct);
+	else if (pct)
+		fprintf(config->output, "  ( +-%6.2f%% )", pct);
+}
+
+static void print_noise(struct perf_stat_config *config,
+			struct perf_evsel *evsel, double avg)
+{
+	struct perf_stat_evsel *ps;
+
+	if (config->run_count == 1)
+		return;
+
+	ps = evsel->stats;
+	print_noise_pct(config, stddev_stats(&ps->res_stats[0]), avg);
+}
+
+static void aggr_printout(struct perf_stat_config *config,
+			  struct perf_evsel *evsel, int id, int nr)
+{
+	switch (config->aggr_mode) {
+	case AGGR_CORE:
+		fprintf(config->output, "S%d-C%*d%s%*d%s",
+			cpu_map__id_to_socket(id),
+			config->csv_output ? 0 : -8,
+			cpu_map__id_to_cpu(id),
+			config->csv_sep,
+			config->csv_output ? 0 : 4,
+			nr,
+			config->csv_sep);
+		break;
+	case AGGR_SOCKET:
+		fprintf(config->output, "S%*d%s%*d%s",
+			config->csv_output ? 0 : -5,
+			id,
+			config->csv_sep,
+			config->csv_output ? 0 : 4,
+			nr,
+			config->csv_sep);
+			break;
+	case AGGR_NONE:
+		fprintf(config->output, "CPU%*d%s",
+			config->csv_output ? 0 : -4,
+			perf_evsel__cpus(evsel)->map[id], config->csv_sep);
+		break;
+	case AGGR_THREAD:
+		fprintf(config->output, "%*s-%*d%s",
+			config->csv_output ? 0 : 16,
+			thread_map__comm(evsel->threads, id),
+			config->csv_output ? 0 : -8,
+			thread_map__pid(evsel->threads, id),
+			config->csv_sep);
+		break;
+	case AGGR_GLOBAL:
+	case AGGR_UNSET:
+	default:
+		break;
+	}
+}
+
+struct outstate {
+	FILE *fh;
+	bool newline;
+	const char *prefix;
+	int  nfields;
+	int  id, nr;
+	struct perf_evsel *evsel;
+};
+
+#define METRIC_LEN  35
+
+static void new_line_std(struct perf_stat_config *config __maybe_unused,
+			 void *ctx)
+{
+	struct outstate *os = ctx;
+
+	os->newline = true;
+}
+
+static void do_new_line_std(struct perf_stat_config *config,
+			    struct outstate *os)
+{
+	fputc('\n', os->fh);
+	fputs(os->prefix, os->fh);
+	aggr_printout(config, os->evsel, os->id, os->nr);
+	if (config->aggr_mode == AGGR_NONE)
+		fprintf(os->fh, "        ");
+	fprintf(os->fh, "                                                 ");
+}
+
+static void print_metric_std(struct perf_stat_config *config,
+			     void *ctx, const char *color, const char *fmt,
+			     const char *unit, double val)
+{
+	struct outstate *os = ctx;
+	FILE *out = os->fh;
+	int n;
+	bool newline = os->newline;
+
+	os->newline = false;
+
+	if (unit == NULL || fmt == NULL) {
+		fprintf(out, "%-*s", METRIC_LEN, "");
+		return;
+	}
+
+	if (newline)
+		do_new_line_std(config, os);
+
+	n = fprintf(out, " # ");
+	if (color)
+		n += color_fprintf(out, color, fmt, val);
+	else
+		n += fprintf(out, fmt, val);
+	fprintf(out, " %-*s", METRIC_LEN - n - 1, unit);
+}
+
+static void new_line_csv(struct perf_stat_config *config, void *ctx)
+{
+	struct outstate *os = ctx;
+	int i;
+
+	fputc('\n', os->fh);
+	if (os->prefix)
+		fprintf(os->fh, "%s%s", os->prefix, config->csv_sep);
+	aggr_printout(config, os->evsel, os->id, os->nr);
+	for (i = 0; i < os->nfields; i++)
+		fputs(config->csv_sep, os->fh);
+}
+
+static void print_metric_csv(struct perf_stat_config *config __maybe_unused,
+			     void *ctx,
+			     const char *color __maybe_unused,
+			     const char *fmt, const char *unit, double val)
+{
+	struct outstate *os = ctx;
+	FILE *out = os->fh;
+	char buf[64], *vals, *ends;
+
+	if (unit == NULL || fmt == NULL) {
+		fprintf(out, "%s%s", config->csv_sep, config->csv_sep);
+		return;
+	}
+	snprintf(buf, sizeof(buf), fmt, val);
+	ends = vals = ltrim(buf);
+	while (isdigit(*ends) || *ends == '.')
+		ends++;
+	*ends = 0;
+	while (isspace(*unit))
+		unit++;
+	fprintf(out, "%s%s%s%s", config->csv_sep, vals, config->csv_sep, unit);
+}
+
+/* Filter out some columns that don't work well in metrics only mode */
+
+static bool valid_only_metric(const char *unit)
+{
+	if (!unit)
+		return false;
+	if (strstr(unit, "/sec") ||
+	    strstr(unit, "hz") ||
+	    strstr(unit, "Hz") ||
+	    strstr(unit, "CPUs utilized"))
+		return false;
+	return true;
+}
+
+static const char *fixunit(char *buf, struct perf_evsel *evsel,
+			   const char *unit)
+{
+	if (!strncmp(unit, "of all", 6)) {
+		snprintf(buf, 1024, "%s %s", perf_evsel__name(evsel),
+			 unit);
+		return buf;
+	}
+	return unit;
+}
+
+static void print_metric_only(struct perf_stat_config *config,
+			      void *ctx, const char *color, const char *fmt,
+			      const char *unit, double val)
+{
+	struct outstate *os = ctx;
+	FILE *out = os->fh;
+	char buf[1024], str[1024];
+	unsigned mlen = config->metric_only_len;
+
+	if (!valid_only_metric(unit))
+		return;
+	unit = fixunit(buf, os->evsel, unit);
+	if (mlen < strlen(unit))
+		mlen = strlen(unit) + 1;
+
+	if (color)
+		mlen += strlen(color) + sizeof(PERF_COLOR_RESET) - 1;
+
+	color_snprintf(str, sizeof(str), color ?: "", fmt, val);
+	fprintf(out, "%*s ", mlen, str);
+}
+
+static void print_metric_only_csv(struct perf_stat_config *config __maybe_unused,
+				  void *ctx, const char *color __maybe_unused,
+				  const char *fmt,
+				  const char *unit, double val)
+{
+	struct outstate *os = ctx;
+	FILE *out = os->fh;
+	char buf[64], *vals, *ends;
+	char tbuf[1024];
+
+	if (!valid_only_metric(unit))
+		return;
+	unit = fixunit(tbuf, os->evsel, unit);
+	snprintf(buf, sizeof buf, fmt, val);
+	ends = vals = ltrim(buf);
+	while (isdigit(*ends) || *ends == '.')
+		ends++;
+	*ends = 0;
+	fprintf(out, "%s%s", vals, config->csv_sep);
+}
+
+static void new_line_metric(struct perf_stat_config *config __maybe_unused,
+			    void *ctx __maybe_unused)
+{
+}
+
+static void print_metric_header(struct perf_stat_config *config,
+				void *ctx, const char *color __maybe_unused,
+				const char *fmt __maybe_unused,
+				const char *unit, double val __maybe_unused)
+{
+	struct outstate *os = ctx;
+	char tbuf[1024];
+
+	if (!valid_only_metric(unit))
+		return;
+	unit = fixunit(tbuf, os->evsel, unit);
+	if (config->csv_output)
+		fprintf(os->fh, "%s%s", unit, config->csv_sep);
+	else
+		fprintf(os->fh, "%*s ", config->metric_only_len, unit);
+}
+
+static int first_shadow_cpu(struct perf_stat_config *config,
+			    struct perf_evsel *evsel, int id)
+{
+	struct perf_evlist *evlist = evsel->evlist;
+	int i;
+
+	if (!config->aggr_get_id)
+		return 0;
+
+	if (config->aggr_mode == AGGR_NONE)
+		return id;
+
+	if (config->aggr_mode == AGGR_GLOBAL)
+		return 0;
+
+	for (i = 0; i < perf_evsel__nr_cpus(evsel); i++) {
+		int cpu2 = perf_evsel__cpus(evsel)->map[i];
+
+		if (config->aggr_get_id(config, evlist->cpus, cpu2) == id)
+			return cpu2;
+	}
+	return 0;
+}
+
+static void abs_printout(struct perf_stat_config *config,
+			 int id, int nr, struct perf_evsel *evsel, double avg)
+{
+	FILE *output = config->output;
+	double sc =  evsel->scale;
+	const char *fmt;
+
+	if (config->csv_output) {
+		fmt = floor(sc) != sc ?  "%.2f%s" : "%.0f%s";
+	} else {
+		if (config->big_num)
+			fmt = floor(sc) != sc ? "%'18.2f%s" : "%'18.0f%s";
+		else
+			fmt = floor(sc) != sc ? "%18.2f%s" : "%18.0f%s";
+	}
+
+	aggr_printout(config, evsel, id, nr);
+
+	fprintf(output, fmt, avg, config->csv_sep);
+
+	if (evsel->unit)
+		fprintf(output, "%-*s%s",
+			config->csv_output ? 0 : config->unit_width,
+			evsel->unit, config->csv_sep);
+
+	fprintf(output, "%-*s", config->csv_output ? 0 : 25, perf_evsel__name(evsel));
+
+	if (evsel->cgrp)
+		fprintf(output, "%s%s", config->csv_sep, evsel->cgrp->name);
+}
+
+static bool is_mixed_hw_group(struct perf_evsel *counter)
+{
+	struct perf_evlist *evlist = counter->evlist;
+	u32 pmu_type = counter->attr.type;
+	struct perf_evsel *pos;
+
+	if (counter->nr_members < 2)
+		return false;
+
+	evlist__for_each_entry(evlist, pos) {
+		/* software events can be part of any hardware group */
+		if (pos->attr.type == PERF_TYPE_SOFTWARE)
+			continue;
+		if (pmu_type == PERF_TYPE_SOFTWARE) {
+			pmu_type = pos->attr.type;
+			continue;
+		}
+		if (pmu_type != pos->attr.type)
+			return true;
+	}
+
+	return false;
+}
+
+static void printout(struct perf_stat_config *config, int id, int nr,
+		     struct perf_evsel *counter, double uval,
+		     char *prefix, u64 run, u64 ena, double noise,
+		     struct runtime_stat *st)
+{
+	struct perf_stat_output_ctx out;
+	struct outstate os = {
+		.fh = config->output,
+		.prefix = prefix ? prefix : "",
+		.id = id,
+		.nr = nr,
+		.evsel = counter,
+	};
+	print_metric_t pm = print_metric_std;
+	new_line_t nl;
+
+	if (config->metric_only) {
+		nl = new_line_metric;
+		if (config->csv_output)
+			pm = print_metric_only_csv;
+		else
+			pm = print_metric_only;
+	} else
+		nl = new_line_std;
+
+	if (config->csv_output && !config->metric_only) {
+		static int aggr_fields[] = {
+			[AGGR_GLOBAL] = 0,
+			[AGGR_THREAD] = 1,
+			[AGGR_NONE] = 1,
+			[AGGR_SOCKET] = 2,
+			[AGGR_CORE] = 2,
+		};
+
+		pm = print_metric_csv;
+		nl = new_line_csv;
+		os.nfields = 3;
+		os.nfields += aggr_fields[config->aggr_mode];
+		if (counter->cgrp)
+			os.nfields++;
+	}
+	if (run == 0 || ena == 0 || counter->counts->scaled == -1) {
+		if (config->metric_only) {
+			pm(config, &os, NULL, "", "", 0);
+			return;
+		}
+		aggr_printout(config, counter, id, nr);
+
+		fprintf(config->output, "%*s%s",
+			config->csv_output ? 0 : 18,
+			counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
+			config->csv_sep);
+
+		if (counter->supported) {
+			config->print_free_counters_hint = 1;
+			if (is_mixed_hw_group(counter))
+				config->print_mixed_hw_group_error = 1;
+		}
+
+		fprintf(config->output, "%-*s%s",
+			config->csv_output ? 0 : config->unit_width,
+			counter->unit, config->csv_sep);
+
+		fprintf(config->output, "%*s",
+			config->csv_output ? 0 : -25,
+			perf_evsel__name(counter));
+
+		if (counter->cgrp)
+			fprintf(config->output, "%s%s",
+				config->csv_sep, counter->cgrp->name);
+
+		if (!config->csv_output)
+			pm(config, &os, NULL, NULL, "", 0);
+		print_noise(config, counter, noise);
+		print_running(config, run, ena);
+		if (config->csv_output)
+			pm(config, &os, NULL, NULL, "", 0);
+		return;
+	}
+
+	if (!config->metric_only)
+		abs_printout(config, id, nr, counter, uval);
+
+	out.print_metric = pm;
+	out.new_line = nl;
+	out.ctx = &os;
+	out.force_header = false;
+
+	if (config->csv_output && !config->metric_only) {
+		print_noise(config, counter, noise);
+		print_running(config, run, ena);
+	}
+
+	perf_stat__print_shadow_stats(config, counter, uval,
+				first_shadow_cpu(config, counter, id),
+				&out, &config->metric_events, st);
+	if (!config->csv_output && !config->metric_only) {
+		print_noise(config, counter, noise);
+		print_running(config, run, ena);
+	}
+}
+
+static void aggr_update_shadow(struct perf_stat_config *config,
+			       struct perf_evlist *evlist)
+{
+	int cpu, s2, id, s;
+	u64 val;
+	struct perf_evsel *counter;
+
+	for (s = 0; s < config->aggr_map->nr; s++) {
+		id = config->aggr_map->map[s];
+		evlist__for_each_entry(evlist, counter) {
+			val = 0;
+			for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
+				s2 = config->aggr_get_id(config, evlist->cpus, cpu);
+				if (s2 != id)
+					continue;
+				val += perf_counts(counter->counts, cpu, 0)->val;
+			}
+			perf_stat__update_shadow_stats(counter, val,
+					first_shadow_cpu(config, counter, id),
+					&rt_stat);
+		}
+	}
+}
+
+static void uniquify_event_name(struct perf_evsel *counter)
+{
+	char *new_name;
+	char *config;
+
+	if (counter->uniquified_name ||
+	    !counter->pmu_name || !strncmp(counter->name, counter->pmu_name,
+					   strlen(counter->pmu_name)))
+		return;
+
+	config = strchr(counter->name, '/');
+	if (config) {
+		if (asprintf(&new_name,
+			     "%s%s", counter->pmu_name, config) > 0) {
+			free(counter->name);
+			counter->name = new_name;
+		}
+	} else {
+		if (asprintf(&new_name,
+			     "%s [%s]", counter->name, counter->pmu_name) > 0) {
+			free(counter->name);
+			counter->name = new_name;
+		}
+	}
+
+	counter->uniquified_name = true;
+}
+
+static void collect_all_aliases(struct perf_stat_config *config, struct perf_evsel *counter,
+			    void (*cb)(struct perf_stat_config *config, struct perf_evsel *counter, void *data,
+				       bool first),
+			    void *data)
+{
+	struct perf_evlist *evlist = counter->evlist;
+	struct perf_evsel *alias;
+
+	alias = list_prepare_entry(counter, &(evlist->entries), node);
+	list_for_each_entry_continue (alias, &evlist->entries, node) {
+		if (strcmp(perf_evsel__name(alias), perf_evsel__name(counter)) ||
+		    alias->scale != counter->scale ||
+		    alias->cgrp != counter->cgrp ||
+		    strcmp(alias->unit, counter->unit) ||
+		    perf_evsel__is_clock(alias) != perf_evsel__is_clock(counter))
+			break;
+		alias->merged_stat = true;
+		cb(config, alias, data, false);
+	}
+}
+
+static bool collect_data(struct perf_stat_config *config, struct perf_evsel *counter,
+			    void (*cb)(struct perf_stat_config *config, struct perf_evsel *counter, void *data,
+				       bool first),
+			    void *data)
+{
+	if (counter->merged_stat)
+		return false;
+	cb(config, counter, data, true);
+	if (config->no_merge)
+		uniquify_event_name(counter);
+	else if (counter->auto_merge_stats)
+		collect_all_aliases(config, counter, cb, data);
+	return true;
+}
+
+struct aggr_data {
+	u64 ena, run, val;
+	int id;
+	int nr;
+	int cpu;
+};
+
+static void aggr_cb(struct perf_stat_config *config,
+		    struct perf_evsel *counter, void *data, bool first)
+{
+	struct aggr_data *ad = data;
+	int cpu, s2;
+
+	for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
+		struct perf_counts_values *counts;
+
+		s2 = config->aggr_get_id(config, perf_evsel__cpus(counter), cpu);
+		if (s2 != ad->id)
+			continue;
+		if (first)
+			ad->nr++;
+		counts = perf_counts(counter->counts, cpu, 0);
+		/*
+		 * When any result is bad, make them all to give
+		 * consistent output in interval mode.
+		 */
+		if (counts->ena == 0 || counts->run == 0 ||
+		    counter->counts->scaled == -1) {
+			ad->ena = 0;
+			ad->run = 0;
+			break;
+		}
+		ad->val += counts->val;
+		ad->ena += counts->ena;
+		ad->run += counts->run;
+	}
+}
+
+static void print_aggr(struct perf_stat_config *config,
+		       struct perf_evlist *evlist,
+		       char *prefix)
+{
+	bool metric_only = config->metric_only;
+	FILE *output = config->output;
+	struct perf_evsel *counter;
+	int s, id, nr;
+	double uval;
+	u64 ena, run, val;
+	bool first;
+
+	if (!(config->aggr_map || config->aggr_get_id))
+		return;
+
+	aggr_update_shadow(config, evlist);
+
+	/*
+	 * With metric_only everything is on a single line.
+	 * Without each counter has its own line.
+	 */
+	for (s = 0; s < config->aggr_map->nr; s++) {
+		struct aggr_data ad;
+		if (prefix && metric_only)
+			fprintf(output, "%s", prefix);
+
+		ad.id = id = config->aggr_map->map[s];
+		first = true;
+		evlist__for_each_entry(evlist, counter) {
+			if (is_duration_time(counter))
+				continue;
+
+			ad.val = ad.ena = ad.run = 0;
+			ad.nr = 0;
+			if (!collect_data(config, counter, aggr_cb, &ad))
+				continue;
+			nr = ad.nr;
+			ena = ad.ena;
+			run = ad.run;
+			val = ad.val;
+			if (first && metric_only) {
+				first = false;
+				aggr_printout(config, counter, id, nr);
+			}
+			if (prefix && !metric_only)
+				fprintf(output, "%s", prefix);
+
+			uval = val * counter->scale;
+			printout(config, id, nr, counter, uval, prefix,
+				 run, ena, 1.0, &rt_stat);
+			if (!metric_only)
+				fputc('\n', output);
+		}
+		if (metric_only)
+			fputc('\n', output);
+	}
+}
+
+static int cmp_val(const void *a, const void *b)
+{
+	return ((struct perf_aggr_thread_value *)b)->val -
+		((struct perf_aggr_thread_value *)a)->val;
+}
+
+static struct perf_aggr_thread_value *sort_aggr_thread(
+					struct perf_evsel *counter,
+					int nthreads, int ncpus,
+					int *ret,
+					struct target *_target)
+{
+	int cpu, thread, i = 0;
+	double uval;
+	struct perf_aggr_thread_value *buf;
+
+	buf = calloc(nthreads, sizeof(struct perf_aggr_thread_value));
+	if (!buf)
+		return NULL;
+
+	for (thread = 0; thread < nthreads; thread++) {
+		u64 ena = 0, run = 0, val = 0;
+
+		for (cpu = 0; cpu < ncpus; cpu++) {
+			val += perf_counts(counter->counts, cpu, thread)->val;
+			ena += perf_counts(counter->counts, cpu, thread)->ena;
+			run += perf_counts(counter->counts, cpu, thread)->run;
+		}
+
+		uval = val * counter->scale;
+
+		/*
+		 * Skip value 0 when enabling --per-thread globally,
+		 * otherwise too many 0 output.
+		 */
+		if (uval == 0.0 && target__has_per_thread(_target))
+			continue;
+
+		buf[i].counter = counter;
+		buf[i].id = thread;
+		buf[i].uval = uval;
+		buf[i].val = val;
+		buf[i].run = run;
+		buf[i].ena = ena;
+		i++;
+	}
+
+	qsort(buf, i, sizeof(struct perf_aggr_thread_value), cmp_val);
+
+	if (ret)
+		*ret = i;
+
+	return buf;
+}
+
+static void print_aggr_thread(struct perf_stat_config *config,
+			      struct target *_target,
+			      struct perf_evsel *counter, char *prefix)
+{
+	FILE *output = config->output;
+	int nthreads = thread_map__nr(counter->threads);
+	int ncpus = cpu_map__nr(counter->cpus);
+	int thread, sorted_threads, id;
+	struct perf_aggr_thread_value *buf;
+
+	buf = sort_aggr_thread(counter, nthreads, ncpus, &sorted_threads, _target);
+	if (!buf) {
+		perror("cannot sort aggr thread");
+		return;
+	}
+
+	for (thread = 0; thread < sorted_threads; thread++) {
+		if (prefix)
+			fprintf(output, "%s", prefix);
+
+		id = buf[thread].id;
+		if (config->stats)
+			printout(config, id, 0, buf[thread].counter, buf[thread].uval,
+				 prefix, buf[thread].run, buf[thread].ena, 1.0,
+				 &config->stats[id]);
+		else
+			printout(config, id, 0, buf[thread].counter, buf[thread].uval,
+				 prefix, buf[thread].run, buf[thread].ena, 1.0,
+				 &rt_stat);
+		fputc('\n', output);
+	}
+
+	free(buf);
+}
+
+struct caggr_data {
+	double avg, avg_enabled, avg_running;
+};
+
+static void counter_aggr_cb(struct perf_stat_config *config __maybe_unused,
+			    struct perf_evsel *counter, void *data,
+			    bool first __maybe_unused)
+{
+	struct caggr_data *cd = data;
+	struct perf_stat_evsel *ps = counter->stats;
+
+	cd->avg += avg_stats(&ps->res_stats[0]);
+	cd->avg_enabled += avg_stats(&ps->res_stats[1]);
+	cd->avg_running += avg_stats(&ps->res_stats[2]);
+}
+
+/*
+ * Print out the results of a single counter:
+ * aggregated counts in system-wide mode
+ */
+static void print_counter_aggr(struct perf_stat_config *config,
+			       struct perf_evsel *counter, char *prefix)
+{
+	bool metric_only = config->metric_only;
+	FILE *output = config->output;
+	double uval;
+	struct caggr_data cd = { .avg = 0.0 };
+
+	if (!collect_data(config, counter, counter_aggr_cb, &cd))
+		return;
+
+	if (prefix && !metric_only)
+		fprintf(output, "%s", prefix);
+
+	uval = cd.avg * counter->scale;
+	printout(config, -1, 0, counter, uval, prefix, cd.avg_running, cd.avg_enabled,
+		 cd.avg, &rt_stat);
+	if (!metric_only)
+		fprintf(output, "\n");
+}
+
+static void counter_cb(struct perf_stat_config *config __maybe_unused,
+		       struct perf_evsel *counter, void *data,
+		       bool first __maybe_unused)
+{
+	struct aggr_data *ad = data;
+
+	ad->val += perf_counts(counter->counts, ad->cpu, 0)->val;
+	ad->ena += perf_counts(counter->counts, ad->cpu, 0)->ena;
+	ad->run += perf_counts(counter->counts, ad->cpu, 0)->run;
+}
+
+/*
+ * Print out the results of a single counter:
+ * does not use aggregated count in system-wide
+ */
+static void print_counter(struct perf_stat_config *config,
+			  struct perf_evsel *counter, char *prefix)
+{
+	FILE *output = config->output;
+	u64 ena, run, val;
+	double uval;
+	int cpu;
+
+	for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
+		struct aggr_data ad = { .cpu = cpu };
+
+		if (!collect_data(config, counter, counter_cb, &ad))
+			return;
+		val = ad.val;
+		ena = ad.ena;
+		run = ad.run;
+
+		if (prefix)
+			fprintf(output, "%s", prefix);
+
+		uval = val * counter->scale;
+		printout(config, cpu, 0, counter, uval, prefix, run, ena, 1.0,
+			 &rt_stat);
+
+		fputc('\n', output);
+	}
+}
+
+static void print_no_aggr_metric(struct perf_stat_config *config,
+				 struct perf_evlist *evlist,
+				 char *prefix)
+{
+	int cpu;
+	int nrcpus = 0;
+	struct perf_evsel *counter;
+	u64 ena, run, val;
+	double uval;
+
+	nrcpus = evlist->cpus->nr;
+	for (cpu = 0; cpu < nrcpus; cpu++) {
+		bool first = true;
+
+		if (prefix)
+			fputs(prefix, config->output);
+		evlist__for_each_entry(evlist, counter) {
+			if (is_duration_time(counter))
+				continue;
+			if (first) {
+				aggr_printout(config, counter, cpu, 0);
+				first = false;
+			}
+			val = perf_counts(counter->counts, cpu, 0)->val;
+			ena = perf_counts(counter->counts, cpu, 0)->ena;
+			run = perf_counts(counter->counts, cpu, 0)->run;
+
+			uval = val * counter->scale;
+			printout(config, cpu, 0, counter, uval, prefix, run, ena, 1.0,
+				 &rt_stat);
+		}
+		fputc('\n', config->output);
+	}
+}
+
+static int aggr_header_lens[] = {
+	[AGGR_CORE] = 18,
+	[AGGR_SOCKET] = 12,
+	[AGGR_NONE] = 6,
+	[AGGR_THREAD] = 24,
+	[AGGR_GLOBAL] = 0,
+};
+
+static const char *aggr_header_csv[] = {
+	[AGGR_CORE] 	= 	"core,cpus,",
+	[AGGR_SOCKET] 	= 	"socket,cpus",
+	[AGGR_NONE] 	= 	"cpu,",
+	[AGGR_THREAD] 	= 	"comm-pid,",
+	[AGGR_GLOBAL] 	=	""
+};
+
+static void print_metric_headers(struct perf_stat_config *config,
+				 struct perf_evlist *evlist,
+				 const char *prefix, bool no_indent)
+{
+	struct perf_stat_output_ctx out;
+	struct perf_evsel *counter;
+	struct outstate os = {
+		.fh = config->output
+	};
+
+	if (prefix)
+		fprintf(config->output, "%s", prefix);
+
+	if (!config->csv_output && !no_indent)
+		fprintf(config->output, "%*s",
+			aggr_header_lens[config->aggr_mode], "");
+	if (config->csv_output) {
+		if (config->interval)
+			fputs("time,", config->output);
+		fputs(aggr_header_csv[config->aggr_mode], config->output);
+	}
+
+	/* Print metrics headers only */
+	evlist__for_each_entry(evlist, counter) {
+		if (is_duration_time(counter))
+			continue;
+		os.evsel = counter;
+		out.ctx = &os;
+		out.print_metric = print_metric_header;
+		out.new_line = new_line_metric;
+		out.force_header = true;
+		os.evsel = counter;
+		perf_stat__print_shadow_stats(config, counter, 0,
+					      0,
+					      &out,
+					      &config->metric_events,
+					      &rt_stat);
+	}
+	fputc('\n', config->output);
+}
+
+static void print_interval(struct perf_stat_config *config,
+			   struct perf_evlist *evlist,
+			   char *prefix, struct timespec *ts)
+{
+	bool metric_only = config->metric_only;
+	unsigned int unit_width = config->unit_width;
+	FILE *output = config->output;
+	static int num_print_interval;
+
+	if (config->interval_clear)
+		puts(CONSOLE_CLEAR);
+
+	sprintf(prefix, "%6lu.%09lu%s", ts->tv_sec, ts->tv_nsec, config->csv_sep);
+
+	if ((num_print_interval == 0 && !config->csv_output) || config->interval_clear) {
+		switch (config->aggr_mode) {
+		case AGGR_SOCKET:
+			fprintf(output, "#           time socket cpus");
+			if (!metric_only)
+				fprintf(output, "             counts %*s events\n", unit_width, "unit");
+			break;
+		case AGGR_CORE:
+			fprintf(output, "#           time core         cpus");
+			if (!metric_only)
+				fprintf(output, "             counts %*s events\n", unit_width, "unit");
+			break;
+		case AGGR_NONE:
+			fprintf(output, "#           time CPU    ");
+			if (!metric_only)
+				fprintf(output, "                counts %*s events\n", unit_width, "unit");
+			break;
+		case AGGR_THREAD:
+			fprintf(output, "#           time             comm-pid");
+			if (!metric_only)
+				fprintf(output, "                  counts %*s events\n", unit_width, "unit");
+			break;
+		case AGGR_GLOBAL:
+		default:
+			fprintf(output, "#           time");
+			if (!metric_only)
+				fprintf(output, "             counts %*s events\n", unit_width, "unit");
+		case AGGR_UNSET:
+			break;
+		}
+	}
+
+	if ((num_print_interval == 0 || config->interval_clear) && metric_only)
+		print_metric_headers(config, evlist, " ", true);
+	if (++num_print_interval == 25)
+		num_print_interval = 0;
+}
+
+static void print_header(struct perf_stat_config *config,
+			 struct target *_target,
+			 int argc, const char **argv)
+{
+	FILE *output = config->output;
+	int i;
+
+	fflush(stdout);
+
+	if (!config->csv_output) {
+		fprintf(output, "\n");
+		fprintf(output, " Performance counter stats for ");
+		if (_target->system_wide)
+			fprintf(output, "\'system wide");
+		else if (_target->cpu_list)
+			fprintf(output, "\'CPU(s) %s", _target->cpu_list);
+		else if (!target__has_task(_target)) {
+			fprintf(output, "\'%s", argv ? argv[0] : "pipe");
+			for (i = 1; argv && (i < argc); i++)
+				fprintf(output, " %s", argv[i]);
+		} else if (_target->pid)
+			fprintf(output, "process id \'%s", _target->pid);
+		else
+			fprintf(output, "thread id \'%s", _target->tid);
+
+		fprintf(output, "\'");
+		if (config->run_count > 1)
+			fprintf(output, " (%d runs)", config->run_count);
+		fprintf(output, ":\n\n");
+	}
+}
+
+static int get_precision(double num)
+{
+	if (num > 1)
+		return 0;
+
+	return lround(ceil(-log10(num)));
+}
+
+static void print_table(struct perf_stat_config *config,
+			FILE *output, int precision, double avg)
+{
+	char tmp[64];
+	int idx, indent = 0;
+
+	scnprintf(tmp, 64, " %17.*f", precision, avg);
+	while (tmp[indent] == ' ')
+		indent++;
+
+	fprintf(output, "%*s# Table of individual measurements:\n", indent, "");
+
+	for (idx = 0; idx < config->run_count; idx++) {
+		double run = (double) config->walltime_run[idx] / NSEC_PER_SEC;
+		int h, n = 1 + abs((int) (100.0 * (run - avg)/run) / 5);
+
+		fprintf(output, " %17.*f (%+.*f) ",
+			precision, run, precision, run - avg);
+
+		for (h = 0; h < n; h++)
+			fprintf(output, "#");
+
+		fprintf(output, "\n");
+	}
+
+	fprintf(output, "\n%*s# Final result:\n", indent, "");
+}
+
+static double timeval2double(struct timeval *t)
+{
+	return t->tv_sec + (double) t->tv_usec/USEC_PER_SEC;
+}
+
+static void print_footer(struct perf_stat_config *config)
+{
+	double avg = avg_stats(config->walltime_nsecs_stats) / NSEC_PER_SEC;
+	FILE *output = config->output;
+	int n;
+
+	if (!config->null_run)
+		fprintf(output, "\n");
+
+	if (config->run_count == 1) {
+		fprintf(output, " %17.9f seconds time elapsed", avg);
+
+		if (config->ru_display) {
+			double ru_utime = timeval2double(&config->ru_data.ru_utime);
+			double ru_stime = timeval2double(&config->ru_data.ru_stime);
+
+			fprintf(output, "\n\n");
+			fprintf(output, " %17.9f seconds user\n", ru_utime);
+			fprintf(output, " %17.9f seconds sys\n", ru_stime);
+		}
+	} else {
+		double sd = stddev_stats(config->walltime_nsecs_stats) / NSEC_PER_SEC;
+		/*
+		 * Display at most 2 more significant
+		 * digits than the stddev inaccuracy.
+		 */
+		int precision = get_precision(sd) + 2;
+
+		if (config->walltime_run_table)
+			print_table(config, output, precision, avg);
+
+		fprintf(output, " %17.*f +- %.*f seconds time elapsed",
+			precision, avg, precision, sd);
+
+		print_noise_pct(config, sd, avg);
+	}
+	fprintf(output, "\n\n");
+
+	if (config->print_free_counters_hint &&
+	    sysctl__read_int("kernel/nmi_watchdog", &n) >= 0 &&
+	    n > 0)
+		fprintf(output,
+"Some events weren't counted. Try disabling the NMI watchdog:\n"
+"	echo 0 > /proc/sys/kernel/nmi_watchdog\n"
+"	perf stat ...\n"
+"	echo 1 > /proc/sys/kernel/nmi_watchdog\n");
+
+	if (config->print_mixed_hw_group_error)
+		fprintf(output,
+			"The events in group usually have to be from "
+			"the same PMU. Try reorganizing the group.\n");
+}
+
+void
+perf_evlist__print_counters(struct perf_evlist *evlist,
+			    struct perf_stat_config *config,
+			    struct target *_target,
+			    struct timespec *ts,
+			    int argc, const char **argv)
+{
+	bool metric_only = config->metric_only;
+	int interval = config->interval;
+	struct perf_evsel *counter;
+	char buf[64], *prefix = NULL;
+
+	if (interval)
+		print_interval(config, evlist, prefix = buf, ts);
+	else
+		print_header(config, _target, argc, argv);
+
+	if (metric_only) {
+		static int num_print_iv;
+
+		if (num_print_iv == 0 && !interval)
+			print_metric_headers(config, evlist, prefix, false);
+		if (num_print_iv++ == 25)
+			num_print_iv = 0;
+		if (config->aggr_mode == AGGR_GLOBAL && prefix)
+			fprintf(config->output, "%s", prefix);
+	}
+
+	switch (config->aggr_mode) {
+	case AGGR_CORE:
+	case AGGR_SOCKET:
+		print_aggr(config, evlist, prefix);
+		break;
+	case AGGR_THREAD:
+		evlist__for_each_entry(evlist, counter) {
+			if (is_duration_time(counter))
+				continue;
+			print_aggr_thread(config, _target, counter, prefix);
+		}
+		break;
+	case AGGR_GLOBAL:
+		evlist__for_each_entry(evlist, counter) {
+			if (is_duration_time(counter))
+				continue;
+			print_counter_aggr(config, counter, prefix);
+		}
+		if (metric_only)
+			fputc('\n', config->output);
+		break;
+	case AGGR_NONE:
+		if (metric_only)
+			print_no_aggr_metric(config, evlist, prefix);
+		else {
+			evlist__for_each_entry(evlist, counter) {
+				if (is_duration_time(counter))
+					continue;
+				print_counter(config, counter, prefix);
+			}
+		}
+		break;
+	case AGGR_UNSET:
+	default:
+		break;
+	}
+
+	if (!interval && !config->csv_output)
+		print_footer(config);
+
+	fflush(config->output);
+}
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 8d3354e21e19..3a13a6dc5a62 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -215,4 +215,10 @@ int perf_stat_synthesize_config(struct perf_stat_config *config,
 				struct perf_evlist *evlist,
 				perf_event__handler_t process,
 				bool attrs);
+void
+perf_evlist__print_counters(struct perf_evlist *evlist,
+			    struct perf_stat_config *config,
+			    struct target *_target,
+			    struct timespec *ts,
+			    int argc, const char **argv);
 #endif
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 88+ messages in thread

* Re: [PATCH 00/43] perf stat: Make some of the stat code generic
  2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
                   ` (42 preceding siblings ...)
  2018-08-30  6:32 ` [PATCH 43/43] perf stat: Move display functions into stat-display.c Jiri Olsa
@ 2018-08-30 17:54 ` Arnaldo Carvalho de Melo
  43 siblings, 0 replies; 88+ messages in thread
From: Arnaldo Carvalho de Melo @ 2018-08-30 17:54 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: lkml, Ingo Molnar, Namhyung Kim, David Ahern, Alexander Shishkin,
	Peter Zijlstra, Andi Kleen

Em Thu, Aug 30, 2018 at 08:32:09AM +0200, Jiri Olsa escreveu:
> hi,
> while going for the ability to store/display stat data
> in perf record/top I ended up with bunch of generic
> patches that make some of the stat functions standalone
> and simplify/reduce the builtin-stat.c code.
> 
> This patchset mostly separates the display functions
> into separate object, plus several other functions.
> 
> Also available in here:
>   git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf.git
>   perf/fixes

Thanks, applied,

- Arnaldo

^ permalink raw reply	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf stat: Use evsel->threads in create_perf_stat_counter()
  2018-08-30  6:32 ` [PATCH 01/43] perf stat: Use evsel->threads in create_perf_stat_counter Jiri Olsa
@ 2018-09-06 13:21   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:21 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: namhyung, peterz, tglx, jolsa, hpa, mingo, acme, andi, dsahern,
	linux-kernel, alexander.shishkin

Commit-ID:  d50ed0ce820414dbe249a6ad5c9830e29cc46fcc
Gitweb:     https://git.kernel.org/tip/d50ed0ce820414dbe249a6ad5c9830e29cc46fcc
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:10 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:21 -0300

perf stat: Use evsel->threads in create_perf_stat_counter()

Get rid of the evsel_list dependency, here we can use the evsel->threads
copy of the struct thread_map.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-2-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index d097b5b47eb8..d389ed623715 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -293,7 +293,7 @@ static int create_perf_stat_counter(struct perf_evsel *evsel)
 	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);
+	return perf_evsel__open_per_thread(evsel, evsel->threads);
 }
 
 static int process_synthesized_event(struct perf_tool *tool __maybe_unused,

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf stat: Move 'initial_delay' to 'struct perf_stat_config'
  2018-08-30  6:32 ` [PATCH 02/43] perf stat: Move initial_delay into struct perf_stat_config Jiri Olsa
@ 2018-09-06 13:21   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:21 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: andi, linux-kernel, mingo, tglx, dsahern, acme, peterz,
	alexander.shishkin, hpa, jolsa, namhyung

Commit-ID:  728c0ee0a896fcb0957b496afdb78bf195397645
Gitweb:     https://git.kernel.org/tip/728c0ee0a896fcb0957b496afdb78bf195397645
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:11 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:21 -0300

perf stat: Move 'initial_delay' to 'struct perf_stat_config'

Move the static 'initial_delay' variable to 'struct perf_stat_config',
so it can be passed around and used outside the 'perf stat' command.

Add 'struct perf_stat_config' argument to create_perf_stat_counter() and
use its 'initial_delay' member instead of the static one.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-3-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 16 ++++++++--------
 tools/perf/util/stat.h    | 18 ++++++++++--------
 2 files changed, 18 insertions(+), 16 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index d389ed623715..719abdd3b7de 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -164,7 +164,6 @@ static bool			group				= false;
 static const char		*pre_cmd			= NULL;
 static const char		*post_cmd			= NULL;
 static bool			sync_run			= false;
-static unsigned int		initial_delay			= 0;
 static unsigned int		unit_width			= 4; /* strlen("unit") */
 static bool			forever				= false;
 static bool			metric_only			= false;
@@ -236,7 +235,8 @@ static void perf_stat__reset_stats(void)
 		perf_stat__reset_shadow_per_stat(&stat_config.stats[i]);
 }
 
-static int create_perf_stat_counter(struct perf_evsel *evsel)
+static int create_perf_stat_counter(struct perf_evsel *evsel,
+				    struct perf_stat_config *config)
 {
 	struct perf_event_attr *attr = &evsel->attr;
 	struct perf_evsel *leader = evsel->leader;
@@ -286,7 +286,7 @@ static int create_perf_stat_counter(struct perf_evsel *evsel)
 		 * In case of initial_delay we enable tracee
 		 * events manually.
 		 */
-		if (target__none(&target) && !initial_delay)
+		if (target__none(&target) && !config->initial_delay)
 			attr->enable_on_exec = 1;
 	}
 
@@ -428,15 +428,15 @@ static void process_interval(void)
 
 static void enable_counters(void)
 {
-	if (initial_delay)
-		usleep(initial_delay * USEC_PER_MSEC);
+	if (stat_config.initial_delay)
+		usleep(stat_config.initial_delay * USEC_PER_MSEC);
 
 	/*
 	 * We need to enable counters only if:
 	 * - we don't have tracee (attaching to task or cpu)
 	 * - we have initial delay configured
 	 */
-	if (!target__none(&target) || initial_delay)
+	if (!target__none(&target) || stat_config.initial_delay)
 		perf_evlist__enable(evsel_list);
 }
 
@@ -609,7 +609,7 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
 
 	evlist__for_each_entry(evsel_list, counter) {
 try_again:
-		if (create_perf_stat_counter(counter) < 0) {
+		if (create_perf_stat_counter(counter, &stat_config) < 0) {
 
 			/* Weak group failed. Reset the group. */
 			if ((errno == EINVAL || errno == EBADF) &&
@@ -2027,7 +2027,7 @@ static const struct option stat_options[] = {
 		     "aggregate counts per physical processor core", AGGR_CORE),
 	OPT_SET_UINT(0, "per-thread", &stat_config.aggr_mode,
 		     "aggregate counts per thread", AGGR_THREAD),
-	OPT_UINTEGER('D', "delay", &initial_delay,
+	OPT_UINTEGER('D', "delay", &stat_config.initial_delay,
 		     "ms to wait before starting measurement after program start"),
 	OPT_CALLBACK_NOOPT(0, "metric-only", &metric_only, NULL,
 			"Only print computed metrics. No raw values", enable_metric_only),
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 36efb986f7fc..91e6609fce6e 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -6,6 +6,7 @@
 #include <stdio.h>
 #include "xyarray.h"
 #include "rblist.h"
+#include "perf.h"
 
 struct stats {
 	double n, mean, M2;
@@ -85,14 +86,15 @@ struct runtime_stat {
 };
 
 struct perf_stat_config {
-	enum aggr_mode	aggr_mode;
-	bool		scale;
-	FILE		*output;
-	unsigned int	interval;
-	unsigned int	timeout;
-	int		times;
-	struct runtime_stat *stats;
-	int		stats_num;
+	enum aggr_mode		 aggr_mode;
+	bool			 scale;
+	FILE			*output;
+	unsigned int		 interval;
+	unsigned int		 timeout;
+	unsigned int		 initial_delay;
+	int			 times;
+	struct runtime_stat	*stats;
+	int			 stats_num;
 };
 
 void update_stats(struct stats *stats, u64 val);

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf stat: Move 'no_inherit' to 'struct perf_stat_config'
  2018-08-30  6:32 ` [PATCH 03/43] perf stat: Move no_inherit into struct perf_stat_config Jiri Olsa
@ 2018-09-06 13:22   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:22 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: tglx, peterz, mingo, alexander.shishkin, linux-kernel, hpa,
	jolsa, acme, andi, dsahern, namhyung

Commit-ID:  5698f26b46e4f47f2371418eb92732048fa4fa66
Gitweb:     https://git.kernel.org/tip/5698f26b46e4f47f2371418eb92732048fa4fa66
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:12 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:21 -0300

perf stat: Move 'no_inherit' to 'struct perf_stat_config'

Move the static 'no_inherit' variable to 'struct perf_stat_config', so
it can be passed around and used outside the 'perf stat' command.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-4-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 5 ++---
 tools/perf/util/stat.h    | 1 +
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 719abdd3b7de..84dbac526925 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -148,7 +148,6 @@ typedef int (*aggr_get_id_t)(struct cpu_map *m, int cpu);
 #define METRIC_ONLY_LEN 20
 
 static int			run_count			=  1;
-static bool			no_inherit			= false;
 static volatile pid_t		child_pid			= -1;
 static bool			null_run			=  false;
 static int			detailed_run			=  0;
@@ -254,7 +253,7 @@ static int create_perf_stat_counter(struct perf_evsel *evsel,
 	if (leader->nr_members > 1)
 		attr->read_format |= PERF_FORMAT_ID|PERF_FORMAT_GROUP;
 
-	attr->inherit = !no_inherit;
+	attr->inherit = !config->no_inherit;
 
 	/*
 	 * Some events get initialized with sample_(period/type) set,
@@ -1969,7 +1968,7 @@ static const struct option stat_options[] = {
 		     parse_events_option),
 	OPT_CALLBACK(0, "filter", &evsel_list, "filter",
 		     "event filter", parse_filter),
-	OPT_BOOLEAN('i', "no-inherit", &no_inherit,
+	OPT_BOOLEAN('i', "no-inherit", &stat_config.no_inherit,
 		    "child tasks do not inherit counters"),
 	OPT_STRING('p', "pid", &target.pid, "pid",
 		   "stat events on existing process id"),
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 91e6609fce6e..53b2415ba3f3 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -88,6 +88,7 @@ struct runtime_stat {
 struct perf_stat_config {
 	enum aggr_mode		 aggr_mode;
 	bool			 scale;
+	bool			 no_inherit;
 	FILE			*output;
 	unsigned int		 interval;
 	unsigned int		 timeout;

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf stat: Use local config arg for scale in create_perf_stat_counter()
  2018-08-30  6:32 ` [PATCH 04/43] perf stat: Use local config arg for scale in create_perf_stat_counter Jiri Olsa
@ 2018-09-06 13:22   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:22 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: peterz, namhyung, tglx, andi, mingo, hpa, acme, jolsa,
	linux-kernel, dsahern, alexander.shishkin

Commit-ID:  35386233fcf78f20cb8a51199518da9f81eca280
Gitweb:     https://git.kernel.org/tip/35386233fcf78f20cb8a51199518da9f81eca280
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:13 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:21 -0300

perf stat: Use local config arg for scale in create_perf_stat_counter()

Use the local 'scale' member in the 'struct perf_stat_config' argument
instead of the global 'stat_config' variable, to make the function
independent.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-5-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 84dbac526925..47789558899a 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -240,7 +240,7 @@ static int create_perf_stat_counter(struct perf_evsel *evsel,
 	struct perf_event_attr *attr = &evsel->attr;
 	struct perf_evsel *leader = evsel->leader;
 
-	if (stat_config.scale) {
+	if (config->scale) {
 		attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
 				    PERF_FORMAT_TOTAL_TIME_RUNNING;
 	}

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf stat: Add 'identifier' flag to 'struct perf_stat_config'
  2018-08-30  6:32 ` [PATCH 05/43] perf stat: Add identifier flag into struct stat_opts Jiri Olsa
@ 2018-09-06 13:23   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:23 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, alexander.shishkin, mingo, peterz, acme, andi,
	namhyung, dsahern, hpa, jolsa, tglx

Commit-ID:  7d9ad16afe2bfc73b8967cc2aa2dc30f0170a8e2
Gitweb:     https://git.kernel.org/tip/7d9ad16afe2bfc73b8967cc2aa2dc30f0170a8e2
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:14 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:21 -0300

perf stat: Add 'identifier' flag to 'struct perf_stat_config'

Add 'identifier' flag to 'struct perf_stat_config' to carry the info
whether to use PERF_SAMPLE_IDENTIFIER for events.

This makes create_perf_stat_counter() independent.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-6-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 22 ++++++++++++----------
 tools/perf/util/stat.h    |  1 +
 2 files changed, 13 insertions(+), 10 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 47789558899a..48c88f568fe1 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -261,16 +261,7 @@ static int create_perf_stat_counter(struct perf_evsel *evsel,
 	 */
 	attr->sample_period = 0;
 
-	/*
-	 * But set sample_type to PERF_SAMPLE_IDENTIFIER, which should be harmless
-	 * while avoiding that older tools show confusing messages.
-	 *
-	 * However for pipe sessions we need to keep it zero,
-	 * because script's perf_evsel__check_attr is triggered
-	 * by attr->sample_type != 0, and we can't run it on
-	 * stat sessions.
-	 */
-	if (!(STAT_RECORD && perf_stat.data.is_pipe))
+	if (config->identifier)
 		attr->sample_type = PERF_SAMPLE_IDENTIFIER;
 
 	/*
@@ -3064,6 +3055,17 @@ int cmd_stat(int argc, const char **argv)
 	if (perf_stat_init_aggr_mode())
 		goto out;
 
+	/*
+	 * Set sample_type to PERF_SAMPLE_IDENTIFIER, which should be harmless
+	 * while avoiding that older tools show confusing messages.
+	 *
+	 * However for pipe sessions we need to keep it zero,
+	 * because script's perf_evsel__check_attr is triggered
+	 * by attr->sample_type != 0, and we can't run it on
+	 * stat sessions.
+	 */
+	stat_config.identifier = !(STAT_RECORD && perf_stat.data.is_pipe);
+
 	/*
 	 * We dont want to block the signals - that would cause
 	 * child tasks to inherit that and Ctrl-C would not work.
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 53b2415ba3f3..918cde064cdc 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -89,6 +89,7 @@ struct perf_stat_config {
 	enum aggr_mode		 aggr_mode;
 	bool			 scale;
 	bool			 no_inherit;
+	bool			 identifier;
 	FILE			*output;
 	unsigned int		 interval;
 	unsigned int		 timeout;

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf tools: Switch 'session' argument to 'evlist' in perf_event__synthesize_attrs()
  2018-08-30  6:32 ` [PATCH 06/43] perf tools: Switch session argument to evlist in perf_event__synthesize_attrs Jiri Olsa
@ 2018-09-06 13:23   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:23 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: alexander.shishkin, jolsa, linux-kernel, dsahern, peterz, tglx,
	acme, namhyung, andi, hpa, mingo

Commit-ID:  318ec1841a3f26799fe663d8f979a57623c0c470
Gitweb:     https://git.kernel.org/tip/318ec1841a3f26799fe663d8f979a57623c0c470
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:15 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:21 -0300

perf tools: Switch 'session' argument to 'evlist' in perf_event__synthesize_attrs()

To be able to pass in other than session's evlist.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-7-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-record.c | 2 +-
 tools/perf/builtin-stat.c   | 2 +-
 tools/perf/util/header.c    | 6 +++---
 tools/perf/util/header.h    | 2 +-
 4 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 22ebeb92ac51..9853552bcf16 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -758,7 +758,7 @@ static int record__synthesize(struct record *rec, bool tail)
 		 * We need to synthesize events first, because some
 		 * features works on top of them (on report side).
 		 */
-		err = perf_event__synthesize_attrs(tool, session,
+		err = perf_event__synthesize_attrs(tool, rec->evlist,
 						   process_synthesized_event);
 		if (err < 0) {
 			pr_err("Couldn't synthesize attrs.\n");
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 48c88f568fe1..8291f503d0cc 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -459,7 +459,7 @@ static int perf_stat_synthesize_config(bool is_pipe)
 	int err;
 
 	if (is_pipe) {
-		err = perf_event__synthesize_attrs(NULL, perf_stat.session,
+		err = perf_event__synthesize_attrs(NULL, evsel_list,
 						   process_synthesized_event);
 		if (err < 0) {
 			pr_err("Couldn't synthesize attrs.\n");
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 3cadc252dd89..91e6d9cfd906 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -3637,13 +3637,13 @@ size_t perf_event__fprintf_event_update(union perf_event *event, FILE *fp)
 }
 
 int perf_event__synthesize_attrs(struct perf_tool *tool,
-				   struct perf_session *session,
-				   perf_event__handler_t process)
+				 struct perf_evlist *evlist,
+				 perf_event__handler_t process)
 {
 	struct perf_evsel *evsel;
 	int err = 0;
 
-	evlist__for_each_entry(session->evlist, evsel) {
+	evlist__for_each_entry(evlist, evsel) {
 		err = perf_event__synthesize_attr(tool, &evsel->attr, evsel->ids,
 						  evsel->id, process);
 		if (err) {
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 6d7fe44aadc0..ff2a1263fb9b 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -124,7 +124,7 @@ int perf_event__synthesize_attr(struct perf_tool *tool,
 				struct perf_event_attr *attr, u32 ids, u64 *id,
 				perf_event__handler_t process);
 int perf_event__synthesize_attrs(struct perf_tool *tool,
-				 struct perf_session *session,
+				 struct perf_evlist *evlist,
 				 perf_event__handler_t process);
 int perf_event__synthesize_event_update_unit(struct perf_tool *tool,
 					     struct perf_evsel *evsel,

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf evsel: Introduce perf_evsel__store_ids()
  2018-08-30  6:32 ` [PATCH 07/43] perf tools: Add perf_evsel__store_ids function Jiri Olsa
@ 2018-09-06 13:24   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:24 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: andi, jolsa, namhyung, alexander.shishkin, tglx, mingo,
	linux-kernel, peterz, hpa, dsahern, acme

Commit-ID:  650d622046024623e71fea1f28acf1edb7e61a81
Gitweb:     https://git.kernel.org/tip/650d622046024623e71fea1f28acf1edb7e61a81
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:16 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:21 -0300

perf evsel: Introduce perf_evsel__store_ids()

Add perf_evsel__store_ids() from stat's store_counter_ids() code to the
evsel class, so that it can be used globally.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-8-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 33 +--------------------------------
 tools/perf/util/evsel.c   | 29 +++++++++++++++++++++++++++++
 tools/perf/util/evsel.h   |  1 +
 3 files changed, 31 insertions(+), 32 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 8291f503d0cc..45bbd156d496 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -497,37 +497,6 @@ static int perf_stat_synthesize_config(bool is_pipe)
 	return 0;
 }
 
-#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
-
-static int __store_counter_ids(struct perf_evsel *counter)
-{
-	int cpu, thread;
-
-	for (cpu = 0; cpu < xyarray__max_x(counter->fd); cpu++) {
-		for (thread = 0; thread < xyarray__max_y(counter->fd);
-		     thread++) {
-			int fd = FD(counter, cpu, thread);
-
-			if (perf_evlist__id_add_fd(evsel_list, counter,
-						   cpu, thread, fd) < 0)
-				return -1;
-		}
-	}
-
-	return 0;
-}
-
-static int store_counter_ids(struct perf_evsel *counter)
-{
-	struct cpu_map *cpus = counter->cpus;
-	struct thread_map *threads = counter->threads;
-
-	if (perf_evsel__alloc_id(counter, cpus->nr, threads->nr))
-		return -ENOMEM;
-
-	return __store_counter_ids(counter);
-}
-
 static bool perf_evsel__should_store_id(struct perf_evsel *counter)
 {
 	return STAT_RECORD || counter->attr.read_format & PERF_FORMAT_ID;
@@ -658,7 +627,7 @@ try_again:
 			unit_width = l;
 
 		if (perf_evsel__should_store_id(counter) &&
-		    store_counter_ids(counter))
+		    perf_evsel__store_ids(counter, evsel_list))
 			return -1;
 	}
 
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 1a61628a1c12..4ec909d57e9c 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -2940,3 +2940,32 @@ struct perf_env *perf_evsel__env(struct perf_evsel *evsel)
 		return evsel->evlist->env;
 	return NULL;
 }
+
+static int store_evsel_ids(struct perf_evsel *evsel, struct perf_evlist *evlist)
+{
+	int cpu, thread;
+
+	for (cpu = 0; cpu < xyarray__max_x(evsel->fd); cpu++) {
+		for (thread = 0; thread < xyarray__max_y(evsel->fd);
+		     thread++) {
+			int fd = FD(evsel, cpu, thread);
+
+			if (perf_evlist__id_add_fd(evlist, evsel,
+						   cpu, thread, fd) < 0)
+				return -1;
+		}
+	}
+
+	return 0;
+}
+
+int perf_evsel__store_ids(struct perf_evsel *evsel, struct perf_evlist *evlist)
+{
+	struct cpu_map *cpus = evsel->cpus;
+	struct thread_map *threads = evsel->threads;
+
+	if (perf_evsel__alloc_id(evsel, cpus->nr, threads->nr))
+		return -ENOMEM;
+
+	return store_evsel_ids(evsel, evlist);
+}
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 163c960614d3..4f8430a85531 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -481,4 +481,5 @@ int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr,
 
 struct perf_env *perf_evsel__env(struct perf_evsel *evsel);
 
+int perf_evsel__store_ids(struct perf_evsel *evsel, struct perf_evlist *evlist);
 #endif /* __PERF_EVSEL_H */

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf stat: Move create_perf_stat_counter() to stat.c
  2018-08-30  6:32 ` [PATCH 08/43] perf stat: Move create_perf_stat_counter into stat.c Jiri Olsa
@ 2018-09-06 13:24   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:24 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: acme, dsahern, linux-kernel, mingo, jolsa, hpa,
	alexander.shishkin, peterz, namhyung, andi, tglx

Commit-ID:  d09cefd2ef9945b4b767bb67f473a0eb2066374f
Gitweb:     https://git.kernel.org/tip/d09cefd2ef9945b4b767bb67f473a0eb2066374f
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:17 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:22 -0300

perf stat: Move create_perf_stat_counter() to stat.c

Move create_perf_stat_counter() to the 'stat' class, so that we can use
it globally.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-9-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 54 +----------------------------------------------
 tools/perf/util/stat.c    | 53 ++++++++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/stat.h    |  4 ++++
 3 files changed, 58 insertions(+), 53 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 45bbd156d496..142cff8eb12b 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -234,58 +234,6 @@ static void perf_stat__reset_stats(void)
 		perf_stat__reset_shadow_per_stat(&stat_config.stats[i]);
 }
 
-static int create_perf_stat_counter(struct perf_evsel *evsel,
-				    struct perf_stat_config *config)
-{
-	struct perf_event_attr *attr = &evsel->attr;
-	struct perf_evsel *leader = evsel->leader;
-
-	if (config->scale) {
-		attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
-				    PERF_FORMAT_TOTAL_TIME_RUNNING;
-	}
-
-	/*
-	 * The event is part of non trivial group, let's enable
-	 * the group read (for leader) and ID retrieval for all
-	 * members.
-	 */
-	if (leader->nr_members > 1)
-		attr->read_format |= PERF_FORMAT_ID|PERF_FORMAT_GROUP;
-
-	attr->inherit = !config->no_inherit;
-
-	/*
-	 * Some events get initialized with sample_(period/type) set,
-	 * like tracepoints. Clear it up for counting.
-	 */
-	attr->sample_period = 0;
-
-	if (config->identifier)
-		attr->sample_type = PERF_SAMPLE_IDENTIFIER;
-
-	/*
-	 * Disabling all counters initially, they will be enabled
-	 * either manually by us or by kernel via enable_on_exec
-	 * set later.
-	 */
-	if (perf_evsel__is_group_leader(evsel)) {
-		attr->disabled = 1;
-
-		/*
-		 * In case of initial_delay we enable tracee
-		 * events manually.
-		 */
-		if (target__none(&target) && !config->initial_delay)
-			attr->enable_on_exec = 1;
-	}
-
-	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->threads);
-}
-
 static int process_synthesized_event(struct perf_tool *tool __maybe_unused,
 				     union perf_event *event,
 				     struct perf_sample *sample __maybe_unused,
@@ -568,7 +516,7 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
 
 	evlist__for_each_entry(evsel_list, counter) {
 try_again:
-		if (create_perf_stat_counter(counter, &stat_config) < 0) {
+		if (create_perf_stat_counter(counter, &stat_config, &target) < 0) {
 
 			/* Weak group failed. Reset the group. */
 			if ((errno == EINVAL || errno == EBADF) &&
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index a0061e0b0fad..3bd24255376a 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -435,3 +435,56 @@ size_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp)
 
 	return ret;
 }
+
+int create_perf_stat_counter(struct perf_evsel *evsel,
+			     struct perf_stat_config *config,
+			     struct target *target)
+{
+	struct perf_event_attr *attr = &evsel->attr;
+	struct perf_evsel *leader = evsel->leader;
+
+	if (config->scale) {
+		attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
+				    PERF_FORMAT_TOTAL_TIME_RUNNING;
+	}
+
+	/*
+	 * The event is part of non trivial group, let's enable
+	 * the group read (for leader) and ID retrieval for all
+	 * members.
+	 */
+	if (leader->nr_members > 1)
+		attr->read_format |= PERF_FORMAT_ID|PERF_FORMAT_GROUP;
+
+	attr->inherit = !config->no_inherit;
+
+	/*
+	 * Some events get initialized with sample_(period/type) set,
+	 * like tracepoints. Clear it up for counting.
+	 */
+	attr->sample_period = 0;
+
+	if (config->identifier)
+		attr->sample_type = PERF_SAMPLE_IDENTIFIER;
+
+	/*
+	 * Disabling all counters initially, they will be enabled
+	 * either manually by us or by kernel via enable_on_exec
+	 * set later.
+	 */
+	if (perf_evsel__is_group_leader(evsel)) {
+		attr->disabled = 1;
+
+		/*
+		 * In case of initial_delay we enable tracee
+		 * events manually.
+		 */
+		if (target__none(target) && !config->initial_delay)
+			attr->enable_on_exec = 1;
+	}
+
+	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->threads);
+}
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 918cde064cdc..8fb596641545 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -175,4 +175,8 @@ int perf_event__process_stat_event(struct perf_tool *tool,
 size_t perf_event__fprintf_stat(union perf_event *event, FILE *fp);
 size_t perf_event__fprintf_stat_round(union perf_event *event, FILE *fp);
 size_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp);
+
+int create_perf_stat_counter(struct perf_evsel *evsel,
+			     struct perf_stat_config *config,
+			     struct target *target);
 #endif

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf stat: Rename 'is_pipe' argument to 'attrs' in perf_stat_synthesize_config()
  2018-08-30  6:32 ` [PATCH 09/43] perf stat: Rename is_pipe argument to attrs perf_stat_synthesize_config Jiri Olsa
@ 2018-09-06 13:25   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:25 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: hpa, jolsa, tglx, linux-kernel, alexander.shishkin, dsahern,
	mingo, acme, andi, namhyung, peterz

Commit-ID:  491073a6126644d3c60b677b777006deb3c0e16b
Gitweb:     https://git.kernel.org/tip/491073a6126644d3c60b677b777006deb3c0e16b
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:18 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:22 -0300

perf stat: Rename 'is_pipe' argument to 'attrs' in perf_stat_synthesize_config()

The attrs name makes more sense.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-10-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 142cff8eb12b..0a358c2e1a93 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -402,11 +402,11 @@ static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *inf
 	workload_exec_errno = info->si_value.sival_int;
 }
 
-static int perf_stat_synthesize_config(bool is_pipe)
+static int perf_stat_synthesize_config(bool attrs)
 {
 	int err;
 
-	if (is_pipe) {
+	if (attrs) {
 		err = perf_event__synthesize_attrs(NULL, evsel_list,
 						   process_synthesized_event);
 		if (err < 0) {
@@ -418,7 +418,7 @@ static int perf_stat_synthesize_config(bool is_pipe)
 	err = perf_event__synthesize_extra_attr(NULL,
 						evsel_list,
 						process_synthesized_event,
-						is_pipe);
+						attrs);
 
 	err = perf_event__synthesize_thread_map2(NULL, evsel_list->threads,
 						process_synthesized_event,

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf stat: Add 'struct perf_stat_config' argument to perf_stat_synthesize_config()
  2018-08-30  6:32 ` [PATCH 10/43] perf stat: Add struct perf_stat_config argument to perf_stat_synthesize_config Jiri Olsa
@ 2018-09-06 13:26   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:26 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: acme, andi, linux-kernel, hpa, dsahern, alexander.shishkin,
	peterz, jolsa, mingo, namhyung, tglx

Commit-ID:  73d586c3917d5109bb547c16d90d0eb97203986a
Gitweb:     https://git.kernel.org/tip/73d586c3917d5109bb547c16d90d0eb97203986a
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:19 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:22 -0300

perf stat: Add 'struct perf_stat_config' argument to perf_stat_synthesize_config()

Add a 'struct perf_stat_config' argument to perf_stat_synthesize_config(),
so we could synthesize arbitrary config.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-11-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 0a358c2e1a93..d0d19a5ffa85 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -402,7 +402,8 @@ static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *inf
 	workload_exec_errno = info->si_value.sival_int;
 }
 
-static int perf_stat_synthesize_config(bool attrs)
+static int perf_stat_synthesize_config(struct perf_stat_config *config,
+				       bool attrs)
 {
 	int err;
 
@@ -435,7 +436,7 @@ static int perf_stat_synthesize_config(bool attrs)
 		return err;
 	}
 
-	err = perf_event__synthesize_stat_config(NULL, &stat_config,
+	err = perf_event__synthesize_stat_config(NULL, config,
 						 process_synthesized_event, NULL);
 	if (err < 0) {
 		pr_err("Couldn't synthesize config.\n");
@@ -606,7 +607,7 @@ try_again:
 		if (err < 0)
 			return err;
 
-		err = perf_stat_synthesize_config(is_pipe);
+		err = perf_stat_synthesize_config(&stat_config, is_pipe);
 		if (err < 0)
 			return err;
 	}

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf stat: Add 'struct perf_tool' argument to perf_stat_synthesize_config()
  2018-08-30  6:32 ` [PATCH 11/43] perf stat: Add struct perf_tool argument to perf_stat_synthesize_config Jiri Olsa
@ 2018-09-06 13:26   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:26 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: alexander.shishkin, linux-kernel, andi, tglx, mingo, jolsa,
	namhyung, dsahern, peterz, acme, hpa

Commit-ID:  1821f4eb480bdd3c7c2a1863431ba539c7b0c1f8
Gitweb:     https://git.kernel.org/tip/1821f4eb480bdd3c7c2a1863431ba539c7b0c1f8
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:20 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:22 -0300

perf stat: Add 'struct perf_tool' argument to perf_stat_synthesize_config()

So that we can use the function outside the 'perf stat' command with standard
synthesize functions, that take 'struct perf_tool *' argument.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-12-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index d0d19a5ffa85..ae5029875e87 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -403,12 +403,13 @@ static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *inf
 }
 
 static int perf_stat_synthesize_config(struct perf_stat_config *config,
+				       struct perf_tool *tool,
 				       bool attrs)
 {
 	int err;
 
 	if (attrs) {
-		err = perf_event__synthesize_attrs(NULL, evsel_list,
+		err = perf_event__synthesize_attrs(tool, evsel_list,
 						   process_synthesized_event);
 		if (err < 0) {
 			pr_err("Couldn't synthesize attrs.\n");
@@ -416,12 +417,12 @@ static int perf_stat_synthesize_config(struct perf_stat_config *config,
 		}
 	}
 
-	err = perf_event__synthesize_extra_attr(NULL,
+	err = perf_event__synthesize_extra_attr(tool,
 						evsel_list,
 						process_synthesized_event,
 						attrs);
 
-	err = perf_event__synthesize_thread_map2(NULL, evsel_list->threads,
+	err = perf_event__synthesize_thread_map2(tool, evsel_list->threads,
 						process_synthesized_event,
 						NULL);
 	if (err < 0) {
@@ -429,14 +430,14 @@ static int perf_stat_synthesize_config(struct perf_stat_config *config,
 		return err;
 	}
 
-	err = perf_event__synthesize_cpu_map(NULL, evsel_list->cpus,
+	err = perf_event__synthesize_cpu_map(tool, evsel_list->cpus,
 					     process_synthesized_event, NULL);
 	if (err < 0) {
 		pr_err("Couldn't synthesize thread map.\n");
 		return err;
 	}
 
-	err = perf_event__synthesize_stat_config(NULL, config,
+	err = perf_event__synthesize_stat_config(tool, config,
 						 process_synthesized_event, NULL);
 	if (err < 0) {
 		pr_err("Couldn't synthesize config.\n");
@@ -607,7 +608,7 @@ try_again:
 		if (err < 0)
 			return err;
 
-		err = perf_stat_synthesize_config(&stat_config, is_pipe);
+		err = perf_stat_synthesize_config(&stat_config, NULL, is_pipe);
 		if (err < 0)
 			return err;
 	}

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf stat: Add 'struct perf_evlist' argument to perf_stat_synthesize_config()
  2018-08-30  6:32 ` [PATCH 12/43] perf stat: Add struct perf_evlist argument to perf_stat_synthesize_config Jiri Olsa
@ 2018-09-06 13:27   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:27 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: alexander.shishkin, acme, andi, peterz, mingo, dsahern, hpa,
	namhyung, tglx, linux-kernel, jolsa

Commit-ID:  1c21e9899d6a9ea72d4d678faa7b0ec22bcf59a9
Gitweb:     https://git.kernel.org/tip/1c21e9899d6a9ea72d4d678faa7b0ec22bcf59a9
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:21 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:22 -0300

perf stat: Add 'struct perf_evlist' argument to perf_stat_synthesize_config()

Get rid of the 'evsel_list' global variable dependency, here in
perf_stat_synthesize_config() we are adding the 'evlist' arg.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-13-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index ae5029875e87..cb36344c25b7 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -404,12 +404,13 @@ static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *inf
 
 static int perf_stat_synthesize_config(struct perf_stat_config *config,
 				       struct perf_tool *tool,
+				       struct perf_evlist *evlist,
 				       bool attrs)
 {
 	int err;
 
 	if (attrs) {
-		err = perf_event__synthesize_attrs(tool, evsel_list,
+		err = perf_event__synthesize_attrs(tool, evlist,
 						   process_synthesized_event);
 		if (err < 0) {
 			pr_err("Couldn't synthesize attrs.\n");
@@ -417,12 +418,11 @@ static int perf_stat_synthesize_config(struct perf_stat_config *config,
 		}
 	}
 
-	err = perf_event__synthesize_extra_attr(tool,
-						evsel_list,
+	err = perf_event__synthesize_extra_attr(tool, evlist,
 						process_synthesized_event,
 						attrs);
 
-	err = perf_event__synthesize_thread_map2(tool, evsel_list->threads,
+	err = perf_event__synthesize_thread_map2(tool, evlist->threads,
 						process_synthesized_event,
 						NULL);
 	if (err < 0) {
@@ -430,7 +430,7 @@ static int perf_stat_synthesize_config(struct perf_stat_config *config,
 		return err;
 	}
 
-	err = perf_event__synthesize_cpu_map(tool, evsel_list->cpus,
+	err = perf_event__synthesize_cpu_map(tool, evlist->cpus,
 					     process_synthesized_event, NULL);
 	if (err < 0) {
 		pr_err("Couldn't synthesize thread map.\n");
@@ -608,7 +608,8 @@ try_again:
 		if (err < 0)
 			return err;
 
-		err = perf_stat_synthesize_config(&stat_config, NULL, is_pipe);
+		err = perf_stat_synthesize_config(&stat_config, NULL, evsel_list,
+						  is_pipe);
 		if (err < 0)
 			return err;
 	}

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf stat: Add 'perf_event__handler_t' argument to perf_stat_synthesize_config()
  2018-08-30  6:32 ` [PATCH 13/43] perf stat: Add perf_event__handler_t argument to perf_stat_synthesize_config Jiri Olsa
@ 2018-09-06 13:27   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:27 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: andi, linux-kernel, hpa, mingo, namhyung, peterz,
	alexander.shishkin, acme, tglx, dsahern, jolsa

Commit-ID:  c2c247f2dd87706961fa16d033f9dbf173145e70
Gitweb:     https://git.kernel.org/tip/c2c247f2dd87706961fa16d033f9dbf173145e70
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:22 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:22 -0300

perf stat: Add 'perf_event__handler_t' argument to perf_stat_synthesize_config()

So that it's completely independent and can be used outside the 'perf stat' command.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-14-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 17 +++++++----------
 1 file changed, 7 insertions(+), 10 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index cb36344c25b7..1171d4e00276 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -405,40 +405,37 @@ static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *inf
 static int perf_stat_synthesize_config(struct perf_stat_config *config,
 				       struct perf_tool *tool,
 				       struct perf_evlist *evlist,
+				       perf_event__handler_t process,
 				       bool attrs)
 {
 	int err;
 
 	if (attrs) {
-		err = perf_event__synthesize_attrs(tool, evlist,
-						   process_synthesized_event);
+		err = perf_event__synthesize_attrs(tool, evlist, process);
 		if (err < 0) {
 			pr_err("Couldn't synthesize attrs.\n");
 			return err;
 		}
 	}
 
-	err = perf_event__synthesize_extra_attr(tool, evlist,
-						process_synthesized_event,
+	err = perf_event__synthesize_extra_attr(tool, evlist, process,
 						attrs);
 
 	err = perf_event__synthesize_thread_map2(tool, evlist->threads,
-						process_synthesized_event,
-						NULL);
+						 process, NULL);
 	if (err < 0) {
 		pr_err("Couldn't synthesize thread map.\n");
 		return err;
 	}
 
 	err = perf_event__synthesize_cpu_map(tool, evlist->cpus,
-					     process_synthesized_event, NULL);
+					     process, NULL);
 	if (err < 0) {
 		pr_err("Couldn't synthesize thread map.\n");
 		return err;
 	}
 
-	err = perf_event__synthesize_stat_config(tool, config,
-						 process_synthesized_event, NULL);
+	err = perf_event__synthesize_stat_config(tool, config, process, NULL);
 	if (err < 0) {
 		pr_err("Couldn't synthesize config.\n");
 		return err;
@@ -609,7 +606,7 @@ try_again:
 			return err;
 
 		err = perf_stat_synthesize_config(&stat_config, NULL, evsel_list,
-						  is_pipe);
+						  process_synthesized_event, is_pipe);
 		if (err < 0)
 			return err;
 	}

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf stat: Move perf_stat_synthesize_config() to stat.c
  2018-08-30  6:32 ` [PATCH 14/43] perf stat: Move perf_stat_synthesize_config into stat.c Jiri Olsa
@ 2018-09-06 13:28   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:28 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: mingo, alexander.shishkin, tglx, acme, andi, dsahern, namhyung,
	jolsa, peterz, hpa, linux-kernel

Commit-ID:  0a4e64d391a2c771ae33e648cf84d4492369560c
Gitweb:     https://git.kernel.org/tip/0a4e64d391a2c771ae33e648cf84d4492369560c
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:23 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:22 -0300

perf stat: Move perf_stat_synthesize_config() to stat.c

So that it can be used globally.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-15-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 42 ------------------------------------------
 tools/perf/util/stat.c    | 42 ++++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/stat.h    |  6 ++++++
 3 files changed, 48 insertions(+), 42 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 1171d4e00276..54768ec15dbc 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -402,48 +402,6 @@ static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *inf
 	workload_exec_errno = info->si_value.sival_int;
 }
 
-static int perf_stat_synthesize_config(struct perf_stat_config *config,
-				       struct perf_tool *tool,
-				       struct perf_evlist *evlist,
-				       perf_event__handler_t process,
-				       bool attrs)
-{
-	int err;
-
-	if (attrs) {
-		err = perf_event__synthesize_attrs(tool, evlist, process);
-		if (err < 0) {
-			pr_err("Couldn't synthesize attrs.\n");
-			return err;
-		}
-	}
-
-	err = perf_event__synthesize_extra_attr(tool, evlist, process,
-						attrs);
-
-	err = perf_event__synthesize_thread_map2(tool, evlist->threads,
-						 process, NULL);
-	if (err < 0) {
-		pr_err("Couldn't synthesize thread map.\n");
-		return err;
-	}
-
-	err = perf_event__synthesize_cpu_map(tool, evlist->cpus,
-					     process, NULL);
-	if (err < 0) {
-		pr_err("Couldn't synthesize thread map.\n");
-		return err;
-	}
-
-	err = perf_event__synthesize_stat_config(tool, config, process, NULL);
-	if (err < 0) {
-		pr_err("Couldn't synthesize config.\n");
-		return err;
-	}
-
-	return 0;
-}
-
 static bool perf_evsel__should_store_id(struct perf_evsel *counter)
 {
 	return STAT_RECORD || counter->attr.read_format & PERF_FORMAT_ID;
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index 3bd24255376a..5d3172bcc4ae 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -488,3 +488,45 @@ int create_perf_stat_counter(struct perf_evsel *evsel,
 
 	return perf_evsel__open_per_thread(evsel, evsel->threads);
 }
+
+int perf_stat_synthesize_config(struct perf_stat_config *config,
+				struct perf_tool *tool,
+				struct perf_evlist *evlist,
+				perf_event__handler_t process,
+				bool attrs)
+{
+	int err;
+
+	if (attrs) {
+		err = perf_event__synthesize_attrs(tool, evlist, process);
+		if (err < 0) {
+			pr_err("Couldn't synthesize attrs.\n");
+			return err;
+		}
+	}
+
+	err = perf_event__synthesize_extra_attr(tool, evlist, process,
+						attrs);
+
+	err = perf_event__synthesize_thread_map2(tool, evlist->threads,
+						 process, NULL);
+	if (err < 0) {
+		pr_err("Couldn't synthesize thread map.\n");
+		return err;
+	}
+
+	err = perf_event__synthesize_cpu_map(tool, evlist->cpus,
+					     process, NULL);
+	if (err < 0) {
+		pr_err("Couldn't synthesize thread map.\n");
+		return err;
+	}
+
+	err = perf_event__synthesize_stat_config(tool, config, process, NULL);
+	if (err < 0) {
+		pr_err("Couldn't synthesize config.\n");
+		return err;
+	}
+
+	return 0;
+}
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 8fb596641545..da6a706daecc 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -7,6 +7,7 @@
 #include "xyarray.h"
 #include "rblist.h"
 #include "perf.h"
+#include "event.h"
 
 struct stats {
 	double n, mean, M2;
@@ -179,4 +180,9 @@ size_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp);
 int create_perf_stat_counter(struct perf_evsel *evsel,
 			     struct perf_stat_config *config,
 			     struct target *target);
+int perf_stat_synthesize_config(struct perf_stat_config *config,
+				struct perf_tool *tool,
+				struct perf_evlist *evlist,
+				perf_event__handler_t process,
+				bool attrs);
 #endif

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf stat: Introduce perf_evlist__print_counters()
  2018-08-30  6:32 ` [PATCH 15/43] perf stat: Add perf_evlist__print_counters function Jiri Olsa
@ 2018-09-06 13:28   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:28 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: jolsa, acme, tglx, peterz, mingo, namhyung, andi,
	alexander.shishkin, dsahern, hpa, linux-kernel

Commit-ID:  a5a9eac1a018ad3bfcf9a3ec11eae99fd35f466b
Gitweb:     https://git.kernel.org/tip/a5a9eac1a018ad3bfcf9a3ec11eae99fd35f466b
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:24 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:22 -0300

perf stat: Introduce perf_evlist__print_counters()

To be in charge of printing out the stat output. It will be moved out of
the 'perf stat' command in the following patches.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-16-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 54768ec15dbc..db11832bbdbc 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1692,7 +1692,10 @@ static void print_footer(void)
 			"the same PMU. Try reorganizing the group.\n");
 }
 
-static void print_counters(struct timespec *ts, int argc, const char **argv)
+static void
+perf_evlist__print_counters(struct perf_evlist *evlist,
+			    struct timespec *ts,
+			    int argc, const char **argv)
 {
 	int interval = stat_config.interval;
 	struct perf_evsel *counter;
@@ -1724,14 +1727,14 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)
 		print_aggr(prefix);
 		break;
 	case AGGR_THREAD:
-		evlist__for_each_entry(evsel_list, counter) {
+		evlist__for_each_entry(evlist, counter) {
 			if (is_duration_time(counter))
 				continue;
 			print_aggr_thread(counter, prefix);
 		}
 		break;
 	case AGGR_GLOBAL:
-		evlist__for_each_entry(evsel_list, counter) {
+		evlist__for_each_entry(evlist, counter) {
 			if (is_duration_time(counter))
 				continue;
 			print_counter_aggr(counter, prefix);
@@ -1743,7 +1746,7 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)
 		if (metric_only)
 			print_no_aggr_metric(prefix);
 		else {
-			evlist__for_each_entry(evsel_list, counter) {
+			evlist__for_each_entry(evlist, counter) {
 				if (is_duration_time(counter))
 					continue;
 				print_counter(counter, prefix);
@@ -1761,6 +1764,11 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)
 	fflush(stat_config.output);
 }
 
+static void print_counters(struct timespec *ts, int argc, const char **argv)
+{
+	perf_evlist__print_counters(evsel_list, ts, argc, argv);
+}
+
 static volatile int signr = -1;
 
 static void skip_signal(int signo)

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf stat: Move STAT_RECORD out of perf_evlist__print_counters()
  2018-08-30  6:32 ` [PATCH 16/43] perf stat: Move STAT_RECORD out of perf_evlist__print_counters Jiri Olsa
@ 2018-09-06 13:29   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:29 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: jolsa, linux-kernel, hpa, peterz, alexander.shishkin, dsahern,
	mingo, namhyung, tglx, acme, andi

Commit-ID:  0174820a8ba108f2e72dac5caaea3500c8ca6323
Gitweb:     https://git.kernel.org/tip/0174820a8ba108f2e72dac5caaea3500c8ca6323
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:25 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:22 -0300

perf stat: Move STAT_RECORD out of perf_evlist__print_counters()

It's stat related and should stay in the 'perf stat' command.  The
perf_evlist__print_counters function will be moved out in the following
patches.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-17-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index db11832bbdbc..4ffbb6594eb6 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1701,10 +1701,6 @@ perf_evlist__print_counters(struct perf_evlist *evlist,
 	struct perf_evsel *counter;
 	char buf[64], *prefix = NULL;
 
-	/* Do not print anything if we record to the pipe. */
-	if (STAT_RECORD && perf_stat.data.is_pipe)
-		return;
-
 	if (interval)
 		print_interval(prefix = buf, ts);
 	else
@@ -1766,6 +1762,10 @@ perf_evlist__print_counters(struct perf_evlist *evlist,
 
 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;
+
 	perf_evlist__print_counters(evsel_list, ts, argc, argv);
 }
 

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf stat: Add 'struct perf_stat_config' argument to perf_evlist__print_counters()
  2018-08-30  6:32 ` [PATCH 17/43] perf stat: Add stat_config argument to perf_evlist__print_counters Jiri Olsa
@ 2018-09-06 13:29   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:29 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: mingo, hpa, andi, dsahern, namhyung, peterz, linux-kernel, tglx,
	acme, alexander.shishkin, jolsa

Commit-ID:  b64df7f33743cd6095b4a007f5f15ff4432fbcf5
Gitweb:     https://git.kernel.org/tip/b64df7f33743cd6095b4a007f5f15ff4432fbcf5
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:26 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:22 -0300

perf stat: Add 'struct perf_stat_config' argument to perf_evlist__print_counters()

Add a 'struct perf_stat_config' argument to perf_evlist__print_counters(),
so that it can be moved out of the 'perf stat' command to generic object
in the following patches.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-18-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 4ffbb6594eb6..f340641fe63a 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1694,10 +1694,11 @@ static void print_footer(void)
 
 static void
 perf_evlist__print_counters(struct perf_evlist *evlist,
+			    struct perf_stat_config *config,
 			    struct timespec *ts,
 			    int argc, const char **argv)
 {
-	int interval = stat_config.interval;
+	int interval = config->interval;
 	struct perf_evsel *counter;
 	char buf[64], *prefix = NULL;
 
@@ -1713,11 +1714,11 @@ perf_evlist__print_counters(struct perf_evlist *evlist,
 			print_metric_headers(prefix, false);
 		if (num_print_iv++ == 25)
 			num_print_iv = 0;
-		if (stat_config.aggr_mode == AGGR_GLOBAL && prefix)
-			fprintf(stat_config.output, "%s", prefix);
+		if (config->aggr_mode == AGGR_GLOBAL && prefix)
+			fprintf(config->output, "%s", prefix);
 	}
 
-	switch (stat_config.aggr_mode) {
+	switch (config->aggr_mode) {
 	case AGGR_CORE:
 	case AGGR_SOCKET:
 		print_aggr(prefix);
@@ -1736,7 +1737,7 @@ perf_evlist__print_counters(struct perf_evlist *evlist,
 			print_counter_aggr(counter, prefix);
 		}
 		if (metric_only)
-			fputc('\n', stat_config.output);
+			fputc('\n', config->output);
 		break;
 	case AGGR_NONE:
 		if (metric_only)
@@ -1757,7 +1758,7 @@ perf_evlist__print_counters(struct perf_evlist *evlist,
 	if (!interval && !csv_output)
 		print_footer();
 
-	fflush(stat_config.output);
+	fflush(config->output);
 }
 
 static void print_counters(struct timespec *ts, int argc, const char **argv)
@@ -1766,7 +1767,8 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)
 	if (STAT_RECORD && perf_stat.data.is_pipe)
 		return;
 
-	perf_evlist__print_counters(evsel_list, ts, argc, argv);
+	perf_evlist__print_counters(evsel_list, &stat_config,
+				    ts, argc, argv);
 }
 
 static volatile int signr = -1;

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf stat: Pass 'struct perf_stat_config' argument to local print functions
  2018-08-30  6:32 ` [PATCH 18/43] perf stat: Pass stat_config argument to local print functions Jiri Olsa
@ 2018-09-06 13:30   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:30 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: namhyung, acme, dsahern, mingo, alexander.shishkin, peterz, tglx,
	hpa, linux-kernel, andi, jolsa

Commit-ID:  f3ca50e61ff4aebfbefc666be2e064d277ad524c
Gitweb:     https://git.kernel.org/tip/f3ca50e61ff4aebfbefc666be2e064d277ad524c
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:27 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:23 -0300

perf stat: Pass 'struct perf_stat_config' argument to local print functions

Add 'struct perf_stat_config' argument to print functions, so that those
functions can be moved out of the 'perf stat' command to a generic class
in the following patches.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-19-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 149 +++++++++++++++++++++++++---------------------
 1 file changed, 80 insertions(+), 69 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index f340641fe63a..f56da22abccc 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -660,30 +660,33 @@ static int run_perf_stat(int argc, const char **argv, int run_idx)
 	return ret;
 }
 
-static void print_running(u64 run, u64 ena)
+static void print_running(struct perf_stat_config *config,
+			  u64 run, u64 ena)
 {
 	if (csv_output) {
-		fprintf(stat_config.output, "%s%" PRIu64 "%s%.2f",
+		fprintf(config->output, "%s%" PRIu64 "%s%.2f",
 					csv_sep,
 					run,
 					csv_sep,
 					ena ? 100.0 * run / ena : 100.0);
 	} else if (run != ena) {
-		fprintf(stat_config.output, "  (%.2f%%)", 100.0 * run / ena);
+		fprintf(config->output, "  (%.2f%%)", 100.0 * run / ena);
 	}
 }
 
-static void print_noise_pct(double total, double avg)
+static void print_noise_pct(struct perf_stat_config *config,
+			    double total, double avg)
 {
 	double pct = rel_stddev_stats(total, avg);
 
 	if (csv_output)
-		fprintf(stat_config.output, "%s%.2f%%", csv_sep, pct);
+		fprintf(config->output, "%s%.2f%%", csv_sep, pct);
 	else if (pct)
-		fprintf(stat_config.output, "  ( +-%6.2f%% )", pct);
+		fprintf(config->output, "  ( +-%6.2f%% )", pct);
 }
 
-static void print_noise(struct perf_evsel *evsel, double avg)
+static void print_noise(struct perf_stat_config *config,
+			struct perf_evsel *evsel, double avg)
 {
 	struct perf_stat_evsel *ps;
 
@@ -691,7 +694,7 @@ static void print_noise(struct perf_evsel *evsel, double avg)
 		return;
 
 	ps = evsel->stats;
-	print_noise_pct(stddev_stats(&ps->res_stats[0]), avg);
+	print_noise_pct(config, stddev_stats(&ps->res_stats[0]), avg);
 }
 
 static void aggr_printout(struct perf_evsel *evsel, int id, int nr)
@@ -987,13 +990,14 @@ static bool is_mixed_hw_group(struct perf_evsel *counter)
 	return false;
 }
 
-static void printout(int id, int nr, struct perf_evsel *counter, double uval,
+static void printout(struct perf_stat_config *config, int id, int nr,
+		     struct perf_evsel *counter, double uval,
 		     char *prefix, u64 run, u64 ena, double noise,
 		     struct runtime_stat *st)
 {
 	struct perf_stat_output_ctx out;
 	struct outstate os = {
-		.fh = stat_config.output,
+		.fh = config->output,
 		.prefix = prefix ? prefix : "",
 		.id = id,
 		.nr = nr,
@@ -1023,7 +1027,7 @@ static void printout(int id, int nr, struct perf_evsel *counter, double uval,
 		pm = print_metric_csv;
 		nl = new_line_csv;
 		os.nfields = 3;
-		os.nfields += aggr_fields[stat_config.aggr_mode];
+		os.nfields += aggr_fields[config->aggr_mode];
 		if (counter->cgrp)
 			os.nfields++;
 	}
@@ -1034,7 +1038,7 @@ static void printout(int id, int nr, struct perf_evsel *counter, double uval,
 		}
 		aggr_printout(counter, id, nr);
 
-		fprintf(stat_config.output, "%*s%s",
+		fprintf(config->output, "%*s%s",
 			csv_output ? 0 : 18,
 			counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
 			csv_sep);
@@ -1045,22 +1049,22 @@ static void printout(int id, int nr, struct perf_evsel *counter, double uval,
 				print_mixed_hw_group_error = 1;
 		}
 
-		fprintf(stat_config.output, "%-*s%s",
+		fprintf(config->output, "%-*s%s",
 			csv_output ? 0 : unit_width,
 			counter->unit, csv_sep);
 
-		fprintf(stat_config.output, "%*s",
+		fprintf(config->output, "%*s",
 			csv_output ? 0 : -25,
 			perf_evsel__name(counter));
 
 		if (counter->cgrp)
-			fprintf(stat_config.output, "%s%s",
+			fprintf(config->output, "%s%s",
 				csv_sep, counter->cgrp->name);
 
 		if (!csv_output)
 			pm(&os, NULL, NULL, "", 0);
-		print_noise(counter, noise);
-		print_running(run, ena);
+		print_noise(config, counter, noise);
+		print_running(config, run, ena);
 		if (csv_output)
 			pm(&os, NULL, NULL, "", 0);
 		return;
@@ -1075,16 +1079,16 @@ static void printout(int id, int nr, struct perf_evsel *counter, double uval,
 	out.force_header = false;
 
 	if (csv_output && !metric_only) {
-		print_noise(counter, noise);
-		print_running(run, ena);
+		print_noise(config, counter, noise);
+		print_running(config, run, ena);
 	}
 
 	perf_stat__print_shadow_stats(counter, uval,
 				first_shadow_cpu(counter, id),
 				&out, &metric_events, st);
 	if (!csv_output && !metric_only) {
-		print_noise(counter, noise);
-		print_running(run, ena);
+		print_noise(config, counter, noise);
+		print_running(config, run, ena);
 	}
 }
 
@@ -1211,9 +1215,10 @@ static void aggr_cb(struct perf_evsel *counter, void *data, bool first)
 	}
 }
 
-static void print_aggr(char *prefix)
+static void print_aggr(struct perf_stat_config *config,
+		       char *prefix)
 {
-	FILE *output = stat_config.output;
+	FILE *output = config->output;
 	struct perf_evsel *counter;
 	int s, id, nr;
 	double uval;
@@ -1256,8 +1261,8 @@ static void print_aggr(char *prefix)
 				fprintf(output, "%s", prefix);
 
 			uval = val * counter->scale;
-			printout(id, nr, counter, uval, prefix, run, ena, 1.0,
-				 &rt_stat);
+			printout(config, id, nr, counter, uval, prefix,
+				 run, ena, 1.0, &rt_stat);
 			if (!metric_only)
 				fputc('\n', output);
 		}
@@ -1320,9 +1325,10 @@ static struct perf_aggr_thread_value *sort_aggr_thread(
 	return buf;
 }
 
-static void print_aggr_thread(struct perf_evsel *counter, char *prefix)
+static void print_aggr_thread(struct perf_stat_config *config,
+			      struct perf_evsel *counter, char *prefix)
 {
-	FILE *output = stat_config.output;
+	FILE *output = config->output;
 	int nthreads = thread_map__nr(counter->threads);
 	int ncpus = cpu_map__nr(counter->cpus);
 	int thread, sorted_threads, id;
@@ -1339,12 +1345,12 @@ static void print_aggr_thread(struct perf_evsel *counter, char *prefix)
 			fprintf(output, "%s", prefix);
 
 		id = buf[thread].id;
-		if (stat_config.stats)
-			printout(id, 0, buf[thread].counter, buf[thread].uval,
+		if (config->stats)
+			printout(config, id, 0, buf[thread].counter, buf[thread].uval,
 				 prefix, buf[thread].run, buf[thread].ena, 1.0,
-				 &stat_config.stats[id]);
+				 &config->stats[id]);
 		else
-			printout(id, 0, buf[thread].counter, buf[thread].uval,
+			printout(config, id, 0, buf[thread].counter, buf[thread].uval,
 				 prefix, buf[thread].run, buf[thread].ena, 1.0,
 				 &rt_stat);
 		fputc('\n', output);
@@ -1372,9 +1378,10 @@ static void counter_aggr_cb(struct perf_evsel *counter, void *data,
  * Print out the results of a single counter:
  * aggregated counts in system-wide mode
  */
-static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
+static void print_counter_aggr(struct perf_stat_config *config,
+			       struct perf_evsel *counter, char *prefix)
 {
-	FILE *output = stat_config.output;
+	FILE *output = config->output;
 	double uval;
 	struct caggr_data cd = { .avg = 0.0 };
 
@@ -1385,7 +1392,7 @@ static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
 		fprintf(output, "%s", prefix);
 
 	uval = cd.avg * counter->scale;
-	printout(-1, 0, counter, uval, prefix, cd.avg_running, cd.avg_enabled,
+	printout(config, -1, 0, counter, uval, prefix, cd.avg_running, cd.avg_enabled,
 		 cd.avg, &rt_stat);
 	if (!metric_only)
 		fprintf(output, "\n");
@@ -1405,9 +1412,10 @@ static void counter_cb(struct perf_evsel *counter, void *data,
  * Print out the results of a single counter:
  * does not use aggregated count in system-wide
  */
-static void print_counter(struct perf_evsel *counter, char *prefix)
+static void print_counter(struct perf_stat_config *config,
+			  struct perf_evsel *counter, char *prefix)
 {
-	FILE *output = stat_config.output;
+	FILE *output = config->output;
 	u64 ena, run, val;
 	double uval;
 	int cpu;
@@ -1425,14 +1433,15 @@ static void print_counter(struct perf_evsel *counter, char *prefix)
 			fprintf(output, "%s", prefix);
 
 		uval = val * counter->scale;
-		printout(cpu, 0, counter, uval, prefix, run, ena, 1.0,
+		printout(config, cpu, 0, counter, uval, prefix, run, ena, 1.0,
 			 &rt_stat);
 
 		fputc('\n', output);
 	}
 }
 
-static void print_no_aggr_metric(char *prefix)
+static void print_no_aggr_metric(struct perf_stat_config *config,
+				 char *prefix)
 {
 	int cpu;
 	int nrcpus = 0;
@@ -1445,7 +1454,7 @@ static void print_no_aggr_metric(char *prefix)
 		bool first = true;
 
 		if (prefix)
-			fputs(prefix, stat_config.output);
+			fputs(prefix, config->output);
 		evlist__for_each_entry(evsel_list, counter) {
 			if (is_duration_time(counter))
 				continue;
@@ -1458,10 +1467,10 @@ static void print_no_aggr_metric(char *prefix)
 			run = perf_counts(counter->counts, cpu, 0)->run;
 
 			uval = val * counter->scale;
-			printout(cpu, 0, counter, uval, prefix, run, ena, 1.0,
+			printout(config, cpu, 0, counter, uval, prefix, run, ena, 1.0,
 				 &rt_stat);
 		}
-		fputc('\n', stat_config.output);
+		fputc('\n', config->output);
 	}
 }
 
@@ -1481,25 +1490,25 @@ static const char *aggr_header_csv[] = {
 	[AGGR_GLOBAL] 	=	""
 };
 
-static void print_metric_headers(const char *prefix, bool no_indent)
+static void print_metric_headers(struct perf_stat_config *config,
+				 const char *prefix, bool no_indent)
 {
 	struct perf_stat_output_ctx out;
 	struct perf_evsel *counter;
 	struct outstate os = {
-		.fh = stat_config.output
+		.fh = config->output
 	};
 
 	if (prefix)
-		fprintf(stat_config.output, "%s", prefix);
+		fprintf(config->output, "%s", prefix);
 
 	if (!csv_output && !no_indent)
-		fprintf(stat_config.output, "%*s",
-			aggr_header_lens[stat_config.aggr_mode], "");
+		fprintf(config->output, "%*s",
+			aggr_header_lens[config->aggr_mode], "");
 	if (csv_output) {
-		if (stat_config.interval)
-			fputs("time,", stat_config.output);
-		fputs(aggr_header_csv[stat_config.aggr_mode],
-			stat_config.output);
+		if (config->interval)
+			fputs("time,", config->output);
+		fputs(aggr_header_csv[config->aggr_mode], config->output);
 	}
 
 	/* Print metrics headers only */
@@ -1518,12 +1527,13 @@ static void print_metric_headers(const char *prefix, bool no_indent)
 					      &metric_events,
 					      &rt_stat);
 	}
-	fputc('\n', stat_config.output);
+	fputc('\n', config->output);
 }
 
-static void print_interval(char *prefix, struct timespec *ts)
+static void print_interval(struct perf_stat_config *config,
+			   char *prefix, struct timespec *ts)
 {
-	FILE *output = stat_config.output;
+	FILE *output = config->output;
 	static int num_print_interval;
 
 	if (interval_clear)
@@ -1532,7 +1542,7 @@ static void print_interval(char *prefix, struct timespec *ts)
 	sprintf(prefix, "%6lu.%09lu%s", ts->tv_sec, ts->tv_nsec, csv_sep);
 
 	if ((num_print_interval == 0 && !csv_output) || interval_clear) {
-		switch (stat_config.aggr_mode) {
+		switch (config->aggr_mode) {
 		case AGGR_SOCKET:
 			fprintf(output, "#           time socket cpus");
 			if (!metric_only)
@@ -1564,14 +1574,15 @@ static void print_interval(char *prefix, struct timespec *ts)
 	}
 
 	if ((num_print_interval == 0 || interval_clear) && metric_only)
-		print_metric_headers(" ", true);
+		print_metric_headers(config, " ", true);
 	if (++num_print_interval == 25)
 		num_print_interval = 0;
 }
 
-static void print_header(int argc, const char **argv)
+static void print_header(struct perf_stat_config *config,
+			 int argc, const char **argv)
 {
-	FILE *output = stat_config.output;
+	FILE *output = config->output;
 	int i;
 
 	fflush(stdout);
@@ -1639,10 +1650,10 @@ static double timeval2double(struct timeval *t)
 	return t->tv_sec + (double) t->tv_usec/USEC_PER_SEC;
 }
 
-static void print_footer(void)
+static void print_footer(struct perf_stat_config *config)
 {
 	double avg = avg_stats(&walltime_nsecs_stats) / NSEC_PER_SEC;
-	FILE *output = stat_config.output;
+	FILE *output = config->output;
 	int n;
 
 	if (!null_run)
@@ -1673,7 +1684,7 @@ static void print_footer(void)
 		fprintf(output, " %17.*f +- %.*f seconds time elapsed",
 			precision, avg, precision, sd);
 
-		print_noise_pct(sd, avg);
+		print_noise_pct(config, sd, avg);
 	}
 	fprintf(output, "\n\n");
 
@@ -1703,15 +1714,15 @@ perf_evlist__print_counters(struct perf_evlist *evlist,
 	char buf[64], *prefix = NULL;
 
 	if (interval)
-		print_interval(prefix = buf, ts);
+		print_interval(config, prefix = buf, ts);
 	else
-		print_header(argc, argv);
+		print_header(config, argc, argv);
 
 	if (metric_only) {
 		static int num_print_iv;
 
 		if (num_print_iv == 0 && !interval)
-			print_metric_headers(prefix, false);
+			print_metric_headers(config, prefix, false);
 		if (num_print_iv++ == 25)
 			num_print_iv = 0;
 		if (config->aggr_mode == AGGR_GLOBAL && prefix)
@@ -1721,32 +1732,32 @@ perf_evlist__print_counters(struct perf_evlist *evlist,
 	switch (config->aggr_mode) {
 	case AGGR_CORE:
 	case AGGR_SOCKET:
-		print_aggr(prefix);
+		print_aggr(config, prefix);
 		break;
 	case AGGR_THREAD:
 		evlist__for_each_entry(evlist, counter) {
 			if (is_duration_time(counter))
 				continue;
-			print_aggr_thread(counter, prefix);
+			print_aggr_thread(config, counter, prefix);
 		}
 		break;
 	case AGGR_GLOBAL:
 		evlist__for_each_entry(evlist, counter) {
 			if (is_duration_time(counter))
 				continue;
-			print_counter_aggr(counter, prefix);
+			print_counter_aggr(config, counter, prefix);
 		}
 		if (metric_only)
 			fputc('\n', config->output);
 		break;
 	case AGGR_NONE:
 		if (metric_only)
-			print_no_aggr_metric(prefix);
+			print_no_aggr_metric(config, prefix);
 		else {
 			evlist__for_each_entry(evlist, counter) {
 				if (is_duration_time(counter))
 					continue;
-				print_counter(counter, prefix);
+				print_counter(config, counter, prefix);
 			}
 		}
 		break;
@@ -1756,7 +1767,7 @@ perf_evlist__print_counters(struct perf_evlist *evlist,
 	}
 
 	if (!interval && !csv_output)
-		print_footer();
+		print_footer(config);
 
 	fflush(config->output);
 }

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf stat: Pass a 'struct perf_stat_config' argument to global print functions
  2018-08-30  6:32 ` [PATCH 19/43] perf stat: Pass stat_config argument to global " Jiri Olsa
@ 2018-09-06 13:30   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:30 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: namhyung, jolsa, mingo, linux-kernel, tglx, alexander.shishkin,
	hpa, andi, dsahern, acme, peterz

Commit-ID:  6ca9a082b1908ff7f8adedf08166043b83b266f6
Gitweb:     https://git.kernel.org/tip/6ca9a082b1908ff7f8adedf08166043b83b266f6
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:28 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:23 -0300

perf stat: Pass a 'struct perf_stat_config' argument to global print functions

Add 'struct perf_stat_config' argument to the global print functions, so
that these functions can be used out of the 'perf stat' command code.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-20-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-script.c   |   8 ++-
 tools/perf/builtin-stat.c     |  74 ++++++++++++---------
 tools/perf/util/stat-shadow.c | 147 +++++++++++++++++++++++-------------------
 tools/perf/util/stat.h        |   8 ++-
 4 files changed, 131 insertions(+), 106 deletions(-)

diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index ba481d73f910..6176bae177c2 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -1544,7 +1544,8 @@ struct metric_ctx {
 	FILE 			*fp;
 };
 
-static void script_print_metric(void *ctx, const char *color,
+static void script_print_metric(struct perf_stat_config *config __maybe_unused,
+				void *ctx, const char *color,
 			        const char *fmt,
 			        const char *unit, double val)
 {
@@ -1562,7 +1563,8 @@ static void script_print_metric(void *ctx, const char *color,
 	fprintf(mctx->fp, " %s\n", unit);
 }
 
-static void script_new_line(void *ctx)
+static void script_new_line(struct perf_stat_config *config __maybe_unused,
+			    void *ctx)
 {
 	struct metric_ctx *mctx = ctx;
 
@@ -1608,7 +1610,7 @@ static void perf_sample__fprint_metric(struct perf_script *script,
 	evsel_script(evsel)->val = val;
 	if (evsel_script(evsel->leader)->gnum == evsel->leader->nr_members) {
 		for_each_group_member (ev2, evsel->leader) {
-			perf_stat__print_shadow_stats(ev2,
+			perf_stat__print_shadow_stats(&stat_config, ev2,
 						      evsel_script(ev2)->val,
 						      sample->cpu,
 						      &ctx,
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index f56da22abccc..7a3361308e61 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -697,11 +697,12 @@ static void print_noise(struct perf_stat_config *config,
 	print_noise_pct(config, stddev_stats(&ps->res_stats[0]), avg);
 }
 
-static void aggr_printout(struct perf_evsel *evsel, int id, int nr)
+static void aggr_printout(struct perf_stat_config *config,
+			  struct perf_evsel *evsel, int id, int nr)
 {
-	switch (stat_config.aggr_mode) {
+	switch (config->aggr_mode) {
 	case AGGR_CORE:
-		fprintf(stat_config.output, "S%d-C%*d%s%*d%s",
+		fprintf(config->output, "S%d-C%*d%s%*d%s",
 			cpu_map__id_to_socket(id),
 			csv_output ? 0 : -8,
 			cpu_map__id_to_cpu(id),
@@ -711,7 +712,7 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr)
 			csv_sep);
 		break;
 	case AGGR_SOCKET:
-		fprintf(stat_config.output, "S%*d%s%*d%s",
+		fprintf(config->output, "S%*d%s%*d%s",
 			csv_output ? 0 : -5,
 			id,
 			csv_sep,
@@ -720,12 +721,12 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr)
 			csv_sep);
 			break;
 	case AGGR_NONE:
-		fprintf(stat_config.output, "CPU%*d%s",
+		fprintf(config->output, "CPU%*d%s",
 			csv_output ? 0 : -4,
 			perf_evsel__cpus(evsel)->map[id], csv_sep);
 		break;
 	case AGGR_THREAD:
-		fprintf(stat_config.output, "%*s-%*d%s",
+		fprintf(config->output, "%*s-%*d%s",
 			csv_output ? 0 : 16,
 			thread_map__comm(evsel->threads, id),
 			csv_output ? 0 : -8,
@@ -750,24 +751,27 @@ struct outstate {
 
 #define METRIC_LEN  35
 
-static void new_line_std(void *ctx)
+static void new_line_std(struct perf_stat_config *config __maybe_unused,
+			 void *ctx)
 {
 	struct outstate *os = ctx;
 
 	os->newline = true;
 }
 
-static void do_new_line_std(struct outstate *os)
+static void do_new_line_std(struct perf_stat_config *config,
+			    struct outstate *os)
 {
 	fputc('\n', os->fh);
 	fputs(os->prefix, os->fh);
-	aggr_printout(os->evsel, os->id, os->nr);
-	if (stat_config.aggr_mode == AGGR_NONE)
+	aggr_printout(config, os->evsel, os->id, os->nr);
+	if (config->aggr_mode == AGGR_NONE)
 		fprintf(os->fh, "        ");
 	fprintf(os->fh, "                                                 ");
 }
 
-static void print_metric_std(void *ctx, const char *color, const char *fmt,
+static void print_metric_std(struct perf_stat_config *config,
+			     void *ctx, const char *color, const char *fmt,
 			     const char *unit, double val)
 {
 	struct outstate *os = ctx;
@@ -783,7 +787,7 @@ static void print_metric_std(void *ctx, const char *color, const char *fmt,
 	}
 
 	if (newline)
-		do_new_line_std(os);
+		do_new_line_std(config, os);
 
 	n = fprintf(out, " # ");
 	if (color)
@@ -793,7 +797,7 @@ static void print_metric_std(void *ctx, const char *color, const char *fmt,
 	fprintf(out, " %-*s", METRIC_LEN - n - 1, unit);
 }
 
-static void new_line_csv(void *ctx)
+static void new_line_csv(struct perf_stat_config *config, void *ctx)
 {
 	struct outstate *os = ctx;
 	int i;
@@ -801,12 +805,13 @@ static void new_line_csv(void *ctx)
 	fputc('\n', os->fh);
 	if (os->prefix)
 		fprintf(os->fh, "%s%s", os->prefix, csv_sep);
-	aggr_printout(os->evsel, os->id, os->nr);
+	aggr_printout(config, os->evsel, os->id, os->nr);
 	for (i = 0; i < os->nfields; i++)
 		fputs(csv_sep, os->fh);
 }
 
-static void print_metric_csv(void *ctx,
+static void print_metric_csv(struct perf_stat_config *config __maybe_unused,
+			     void *ctx,
 			     const char *color __maybe_unused,
 			     const char *fmt, const char *unit, double val)
 {
@@ -853,7 +858,8 @@ static const char *fixunit(char *buf, struct perf_evsel *evsel,
 	return unit;
 }
 
-static void print_metric_only(void *ctx, const char *color, const char *fmt,
+static void print_metric_only(struct perf_stat_config *config __maybe_unused,
+			      void *ctx, const char *color, const char *fmt,
 			      const char *unit, double val)
 {
 	struct outstate *os = ctx;
@@ -874,7 +880,8 @@ static void print_metric_only(void *ctx, const char *color, const char *fmt,
 	fprintf(out, "%*s ", mlen, str);
 }
 
-static void print_metric_only_csv(void *ctx, const char *color __maybe_unused,
+static void print_metric_only_csv(struct perf_stat_config *config __maybe_unused,
+				  void *ctx, const char *color __maybe_unused,
 				  const char *fmt,
 				  const char *unit, double val)
 {
@@ -894,11 +901,13 @@ static void print_metric_only_csv(void *ctx, const char *color __maybe_unused,
 	fprintf(out, "%s%s", vals, csv_sep);
 }
 
-static void new_line_metric(void *ctx __maybe_unused)
+static void new_line_metric(struct perf_stat_config *config __maybe_unused,
+			    void *ctx __maybe_unused)
 {
 }
 
-static void print_metric_header(void *ctx, const char *color __maybe_unused,
+static void print_metric_header(struct perf_stat_config *config __maybe_unused,
+				void *ctx, const char *color __maybe_unused,
 				const char *fmt __maybe_unused,
 				const char *unit, double val __maybe_unused)
 {
@@ -936,9 +945,10 @@ static int first_shadow_cpu(struct perf_evsel *evsel, int id)
 	return 0;
 }
 
-static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
+static void abs_printout(struct perf_stat_config *config,
+			 int id, int nr, struct perf_evsel *evsel, double avg)
 {
-	FILE *output = stat_config.output;
+	FILE *output = config->output;
 	double sc =  evsel->scale;
 	const char *fmt;
 
@@ -951,7 +961,7 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
 			fmt = floor(sc) != sc ? "%18.2f%s" : "%18.0f%s";
 	}
 
-	aggr_printout(evsel, id, nr);
+	aggr_printout(config, evsel, id, nr);
 
 	fprintf(output, fmt, avg, csv_sep);
 
@@ -1004,7 +1014,7 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 		.evsel = counter,
 	};
 	print_metric_t pm = print_metric_std;
-	void (*nl)(void *);
+	new_line_t nl;
 
 	if (metric_only) {
 		nl = new_line_metric;
@@ -1033,10 +1043,10 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 	}
 	if (run == 0 || ena == 0 || counter->counts->scaled == -1) {
 		if (metric_only) {
-			pm(&os, NULL, "", "", 0);
+			pm(config, &os, NULL, "", "", 0);
 			return;
 		}
-		aggr_printout(counter, id, nr);
+		aggr_printout(config, counter, id, nr);
 
 		fprintf(config->output, "%*s%s",
 			csv_output ? 0 : 18,
@@ -1062,16 +1072,16 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 				csv_sep, counter->cgrp->name);
 
 		if (!csv_output)
-			pm(&os, NULL, NULL, "", 0);
+			pm(config, &os, NULL, NULL, "", 0);
 		print_noise(config, counter, noise);
 		print_running(config, run, ena);
 		if (csv_output)
-			pm(&os, NULL, NULL, "", 0);
+			pm(config, &os, NULL, NULL, "", 0);
 		return;
 	}
 
 	if (!metric_only)
-		abs_printout(id, nr, counter, uval);
+		abs_printout(config, id, nr, counter, uval);
 
 	out.print_metric = pm;
 	out.new_line = nl;
@@ -1083,7 +1093,7 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 		print_running(config, run, ena);
 	}
 
-	perf_stat__print_shadow_stats(counter, uval,
+	perf_stat__print_shadow_stats(config, counter, uval,
 				first_shadow_cpu(counter, id),
 				&out, &metric_events, st);
 	if (!csv_output && !metric_only) {
@@ -1255,7 +1265,7 @@ static void print_aggr(struct perf_stat_config *config,
 			val = ad.val;
 			if (first && metric_only) {
 				first = false;
-				aggr_printout(counter, id, nr);
+				aggr_printout(config, counter, id, nr);
 			}
 			if (prefix && !metric_only)
 				fprintf(output, "%s", prefix);
@@ -1459,7 +1469,7 @@ static void print_no_aggr_metric(struct perf_stat_config *config,
 			if (is_duration_time(counter))
 				continue;
 			if (first) {
-				aggr_printout(counter, cpu, 0);
+				aggr_printout(config, counter, cpu, 0);
 				first = false;
 			}
 			val = perf_counts(counter->counts, cpu, 0)->val;
@@ -1521,7 +1531,7 @@ static void print_metric_headers(struct perf_stat_config *config,
 		out.new_line = new_line_metric;
 		out.force_header = true;
 		os.evsel = counter;
-		perf_stat__print_shadow_stats(counter, 0,
+		perf_stat__print_shadow_stats(config, counter, 0,
 					      0,
 					      &out,
 					      &metric_events,
diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c
index 99990f5f2512..8ad32763cfff 100644
--- a/tools/perf/util/stat-shadow.c
+++ b/tools/perf/util/stat-shadow.c
@@ -410,7 +410,8 @@ static double runtime_stat_n(struct runtime_stat *st,
 	return v->stats.n;
 }
 
-static void print_stalled_cycles_frontend(int cpu,
+static void print_stalled_cycles_frontend(struct perf_stat_config *config,
+					  int cpu,
 					  struct perf_evsel *evsel, double avg,
 					  struct perf_stat_output_ctx *out,
 					  struct runtime_stat *st)
@@ -427,13 +428,14 @@ static void print_stalled_cycles_frontend(int cpu,
 	color = get_ratio_color(GRC_STALLED_CYCLES_FE, ratio);
 
 	if (ratio)
-		out->print_metric(out->ctx, color, "%7.2f%%", "frontend cycles idle",
+		out->print_metric(config, out->ctx, color, "%7.2f%%", "frontend cycles idle",
 				  ratio);
 	else
-		out->print_metric(out->ctx, NULL, NULL, "frontend cycles idle", 0);
+		out->print_metric(config, out->ctx, NULL, NULL, "frontend cycles idle", 0);
 }
 
-static void print_stalled_cycles_backend(int cpu,
+static void print_stalled_cycles_backend(struct perf_stat_config *config,
+					 int cpu,
 					 struct perf_evsel *evsel, double avg,
 					 struct perf_stat_output_ctx *out,
 					 struct runtime_stat *st)
@@ -449,10 +451,11 @@ static void print_stalled_cycles_backend(int cpu,
 
 	color = get_ratio_color(GRC_STALLED_CYCLES_BE, ratio);
 
-	out->print_metric(out->ctx, color, "%7.2f%%", "backend cycles idle", ratio);
+	out->print_metric(config, out->ctx, color, "%7.2f%%", "backend cycles idle", ratio);
 }
 
-static void print_branch_misses(int cpu,
+static void print_branch_misses(struct perf_stat_config *config,
+				int cpu,
 				struct perf_evsel *evsel,
 				double avg,
 				struct perf_stat_output_ctx *out,
@@ -469,10 +472,11 @@ static void print_branch_misses(int cpu,
 
 	color = get_ratio_color(GRC_CACHE_MISSES, ratio);
 
-	out->print_metric(out->ctx, color, "%7.2f%%", "of all branches", ratio);
+	out->print_metric(config, out->ctx, color, "%7.2f%%", "of all branches", ratio);
 }
 
-static void print_l1_dcache_misses(int cpu,
+static void print_l1_dcache_misses(struct perf_stat_config *config,
+				   int cpu,
 				   struct perf_evsel *evsel,
 				   double avg,
 				   struct perf_stat_output_ctx *out,
@@ -490,10 +494,11 @@ static void print_l1_dcache_misses(int cpu,
 
 	color = get_ratio_color(GRC_CACHE_MISSES, ratio);
 
-	out->print_metric(out->ctx, color, "%7.2f%%", "of all L1-dcache hits", ratio);
+	out->print_metric(config, out->ctx, color, "%7.2f%%", "of all L1-dcache hits", ratio);
 }
 
-static void print_l1_icache_misses(int cpu,
+static void print_l1_icache_misses(struct perf_stat_config *config,
+				   int cpu,
 				   struct perf_evsel *evsel,
 				   double avg,
 				   struct perf_stat_output_ctx *out,
@@ -510,10 +515,11 @@ static void print_l1_icache_misses(int cpu,
 		ratio = avg / total * 100.0;
 
 	color = get_ratio_color(GRC_CACHE_MISSES, ratio);
-	out->print_metric(out->ctx, color, "%7.2f%%", "of all L1-icache hits", ratio);
+	out->print_metric(config, out->ctx, color, "%7.2f%%", "of all L1-icache hits", ratio);
 }
 
-static void print_dtlb_cache_misses(int cpu,
+static void print_dtlb_cache_misses(struct perf_stat_config *config,
+				    int cpu,
 				    struct perf_evsel *evsel,
 				    double avg,
 				    struct perf_stat_output_ctx *out,
@@ -529,10 +535,11 @@ static void print_dtlb_cache_misses(int cpu,
 		ratio = avg / total * 100.0;
 
 	color = get_ratio_color(GRC_CACHE_MISSES, ratio);
-	out->print_metric(out->ctx, color, "%7.2f%%", "of all dTLB cache hits", ratio);
+	out->print_metric(config, out->ctx, color, "%7.2f%%", "of all dTLB cache hits", ratio);
 }
 
-static void print_itlb_cache_misses(int cpu,
+static void print_itlb_cache_misses(struct perf_stat_config *config,
+				    int cpu,
 				    struct perf_evsel *evsel,
 				    double avg,
 				    struct perf_stat_output_ctx *out,
@@ -548,10 +555,11 @@ static void print_itlb_cache_misses(int cpu,
 		ratio = avg / total * 100.0;
 
 	color = get_ratio_color(GRC_CACHE_MISSES, ratio);
-	out->print_metric(out->ctx, color, "%7.2f%%", "of all iTLB cache hits", ratio);
+	out->print_metric(config, out->ctx, color, "%7.2f%%", "of all iTLB cache hits", ratio);
 }
 
-static void print_ll_cache_misses(int cpu,
+static void print_ll_cache_misses(struct perf_stat_config *config,
+				  int cpu,
 				  struct perf_evsel *evsel,
 				  double avg,
 				  struct perf_stat_output_ctx *out,
@@ -567,7 +575,7 @@ static void print_ll_cache_misses(int cpu,
 		ratio = avg / total * 100.0;
 
 	color = get_ratio_color(GRC_CACHE_MISSES, ratio);
-	out->print_metric(out->ctx, color, "%7.2f%%", "of all LL-cache hits", ratio);
+	out->print_metric(config, out->ctx, color, "%7.2f%%", "of all LL-cache hits", ratio);
 }
 
 /*
@@ -674,7 +682,8 @@ static double td_be_bound(int ctx, int cpu, struct runtime_stat *st)
 	return sanitize_val(1.0 - sum);
 }
 
-static void print_smi_cost(int cpu, struct perf_evsel *evsel,
+static void print_smi_cost(struct perf_stat_config *config,
+			   int cpu, struct perf_evsel *evsel,
 			   struct perf_stat_output_ctx *out,
 			   struct runtime_stat *st)
 {
@@ -694,11 +703,12 @@ static void print_smi_cost(int cpu, struct perf_evsel *evsel,
 
 	if (cost > 10)
 		color = PERF_COLOR_RED;
-	out->print_metric(out->ctx, color, "%8.1f%%", "SMI cycles%", cost);
-	out->print_metric(out->ctx, NULL, "%4.0f", "SMI#", smi_num);
+	out->print_metric(config, out->ctx, color, "%8.1f%%", "SMI cycles%", cost);
+	out->print_metric(config, out->ctx, NULL, "%4.0f", "SMI#", smi_num);
 }
 
-static void generic_metric(const char *metric_expr,
+static void generic_metric(struct perf_stat_config *config,
+			   const char *metric_expr,
 			   struct perf_evsel **metric_events,
 			   char *name,
 			   const char *metric_name,
@@ -737,20 +747,21 @@ static void generic_metric(const char *metric_expr,
 		const char *p = metric_expr;
 
 		if (expr__parse(&ratio, &pctx, &p) == 0)
-			print_metric(ctxp, NULL, "%8.1f",
+			print_metric(config, ctxp, NULL, "%8.1f",
 				metric_name ?
 				metric_name :
 				out->force_header ?  name : "",
 				ratio);
 		else
-			print_metric(ctxp, NULL, NULL,
+			print_metric(config, ctxp, NULL, NULL,
 				     out->force_header ?
 				     (metric_name ? metric_name : name) : "", 0);
 	} else
-		print_metric(ctxp, NULL, NULL, "", 0);
+		print_metric(config, ctxp, NULL, NULL, "", 0);
 }
 
-void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
+void perf_stat__print_shadow_stats(struct perf_stat_config *config,
+				   struct perf_evsel *evsel,
 				   double avg, int cpu,
 				   struct perf_stat_output_ctx *out,
 				   struct rblist *metric_events,
@@ -769,10 +780,10 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
 
 		if (total) {
 			ratio = avg / total;
-			print_metric(ctxp, NULL, "%7.2f ",
+			print_metric(config, ctxp, NULL, "%7.2f ",
 					"insn per cycle", ratio);
 		} else {
-			print_metric(ctxp, NULL, NULL, "insn per cycle", 0);
+			print_metric(config, ctxp, NULL, NULL, "insn per cycle", 0);
 		}
 
 		total = runtime_stat_avg(st, STAT_STALLED_CYCLES_FRONT,
@@ -783,20 +794,20 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
 						    ctx, cpu));
 
 		if (total && avg) {
-			out->new_line(ctxp);
+			out->new_line(config, ctxp);
 			ratio = total / avg;
-			print_metric(ctxp, NULL, "%7.2f ",
+			print_metric(config, ctxp, NULL, "%7.2f ",
 					"stalled cycles per insn",
 					ratio);
 		} else if (have_frontend_stalled) {
-			print_metric(ctxp, NULL, NULL,
+			print_metric(config, ctxp, NULL, NULL,
 				     "stalled cycles per insn", 0);
 		}
 	} else if (perf_evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES)) {
 		if (runtime_stat_n(st, STAT_BRANCHES, ctx, cpu) != 0)
-			print_branch_misses(cpu, evsel, avg, out, st);
+			print_branch_misses(config, cpu, evsel, avg, out, st);
 		else
-			print_metric(ctxp, NULL, NULL, "of all branches", 0);
+			print_metric(config, ctxp, NULL, NULL, "of all branches", 0);
 	} else if (
 		evsel->attr.type == PERF_TYPE_HW_CACHE &&
 		evsel->attr.config ==  ( PERF_COUNT_HW_CACHE_L1D |
@@ -804,9 +815,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
 					 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) {
 
 		if (runtime_stat_n(st, STAT_L1_DCACHE, ctx, cpu) != 0)
-			print_l1_dcache_misses(cpu, evsel, avg, out, st);
+			print_l1_dcache_misses(config, cpu, evsel, avg, out, st);
 		else
-			print_metric(ctxp, NULL, NULL, "of all L1-dcache hits", 0);
+			print_metric(config, ctxp, NULL, NULL, "of all L1-dcache hits", 0);
 	} else if (
 		evsel->attr.type == PERF_TYPE_HW_CACHE &&
 		evsel->attr.config ==  ( PERF_COUNT_HW_CACHE_L1I |
@@ -814,9 +825,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
 					 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) {
 
 		if (runtime_stat_n(st, STAT_L1_ICACHE, ctx, cpu) != 0)
-			print_l1_icache_misses(cpu, evsel, avg, out, st);
+			print_l1_icache_misses(config, cpu, evsel, avg, out, st);
 		else
-			print_metric(ctxp, NULL, NULL, "of all L1-icache hits", 0);
+			print_metric(config, ctxp, NULL, NULL, "of all L1-icache hits", 0);
 	} else if (
 		evsel->attr.type == PERF_TYPE_HW_CACHE &&
 		evsel->attr.config ==  ( PERF_COUNT_HW_CACHE_DTLB |
@@ -824,9 +835,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
 					 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) {
 
 		if (runtime_stat_n(st, STAT_DTLB_CACHE, ctx, cpu) != 0)
-			print_dtlb_cache_misses(cpu, evsel, avg, out, st);
+			print_dtlb_cache_misses(config, cpu, evsel, avg, out, st);
 		else
-			print_metric(ctxp, NULL, NULL, "of all dTLB cache hits", 0);
+			print_metric(config, ctxp, NULL, NULL, "of all dTLB cache hits", 0);
 	} else if (
 		evsel->attr.type == PERF_TYPE_HW_CACHE &&
 		evsel->attr.config ==  ( PERF_COUNT_HW_CACHE_ITLB |
@@ -834,9 +845,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
 					 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) {
 
 		if (runtime_stat_n(st, STAT_ITLB_CACHE, ctx, cpu) != 0)
-			print_itlb_cache_misses(cpu, evsel, avg, out, st);
+			print_itlb_cache_misses(config, cpu, evsel, avg, out, st);
 		else
-			print_metric(ctxp, NULL, NULL, "of all iTLB cache hits", 0);
+			print_metric(config, ctxp, NULL, NULL, "of all iTLB cache hits", 0);
 	} else if (
 		evsel->attr.type == PERF_TYPE_HW_CACHE &&
 		evsel->attr.config ==  ( PERF_COUNT_HW_CACHE_LL |
@@ -844,9 +855,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
 					 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) {
 
 		if (runtime_stat_n(st, STAT_LL_CACHE, ctx, cpu) != 0)
-			print_ll_cache_misses(cpu, evsel, avg, out, st);
+			print_ll_cache_misses(config, cpu, evsel, avg, out, st);
 		else
-			print_metric(ctxp, NULL, NULL, "of all LL-cache hits", 0);
+			print_metric(config, ctxp, NULL, NULL, "of all LL-cache hits", 0);
 	} else if (perf_evsel__match(evsel, HARDWARE, HW_CACHE_MISSES)) {
 		total = runtime_stat_avg(st, STAT_CACHEREFS, ctx, cpu);
 
@@ -854,32 +865,32 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
 			ratio = avg * 100 / total;
 
 		if (runtime_stat_n(st, STAT_CACHEREFS, ctx, cpu) != 0)
-			print_metric(ctxp, NULL, "%8.3f %%",
+			print_metric(config, ctxp, NULL, "%8.3f %%",
 				     "of all cache refs", ratio);
 		else
-			print_metric(ctxp, NULL, NULL, "of all cache refs", 0);
+			print_metric(config, ctxp, NULL, NULL, "of all cache refs", 0);
 	} else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) {
-		print_stalled_cycles_frontend(cpu, evsel, avg, out, st);
+		print_stalled_cycles_frontend(config, cpu, evsel, avg, out, st);
 	} else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_BACKEND)) {
-		print_stalled_cycles_backend(cpu, evsel, avg, out, st);
+		print_stalled_cycles_backend(config, cpu, evsel, avg, out, st);
 	} else if (perf_evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)) {
 		total = runtime_stat_avg(st, STAT_NSECS, 0, cpu);
 
 		if (total) {
 			ratio = avg / total;
-			print_metric(ctxp, NULL, "%8.3f", "GHz", ratio);
+			print_metric(config, ctxp, NULL, "%8.3f", "GHz", ratio);
 		} else {
-			print_metric(ctxp, NULL, NULL, "Ghz", 0);
+			print_metric(config, ctxp, NULL, NULL, "Ghz", 0);
 		}
 	} else if (perf_stat_evsel__is(evsel, CYCLES_IN_TX)) {
 		total = runtime_stat_avg(st, STAT_CYCLES, ctx, cpu);
 
 		if (total)
-			print_metric(ctxp, NULL,
+			print_metric(config, ctxp, NULL,
 					"%7.2f%%", "transactional cycles",
 					100.0 * (avg / total));
 		else
-			print_metric(ctxp, NULL, NULL, "transactional cycles",
+			print_metric(config, ctxp, NULL, NULL, "transactional cycles",
 				     0);
 	} else if (perf_stat_evsel__is(evsel, CYCLES_IN_TX_CP)) {
 		total = runtime_stat_avg(st, STAT_CYCLES, ctx, cpu);
@@ -888,10 +899,10 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
 		if (total2 < avg)
 			total2 = avg;
 		if (total)
-			print_metric(ctxp, NULL, "%7.2f%%", "aborted cycles",
+			print_metric(config, ctxp, NULL, "%7.2f%%", "aborted cycles",
 				100.0 * ((total2-avg) / total));
 		else
-			print_metric(ctxp, NULL, NULL, "aborted cycles", 0);
+			print_metric(config, ctxp, NULL, NULL, "aborted cycles", 0);
 	} else if (perf_stat_evsel__is(evsel, TRANSACTION_START)) {
 		total = runtime_stat_avg(st, STAT_CYCLES_IN_TX,
 					 ctx, cpu);
@@ -900,10 +911,10 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
 			ratio = total / avg;
 
 		if (runtime_stat_n(st, STAT_CYCLES_IN_TX, ctx, cpu) != 0)
-			print_metric(ctxp, NULL, "%8.0f",
+			print_metric(config, ctxp, NULL, "%8.0f",
 				     "cycles / transaction", ratio);
 		else
-			print_metric(ctxp, NULL, NULL, "cycles / transaction",
+			print_metric(config, ctxp, NULL, NULL, "cycles / transaction",
 				      0);
 	} else if (perf_stat_evsel__is(evsel, ELISION_START)) {
 		total = runtime_stat_avg(st, STAT_CYCLES_IN_TX,
@@ -912,33 +923,33 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
 		if (avg)
 			ratio = total / avg;
 
-		print_metric(ctxp, NULL, "%8.0f", "cycles / elision", ratio);
+		print_metric(config, ctxp, NULL, "%8.0f", "cycles / elision", ratio);
 	} else if (perf_evsel__is_clock(evsel)) {
 		if ((ratio = avg_stats(&walltime_nsecs_stats)) != 0)
-			print_metric(ctxp, NULL, "%8.3f", "CPUs utilized",
+			print_metric(config, ctxp, NULL, "%8.3f", "CPUs utilized",
 				     avg / (ratio * evsel->scale));
 		else
-			print_metric(ctxp, NULL, NULL, "CPUs utilized", 0);
+			print_metric(config, ctxp, NULL, NULL, "CPUs utilized", 0);
 	} else if (perf_stat_evsel__is(evsel, TOPDOWN_FETCH_BUBBLES)) {
 		double fe_bound = td_fe_bound(ctx, cpu, st);
 
 		if (fe_bound > 0.2)
 			color = PERF_COLOR_RED;
-		print_metric(ctxp, color, "%8.1f%%", "frontend bound",
+		print_metric(config, ctxp, color, "%8.1f%%", "frontend bound",
 				fe_bound * 100.);
 	} else if (perf_stat_evsel__is(evsel, TOPDOWN_SLOTS_RETIRED)) {
 		double retiring = td_retiring(ctx, cpu, st);
 
 		if (retiring > 0.7)
 			color = PERF_COLOR_GREEN;
-		print_metric(ctxp, color, "%8.1f%%", "retiring",
+		print_metric(config, ctxp, color, "%8.1f%%", "retiring",
 				retiring * 100.);
 	} else if (perf_stat_evsel__is(evsel, TOPDOWN_RECOVERY_BUBBLES)) {
 		double bad_spec = td_bad_spec(ctx, cpu, st);
 
 		if (bad_spec > 0.1)
 			color = PERF_COLOR_RED;
-		print_metric(ctxp, color, "%8.1f%%", "bad speculation",
+		print_metric(config, ctxp, color, "%8.1f%%", "bad speculation",
 				bad_spec * 100.);
 	} else if (perf_stat_evsel__is(evsel, TOPDOWN_SLOTS_ISSUED)) {
 		double be_bound = td_be_bound(ctx, cpu, st);
@@ -955,12 +966,12 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
 		if (be_bound > 0.2)
 			color = PERF_COLOR_RED;
 		if (td_total_slots(ctx, cpu, st) > 0)
-			print_metric(ctxp, color, "%8.1f%%", name,
+			print_metric(config, ctxp, color, "%8.1f%%", name,
 					be_bound * 100.);
 		else
-			print_metric(ctxp, NULL, NULL, name, 0);
+			print_metric(config, ctxp, NULL, NULL, name, 0);
 	} else if (evsel->metric_expr) {
-		generic_metric(evsel->metric_expr, evsel->metric_events, evsel->name,
+		generic_metric(config, evsel->metric_expr, evsel->metric_events, evsel->name,
 				evsel->metric_name, avg, cpu, out, st);
 	} else if (runtime_stat_n(st, STAT_NSECS, 0, cpu) != 0) {
 		char unit = 'M';
@@ -975,9 +986,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
 			unit = 'K';
 		}
 		snprintf(unit_buf, sizeof(unit_buf), "%c/sec", unit);
-		print_metric(ctxp, NULL, "%8.3f", unit_buf, ratio);
+		print_metric(config, ctxp, NULL, "%8.3f", unit_buf, ratio);
 	} else if (perf_stat_evsel__is(evsel, SMI_NUM)) {
-		print_smi_cost(cpu, evsel, out, st);
+		print_smi_cost(config, cpu, evsel, out, st);
 	} else {
 		num = 0;
 	}
@@ -987,12 +998,12 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
 
 		list_for_each_entry (mexp, &me->head, nd) {
 			if (num++ > 0)
-				out->new_line(ctxp);
-			generic_metric(mexp->metric_expr, mexp->metric_events,
+				out->new_line(config, ctxp);
+			generic_metric(config, mexp->metric_expr, mexp->metric_events,
 					evsel->name, mexp->metric_name,
 					avg, cpu, out, st);
 		}
 	}
 	if (num == 0)
-		print_metric(ctxp, NULL, NULL, NULL, 0);
+		print_metric(config, ctxp, NULL, NULL, NULL, 0);
 }
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index da6a706daecc..dffcf2110706 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -135,9 +135,10 @@ bool __perf_evsel_stat__is(struct perf_evsel *evsel,
 extern struct runtime_stat rt_stat;
 extern struct stats walltime_nsecs_stats;
 
-typedef void (*print_metric_t)(void *ctx, const char *color, const char *unit,
+typedef void (*print_metric_t)(struct perf_stat_config *config,
+			       void *ctx, const char *color, const char *unit,
 			       const char *fmt, double val);
-typedef void (*new_line_t )(void *ctx);
+typedef void (*new_line_t)(struct perf_stat_config *config, void *ctx);
 
 void runtime_stat__init(struct runtime_stat *st);
 void runtime_stat__exit(struct runtime_stat *st);
@@ -153,7 +154,8 @@ struct perf_stat_output_ctx {
 	bool force_header;
 };
 
-void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
+void perf_stat__print_shadow_stats(struct perf_stat_config *config,
+				   struct perf_evsel *evsel,
 				   double avg, int cpu,
 				   struct perf_stat_output_ctx *out,
 				   struct rblist *metric_events,

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf stat: Move csv_* to 'struct perf_stat_config'
  2018-08-30  6:32 ` [PATCH 20/43] perf stat: Move csv_* into struct perf_stat_config Jiri Olsa
@ 2018-09-06 13:31   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:31 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: acme, hpa, mingo, andi, linux-kernel, tglx, jolsa, namhyung,
	alexander.shishkin, dsahern, peterz

Commit-ID:  fa7070a38676d660c0a71ab6981bfdca3b340ccd
Gitweb:     https://git.kernel.org/tip/fa7070a38676d660c0a71ab6981bfdca3b340ccd
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:29 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:23 -0300

perf stat: Move csv_* to 'struct perf_stat_config'

Move the static csv_* variables to 'struct perf_stat_config', so that it
can be passed around and used outside the 'perf stat' command.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-21-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 114 +++++++++++++++++++++++-----------------------
 tools/perf/util/stat.h    |   2 +
 2 files changed, 58 insertions(+), 58 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 7a3361308e61..4c29e5065e02 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -157,8 +157,6 @@ static bool			smi_cost			= false;
 static bool			smi_reset			= false;
 static bool			big_num				=  true;
 static int			big_num_opt			=  -1;
-static const char		*csv_sep			= NULL;
-static bool			csv_output			= false;
 static bool			group				= false;
 static const char		*pre_cmd			= NULL;
 static const char		*post_cmd			= NULL;
@@ -663,11 +661,11 @@ static int run_perf_stat(int argc, const char **argv, int run_idx)
 static void print_running(struct perf_stat_config *config,
 			  u64 run, u64 ena)
 {
-	if (csv_output) {
+	if (config->csv_output) {
 		fprintf(config->output, "%s%" PRIu64 "%s%.2f",
-					csv_sep,
+					config->csv_sep,
 					run,
-					csv_sep,
+					config->csv_sep,
 					ena ? 100.0 * run / ena : 100.0);
 	} else if (run != ena) {
 		fprintf(config->output, "  (%.2f%%)", 100.0 * run / ena);
@@ -679,8 +677,8 @@ static void print_noise_pct(struct perf_stat_config *config,
 {
 	double pct = rel_stddev_stats(total, avg);
 
-	if (csv_output)
-		fprintf(config->output, "%s%.2f%%", csv_sep, pct);
+	if (config->csv_output)
+		fprintf(config->output, "%s%.2f%%", config->csv_sep, pct);
 	else if (pct)
 		fprintf(config->output, "  ( +-%6.2f%% )", pct);
 }
@@ -704,34 +702,34 @@ static void aggr_printout(struct perf_stat_config *config,
 	case AGGR_CORE:
 		fprintf(config->output, "S%d-C%*d%s%*d%s",
 			cpu_map__id_to_socket(id),
-			csv_output ? 0 : -8,
+			config->csv_output ? 0 : -8,
 			cpu_map__id_to_cpu(id),
-			csv_sep,
-			csv_output ? 0 : 4,
+			config->csv_sep,
+			config->csv_output ? 0 : 4,
 			nr,
-			csv_sep);
+			config->csv_sep);
 		break;
 	case AGGR_SOCKET:
 		fprintf(config->output, "S%*d%s%*d%s",
-			csv_output ? 0 : -5,
+			config->csv_output ? 0 : -5,
 			id,
-			csv_sep,
-			csv_output ? 0 : 4,
+			config->csv_sep,
+			config->csv_output ? 0 : 4,
 			nr,
-			csv_sep);
+			config->csv_sep);
 			break;
 	case AGGR_NONE:
 		fprintf(config->output, "CPU%*d%s",
-			csv_output ? 0 : -4,
-			perf_evsel__cpus(evsel)->map[id], csv_sep);
+			config->csv_output ? 0 : -4,
+			perf_evsel__cpus(evsel)->map[id], config->csv_sep);
 		break;
 	case AGGR_THREAD:
 		fprintf(config->output, "%*s-%*d%s",
-			csv_output ? 0 : 16,
+			config->csv_output ? 0 : 16,
 			thread_map__comm(evsel->threads, id),
-			csv_output ? 0 : -8,
+			config->csv_output ? 0 : -8,
 			thread_map__pid(evsel->threads, id),
-			csv_sep);
+			config->csv_sep);
 		break;
 	case AGGR_GLOBAL:
 	case AGGR_UNSET:
@@ -804,10 +802,10 @@ static void new_line_csv(struct perf_stat_config *config, void *ctx)
 
 	fputc('\n', os->fh);
 	if (os->prefix)
-		fprintf(os->fh, "%s%s", os->prefix, csv_sep);
+		fprintf(os->fh, "%s%s", os->prefix, config->csv_sep);
 	aggr_printout(config, os->evsel, os->id, os->nr);
 	for (i = 0; i < os->nfields; i++)
-		fputs(csv_sep, os->fh);
+		fputs(config->csv_sep, os->fh);
 }
 
 static void print_metric_csv(struct perf_stat_config *config __maybe_unused,
@@ -820,7 +818,7 @@ static void print_metric_csv(struct perf_stat_config *config __maybe_unused,
 	char buf[64], *vals, *ends;
 
 	if (unit == NULL || fmt == NULL) {
-		fprintf(out, "%s%s", csv_sep, csv_sep);
+		fprintf(out, "%s%s", config->csv_sep, config->csv_sep);
 		return;
 	}
 	snprintf(buf, sizeof(buf), fmt, val);
@@ -830,7 +828,7 @@ static void print_metric_csv(struct perf_stat_config *config __maybe_unused,
 	*ends = 0;
 	while (isspace(*unit))
 		unit++;
-	fprintf(out, "%s%s%s%s", csv_sep, vals, csv_sep, unit);
+	fprintf(out, "%s%s%s%s", config->csv_sep, vals, config->csv_sep, unit);
 }
 
 /* Filter out some columns that don't work well in metrics only mode */
@@ -898,7 +896,7 @@ static void print_metric_only_csv(struct perf_stat_config *config __maybe_unused
 	while (isdigit(*ends) || *ends == '.')
 		ends++;
 	*ends = 0;
-	fprintf(out, "%s%s", vals, csv_sep);
+	fprintf(out, "%s%s", vals, config->csv_sep);
 }
 
 static void new_line_metric(struct perf_stat_config *config __maybe_unused,
@@ -917,8 +915,8 @@ static void print_metric_header(struct perf_stat_config *config __maybe_unused,
 	if (!valid_only_metric(unit))
 		return;
 	unit = fixunit(tbuf, os->evsel, unit);
-	if (csv_output)
-		fprintf(os->fh, "%s%s", unit, csv_sep);
+	if (config->csv_output)
+		fprintf(os->fh, "%s%s", unit, config->csv_sep);
 	else
 		fprintf(os->fh, "%*s ", metric_only_len, unit);
 }
@@ -952,7 +950,7 @@ static void abs_printout(struct perf_stat_config *config,
 	double sc =  evsel->scale;
 	const char *fmt;
 
-	if (csv_output) {
+	if (config->csv_output) {
 		fmt = floor(sc) != sc ?  "%.2f%s" : "%.0f%s";
 	} else {
 		if (big_num)
@@ -963,17 +961,17 @@ static void abs_printout(struct perf_stat_config *config,
 
 	aggr_printout(config, evsel, id, nr);
 
-	fprintf(output, fmt, avg, csv_sep);
+	fprintf(output, fmt, avg, config->csv_sep);
 
 	if (evsel->unit)
 		fprintf(output, "%-*s%s",
-			csv_output ? 0 : unit_width,
-			evsel->unit, csv_sep);
+			config->csv_output ? 0 : unit_width,
+			evsel->unit, config->csv_sep);
 
-	fprintf(output, "%-*s", csv_output ? 0 : 25, perf_evsel__name(evsel));
+	fprintf(output, "%-*s", config->csv_output ? 0 : 25, perf_evsel__name(evsel));
 
 	if (evsel->cgrp)
-		fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
+		fprintf(output, "%s%s", config->csv_sep, evsel->cgrp->name);
 }
 
 static bool is_mixed_hw_group(struct perf_evsel *counter)
@@ -1018,14 +1016,14 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 
 	if (metric_only) {
 		nl = new_line_metric;
-		if (csv_output)
+		if (config->csv_output)
 			pm = print_metric_only_csv;
 		else
 			pm = print_metric_only;
 	} else
 		nl = new_line_std;
 
-	if (csv_output && !metric_only) {
+	if (config->csv_output && !metric_only) {
 		static int aggr_fields[] = {
 			[AGGR_GLOBAL] = 0,
 			[AGGR_THREAD] = 1,
@@ -1049,9 +1047,9 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 		aggr_printout(config, counter, id, nr);
 
 		fprintf(config->output, "%*s%s",
-			csv_output ? 0 : 18,
+			config->csv_output ? 0 : 18,
 			counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
-			csv_sep);
+			config->csv_sep);
 
 		if (counter->supported) {
 			print_free_counters_hint = 1;
@@ -1060,22 +1058,22 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 		}
 
 		fprintf(config->output, "%-*s%s",
-			csv_output ? 0 : unit_width,
-			counter->unit, csv_sep);
+			config->csv_output ? 0 : unit_width,
+			counter->unit, config->csv_sep);
 
 		fprintf(config->output, "%*s",
-			csv_output ? 0 : -25,
+			config->csv_output ? 0 : -25,
 			perf_evsel__name(counter));
 
 		if (counter->cgrp)
 			fprintf(config->output, "%s%s",
-				csv_sep, counter->cgrp->name);
+				config->csv_sep, counter->cgrp->name);
 
-		if (!csv_output)
+		if (!config->csv_output)
 			pm(config, &os, NULL, NULL, "", 0);
 		print_noise(config, counter, noise);
 		print_running(config, run, ena);
-		if (csv_output)
+		if (config->csv_output)
 			pm(config, &os, NULL, NULL, "", 0);
 		return;
 	}
@@ -1088,7 +1086,7 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 	out.ctx = &os;
 	out.force_header = false;
 
-	if (csv_output && !metric_only) {
+	if (config->csv_output && !metric_only) {
 		print_noise(config, counter, noise);
 		print_running(config, run, ena);
 	}
@@ -1096,7 +1094,7 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 	perf_stat__print_shadow_stats(config, counter, uval,
 				first_shadow_cpu(counter, id),
 				&out, &metric_events, st);
-	if (!csv_output && !metric_only) {
+	if (!config->csv_output && !metric_only) {
 		print_noise(config, counter, noise);
 		print_running(config, run, ena);
 	}
@@ -1512,10 +1510,10 @@ static void print_metric_headers(struct perf_stat_config *config,
 	if (prefix)
 		fprintf(config->output, "%s", prefix);
 
-	if (!csv_output && !no_indent)
+	if (!config->csv_output && !no_indent)
 		fprintf(config->output, "%*s",
 			aggr_header_lens[config->aggr_mode], "");
-	if (csv_output) {
+	if (config->csv_output) {
 		if (config->interval)
 			fputs("time,", config->output);
 		fputs(aggr_header_csv[config->aggr_mode], config->output);
@@ -1549,9 +1547,9 @@ static void print_interval(struct perf_stat_config *config,
 	if (interval_clear)
 		puts(CONSOLE_CLEAR);
 
-	sprintf(prefix, "%6lu.%09lu%s", ts->tv_sec, ts->tv_nsec, csv_sep);
+	sprintf(prefix, "%6lu.%09lu%s", ts->tv_sec, ts->tv_nsec, config->csv_sep);
 
-	if ((num_print_interval == 0 && !csv_output) || interval_clear) {
+	if ((num_print_interval == 0 && !config->csv_output) || interval_clear) {
 		switch (config->aggr_mode) {
 		case AGGR_SOCKET:
 			fprintf(output, "#           time socket cpus");
@@ -1597,7 +1595,7 @@ static void print_header(struct perf_stat_config *config,
 
 	fflush(stdout);
 
-	if (!csv_output) {
+	if (!config->csv_output) {
 		fprintf(output, "\n");
 		fprintf(output, " Performance counter stats for ");
 		if (target.system_wide)
@@ -1776,7 +1774,7 @@ perf_evlist__print_counters(struct perf_evlist *evlist,
 		break;
 	}
 
-	if (!interval && !csv_output)
+	if (!interval && !config->csv_output)
 		print_footer(config);
 
 	fflush(config->output);
@@ -1896,7 +1894,7 @@ static const struct option stat_options[] = {
 	OPT_SET_UINT('A', "no-aggr", &stat_config.aggr_mode,
 		    "disable CPU count aggregation", AGGR_NONE),
 	OPT_BOOLEAN(0, "no-merge", &no_merge, "Do not merge identical named events"),
-	OPT_STRING('x', "field-separator", &csv_sep, "separator",
+	OPT_STRING('x', "field-separator", &stat_config.csv_sep, "separator",
 		   "print counts with custom separator"),
 	OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
 		     "monitor event in cgroup name only", parse_cgroups),
@@ -2749,12 +2747,12 @@ int cmd_stat(int argc, const char **argv)
 	perf_stat__collect_metric_expr(evsel_list);
 	perf_stat__init_shadow_stats();
 
-	if (csv_sep) {
-		csv_output = true;
-		if (!strcmp(csv_sep, "\\t"))
-			csv_sep = "\t";
+	if (stat_config.csv_sep) {
+		stat_config.csv_output = true;
+		if (!strcmp(stat_config.csv_sep, "\\t"))
+			stat_config.csv_sep = "\t";
 	} else
-		csv_sep = DEFAULT_SEPARATOR;
+		stat_config.csv_sep = DEFAULT_SEPARATOR;
 
 	if (argc && !strncmp(argv[0], "rec", 3)) {
 		argc = __cmd_record(argc, argv);
@@ -2827,7 +2825,7 @@ int cmd_stat(int argc, const char **argv)
 	/*
 	 * let the spreadsheet do the pretty-printing
 	 */
-	if (csv_output) {
+	if (stat_config.csv_output) {
 		/* User explicitly passed -B? */
 		if (big_num_opt == 1) {
 			fprintf(stderr, "-B option not supported with -x\n");
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index dffcf2110706..18546d8b0279 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -91,6 +91,7 @@ struct perf_stat_config {
 	bool			 scale;
 	bool			 no_inherit;
 	bool			 identifier;
+	bool			 csv_output;
 	FILE			*output;
 	unsigned int		 interval;
 	unsigned int		 timeout;
@@ -98,6 +99,7 @@ struct perf_stat_config {
 	int			 times;
 	struct runtime_stat	*stats;
 	int			 stats_num;
+	const char		*csv_sep;
 };
 
 void update_stats(struct stats *stats, u64 val);

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf stat: Move 'interval_clear' to 'struct perf_stat_config'
  2018-08-30  6:32 ` [PATCH 21/43] perf stat: Move interval_clear into struct perf_stat_config Jiri Olsa
@ 2018-09-06 13:31   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:31 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: alexander.shishkin, namhyung, dsahern, jolsa, mingo, hpa, peterz,
	linux-kernel, acme, andi, tglx

Commit-ID:  132c6ba3c440fd21a45ff7f9d7a1f53813f4d0e3
Gitweb:     https://git.kernel.org/tip/132c6ba3c440fd21a45ff7f9d7a1f53813f4d0e3
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:30 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:23 -0300

perf stat: Move 'interval_clear' to 'struct perf_stat_config'

Move the static 'interval_clear' variable to 'struct perf_stat_config',
so it can be passed around and used outside the 'perf stat' command.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-22-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 9 ++++-----
 tools/perf/util/stat.h    | 1 +
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 4c29e5065e02..89297ab77d21 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -172,7 +172,6 @@ static struct cpu_map		*aggr_map;
 static aggr_get_id_t		aggr_get_id;
 static bool			append_file;
 static bool			interval_count;
-static bool			interval_clear;
 static const char		*output_name;
 static int			output_fd;
 static int			print_free_counters_hint;
@@ -1544,12 +1543,12 @@ static void print_interval(struct perf_stat_config *config,
 	FILE *output = config->output;
 	static int num_print_interval;
 
-	if (interval_clear)
+	if (config->interval_clear)
 		puts(CONSOLE_CLEAR);
 
 	sprintf(prefix, "%6lu.%09lu%s", ts->tv_sec, ts->tv_nsec, config->csv_sep);
 
-	if ((num_print_interval == 0 && !config->csv_output) || interval_clear) {
+	if ((num_print_interval == 0 && !config->csv_output) || config->interval_clear) {
 		switch (config->aggr_mode) {
 		case AGGR_SOCKET:
 			fprintf(output, "#           time socket cpus");
@@ -1581,7 +1580,7 @@ static void print_interval(struct perf_stat_config *config,
 		}
 	}
 
-	if ((num_print_interval == 0 || interval_clear) && metric_only)
+	if ((num_print_interval == 0 || config->interval_clear) && metric_only)
 		print_metric_headers(config, " ", true);
 	if (++num_print_interval == 25)
 		num_print_interval = 0;
@@ -1911,7 +1910,7 @@ static const struct option stat_options[] = {
 		    "(overhead is possible for values <= 100ms)"),
 	OPT_INTEGER(0, "interval-count", &stat_config.times,
 		    "print counts for fixed number of times"),
-	OPT_BOOLEAN(0, "interval-clear", &interval_clear,
+	OPT_BOOLEAN(0, "interval-clear", &stat_config.interval_clear,
 		    "clear screen in between new interval"),
 	OPT_UINTEGER(0, "timeout", &stat_config.timeout,
 		    "stop workload and print counts after a timeout period in ms (>= 10ms)"),
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 18546d8b0279..470ab37601be 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -92,6 +92,7 @@ struct perf_stat_config {
 	bool			 no_inherit;
 	bool			 identifier;
 	bool			 csv_output;
+	bool			 interval_clear;
 	FILE			*output;
 	unsigned int		 interval;
 	unsigned int		 timeout;

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf stat: Move 'metric_only' to 'struct perf_stat_config'
  2018-08-30  6:32 ` [PATCH 22/43] perf stat: Move metric_only into struct perf_stat_config Jiri Olsa
@ 2018-09-06 13:32   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:32 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: peterz, andi, namhyung, linux-kernel, alexander.shishkin, jolsa,
	tglx, mingo, dsahern, hpa, acme

Commit-ID:  0ce5aa0266604c77ee64882b70c980e843629177
Gitweb:     https://git.kernel.org/tip/0ce5aa0266604c77ee64882b70c980e843629177
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:31 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:23 -0300

perf stat: Move 'metric_only' to 'struct perf_stat_config'

Move the static 'metric_only' variable to 'struct perf_stat_config', so
it can be passed around and used outside the 'perf stat' command.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-23-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 29 ++++++++++++++++-------------
 tools/perf/util/stat.h    |  1 +
 2 files changed, 17 insertions(+), 13 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 89297ab77d21..397cb4f28d7f 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -163,7 +163,6 @@ static const char		*post_cmd			= NULL;
 static bool			sync_run			= false;
 static unsigned int		unit_width			= 4; /* strlen("unit") */
 static bool			forever				= false;
-static bool			metric_only			= false;
 static bool			force_metric_only		= false;
 static bool			no_merge			= false;
 static bool			walltime_run_table		= false;
@@ -1013,7 +1012,7 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 	print_metric_t pm = print_metric_std;
 	new_line_t nl;
 
-	if (metric_only) {
+	if (config->metric_only) {
 		nl = new_line_metric;
 		if (config->csv_output)
 			pm = print_metric_only_csv;
@@ -1022,7 +1021,7 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 	} else
 		nl = new_line_std;
 
-	if (config->csv_output && !metric_only) {
+	if (config->csv_output && !config->metric_only) {
 		static int aggr_fields[] = {
 			[AGGR_GLOBAL] = 0,
 			[AGGR_THREAD] = 1,
@@ -1039,7 +1038,7 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 			os.nfields++;
 	}
 	if (run == 0 || ena == 0 || counter->counts->scaled == -1) {
-		if (metric_only) {
+		if (config->metric_only) {
 			pm(config, &os, NULL, "", "", 0);
 			return;
 		}
@@ -1077,7 +1076,7 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 		return;
 	}
 
-	if (!metric_only)
+	if (!config->metric_only)
 		abs_printout(config, id, nr, counter, uval);
 
 	out.print_metric = pm;
@@ -1085,7 +1084,7 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 	out.ctx = &os;
 	out.force_header = false;
 
-	if (config->csv_output && !metric_only) {
+	if (config->csv_output && !config->metric_only) {
 		print_noise(config, counter, noise);
 		print_running(config, run, ena);
 	}
@@ -1093,7 +1092,7 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 	perf_stat__print_shadow_stats(config, counter, uval,
 				first_shadow_cpu(counter, id),
 				&out, &metric_events, st);
-	if (!config->csv_output && !metric_only) {
+	if (!config->csv_output && !config->metric_only) {
 		print_noise(config, counter, noise);
 		print_running(config, run, ena);
 	}
@@ -1225,6 +1224,7 @@ static void aggr_cb(struct perf_evsel *counter, void *data, bool first)
 static void print_aggr(struct perf_stat_config *config,
 		       char *prefix)
 {
+	bool metric_only = config->metric_only;
 	FILE *output = config->output;
 	struct perf_evsel *counter;
 	int s, id, nr;
@@ -1388,6 +1388,7 @@ static void counter_aggr_cb(struct perf_evsel *counter, void *data,
 static void print_counter_aggr(struct perf_stat_config *config,
 			       struct perf_evsel *counter, char *prefix)
 {
+	bool metric_only = config->metric_only;
 	FILE *output = config->output;
 	double uval;
 	struct caggr_data cd = { .avg = 0.0 };
@@ -1540,6 +1541,7 @@ static void print_metric_headers(struct perf_stat_config *config,
 static void print_interval(struct perf_stat_config *config,
 			   char *prefix, struct timespec *ts)
 {
+	bool metric_only = config->metric_only;
 	FILE *output = config->output;
 	static int num_print_interval;
 
@@ -1716,6 +1718,7 @@ perf_evlist__print_counters(struct perf_evlist *evlist,
 			    struct timespec *ts,
 			    int argc, const char **argv)
 {
+	bool metric_only = config->metric_only;
 	int interval = config->interval;
 	struct perf_evsel *counter;
 	char buf[64], *prefix = NULL;
@@ -1843,7 +1846,7 @@ static int enable_metric_only(const struct option *opt __maybe_unused,
 			      const char *s __maybe_unused, int unset)
 {
 	force_metric_only = true;
-	metric_only = !unset;
+	stat_config.metric_only = !unset;
 	return 0;
 }
 
@@ -1922,7 +1925,7 @@ static const struct option stat_options[] = {
 		     "aggregate counts per thread", AGGR_THREAD),
 	OPT_UINTEGER('D', "delay", &stat_config.initial_delay,
 		     "ms to wait before starting measurement after program start"),
-	OPT_CALLBACK_NOOPT(0, "metric-only", &metric_only, NULL,
+	OPT_CALLBACK_NOOPT(0, "metric-only", &stat_config.metric_only, NULL,
 			"Only print computed metrics. No raw values", enable_metric_only),
 	OPT_BOOLEAN(0, "topdown", &topdown_run,
 			"measure topdown level 1 statistics"),
@@ -2345,7 +2348,7 @@ static int add_default_attributes(void)
 		if (pmu_have_event("msr", "aperf") &&
 		    pmu_have_event("msr", "smi")) {
 			if (!force_metric_only)
-				metric_only = true;
+				stat_config.metric_only = true;
 			err = parse_events(evsel_list, smi_cost_attrs, &errinfo);
 		} else {
 			fprintf(stderr, "To measure SMI cost, it needs "
@@ -2376,7 +2379,7 @@ static int add_default_attributes(void)
 		}
 
 		if (!force_metric_only)
-			metric_only = true;
+			stat_config.metric_only = true;
 		if (topdown_filter_events(topdown_attrs, &str,
 				arch_topdown_check_group(&warn)) < 0) {
 			pr_err("Out of memory\n");
@@ -2776,12 +2779,12 @@ int cmd_stat(int argc, const char **argv)
 		goto out;
 	}
 
-	if (metric_only && stat_config.aggr_mode == AGGR_THREAD) {
+	if (stat_config.metric_only && stat_config.aggr_mode == AGGR_THREAD) {
 		fprintf(stderr, "--metric-only is not supported with --per-thread\n");
 		goto out;
 	}
 
-	if (metric_only && run_count > 1) {
+	if (stat_config.metric_only && run_count > 1) {
 		fprintf(stderr, "--metric-only is not supported with -r\n");
 		goto out;
 	}
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 470ab37601be..da838182b99c 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -93,6 +93,7 @@ struct perf_stat_config {
 	bool			 identifier;
 	bool			 csv_output;
 	bool			 interval_clear;
+	bool			 metric_only;
 	FILE			*output;
 	unsigned int		 interval;
 	unsigned int		 timeout;

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf stat: Move 'unit_width' to 'struct perf_stat_config'
  2018-08-30  6:32 ` [PATCH 23/43] perf stat: Move unit_width into struct perf_stat_config Jiri Olsa
@ 2018-09-06 13:33   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:33 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: alexander.shishkin, dsahern, mingo, acme, jolsa, tglx,
	linux-kernel, andi, namhyung, hpa, peterz

Commit-ID:  df4f7b4d4b1e61e6b16ac2e3760be46bac86e4f4
Gitweb:     https://git.kernel.org/tip/df4f7b4d4b1e61e6b16ac2e3760be46bac86e4f4
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:32 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:23 -0300

perf stat: Move 'unit_width' to 'struct perf_stat_config'

Move the static 'unit_width' variable to 'struct perf_stat_config',
so it can be passed around and used outside the 'perf stat' command.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-24-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 11 ++++++-----
 tools/perf/util/stat.h    |  1 +
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 397cb4f28d7f..24171aa6c41f 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -161,7 +161,6 @@ static bool			group				= false;
 static const char		*pre_cmd			= NULL;
 static const char		*post_cmd			= NULL;
 static bool			sync_run			= false;
-static unsigned int		unit_width			= 4; /* strlen("unit") */
 static bool			forever				= false;
 static bool			force_metric_only		= false;
 static bool			no_merge			= false;
@@ -200,6 +199,7 @@ static volatile int done = 0;
 static struct perf_stat_config stat_config = {
 	.aggr_mode	= AGGR_GLOBAL,
 	.scale		= true,
+	.unit_width	= 4, /* strlen("unit") */
 };
 
 static bool is_duration_time(struct perf_evsel *evsel)
@@ -524,8 +524,8 @@ try_again:
 		counter->supported = true;
 
 		l = strlen(counter->unit);
-		if (l > unit_width)
-			unit_width = l;
+		if (l > stat_config.unit_width)
+			stat_config.unit_width = l;
 
 		if (perf_evsel__should_store_id(counter) &&
 		    perf_evsel__store_ids(counter, evsel_list))
@@ -963,7 +963,7 @@ static void abs_printout(struct perf_stat_config *config,
 
 	if (evsel->unit)
 		fprintf(output, "%-*s%s",
-			config->csv_output ? 0 : unit_width,
+			config->csv_output ? 0 : config->unit_width,
 			evsel->unit, config->csv_sep);
 
 	fprintf(output, "%-*s", config->csv_output ? 0 : 25, perf_evsel__name(evsel));
@@ -1056,7 +1056,7 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 		}
 
 		fprintf(config->output, "%-*s%s",
-			config->csv_output ? 0 : unit_width,
+			config->csv_output ? 0 : config->unit_width,
 			counter->unit, config->csv_sep);
 
 		fprintf(config->output, "%*s",
@@ -1542,6 +1542,7 @@ static void print_interval(struct perf_stat_config *config,
 			   char *prefix, struct timespec *ts)
 {
 	bool metric_only = config->metric_only;
+	unsigned int unit_width = config->unit_width;
 	FILE *output = config->output;
 	static int num_print_interval;
 
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index da838182b99c..2dc66e0ba4b8 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -98,6 +98,7 @@ struct perf_stat_config {
 	unsigned int		 interval;
 	unsigned int		 timeout;
 	unsigned int		 initial_delay;
+	unsigned int		 unit_width;
 	int			 times;
 	struct runtime_stat	*stats;
 	int			 stats_num;

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf stat: Add 'target' argument to perf_evlist__print_counters()
  2018-08-30  6:32 ` [PATCH 24/43] perf stat: Add target argument to perf_evlist__print_counters Jiri Olsa
@ 2018-09-06 13:33   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:33 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: tglx, alexander.shishkin, namhyung, acme, hpa, dsahern,
	linux-kernel, andi, mingo, peterz, jolsa

Commit-ID:  c512e0eae4c63be8c5964c3942b2e9c04dcd459e
Gitweb:     https://git.kernel.org/tip/c512e0eae4c63be8c5964c3942b2e9c04dcd459e
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:33 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:23 -0300

perf stat: Add 'target' argument to perf_evlist__print_counters()

Add 'struct target' argument to perf_evlist__print_counters(), so the
function does not depend on the 'perf stat' command object local target
and can be moved out.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-25-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 20 +++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 24171aa6c41f..528f85146b59 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1590,6 +1590,7 @@ static void print_interval(struct perf_stat_config *config,
 }
 
 static void print_header(struct perf_stat_config *config,
+			 struct target *_target,
 			 int argc, const char **argv)
 {
 	FILE *output = config->output;
@@ -1600,18 +1601,18 @@ static void print_header(struct perf_stat_config *config,
 	if (!config->csv_output) {
 		fprintf(output, "\n");
 		fprintf(output, " Performance counter stats for ");
-		if (target.system_wide)
+		if (_target->system_wide)
 			fprintf(output, "\'system wide");
-		else if (target.cpu_list)
-			fprintf(output, "\'CPU(s) %s", target.cpu_list);
-		else if (!target__has_task(&target)) {
+		else if (_target->cpu_list)
+			fprintf(output, "\'CPU(s) %s", _target->cpu_list);
+		else if (!target__has_task(_target)) {
 			fprintf(output, "\'%s", argv ? argv[0] : "pipe");
 			for (i = 1; argv && (i < argc); i++)
 				fprintf(output, " %s", argv[i]);
-		} else if (target.pid)
-			fprintf(output, "process id \'%s", target.pid);
+		} else if (_target->pid)
+			fprintf(output, "process id \'%s", _target->pid);
 		else
-			fprintf(output, "thread id \'%s", target.tid);
+			fprintf(output, "thread id \'%s", _target->tid);
 
 		fprintf(output, "\'");
 		if (run_count > 1)
@@ -1716,6 +1717,7 @@ static void print_footer(struct perf_stat_config *config)
 static void
 perf_evlist__print_counters(struct perf_evlist *evlist,
 			    struct perf_stat_config *config,
+			    struct target *_target,
 			    struct timespec *ts,
 			    int argc, const char **argv)
 {
@@ -1727,7 +1729,7 @@ perf_evlist__print_counters(struct perf_evlist *evlist,
 	if (interval)
 		print_interval(config, prefix = buf, ts);
 	else
-		print_header(config, argc, argv);
+		print_header(config, _target, argc, argv);
 
 	if (metric_only) {
 		static int num_print_iv;
@@ -1789,7 +1791,7 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)
 	if (STAT_RECORD && perf_stat.data.is_pipe)
 		return;
 
-	perf_evlist__print_counters(evsel_list, &stat_config,
+	perf_evlist__print_counters(evsel_list, &stat_config, &target,
 				    ts, argc, argv);
 }
 

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf stat: Pass 'evlist' argument to print functions
  2018-08-30  6:32 ` [PATCH 25/43] perf stat: Pass evlist argument to print functions Jiri Olsa
@ 2018-09-06 13:34   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:34 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: alexander.shishkin, linux-kernel, mingo, acme, andi, hpa, peterz,
	tglx, dsahern, jolsa, namhyung

Commit-ID:  bc0bcda201e87d62f0922fa664376355b0fc77ff
Gitweb:     https://git.kernel.org/tip/bc0bcda201e87d62f0922fa664376355b0fc77ff
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:34 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:23 -0300

perf stat: Pass 'evlist' argument to print functions

Add 'evlist' argument to print functions to get rid of the global
'evsel_list' variable dependency.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-26-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 22 +++++++++++++---------
 1 file changed, 13 insertions(+), 9 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 528f85146b59..46181ac492c5 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1222,6 +1222,7 @@ static void aggr_cb(struct perf_evsel *counter, void *data, bool first)
 }
 
 static void print_aggr(struct perf_stat_config *config,
+		       struct perf_evlist *evlist,
 		       char *prefix)
 {
 	bool metric_only = config->metric_only;
@@ -1248,7 +1249,7 @@ static void print_aggr(struct perf_stat_config *config,
 
 		ad.id = id = aggr_map->map[s];
 		first = true;
-		evlist__for_each_entry(evsel_list, counter) {
+		evlist__for_each_entry(evlist, counter) {
 			if (is_duration_time(counter))
 				continue;
 
@@ -1449,6 +1450,7 @@ static void print_counter(struct perf_stat_config *config,
 }
 
 static void print_no_aggr_metric(struct perf_stat_config *config,
+				 struct perf_evlist *evlist,
 				 char *prefix)
 {
 	int cpu;
@@ -1457,13 +1459,13 @@ static void print_no_aggr_metric(struct perf_stat_config *config,
 	u64 ena, run, val;
 	double uval;
 
-	nrcpus = evsel_list->cpus->nr;
+	nrcpus = evlist->cpus->nr;
 	for (cpu = 0; cpu < nrcpus; cpu++) {
 		bool first = true;
 
 		if (prefix)
 			fputs(prefix, config->output);
-		evlist__for_each_entry(evsel_list, counter) {
+		evlist__for_each_entry(evlist, counter) {
 			if (is_duration_time(counter))
 				continue;
 			if (first) {
@@ -1499,6 +1501,7 @@ static const char *aggr_header_csv[] = {
 };
 
 static void print_metric_headers(struct perf_stat_config *config,
+				 struct perf_evlist *evlist,
 				 const char *prefix, bool no_indent)
 {
 	struct perf_stat_output_ctx out;
@@ -1520,7 +1523,7 @@ static void print_metric_headers(struct perf_stat_config *config,
 	}
 
 	/* Print metrics headers only */
-	evlist__for_each_entry(evsel_list, counter) {
+	evlist__for_each_entry(evlist, counter) {
 		if (is_duration_time(counter))
 			continue;
 		os.evsel = counter;
@@ -1539,6 +1542,7 @@ static void print_metric_headers(struct perf_stat_config *config,
 }
 
 static void print_interval(struct perf_stat_config *config,
+			   struct perf_evlist *evlist,
 			   char *prefix, struct timespec *ts)
 {
 	bool metric_only = config->metric_only;
@@ -1584,7 +1588,7 @@ static void print_interval(struct perf_stat_config *config,
 	}
 
 	if ((num_print_interval == 0 || config->interval_clear) && metric_only)
-		print_metric_headers(config, " ", true);
+		print_metric_headers(config, evlist, " ", true);
 	if (++num_print_interval == 25)
 		num_print_interval = 0;
 }
@@ -1727,7 +1731,7 @@ perf_evlist__print_counters(struct perf_evlist *evlist,
 	char buf[64], *prefix = NULL;
 
 	if (interval)
-		print_interval(config, prefix = buf, ts);
+		print_interval(config, evlist, prefix = buf, ts);
 	else
 		print_header(config, _target, argc, argv);
 
@@ -1735,7 +1739,7 @@ perf_evlist__print_counters(struct perf_evlist *evlist,
 		static int num_print_iv;
 
 		if (num_print_iv == 0 && !interval)
-			print_metric_headers(config, prefix, false);
+			print_metric_headers(config, evlist, prefix, false);
 		if (num_print_iv++ == 25)
 			num_print_iv = 0;
 		if (config->aggr_mode == AGGR_GLOBAL && prefix)
@@ -1745,7 +1749,7 @@ perf_evlist__print_counters(struct perf_evlist *evlist,
 	switch (config->aggr_mode) {
 	case AGGR_CORE:
 	case AGGR_SOCKET:
-		print_aggr(config, prefix);
+		print_aggr(config, evlist, prefix);
 		break;
 	case AGGR_THREAD:
 		evlist__for_each_entry(evlist, counter) {
@@ -1765,7 +1769,7 @@ perf_evlist__print_counters(struct perf_evlist *evlist,
 		break;
 	case AGGR_NONE:
 		if (metric_only)
-			print_no_aggr_metric(config, prefix);
+			print_no_aggr_metric(config, evlist, prefix);
 		else {
 			evlist__for_each_entry(evlist, counter) {
 				if (is_duration_time(counter))

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf stat: Use 'evsel->evlist' instead of 'evsel_list' in collect_all_aliases()
  2018-08-30  6:32 ` [PATCH 26/43] perf stat: Use evsel->evlist instead of evsel_list in collect_all_aliases Jiri Olsa
@ 2018-09-06 13:34   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:34 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: namhyung, tglx, hpa, linux-kernel, dsahern, jolsa, mingo, acme,
	alexander.shishkin, andi, peterz

Commit-ID:  0c538a9462953dfcde2fe961aca2cf75c2747040
Gitweb:     https://git.kernel.org/tip/0c538a9462953dfcde2fe961aca2cf75c2747040
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:35 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:23 -0300

perf stat: Use 'evsel->evlist' instead of 'evsel_list' in collect_all_aliases()

Use 'evsel->evlist' instead of 'evsel_list' in collect_all_aliases(), to
get rid of the global 'evsel_list' variable dependency.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-27-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 46181ac492c5..11741f3a8342 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1154,10 +1154,11 @@ static void collect_all_aliases(struct perf_evsel *counter,
 				       bool first),
 			    void *data)
 {
+	struct perf_evlist *evlist = counter->evlist;
 	struct perf_evsel *alias;
 
-	alias = list_prepare_entry(counter, &(evsel_list->entries), node);
-	list_for_each_entry_continue (alias, &evsel_list->entries, node) {
+	alias = list_prepare_entry(counter, &(evlist->entries), node);
+	list_for_each_entry_continue (alias, &evlist->entries, node) {
 		if (strcmp(perf_evsel__name(alias), perf_evsel__name(counter)) ||
 		    alias->scale != counter->scale ||
 		    alias->cgrp != counter->cgrp ||

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf stat: Move 'run_count' to 'struct perf_stat_config'
  2018-08-30  6:32 ` [PATCH 27/43] perf stat: Move run_count into struct perf_stat_config Jiri Olsa
@ 2018-09-06 13:35   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:35 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: hpa, peterz, dsahern, linux-kernel, namhyung, andi, tglx, acme,
	jolsa, mingo, alexander.shishkin

Commit-ID:  d97ae04b3d5263be242a6a9f9eef6422fc86326a
Gitweb:     https://git.kernel.org/tip/d97ae04b3d5263be242a6a9f9eef6422fc86326a
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:36 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:23 -0300

perf stat: Move 'run_count' to 'struct perf_stat_config'

Move the static 'run_count' variable to 'struct perf_stat_config', so
that it can be passed around and used outside the 'perf stat' command.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-28-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 39 ++++++++++++++++++++-------------------
 tools/perf/util/stat.h    |  1 +
 2 files changed, 21 insertions(+), 19 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 11741f3a8342..1276596840c9 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -147,7 +147,6 @@ typedef int (*aggr_get_id_t)(struct cpu_map *m, int cpu);
 
 #define METRIC_ONLY_LEN 20
 
-static int			run_count			=  1;
 static volatile pid_t		child_pid			= -1;
 static bool			null_run			=  false;
 static int			detailed_run			=  0;
@@ -200,6 +199,7 @@ static struct perf_stat_config stat_config = {
 	.aggr_mode	= AGGR_GLOBAL,
 	.scale		= true,
 	.unit_width	= 4, /* strlen("unit") */
+	.run_count	= 1,
 };
 
 static bool is_duration_time(struct perf_evsel *evsel)
@@ -686,7 +686,7 @@ static void print_noise(struct perf_stat_config *config,
 {
 	struct perf_stat_evsel *ps;
 
-	if (run_count == 1)
+	if (config->run_count == 1)
 		return;
 
 	ps = evsel->stats;
@@ -1620,8 +1620,8 @@ static void print_header(struct perf_stat_config *config,
 			fprintf(output, "thread id \'%s", _target->tid);
 
 		fprintf(output, "\'");
-		if (run_count > 1)
-			fprintf(output, " (%d runs)", run_count);
+		if (config->run_count > 1)
+			fprintf(output, " (%d runs)", config->run_count);
 		fprintf(output, ":\n\n");
 	}
 }
@@ -1634,7 +1634,8 @@ static int get_precision(double num)
 	return lround(ceil(-log10(num)));
 }
 
-static void print_table(FILE *output, int precision, double avg)
+static void print_table(struct perf_stat_config *config,
+			FILE *output, int precision, double avg)
 {
 	char tmp[64];
 	int idx, indent = 0;
@@ -1645,7 +1646,7 @@ static void print_table(FILE *output, int precision, double avg)
 
 	fprintf(output, "%*s# Table of individual measurements:\n", indent, "");
 
-	for (idx = 0; idx < run_count; idx++) {
+	for (idx = 0; idx < config->run_count; idx++) {
 		double run = (double) walltime_run[idx] / NSEC_PER_SEC;
 		int h, n = 1 + abs((int) (100.0 * (run - avg)/run) / 5);
 
@@ -1675,7 +1676,7 @@ static void print_footer(struct perf_stat_config *config)
 	if (!null_run)
 		fprintf(output, "\n");
 
-	if (run_count == 1) {
+	if (config->run_count == 1) {
 		fprintf(output, " %17.9f seconds time elapsed", avg);
 
 		if (ru_display) {
@@ -1695,7 +1696,7 @@ static void print_footer(struct perf_stat_config *config)
 		int precision = get_precision(sd) + 2;
 
 		if (walltime_run_table)
-			print_table(output, precision, avg);
+			print_table(config, output, precision, avg);
 
 		fprintf(output, " %17.*f +- %.*f seconds time elapsed",
 			precision, avg, precision, sd);
@@ -1886,7 +1887,7 @@ static const struct option stat_options[] = {
 	OPT_BOOLEAN('c', "scale", &stat_config.scale, "scale/normalize counters"),
 	OPT_INCR('v', "verbose", &verbose,
 		    "be more verbose (show counter open errors, etc)"),
-	OPT_INTEGER('r', "repeat", &run_count,
+	OPT_INTEGER('r', "repeat", &stat_config.run_count,
 		    "repeat command and print average + stddev (max: 100, forever: 0)"),
 	OPT_BOOLEAN(0, "table", &walltime_run_table,
 		    "display details about each run (only with -r option)"),
@@ -2484,7 +2485,7 @@ static int __cmd_record(int argc, const char **argv)
 	if (output_name)
 		data->file.path = output_name;
 
-	if (run_count != 1 || forever) {
+	if (stat_config.run_count != 1 || forever) {
 		pr_err("Cannot use -r option with perf stat record.\n");
 		return -1;
 	}
@@ -2792,12 +2793,12 @@ int cmd_stat(int argc, const char **argv)
 		goto out;
 	}
 
-	if (stat_config.metric_only && run_count > 1) {
+	if (stat_config.metric_only && stat_config.run_count > 1) {
 		fprintf(stderr, "--metric-only is not supported with -r\n");
 		goto out;
 	}
 
-	if (walltime_run_table && run_count <= 1) {
+	if (walltime_run_table && stat_config.run_count <= 1) {
 		fprintf(stderr, "--table is only supported with -r\n");
 		parse_options_usage(stat_usage, stat_options, "r", 1);
 		parse_options_usage(NULL, stat_options, "table", 0);
@@ -2853,20 +2854,20 @@ int cmd_stat(int argc, const char **argv)
 	 * Display user/system times only for single
 	 * run and when there's specified tracee.
 	 */
-	if ((run_count == 1) && target__none(&target))
+	if ((stat_config.run_count == 1) && target__none(&target))
 		ru_display = true;
 
-	if (run_count < 0) {
+	if (stat_config.run_count < 0) {
 		pr_err("Run count must be a positive number\n");
 		parse_options_usage(stat_usage, stat_options, "r", 1);
 		goto out;
-	} else if (run_count == 0) {
+	} else if (stat_config.run_count == 0) {
 		forever = true;
-		run_count = 1;
+		stat_config.run_count = 1;
 	}
 
 	if (walltime_run_table) {
-		walltime_run = zalloc(run_count * sizeof(walltime_run[0]));
+		walltime_run = zalloc(stat_config.run_count * sizeof(walltime_run[0]));
 		if (!walltime_run) {
 			pr_err("failed to setup -r option");
 			goto out;
@@ -2994,8 +2995,8 @@ int cmd_stat(int argc, const char **argv)
 	signal(SIGABRT, skip_signal);
 
 	status = 0;
-	for (run_idx = 0; forever || run_idx < run_count; run_idx++) {
-		if (run_count != 1 && verbose > 0)
+	for (run_idx = 0; forever || run_idx < stat_config.run_count; run_idx++) {
+		if (stat_config.run_count != 1 && verbose > 0)
 			fprintf(output, "[ perf stat: executing run #%d ... ]\n",
 				run_idx + 1);
 
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 2dc66e0ba4b8..351a36f5f5b0 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -100,6 +100,7 @@ struct perf_stat_config {
 	unsigned int		 initial_delay;
 	unsigned int		 unit_width;
 	int			 times;
+	int			 run_count;
 	struct runtime_stat	*stats;
 	int			 stats_num;
 	const char		*csv_sep;

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf stat: Move 'metric_only_len' to 'struct perf_stat_config'
  2018-08-30  6:32 ` [PATCH 28/43] perf stat: Move metric_only_len into struct perf_stat_config Jiri Olsa
@ 2018-09-06 13:35   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:35 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: andi, mingo, namhyung, alexander.shishkin, acme, jolsa, tglx,
	hpa, dsahern, linux-kernel, peterz

Commit-ID:  ee1760e2cf623bc6834fc3e4e89c6ad030a25dfd
Gitweb:     https://git.kernel.org/tip/ee1760e2cf623bc6834fc3e4e89c6ad030a25dfd
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:37 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:23 -0300

perf stat: Move 'metric_only_len' to 'struct perf_stat_config'

Move the static 'metric_only_len' variable to 'struct perf_stat_config',
so that it can be passed around and used outside the 'perf stat' command.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-29-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 10 +++++-----
 tools/perf/util/stat.h    |  1 +
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 1276596840c9..e96cef526ef0 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -176,7 +176,6 @@ static int			print_mixed_hw_group_error;
 static u64			*walltime_run;
 static bool			ru_display			= false;
 static struct rusage		ru_data;
-static unsigned int		metric_only_len			= METRIC_ONLY_LEN;
 
 struct perf_stat {
 	bool			 record;
@@ -200,6 +199,7 @@ static struct perf_stat_config stat_config = {
 	.scale		= true,
 	.unit_width	= 4, /* strlen("unit") */
 	.run_count	= 1,
+	.metric_only_len = METRIC_ONLY_LEN,
 };
 
 static bool is_duration_time(struct perf_evsel *evsel)
@@ -854,14 +854,14 @@ static const char *fixunit(char *buf, struct perf_evsel *evsel,
 	return unit;
 }
 
-static void print_metric_only(struct perf_stat_config *config __maybe_unused,
+static void print_metric_only(struct perf_stat_config *config,
 			      void *ctx, const char *color, const char *fmt,
 			      const char *unit, double val)
 {
 	struct outstate *os = ctx;
 	FILE *out = os->fh;
 	char buf[1024], str[1024];
-	unsigned mlen = metric_only_len;
+	unsigned mlen = config->metric_only_len;
 
 	if (!valid_only_metric(unit))
 		return;
@@ -902,7 +902,7 @@ static void new_line_metric(struct perf_stat_config *config __maybe_unused,
 {
 }
 
-static void print_metric_header(struct perf_stat_config *config __maybe_unused,
+static void print_metric_header(struct perf_stat_config *config,
 				void *ctx, const char *color __maybe_unused,
 				const char *fmt __maybe_unused,
 				const char *unit, double val __maybe_unused)
@@ -916,7 +916,7 @@ static void print_metric_header(struct perf_stat_config *config __maybe_unused,
 	if (config->csv_output)
 		fprintf(os->fh, "%s%s", unit, config->csv_sep);
 	else
-		fprintf(os->fh, "%*s ", metric_only_len, unit);
+		fprintf(os->fh, "%*s ", config->metric_only_len, unit);
 }
 
 static int first_shadow_cpu(struct perf_evsel *evsel, int id)
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 351a36f5f5b0..e70e6d93ee1b 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -99,6 +99,7 @@ struct perf_stat_config {
 	unsigned int		 timeout;
 	unsigned int		 initial_delay;
 	unsigned int		 unit_width;
+	unsigned int		 metric_only_len;
 	int			 times;
 	int			 run_count;
 	struct runtime_stat	*stats;

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf stat: Pass 'struct perf_stat_config' to first_shadow_cpu()
  2018-08-30  6:32 ` [PATCH 29/43] perf stat: Pass stat_config to first_shadow_cpu Jiri Olsa
@ 2018-09-06 13:36   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:36 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: hpa, dsahern, mingo, linux-kernel, jolsa, alexander.shishkin,
	andi, peterz, acme, tglx, namhyung

Commit-ID:  ae2d7da554f0dda837b6639d247665f6df90e41f
Gitweb:     https://git.kernel.org/tip/ae2d7da554f0dda837b6639d247665f6df90e41f
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:38 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:24 -0300

perf stat: Pass 'struct perf_stat_config' to first_shadow_cpu()

Pass a 'struct perf_stat_config' arg to first_shadow_cpu(), so that the
function does not depend on the 'perf stat' command object local
'stat_config' variable and can then be moved out.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-30-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index e96cef526ef0..f5ac6545af34 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -919,17 +919,18 @@ static void print_metric_header(struct perf_stat_config *config,
 		fprintf(os->fh, "%*s ", config->metric_only_len, unit);
 }
 
-static int first_shadow_cpu(struct perf_evsel *evsel, int id)
+static int first_shadow_cpu(struct perf_stat_config *config,
+			    struct perf_evsel *evsel, int id)
 {
 	int i;
 
 	if (!aggr_get_id)
 		return 0;
 
-	if (stat_config.aggr_mode == AGGR_NONE)
+	if (config->aggr_mode == AGGR_NONE)
 		return id;
 
-	if (stat_config.aggr_mode == AGGR_GLOBAL)
+	if (config->aggr_mode == AGGR_GLOBAL)
 		return 0;
 
 	for (i = 0; i < perf_evsel__nr_cpus(evsel); i++) {
@@ -1090,7 +1091,7 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 	}
 
 	perf_stat__print_shadow_stats(config, counter, uval,
-				first_shadow_cpu(counter, id),
+				first_shadow_cpu(config, counter, id),
 				&out, &metric_events, st);
 	if (!config->csv_output && !config->metric_only) {
 		print_noise(config, counter, noise);
@@ -1098,7 +1099,7 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 	}
 }
 
-static void aggr_update_shadow(void)
+static void aggr_update_shadow(struct perf_stat_config *config)
 {
 	int cpu, s2, id, s;
 	u64 val;
@@ -1115,7 +1116,7 @@ static void aggr_update_shadow(void)
 				val += perf_counts(counter->counts, cpu, 0)->val;
 			}
 			perf_stat__update_shadow_stats(counter, val,
-					first_shadow_cpu(counter, id),
+					first_shadow_cpu(config, counter, id),
 					&rt_stat);
 		}
 	}
@@ -1237,7 +1238,7 @@ static void print_aggr(struct perf_stat_config *config,
 	if (!(aggr_map || aggr_get_id))
 		return;
 
-	aggr_update_shadow();
+	aggr_update_shadow(config);
 
 	/*
 	 * With metric_only everything is on a single line.

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf stat: Pass 'evlist' to aggr_update_shadow()
  2018-08-30  6:32 ` [PATCH 30/43] perf stat: Pass evlist to aggr_update_shadow Jiri Olsa
@ 2018-09-06 13:37   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:37 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: alexander.shishkin, dsahern, peterz, mingo, acme, hpa, tglx,
	namhyung, andi, linux-kernel, jolsa

Commit-ID:  77e0faf8552c9329d58a4de460928e03252647c6
Gitweb:     https://git.kernel.org/tip/77e0faf8552c9329d58a4de460928e03252647c6
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:39 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:24 -0300

perf stat: Pass 'evlist' to aggr_update_shadow()

Pass a 'evlist' argument to aggr_update_shadow(), to get rid of the
global 'evsel_list' variable dependency.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-31-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index f5ac6545af34..2711d8f6e4b8 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1099,7 +1099,8 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 	}
 }
 
-static void aggr_update_shadow(struct perf_stat_config *config)
+static void aggr_update_shadow(struct perf_stat_config *config,
+			       struct perf_evlist *evlist)
 {
 	int cpu, s2, id, s;
 	u64 val;
@@ -1107,7 +1108,7 @@ static void aggr_update_shadow(struct perf_stat_config *config)
 
 	for (s = 0; s < aggr_map->nr; s++) {
 		id = aggr_map->map[s];
-		evlist__for_each_entry(evsel_list, counter) {
+		evlist__for_each_entry(evlist, counter) {
 			val = 0;
 			for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
 				s2 = aggr_get_id(evsel_list->cpus, cpu);
@@ -1238,7 +1239,7 @@ static void print_aggr(struct perf_stat_config *config,
 	if (!(aggr_map || aggr_get_id))
 		return;
 
-	aggr_update_shadow(config);
+	aggr_update_shadow(config, evlist);
 
 	/*
 	 * With metric_only everything is on a single line.

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf stat: Add 'walltime_nsecs_stats' pointer to 'struct perf_stat_config'
  2018-08-30  6:32 ` [PATCH 31/43] perf stat: Add walltime_nsecs_stats pointer into struct perf_stat_config Jiri Olsa
@ 2018-09-06 13:37   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:37 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: peterz, jolsa, namhyung, mingo, alexander.shishkin, linux-kernel,
	andi, dsahern, acme, tglx, hpa

Commit-ID:  26893a6018f88779c0aded934e99e0ebb6859a58
Gitweb:     https://git.kernel.org/tip/26893a6018f88779c0aded934e99e0ebb6859a58
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:40 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:24 -0300

perf stat: Add 'walltime_nsecs_stats' pointer to 'struct perf_stat_config'

Add 'walltime_nsecs_stats' pointer to 'struct perf_stat_config', so that
it can be passed around and used outside the 'perf stat' command.

It's initialized to point to stat's walltime_nsecs_stats value.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-32-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 15 ++++++++-------
 tools/perf/util/stat.h    |  1 +
 2 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 2711d8f6e4b8..381549a989b4 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -195,11 +195,12 @@ static struct perf_stat		perf_stat;
 static volatile int done = 0;
 
 static struct perf_stat_config stat_config = {
-	.aggr_mode	= AGGR_GLOBAL,
-	.scale		= true,
-	.unit_width	= 4, /* strlen("unit") */
-	.run_count	= 1,
-	.metric_only_len = METRIC_ONLY_LEN,
+	.aggr_mode		= AGGR_GLOBAL,
+	.scale			= true,
+	.unit_width		= 4, /* strlen("unit") */
+	.run_count		= 1,
+	.metric_only_len	= METRIC_ONLY_LEN,
+	.walltime_nsecs_stats	= &walltime_nsecs_stats,
 };
 
 static bool is_duration_time(struct perf_evsel *evsel)
@@ -1671,7 +1672,7 @@ static double timeval2double(struct timeval *t)
 
 static void print_footer(struct perf_stat_config *config)
 {
-	double avg = avg_stats(&walltime_nsecs_stats) / NSEC_PER_SEC;
+	double avg = avg_stats(config->walltime_nsecs_stats) / NSEC_PER_SEC;
 	FILE *output = config->output;
 	int n;
 
@@ -1690,7 +1691,7 @@ static void print_footer(struct perf_stat_config *config)
 			fprintf(output, " %17.9f seconds sys\n", ru_stime);
 		}
 	} else {
-		double sd = stddev_stats(&walltime_nsecs_stats) / NSEC_PER_SEC;
+		double sd = stddev_stats(config->walltime_nsecs_stats) / NSEC_PER_SEC;
 		/*
 		 * Display at most 2 more significant
 		 * digits than the stddev inaccuracy.
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index e70e6d93ee1b..35550e3efd81 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -105,6 +105,7 @@ struct perf_stat_config {
 	struct runtime_stat	*stats;
 	int			 stats_num;
 	const char		*csv_sep;
+	struct stats		*walltime_nsecs_stats;
 };
 
 void update_stats(struct stats *stats, u64 val);

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf stat: Move 'null_run' to 'struct perf_stat_config'
  2018-08-30  6:32 ` [PATCH 32/43] perf stat: Move null_run into struct perf_stat_config Jiri Olsa
@ 2018-09-06 13:38   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:38 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, tglx, dsahern, hpa, acme, mingo,
	alexander.shishkin, namhyung, jolsa, peterz, andi

Commit-ID:  aea0dca1629c72128cf7174d1d3f3807f7297005
Gitweb:     https://git.kernel.org/tip/aea0dca1629c72128cf7174d1d3f3807f7297005
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:41 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:24 -0300

perf stat: Move 'null_run' to 'struct perf_stat_config'

Move the static 'null_run' variable to 'struct perf_stat_config', so
that it can be passed around and used outside the 'perf stat' command.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-33-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 7 +++----
 tools/perf/util/stat.h    | 1 +
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 381549a989b4..844c755564e3 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -148,7 +148,6 @@ typedef int (*aggr_get_id_t)(struct cpu_map *m, int cpu);
 #define METRIC_ONLY_LEN 20
 
 static volatile pid_t		child_pid			= -1;
-static bool			null_run			=  false;
 static int			detailed_run			=  0;
 static bool			transaction_run;
 static bool			topdown_run			= false;
@@ -1676,7 +1675,7 @@ static void print_footer(struct perf_stat_config *config)
 	FILE *output = config->output;
 	int n;
 
-	if (!null_run)
+	if (!config->null_run)
 		fprintf(output, "\n");
 
 	if (config->run_count == 1) {
@@ -1894,7 +1893,7 @@ static const struct option stat_options[] = {
 		    "repeat command and print average + stddev (max: 100, forever: 0)"),
 	OPT_BOOLEAN(0, "table", &walltime_run_table,
 		    "display details about each run (only with -r option)"),
-	OPT_BOOLEAN('n', "null", &null_run,
+	OPT_BOOLEAN('n', "null", &stat_config.null_run,
 		    "null run - dont start any counters"),
 	OPT_INCR('d', "detailed", &detailed_run,
 		    "detailed run - start a lot of events"),
@@ -2309,7 +2308,7 @@ static int add_default_attributes(void)
 	struct parse_events_error errinfo;
 
 	/* Set attrs if no event is selected and !null_run: */
-	if (null_run)
+	if (stat_config.null_run)
 		return 0;
 
 	if (transaction_run) {
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 35550e3efd81..c198926c0e27 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -94,6 +94,7 @@ struct perf_stat_config {
 	bool			 csv_output;
 	bool			 interval_clear;
 	bool			 metric_only;
+	bool			 null_run;
 	FILE			*output;
 	unsigned int		 interval;
 	unsigned int		 timeout;

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf stat: Move 'print_free_counters_hint' to 'struct perf_stat_config'
  2018-08-30  6:32 ` [PATCH 33/43] perf stat: Move print_free_counters_hint into struct perf_stat_config Jiri Olsa
@ 2018-09-06 13:38   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:38 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: dsahern, alexander.shishkin, jolsa, peterz, acme, andi, tglx,
	linux-kernel, hpa, namhyung, mingo

Commit-ID:  31084123c1962dd4235655c1839a50c9cf6c709b
Gitweb:     https://git.kernel.org/tip/31084123c1962dd4235655c1839a50c9cf6c709b
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:42 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:24 -0300

perf stat: Move 'print_free_counters_hint' to 'struct perf_stat_config'

Move the 'print_free_counters_hint' variable to 'struct perf_stat_config',
so that it can be passed around and used outside the 'perf stat' command.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-34-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 5 ++---
 tools/perf/util/stat.h    | 1 +
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 844c755564e3..8748bb5e5403 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -170,7 +170,6 @@ static bool			append_file;
 static bool			interval_count;
 static const char		*output_name;
 static int			output_fd;
-static int			print_free_counters_hint;
 static int			print_mixed_hw_group_error;
 static u64			*walltime_run;
 static bool			ru_display			= false;
@@ -1051,7 +1050,7 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 			config->csv_sep);
 
 		if (counter->supported) {
-			print_free_counters_hint = 1;
+			config->print_free_counters_hint = 1;
 			if (is_mixed_hw_group(counter))
 				print_mixed_hw_group_error = 1;
 		}
@@ -1707,7 +1706,7 @@ static void print_footer(struct perf_stat_config *config)
 	}
 	fprintf(output, "\n\n");
 
-	if (print_free_counters_hint &&
+	if (config->print_free_counters_hint &&
 	    sysctl__read_int("kernel/nmi_watchdog", &n) >= 0 &&
 	    n > 0)
 		fprintf(output,
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index c198926c0e27..8cad17363e90 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -103,6 +103,7 @@ struct perf_stat_config {
 	unsigned int		 metric_only_len;
 	int			 times;
 	int			 run_count;
+	int			 print_free_counters_hint;
 	struct runtime_stat	*stats;
 	int			 stats_num;
 	const char		*csv_sep;

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf stat: Move 'print_mixed_hw_group_error' to 'struct perf_stat_config'
  2018-08-30  6:32 ` [PATCH 34/43] perf stat: Move print_mixed_hw_group_error into struct perf_stat_config Jiri Olsa
@ 2018-09-06 13:39   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:39 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: hpa, jolsa, andi, alexander.shishkin, namhyung, linux-kernel,
	peterz, dsahern, tglx, acme, mingo

Commit-ID:  3b3cd9a41c2b5d97309099ba6eae69b2d3177226
Gitweb:     https://git.kernel.org/tip/3b3cd9a41c2b5d97309099ba6eae69b2d3177226
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:43 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:24 -0300

perf stat: Move 'print_mixed_hw_group_error' to 'struct perf_stat_config'

Move the 'print_mixed_hw_group_error' global variable to 'struct perf_stat_config',
so that it can be passed around and used outside the 'perf stat' command.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-35-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 5 ++---
 tools/perf/util/stat.h    | 1 +
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 8748bb5e5403..f61c2dc8c7e8 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -170,7 +170,6 @@ static bool			append_file;
 static bool			interval_count;
 static const char		*output_name;
 static int			output_fd;
-static int			print_mixed_hw_group_error;
 static u64			*walltime_run;
 static bool			ru_display			= false;
 static struct rusage		ru_data;
@@ -1052,7 +1051,7 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 		if (counter->supported) {
 			config->print_free_counters_hint = 1;
 			if (is_mixed_hw_group(counter))
-				print_mixed_hw_group_error = 1;
+				config->print_mixed_hw_group_error = 1;
 		}
 
 		fprintf(config->output, "%-*s%s",
@@ -1715,7 +1714,7 @@ static void print_footer(struct perf_stat_config *config)
 "	perf stat ...\n"
 "	echo 1 > /proc/sys/kernel/nmi_watchdog\n");
 
-	if (print_mixed_hw_group_error)
+	if (config->print_mixed_hw_group_error)
 		fprintf(output,
 			"The events in group usually have to be from "
 			"the same PMU. Try reorganizing the group.\n");
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 8cad17363e90..6fb4dac26ccc 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -104,6 +104,7 @@ struct perf_stat_config {
 	int			 times;
 	int			 run_count;
 	int			 print_free_counters_hint;
+	int			 print_mixed_hw_group_error;
 	struct runtime_stat	*stats;
 	int			 stats_num;
 	const char		*csv_sep;

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf stat: Move ru_* data to 'struct perf_stat_config'
  2018-08-30  6:32 ` [PATCH 35/43] perf stat: Move ru_* data into struct perf_stat_config Jiri Olsa
@ 2018-09-06 13:39   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:39 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, alexander.shishkin, acme, peterz, jolsa, mingo,
	hpa, tglx, dsahern, andi, namhyung

Commit-ID:  8897a8916efb29fa8bbe9e5f6e5d56362aedf64e
Gitweb:     https://git.kernel.org/tip/8897a8916efb29fa8bbe9e5f6e5d56362aedf64e
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:44 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:24 -0300

perf stat: Move ru_* data to 'struct perf_stat_config'

Move the 'ru_*' global variables to 'struct perf_stat_config', so that
it can be passed around and used outside the 'perf stat' command.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-36-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 12 +++++-------
 tools/perf/util/stat.h    |  6 ++++++
 2 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index f61c2dc8c7e8..942ebfd8ef2e 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -171,8 +171,6 @@ static bool			interval_count;
 static const char		*output_name;
 static int			output_fd;
 static u64			*walltime_run;
-static bool			ru_display			= false;
-static struct rusage		ru_data;
 
 struct perf_stat {
 	bool			 record;
@@ -583,7 +581,7 @@ try_again:
 					break;
 			}
 		}
-		wait4(child_pid, &status, 0, &ru_data);
+		wait4(child_pid, &status, 0, &stat_config.ru_data);
 
 		if (workload_exec_errno) {
 			const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg));
@@ -1679,9 +1677,9 @@ static void print_footer(struct perf_stat_config *config)
 	if (config->run_count == 1) {
 		fprintf(output, " %17.9f seconds time elapsed", avg);
 
-		if (ru_display) {
-			double ru_utime = timeval2double(&ru_data.ru_utime);
-			double ru_stime = timeval2double(&ru_data.ru_stime);
+		if (config->ru_display) {
+			double ru_utime = timeval2double(&config->ru_data.ru_utime);
+			double ru_stime = timeval2double(&config->ru_data.ru_stime);
 
 			fprintf(output, "\n\n");
 			fprintf(output, " %17.9f seconds user\n", ru_utime);
@@ -2855,7 +2853,7 @@ int cmd_stat(int argc, const char **argv)
 	 * run and when there's specified tracee.
 	 */
 	if ((stat_config.run_count == 1) && target__none(&target))
-		ru_display = true;
+		stat_config.ru_display = true;
 
 	if (stat_config.run_count < 0) {
 		pr_err("Run count must be a positive number\n");
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 6fb4dac26ccc..1fd0b7e196c6 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -4,6 +4,10 @@
 
 #include <linux/types.h>
 #include <stdio.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
 #include "xyarray.h"
 #include "rblist.h"
 #include "perf.h"
@@ -95,6 +99,7 @@ struct perf_stat_config {
 	bool			 interval_clear;
 	bool			 metric_only;
 	bool			 null_run;
+	bool			 ru_display;
 	FILE			*output;
 	unsigned int		 interval;
 	unsigned int		 timeout;
@@ -109,6 +114,7 @@ struct perf_stat_config {
 	int			 stats_num;
 	const char		*csv_sep;
 	struct stats		*walltime_nsecs_stats;
+	struct rusage		 ru_data;
 };
 
 void update_stats(struct stats *stats, u64 val);

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf stat: Move *_aggr_* data to 'struct perf_stat_config'
  2018-08-30  6:32 ` [PATCH 36/43] perf stat: Move *_aggr_* data into struct perf_stat_config Jiri Olsa
@ 2018-09-06 13:40   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:40 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: namhyung, linux-kernel, jolsa, tglx, peterz, hpa, andi, acme,
	mingo, alexander.shishkin, dsahern

Commit-ID:  6f6b6594b5f380b0a972b66b275caa6c54bb1fea
Gitweb:     https://git.kernel.org/tip/6f6b6594b5f380b0a972b66b275caa6c54bb1fea
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:45 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:24 -0300

perf stat: Move *_aggr_* data to 'struct perf_stat_config'

Move the *_aggr_* global variables to 'struct perf_stat_config', so that
it can be passed around and used outside 'perf stat' command.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-37-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 112 ++++++++++++++++++++++++----------------------
 tools/perf/util/stat.h    |   6 +++
 2 files changed, 64 insertions(+), 54 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 942ebfd8ef2e..2f606f76b66a 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -143,8 +143,6 @@ static struct target target = {
 	.uid	= UINT_MAX,
 };
 
-typedef int (*aggr_get_id_t)(struct cpu_map *m, int cpu);
-
 #define METRIC_ONLY_LEN 20
 
 static volatile pid_t		child_pid			= -1;
@@ -164,8 +162,6 @@ static bool			force_metric_only		= false;
 static bool			no_merge			= false;
 static bool			walltime_run_table		= false;
 static struct timespec		ref_time;
-static struct cpu_map		*aggr_map;
-static aggr_get_id_t		aggr_get_id;
 static bool			append_file;
 static bool			interval_count;
 static const char		*output_name;
@@ -920,7 +916,7 @@ static int first_shadow_cpu(struct perf_stat_config *config,
 {
 	int i;
 
-	if (!aggr_get_id)
+	if (!config->aggr_get_id)
 		return 0;
 
 	if (config->aggr_mode == AGGR_NONE)
@@ -932,7 +928,7 @@ static int first_shadow_cpu(struct perf_stat_config *config,
 	for (i = 0; i < perf_evsel__nr_cpus(evsel); i++) {
 		int cpu2 = perf_evsel__cpus(evsel)->map[i];
 
-		if (aggr_get_id(evsel_list->cpus, cpu2) == id)
+		if (config->aggr_get_id(config, evsel_list->cpus, cpu2) == id)
 			return cpu2;
 	}
 	return 0;
@@ -1102,12 +1098,12 @@ static void aggr_update_shadow(struct perf_stat_config *config,
 	u64 val;
 	struct perf_evsel *counter;
 
-	for (s = 0; s < aggr_map->nr; s++) {
-		id = aggr_map->map[s];
+	for (s = 0; s < config->aggr_map->nr; s++) {
+		id = config->aggr_map->map[s];
 		evlist__for_each_entry(evlist, counter) {
 			val = 0;
 			for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
-				s2 = aggr_get_id(evsel_list->cpus, cpu);
+				s2 = config->aggr_get_id(config, evsel_list->cpus, cpu);
 				if (s2 != id)
 					continue;
 				val += perf_counts(counter->counts, cpu, 0)->val;
@@ -1147,8 +1143,8 @@ static void uniquify_event_name(struct perf_evsel *counter)
 	counter->uniquified_name = true;
 }
 
-static void collect_all_aliases(struct perf_evsel *counter,
-			    void (*cb)(struct perf_evsel *counter, void *data,
+static void collect_all_aliases(struct perf_stat_config *config, struct perf_evsel *counter,
+			    void (*cb)(struct perf_stat_config *config, struct perf_evsel *counter, void *data,
 				       bool first),
 			    void *data)
 {
@@ -1164,22 +1160,22 @@ static void collect_all_aliases(struct perf_evsel *counter,
 		    perf_evsel__is_clock(alias) != perf_evsel__is_clock(counter))
 			break;
 		alias->merged_stat = true;
-		cb(alias, data, false);
+		cb(config, alias, data, false);
 	}
 }
 
-static bool collect_data(struct perf_evsel *counter,
-			    void (*cb)(struct perf_evsel *counter, void *data,
+static bool collect_data(struct perf_stat_config *config, struct perf_evsel *counter,
+			    void (*cb)(struct perf_stat_config *config, struct perf_evsel *counter, void *data,
 				       bool first),
 			    void *data)
 {
 	if (counter->merged_stat)
 		return false;
-	cb(counter, data, true);
+	cb(config, counter, data, true);
 	if (no_merge)
 		uniquify_event_name(counter);
 	else if (counter->auto_merge_stats)
-		collect_all_aliases(counter, cb, data);
+		collect_all_aliases(config, counter, cb, data);
 	return true;
 }
 
@@ -1190,7 +1186,8 @@ struct aggr_data {
 	int cpu;
 };
 
-static void aggr_cb(struct perf_evsel *counter, void *data, bool first)
+static void aggr_cb(struct perf_stat_config *config,
+		    struct perf_evsel *counter, void *data, bool first)
 {
 	struct aggr_data *ad = data;
 	int cpu, s2;
@@ -1198,7 +1195,7 @@ static void aggr_cb(struct perf_evsel *counter, void *data, bool first)
 	for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
 		struct perf_counts_values *counts;
 
-		s2 = aggr_get_id(perf_evsel__cpus(counter), cpu);
+		s2 = config->aggr_get_id(config, perf_evsel__cpus(counter), cpu);
 		if (s2 != ad->id)
 			continue;
 		if (first)
@@ -1232,7 +1229,7 @@ static void print_aggr(struct perf_stat_config *config,
 	u64 ena, run, val;
 	bool first;
 
-	if (!(aggr_map || aggr_get_id))
+	if (!(config->aggr_map || config->aggr_get_id))
 		return;
 
 	aggr_update_shadow(config, evlist);
@@ -1241,12 +1238,12 @@ static void print_aggr(struct perf_stat_config *config,
 	 * With metric_only everything is on a single line.
 	 * Without each counter has its own line.
 	 */
-	for (s = 0; s < aggr_map->nr; s++) {
+	for (s = 0; s < config->aggr_map->nr; s++) {
 		struct aggr_data ad;
 		if (prefix && metric_only)
 			fprintf(output, "%s", prefix);
 
-		ad.id = id = aggr_map->map[s];
+		ad.id = id = config->aggr_map->map[s];
 		first = true;
 		evlist__for_each_entry(evlist, counter) {
 			if (is_duration_time(counter))
@@ -1254,7 +1251,7 @@ static void print_aggr(struct perf_stat_config *config,
 
 			ad.val = ad.ena = ad.run = 0;
 			ad.nr = 0;
-			if (!collect_data(counter, aggr_cb, &ad))
+			if (!collect_data(config, counter, aggr_cb, &ad))
 				continue;
 			nr = ad.nr;
 			ena = ad.ena;
@@ -1370,7 +1367,8 @@ struct caggr_data {
 	double avg, avg_enabled, avg_running;
 };
 
-static void counter_aggr_cb(struct perf_evsel *counter, void *data,
+static void counter_aggr_cb(struct perf_stat_config *config __maybe_unused,
+			    struct perf_evsel *counter, void *data,
 			    bool first __maybe_unused)
 {
 	struct caggr_data *cd = data;
@@ -1393,7 +1391,7 @@ static void print_counter_aggr(struct perf_stat_config *config,
 	double uval;
 	struct caggr_data cd = { .avg = 0.0 };
 
-	if (!collect_data(counter, counter_aggr_cb, &cd))
+	if (!collect_data(config, counter, counter_aggr_cb, &cd))
 		return;
 
 	if (prefix && !metric_only)
@@ -1406,7 +1404,8 @@ static void print_counter_aggr(struct perf_stat_config *config,
 		fprintf(output, "\n");
 }
 
-static void counter_cb(struct perf_evsel *counter, void *data,
+static void counter_cb(struct perf_stat_config *config __maybe_unused,
+		       struct perf_evsel *counter, void *data,
 		       bool first __maybe_unused)
 {
 	struct aggr_data *ad = data;
@@ -1431,7 +1430,7 @@ static void print_counter(struct perf_stat_config *config,
 	for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
 		struct aggr_data ad = { .cpu = cpu };
 
-		if (!collect_data(counter, counter_cb, &ad))
+		if (!collect_data(config, counter, counter_cb, &ad))
 			return;
 		val = ad.val;
 		ena = ad.ena;
@@ -1944,12 +1943,14 @@ static const struct option stat_options[] = {
 	OPT_END()
 };
 
-static int perf_stat__get_socket(struct cpu_map *map, int cpu)
+static int perf_stat__get_socket(struct perf_stat_config *config __maybe_unused,
+				 struct cpu_map *map, int cpu)
 {
 	return cpu_map__get_socket(map, cpu, NULL);
 }
 
-static int perf_stat__get_core(struct cpu_map *map, int cpu)
+static int perf_stat__get_core(struct perf_stat_config *config __maybe_unused,
+			       struct cpu_map *map, int cpu)
 {
 	return cpu_map__get_core(map, cpu, NULL);
 }
@@ -1966,9 +1967,8 @@ static int cpu_map__get_max(struct cpu_map *map)
 	return max;
 }
 
-static struct cpu_map *cpus_aggr_map;
-
-static int perf_stat__get_aggr(aggr_get_id_t get_id, struct cpu_map *map, int idx)
+static int perf_stat__get_aggr(struct perf_stat_config *config,
+			       aggr_get_id_t get_id, struct cpu_map *map, int idx)
 {
 	int cpu;
 
@@ -1977,20 +1977,22 @@ static int perf_stat__get_aggr(aggr_get_id_t get_id, struct cpu_map *map, int id
 
 	cpu = map->map[idx];
 
-	if (cpus_aggr_map->map[cpu] == -1)
-		cpus_aggr_map->map[cpu] = get_id(map, idx);
+	if (config->cpus_aggr_map->map[cpu] == -1)
+		config->cpus_aggr_map->map[cpu] = get_id(config, map, idx);
 
-	return cpus_aggr_map->map[cpu];
+	return config->cpus_aggr_map->map[cpu];
 }
 
-static int perf_stat__get_socket_cached(struct cpu_map *map, int idx)
+static int perf_stat__get_socket_cached(struct perf_stat_config *config,
+					struct cpu_map *map, int idx)
 {
-	return perf_stat__get_aggr(perf_stat__get_socket, map, idx);
+	return perf_stat__get_aggr(config, perf_stat__get_socket, map, idx);
 }
 
-static int perf_stat__get_core_cached(struct cpu_map *map, int idx)
+static int perf_stat__get_core_cached(struct perf_stat_config *config,
+				      struct cpu_map *map, int idx)
 {
-	return perf_stat__get_aggr(perf_stat__get_core, map, idx);
+	return perf_stat__get_aggr(config, perf_stat__get_core, map, idx);
 }
 
 static int perf_stat_init_aggr_mode(void)
@@ -1999,18 +2001,18 @@ static int perf_stat_init_aggr_mode(void)
 
 	switch (stat_config.aggr_mode) {
 	case AGGR_SOCKET:
-		if (cpu_map__build_socket_map(evsel_list->cpus, &aggr_map)) {
+		if (cpu_map__build_socket_map(evsel_list->cpus, &stat_config.aggr_map)) {
 			perror("cannot build socket map");
 			return -1;
 		}
-		aggr_get_id = perf_stat__get_socket_cached;
+		stat_config.aggr_get_id = perf_stat__get_socket_cached;
 		break;
 	case AGGR_CORE:
-		if (cpu_map__build_core_map(evsel_list->cpus, &aggr_map)) {
+		if (cpu_map__build_core_map(evsel_list->cpus, &stat_config.aggr_map)) {
 			perror("cannot build core map");
 			return -1;
 		}
-		aggr_get_id = perf_stat__get_core_cached;
+		stat_config.aggr_get_id = perf_stat__get_core_cached;
 		break;
 	case AGGR_NONE:
 	case AGGR_GLOBAL:
@@ -2026,16 +2028,16 @@ static int perf_stat_init_aggr_mode(void)
 	 * the aggregation translate cpumap.
 	 */
 	nr = cpu_map__get_max(evsel_list->cpus);
-	cpus_aggr_map = cpu_map__empty_new(nr + 1);
-	return cpus_aggr_map ? 0 : -ENOMEM;
+	stat_config.cpus_aggr_map = cpu_map__empty_new(nr + 1);
+	return stat_config.cpus_aggr_map ? 0 : -ENOMEM;
 }
 
 static void perf_stat__exit_aggr_mode(void)
 {
-	cpu_map__put(aggr_map);
-	cpu_map__put(cpus_aggr_map);
-	aggr_map = NULL;
-	cpus_aggr_map = NULL;
+	cpu_map__put(stat_config.aggr_map);
+	cpu_map__put(stat_config.cpus_aggr_map);
+	stat_config.aggr_map = NULL;
+	stat_config.cpus_aggr_map = NULL;
 }
 
 static inline int perf_env__get_cpu(struct perf_env *env, struct cpu_map *map, int idx)
@@ -2093,12 +2095,14 @@ static int perf_env__build_core_map(struct perf_env *env, struct cpu_map *cpus,
 	return cpu_map__build_map(cpus, corep, perf_env__get_core, env);
 }
 
-static int perf_stat__get_socket_file(struct cpu_map *map, int idx)
+static int perf_stat__get_socket_file(struct perf_stat_config *config __maybe_unused,
+				      struct cpu_map *map, int idx)
 {
 	return perf_env__get_socket(map, idx, &perf_stat.session->header.env);
 }
 
-static int perf_stat__get_core_file(struct cpu_map *map, int idx)
+static int perf_stat__get_core_file(struct perf_stat_config *config __maybe_unused,
+				    struct cpu_map *map, int idx)
 {
 	return perf_env__get_core(map, idx, &perf_stat.session->header.env);
 }
@@ -2109,18 +2113,18 @@ static int perf_stat_init_aggr_mode_file(struct perf_stat *st)
 
 	switch (stat_config.aggr_mode) {
 	case AGGR_SOCKET:
-		if (perf_env__build_socket_map(env, evsel_list->cpus, &aggr_map)) {
+		if (perf_env__build_socket_map(env, evsel_list->cpus, &stat_config.aggr_map)) {
 			perror("cannot build socket map");
 			return -1;
 		}
-		aggr_get_id = perf_stat__get_socket_file;
+		stat_config.aggr_get_id = perf_stat__get_socket_file;
 		break;
 	case AGGR_CORE:
-		if (perf_env__build_core_map(env, evsel_list->cpus, &aggr_map)) {
+		if (perf_env__build_core_map(env, evsel_list->cpus, &stat_config.aggr_map)) {
 			perror("cannot build core map");
 			return -1;
 		}
-		aggr_get_id = perf_stat__get_core_file;
+		stat_config.aggr_get_id = perf_stat__get_core_file;
 		break;
 	case AGGR_NONE:
 	case AGGR_GLOBAL:
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 1fd0b7e196c6..be202b066e62 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -90,6 +90,9 @@ struct runtime_stat {
 	struct rblist value_list;
 };
 
+typedef int (*aggr_get_id_t)(struct perf_stat_config *config,
+			     struct cpu_map *m, int cpu);
+
 struct perf_stat_config {
 	enum aggr_mode		 aggr_mode;
 	bool			 scale;
@@ -115,6 +118,9 @@ struct perf_stat_config {
 	const char		*csv_sep;
 	struct stats		*walltime_nsecs_stats;
 	struct rusage		 ru_data;
+	struct cpu_map		*aggr_map;
+	aggr_get_id_t		 aggr_get_id;
+	struct cpu_map		*cpus_aggr_map;
 };
 
 void update_stats(struct stats *stats, u64 val);

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf stat: Do not use the global 'evsel_list' in print functions
  2018-08-30  6:32 ` [PATCH 37/43] perf stat: Do not use glovab evsel_list in print functions Jiri Olsa
@ 2018-09-06 13:40   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:40 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: peterz, mingo, namhyung, alexander.shishkin, dsahern,
	linux-kernel, acme, jolsa, andi, hpa, tglx

Commit-ID:  a138af663500a07742bb27793302625135a0f6c4
Gitweb:     https://git.kernel.org/tip/a138af663500a07742bb27793302625135a0f6c4
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:46 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:24 -0300

perf stat: Do not use the global 'evsel_list' in print functions

Get rid of the the 'evsel_list' global variable dependency, here we can
use the 'evlist' pointer from the evsel.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-38-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 2f606f76b66a..445673f688de 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -914,6 +914,7 @@ static void print_metric_header(struct perf_stat_config *config,
 static int first_shadow_cpu(struct perf_stat_config *config,
 			    struct perf_evsel *evsel, int id)
 {
+	struct perf_evlist *evlist = evsel->evlist;
 	int i;
 
 	if (!config->aggr_get_id)
@@ -928,7 +929,7 @@ static int first_shadow_cpu(struct perf_stat_config *config,
 	for (i = 0; i < perf_evsel__nr_cpus(evsel); i++) {
 		int cpu2 = perf_evsel__cpus(evsel)->map[i];
 
-		if (config->aggr_get_id(config, evsel_list->cpus, cpu2) == id)
+		if (config->aggr_get_id(config, evlist->cpus, cpu2) == id)
 			return cpu2;
 	}
 	return 0;
@@ -1103,7 +1104,7 @@ static void aggr_update_shadow(struct perf_stat_config *config,
 		evlist__for_each_entry(evlist, counter) {
 			val = 0;
 			for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
-				s2 = config->aggr_get_id(config, evsel_list->cpus, cpu);
+				s2 = config->aggr_get_id(config, evlist->cpus, cpu);
 				if (s2 != id)
 					continue;
 				val += perf_counts(counter->counts, cpu, 0)->val;

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf stat: Move 'big_num' data to 'struct perf_stat_config'
  2018-08-30  6:32 ` [PATCH 38/43] perf stat: Move big_num data into struct perf_stat_config Jiri Olsa
@ 2018-09-06 13:41   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:41 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, hpa, andi, acme, dsahern, namhyung, jolsa, tglx,
	mingo, alexander.shishkin, peterz

Commit-ID:  34ff0866d46ae206de884f54e7235f57096e5588
Gitweb:     https://git.kernel.org/tip/34ff0866d46ae206de884f54e7235f57096e5588
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:47 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:24 -0300

perf stat: Move 'big_num' data to 'struct perf_stat_config'

Move the static variable 'big_num' to 'struct perf_stat_config', so that
it can be passed around and used outside 'perf stat' command.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-39-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 8 ++++----
 tools/perf/util/stat.h    | 1 +
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 445673f688de..8ca85017a973 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -151,7 +151,6 @@ static bool			transaction_run;
 static bool			topdown_run			= false;
 static bool			smi_cost			= false;
 static bool			smi_reset			= false;
-static bool			big_num				=  true;
 static int			big_num_opt			=  -1;
 static bool			group				= false;
 static const char		*pre_cmd			= NULL;
@@ -192,6 +191,7 @@ static struct perf_stat_config stat_config = {
 	.run_count		= 1,
 	.metric_only_len	= METRIC_ONLY_LEN,
 	.walltime_nsecs_stats	= &walltime_nsecs_stats,
+	.big_num		= true,
 };
 
 static bool is_duration_time(struct perf_evsel *evsel)
@@ -945,7 +945,7 @@ static void abs_printout(struct perf_stat_config *config,
 	if (config->csv_output) {
 		fmt = floor(sc) != sc ?  "%.2f%s" : "%.0f%s";
 	} else {
-		if (big_num)
+		if (config->big_num)
 			fmt = floor(sc) != sc ? "%'18.2f%s" : "%'18.0f%s";
 		else
 			fmt = floor(sc) != sc ? "%18.2f%s" : "%18.0f%s";
@@ -2847,9 +2847,9 @@ int cmd_stat(int argc, const char **argv)
 			parse_options_usage(NULL, stat_options, "x", 1);
 			goto out;
 		} else /* Nope, so disable big number formatting */
-			big_num = false;
+			stat_config.big_num = false;
 	} else if (big_num_opt == 0) /* User passed --no-big-num */
-		big_num = false;
+		stat_config.big_num = false;
 
 	setup_system_wide(argc);
 
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index be202b066e62..843672214cca 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -103,6 +103,7 @@ struct perf_stat_config {
 	bool			 metric_only;
 	bool			 null_run;
 	bool			 ru_display;
+	bool			 big_num;
 	FILE			*output;
 	unsigned int		 interval;
 	unsigned int		 timeout;

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf stat: Move 'no_merge' data to 'struct perf_stat_config'
  2018-08-30  6:32 ` [PATCH 39/43] perf stat: Move no_merge data into struct perf_stat_config Jiri Olsa
@ 2018-09-06 13:42   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:42 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: jolsa, dsahern, alexander.shishkin, mingo, peterz, tglx, andi,
	linux-kernel, hpa, acme, namhyung

Commit-ID:  fdee335b00b0807e8d65b8e3d81214556f07bed3
Gitweb:     https://git.kernel.org/tip/fdee335b00b0807e8d65b8e3d81214556f07bed3
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:48 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:24 -0300

perf stat: Move 'no_merge' data to 'struct perf_stat_config'

Move the static variable 'no_merge' to 'struct perf_stat_config', so
that it can be passed around and used outside 'perf stat' command.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-40-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 5 ++---
 tools/perf/util/stat.h    | 1 +
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 8ca85017a973..c4df076f1e54 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -158,7 +158,6 @@ static const char		*post_cmd			= NULL;
 static bool			sync_run			= false;
 static bool			forever				= false;
 static bool			force_metric_only		= false;
-static bool			no_merge			= false;
 static bool			walltime_run_table		= false;
 static struct timespec		ref_time;
 static bool			append_file;
@@ -1173,7 +1172,7 @@ static bool collect_data(struct perf_stat_config *config, struct perf_evsel *cou
 	if (counter->merged_stat)
 		return false;
 	cb(config, counter, data, true);
-	if (no_merge)
+	if (config->no_merge)
 		uniquify_event_name(counter);
 	else if (counter->auto_merge_stats)
 		collect_all_aliases(config, counter, cb, data);
@@ -1902,7 +1901,7 @@ static const struct option stat_options[] = {
 		    "list of cpus to monitor in system-wide"),
 	OPT_SET_UINT('A', "no-aggr", &stat_config.aggr_mode,
 		    "disable CPU count aggregation", AGGR_NONE),
-	OPT_BOOLEAN(0, "no-merge", &no_merge, "Do not merge identical named events"),
+	OPT_BOOLEAN(0, "no-merge", &stat_config.no_merge, "Do not merge identical named events"),
 	OPT_STRING('x', "field-separator", &stat_config.csv_sep, "separator",
 		   "print counts with custom separator"),
 	OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 843672214cca..0758107fe56f 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -104,6 +104,7 @@ struct perf_stat_config {
 	bool			 null_run;
 	bool			 ru_display;
 	bool			 big_num;
+	bool			 no_merge;
 	FILE			*output;
 	unsigned int		 interval;
 	unsigned int		 timeout;

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf stat: Propagate 'struct target' arg to sort_aggr_thread()
  2018-08-30  6:32 ` [PATCH 40/43] perf stat: Propagate struct target arg to sort_aggr_thread Jiri Olsa
@ 2018-09-06 13:42   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:42 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: dsahern, hpa, jolsa, mingo, alexander.shishkin, andi,
	linux-kernel, namhyung, acme, peterz, tglx

Commit-ID:  be54d59325314be9d4d53852cbfbeeaebc3b9239
Gitweb:     https://git.kernel.org/tip/be54d59325314be9d4d53852cbfbeeaebc3b9239
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:49 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:25 -0300

perf stat: Propagate 'struct target' arg to sort_aggr_thread()

Propagate the 'struct target' arg to sort_aggr_thread() so that the
function does not depend on the 'perf stat' command object local
variable 'target' and can be moved out.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-41-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index c4df076f1e54..486b0cf7818d 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1284,7 +1284,8 @@ static int cmp_val(const void *a, const void *b)
 static struct perf_aggr_thread_value *sort_aggr_thread(
 					struct perf_evsel *counter,
 					int nthreads, int ncpus,
-					int *ret)
+					int *ret,
+					struct target *_target)
 {
 	int cpu, thread, i = 0;
 	double uval;
@@ -1309,7 +1310,7 @@ static struct perf_aggr_thread_value *sort_aggr_thread(
 		 * Skip value 0 when enabling --per-thread globally,
 		 * otherwise too many 0 output.
 		 */
-		if (uval == 0.0 && target__has_per_thread(&target))
+		if (uval == 0.0 && target__has_per_thread(_target))
 			continue;
 
 		buf[i].counter = counter;
@@ -1330,6 +1331,7 @@ static struct perf_aggr_thread_value *sort_aggr_thread(
 }
 
 static void print_aggr_thread(struct perf_stat_config *config,
+			      struct target *_target,
 			      struct perf_evsel *counter, char *prefix)
 {
 	FILE *output = config->output;
@@ -1338,7 +1340,7 @@ static void print_aggr_thread(struct perf_stat_config *config,
 	int thread, sorted_threads, id;
 	struct perf_aggr_thread_value *buf;
 
-	buf = sort_aggr_thread(counter, nthreads, ncpus, &sorted_threads);
+	buf = sort_aggr_thread(counter, nthreads, ncpus, &sorted_threads, _target);
 	if (!buf) {
 		perror("cannot sort aggr thread");
 		return;
@@ -1754,7 +1756,7 @@ perf_evlist__print_counters(struct perf_evlist *evlist,
 		evlist__for_each_entry(evlist, counter) {
 			if (is_duration_time(counter))
 				continue;
-			print_aggr_thread(config, counter, prefix);
+			print_aggr_thread(config, _target, counter, prefix);
 		}
 		break;
 	case AGGR_GLOBAL:

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf stat: Move 'walltime_*' data to 'struct perf_stat_config'
  2018-08-30  6:32 ` [PATCH 41/43] perf stat: Move walltime_* data into struct perf_stat_config Jiri Olsa
@ 2018-09-06 13:43   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:43 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: alexander.shishkin, namhyung, hpa, mingo, acme, andi, jolsa,
	tglx, linux-kernel, dsahern, peterz

Commit-ID:  54ac0b1bd25cbdeda226b32a0459e09de46157b3
Gitweb:     https://git.kernel.org/tip/54ac0b1bd25cbdeda226b32a0459e09de46157b3
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:50 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:25 -0300

perf stat: Move 'walltime_*' data to 'struct perf_stat_config'

Move the static variables 'walltime_*' to 'struct perf_stat_config', so
that it can be passed around and used outside 'perf stat' command.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-42-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 22 ++++++++++------------
 tools/perf/util/stat.h    |  2 ++
 2 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 486b0cf7818d..8a4979748cbb 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -158,13 +158,11 @@ static const char		*post_cmd			= NULL;
 static bool			sync_run			= false;
 static bool			forever				= false;
 static bool			force_metric_only		= false;
-static bool			walltime_run_table		= false;
 static struct timespec		ref_time;
 static bool			append_file;
 static bool			interval_count;
 static const char		*output_name;
 static int			output_fd;
-static u64			*walltime_run;
 
 struct perf_stat {
 	bool			 record;
@@ -604,8 +602,8 @@ try_again:
 
 	t1 = rdclock();
 
-	if (walltime_run_table)
-		walltime_run[run_idx] = t1 - t0;
+	if (stat_config.walltime_run_table)
+		stat_config.walltime_run[run_idx] = t1 - t0;
 
 	update_stats(&walltime_nsecs_stats, t1 - t0);
 
@@ -1646,7 +1644,7 @@ static void print_table(struct perf_stat_config *config,
 	fprintf(output, "%*s# Table of individual measurements:\n", indent, "");
 
 	for (idx = 0; idx < config->run_count; idx++) {
-		double run = (double) walltime_run[idx] / NSEC_PER_SEC;
+		double run = (double) config->walltime_run[idx] / NSEC_PER_SEC;
 		int h, n = 1 + abs((int) (100.0 * (run - avg)/run) / 5);
 
 		fprintf(output, " %17.*f (%+.*f) ",
@@ -1694,7 +1692,7 @@ static void print_footer(struct perf_stat_config *config)
 		 */
 		int precision = get_precision(sd) + 2;
 
-		if (walltime_run_table)
+		if (config->walltime_run_table)
 			print_table(config, output, precision, avg);
 
 		fprintf(output, " %17.*f +- %.*f seconds time elapsed",
@@ -1888,7 +1886,7 @@ static const struct option stat_options[] = {
 		    "be more verbose (show counter open errors, etc)"),
 	OPT_INTEGER('r', "repeat", &stat_config.run_count,
 		    "repeat command and print average + stddev (max: 100, forever: 0)"),
-	OPT_BOOLEAN(0, "table", &walltime_run_table,
+	OPT_BOOLEAN(0, "table", &stat_config.walltime_run_table,
 		    "display details about each run (only with -r option)"),
 	OPT_BOOLEAN('n', "null", &stat_config.null_run,
 		    "null run - dont start any counters"),
@@ -2802,7 +2800,7 @@ int cmd_stat(int argc, const char **argv)
 		goto out;
 	}
 
-	if (walltime_run_table && stat_config.run_count <= 1) {
+	if (stat_config.walltime_run_table && stat_config.run_count <= 1) {
 		fprintf(stderr, "--table is only supported with -r\n");
 		parse_options_usage(stat_usage, stat_options, "r", 1);
 		parse_options_usage(NULL, stat_options, "table", 0);
@@ -2870,9 +2868,9 @@ int cmd_stat(int argc, const char **argv)
 		stat_config.run_count = 1;
 	}
 
-	if (walltime_run_table) {
-		walltime_run = zalloc(stat_config.run_count * sizeof(walltime_run[0]));
-		if (!walltime_run) {
+	if (stat_config.walltime_run_table) {
+		stat_config.walltime_run = zalloc(stat_config.run_count * sizeof(stat_config.walltime_run[0]));
+		if (!stat_config.walltime_run) {
 			pr_err("failed to setup -r option");
 			goto out;
 		}
@@ -3052,7 +3050,7 @@ int cmd_stat(int argc, const char **argv)
 	perf_stat__exit_aggr_mode();
 	perf_evlist__free_stats(evsel_list);
 out:
-	free(walltime_run);
+	free(stat_config.walltime_run);
 
 	if (smi_cost && smi_reset)
 		sysfs__write_int(FREEZE_ON_SMI_PATH, 0);
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 0758107fe56f..5193cbf6e4c6 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -105,6 +105,7 @@ struct perf_stat_config {
 	bool			 ru_display;
 	bool			 big_num;
 	bool			 no_merge;
+	bool			 walltime_run_table;
 	FILE			*output;
 	unsigned int		 interval;
 	unsigned int		 timeout;
@@ -123,6 +124,7 @@ struct perf_stat_config {
 	struct cpu_map		*aggr_map;
 	aggr_get_id_t		 aggr_get_id;
 	struct cpu_map		*cpus_aggr_map;
+	u64			*walltime_run;
 };
 
 void update_stats(struct stats *stats, u64 val);

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf stat: Move 'metric_events' to 'struct perf_stat_config'
  2018-08-30  6:32 ` [PATCH 42/43] perf stat: Move metric_events into struct perf_stat_config Jiri Olsa
@ 2018-09-06 13:43   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:43 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: dsahern, jolsa, mingo, andi, acme, namhyung, alexander.shishkin,
	linux-kernel, hpa, tglx, peterz

Commit-ID:  d0192fdba09a8901db133fe5a1fcd22d40fcf545
Gitweb:     https://git.kernel.org/tip/d0192fdba09a8901db133fe5a1fcd22d40fcf545
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:51 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:25 -0300

perf stat: Move 'metric_events' to 'struct perf_stat_config'

Move the static variable 'metric_events' to 'struct perf_stat_config',
so that it can be passed around and used outside 'perf stat' command.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-43-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 10 ++++------
 tools/perf/util/stat.h    |  1 +
 2 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 8a4979748cbb..f4ddedc8619b 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -137,8 +137,6 @@ static const char *smi_cost_attrs = {
 
 static struct perf_evlist	*evsel_list;
 
-static struct rblist		 metric_events;
-
 static struct target target = {
 	.uid	= UINT_MAX,
 };
@@ -1082,7 +1080,7 @@ static void printout(struct perf_stat_config *config, int id, int nr,
 
 	perf_stat__print_shadow_stats(config, counter, uval,
 				first_shadow_cpu(config, counter, id),
-				&out, &metric_events, st);
+				&out, &config->metric_events, st);
 	if (!config->csv_output && !config->metric_only) {
 		print_noise(config, counter, noise);
 		print_running(config, run, ena);
@@ -1533,7 +1531,7 @@ static void print_metric_headers(struct perf_stat_config *config,
 		perf_stat__print_shadow_stats(config, counter, 0,
 					      0,
 					      &out,
-					      &metric_events,
+					      &config->metric_events,
 					      &rt_stat);
 	}
 	fputc('\n', config->output);
@@ -1860,7 +1858,7 @@ static int parse_metric_groups(const struct option *opt,
 			       const char *str,
 			       int unset __maybe_unused)
 {
-	return metricgroup__parse_groups(opt, str, &metric_events);
+	return metricgroup__parse_groups(opt, str, &stat_config.metric_events);
 }
 
 static const struct option stat_options[] = {
@@ -2321,7 +2319,7 @@ static int add_default_attributes(void)
 			struct option opt = { .value = &evsel_list };
 
 			return metricgroup__parse_groups(&opt, "transaction",
-							 &metric_events);
+							 &stat_config.metric_events);
 		}
 
 		if (pmu_have_event("cpu", "cycles-ct") &&
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 5193cbf6e4c6..8d3354e21e19 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -125,6 +125,7 @@ struct perf_stat_config {
 	aggr_get_id_t		 aggr_get_id;
 	struct cpu_map		*cpus_aggr_map;
 	u64			*walltime_run;
+	struct rblist		 metric_events;
 };
 
 void update_stats(struct stats *stats, u64 val);

^ permalink raw reply related	[flat|nested] 88+ messages in thread

* [tip:perf/core] perf stat: Move the display functions to stat-display.c
  2018-08-30  6:32 ` [PATCH 43/43] perf stat: Move display functions into stat-display.c Jiri Olsa
@ 2018-09-06 13:44   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 88+ messages in thread
From: tip-bot for Jiri Olsa @ 2018-09-06 13:44 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: jolsa, linux-kernel, namhyung, dsahern, tglx, acme, andi, peterz,
	alexander.shishkin, mingo, hpa

Commit-ID:  088519f318be3a41d1afe8d628c4a1eb5a50b4c0
Gitweb:     https://git.kernel.org/tip/088519f318be3a41d1afe8d628c4a1eb5a50b4c0
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Thu, 30 Aug 2018 08:32:52 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 30 Aug 2018 15:52:25 -0300

perf stat: Move the display functions to stat-display.c

Move perf_evlist__print_counters() with all its dependency functions to
the stat-display.c object.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180830063252.23729-44-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c      | 1150 ---------------------------------------
 tools/perf/util/Build          |    1 +
 tools/perf/util/stat-display.c | 1166 ++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/stat.h         |    6 +
 4 files changed, 1173 insertions(+), 1150 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index f4ddedc8619b..0b0e3961d511 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -88,8 +88,6 @@
 #include "sane_ctype.h"
 
 #define DEFAULT_SEPARATOR	" "
-#define CNTR_NOT_SUPPORTED	"<not supported>"
-#define CNTR_NOT_COUNTED	"<not counted>"
 #define FREEZE_ON_SMI_PATH	"devices/cpu/freeze_on_smi"
 
 static void print_counters(struct timespec *ts, int argc, const char **argv);
@@ -189,11 +187,6 @@ static struct perf_stat_config stat_config = {
 	.big_num		= true,
 };
 
-static bool is_duration_time(struct perf_evsel *evsel)
-{
-	return !strcmp(evsel->name, "duration_time");
-}
-
 static inline void diff_timespec(struct timespec *r, struct timespec *a,
 				 struct timespec *b)
 {
@@ -643,1149 +636,6 @@ static int run_perf_stat(int argc, const char **argv, int run_idx)
 	return ret;
 }
 
-static void print_running(struct perf_stat_config *config,
-			  u64 run, u64 ena)
-{
-	if (config->csv_output) {
-		fprintf(config->output, "%s%" PRIu64 "%s%.2f",
-					config->csv_sep,
-					run,
-					config->csv_sep,
-					ena ? 100.0 * run / ena : 100.0);
-	} else if (run != ena) {
-		fprintf(config->output, "  (%.2f%%)", 100.0 * run / ena);
-	}
-}
-
-static void print_noise_pct(struct perf_stat_config *config,
-			    double total, double avg)
-{
-	double pct = rel_stddev_stats(total, avg);
-
-	if (config->csv_output)
-		fprintf(config->output, "%s%.2f%%", config->csv_sep, pct);
-	else if (pct)
-		fprintf(config->output, "  ( +-%6.2f%% )", pct);
-}
-
-static void print_noise(struct perf_stat_config *config,
-			struct perf_evsel *evsel, double avg)
-{
-	struct perf_stat_evsel *ps;
-
-	if (config->run_count == 1)
-		return;
-
-	ps = evsel->stats;
-	print_noise_pct(config, stddev_stats(&ps->res_stats[0]), avg);
-}
-
-static void aggr_printout(struct perf_stat_config *config,
-			  struct perf_evsel *evsel, int id, int nr)
-{
-	switch (config->aggr_mode) {
-	case AGGR_CORE:
-		fprintf(config->output, "S%d-C%*d%s%*d%s",
-			cpu_map__id_to_socket(id),
-			config->csv_output ? 0 : -8,
-			cpu_map__id_to_cpu(id),
-			config->csv_sep,
-			config->csv_output ? 0 : 4,
-			nr,
-			config->csv_sep);
-		break;
-	case AGGR_SOCKET:
-		fprintf(config->output, "S%*d%s%*d%s",
-			config->csv_output ? 0 : -5,
-			id,
-			config->csv_sep,
-			config->csv_output ? 0 : 4,
-			nr,
-			config->csv_sep);
-			break;
-	case AGGR_NONE:
-		fprintf(config->output, "CPU%*d%s",
-			config->csv_output ? 0 : -4,
-			perf_evsel__cpus(evsel)->map[id], config->csv_sep);
-		break;
-	case AGGR_THREAD:
-		fprintf(config->output, "%*s-%*d%s",
-			config->csv_output ? 0 : 16,
-			thread_map__comm(evsel->threads, id),
-			config->csv_output ? 0 : -8,
-			thread_map__pid(evsel->threads, id),
-			config->csv_sep);
-		break;
-	case AGGR_GLOBAL:
-	case AGGR_UNSET:
-	default:
-		break;
-	}
-}
-
-struct outstate {
-	FILE *fh;
-	bool newline;
-	const char *prefix;
-	int  nfields;
-	int  id, nr;
-	struct perf_evsel *evsel;
-};
-
-#define METRIC_LEN  35
-
-static void new_line_std(struct perf_stat_config *config __maybe_unused,
-			 void *ctx)
-{
-	struct outstate *os = ctx;
-
-	os->newline = true;
-}
-
-static void do_new_line_std(struct perf_stat_config *config,
-			    struct outstate *os)
-{
-	fputc('\n', os->fh);
-	fputs(os->prefix, os->fh);
-	aggr_printout(config, os->evsel, os->id, os->nr);
-	if (config->aggr_mode == AGGR_NONE)
-		fprintf(os->fh, "        ");
-	fprintf(os->fh, "                                                 ");
-}
-
-static void print_metric_std(struct perf_stat_config *config,
-			     void *ctx, const char *color, const char *fmt,
-			     const char *unit, double val)
-{
-	struct outstate *os = ctx;
-	FILE *out = os->fh;
-	int n;
-	bool newline = os->newline;
-
-	os->newline = false;
-
-	if (unit == NULL || fmt == NULL) {
-		fprintf(out, "%-*s", METRIC_LEN, "");
-		return;
-	}
-
-	if (newline)
-		do_new_line_std(config, os);
-
-	n = fprintf(out, " # ");
-	if (color)
-		n += color_fprintf(out, color, fmt, val);
-	else
-		n += fprintf(out, fmt, val);
-	fprintf(out, " %-*s", METRIC_LEN - n - 1, unit);
-}
-
-static void new_line_csv(struct perf_stat_config *config, void *ctx)
-{
-	struct outstate *os = ctx;
-	int i;
-
-	fputc('\n', os->fh);
-	if (os->prefix)
-		fprintf(os->fh, "%s%s", os->prefix, config->csv_sep);
-	aggr_printout(config, os->evsel, os->id, os->nr);
-	for (i = 0; i < os->nfields; i++)
-		fputs(config->csv_sep, os->fh);
-}
-
-static void print_metric_csv(struct perf_stat_config *config __maybe_unused,
-			     void *ctx,
-			     const char *color __maybe_unused,
-			     const char *fmt, const char *unit, double val)
-{
-	struct outstate *os = ctx;
-	FILE *out = os->fh;
-	char buf[64], *vals, *ends;
-
-	if (unit == NULL || fmt == NULL) {
-		fprintf(out, "%s%s", config->csv_sep, config->csv_sep);
-		return;
-	}
-	snprintf(buf, sizeof(buf), fmt, val);
-	ends = vals = ltrim(buf);
-	while (isdigit(*ends) || *ends == '.')
-		ends++;
-	*ends = 0;
-	while (isspace(*unit))
-		unit++;
-	fprintf(out, "%s%s%s%s", config->csv_sep, vals, config->csv_sep, unit);
-}
-
-/* Filter out some columns that don't work well in metrics only mode */
-
-static bool valid_only_metric(const char *unit)
-{
-	if (!unit)
-		return false;
-	if (strstr(unit, "/sec") ||
-	    strstr(unit, "hz") ||
-	    strstr(unit, "Hz") ||
-	    strstr(unit, "CPUs utilized"))
-		return false;
-	return true;
-}
-
-static const char *fixunit(char *buf, struct perf_evsel *evsel,
-			   const char *unit)
-{
-	if (!strncmp(unit, "of all", 6)) {
-		snprintf(buf, 1024, "%s %s", perf_evsel__name(evsel),
-			 unit);
-		return buf;
-	}
-	return unit;
-}
-
-static void print_metric_only(struct perf_stat_config *config,
-			      void *ctx, const char *color, const char *fmt,
-			      const char *unit, double val)
-{
-	struct outstate *os = ctx;
-	FILE *out = os->fh;
-	char buf[1024], str[1024];
-	unsigned mlen = config->metric_only_len;
-
-	if (!valid_only_metric(unit))
-		return;
-	unit = fixunit(buf, os->evsel, unit);
-	if (mlen < strlen(unit))
-		mlen = strlen(unit) + 1;
-
-	if (color)
-		mlen += strlen(color) + sizeof(PERF_COLOR_RESET) - 1;
-
-	color_snprintf(str, sizeof(str), color ?: "", fmt, val);
-	fprintf(out, "%*s ", mlen, str);
-}
-
-static void print_metric_only_csv(struct perf_stat_config *config __maybe_unused,
-				  void *ctx, const char *color __maybe_unused,
-				  const char *fmt,
-				  const char *unit, double val)
-{
-	struct outstate *os = ctx;
-	FILE *out = os->fh;
-	char buf[64], *vals, *ends;
-	char tbuf[1024];
-
-	if (!valid_only_metric(unit))
-		return;
-	unit = fixunit(tbuf, os->evsel, unit);
-	snprintf(buf, sizeof buf, fmt, val);
-	ends = vals = ltrim(buf);
-	while (isdigit(*ends) || *ends == '.')
-		ends++;
-	*ends = 0;
-	fprintf(out, "%s%s", vals, config->csv_sep);
-}
-
-static void new_line_metric(struct perf_stat_config *config __maybe_unused,
-			    void *ctx __maybe_unused)
-{
-}
-
-static void print_metric_header(struct perf_stat_config *config,
-				void *ctx, const char *color __maybe_unused,
-				const char *fmt __maybe_unused,
-				const char *unit, double val __maybe_unused)
-{
-	struct outstate *os = ctx;
-	char tbuf[1024];
-
-	if (!valid_only_metric(unit))
-		return;
-	unit = fixunit(tbuf, os->evsel, unit);
-	if (config->csv_output)
-		fprintf(os->fh, "%s%s", unit, config->csv_sep);
-	else
-		fprintf(os->fh, "%*s ", config->metric_only_len, unit);
-}
-
-static int first_shadow_cpu(struct perf_stat_config *config,
-			    struct perf_evsel *evsel, int id)
-{
-	struct perf_evlist *evlist = evsel->evlist;
-	int i;
-
-	if (!config->aggr_get_id)
-		return 0;
-
-	if (config->aggr_mode == AGGR_NONE)
-		return id;
-
-	if (config->aggr_mode == AGGR_GLOBAL)
-		return 0;
-
-	for (i = 0; i < perf_evsel__nr_cpus(evsel); i++) {
-		int cpu2 = perf_evsel__cpus(evsel)->map[i];
-
-		if (config->aggr_get_id(config, evlist->cpus, cpu2) == id)
-			return cpu2;
-	}
-	return 0;
-}
-
-static void abs_printout(struct perf_stat_config *config,
-			 int id, int nr, struct perf_evsel *evsel, double avg)
-{
-	FILE *output = config->output;
-	double sc =  evsel->scale;
-	const char *fmt;
-
-	if (config->csv_output) {
-		fmt = floor(sc) != sc ?  "%.2f%s" : "%.0f%s";
-	} else {
-		if (config->big_num)
-			fmt = floor(sc) != sc ? "%'18.2f%s" : "%'18.0f%s";
-		else
-			fmt = floor(sc) != sc ? "%18.2f%s" : "%18.0f%s";
-	}
-
-	aggr_printout(config, evsel, id, nr);
-
-	fprintf(output, fmt, avg, config->csv_sep);
-
-	if (evsel->unit)
-		fprintf(output, "%-*s%s",
-			config->csv_output ? 0 : config->unit_width,
-			evsel->unit, config->csv_sep);
-
-	fprintf(output, "%-*s", config->csv_output ? 0 : 25, perf_evsel__name(evsel));
-
-	if (evsel->cgrp)
-		fprintf(output, "%s%s", config->csv_sep, evsel->cgrp->name);
-}
-
-static bool is_mixed_hw_group(struct perf_evsel *counter)
-{
-	struct perf_evlist *evlist = counter->evlist;
-	u32 pmu_type = counter->attr.type;
-	struct perf_evsel *pos;
-
-	if (counter->nr_members < 2)
-		return false;
-
-	evlist__for_each_entry(evlist, pos) {
-		/* software events can be part of any hardware group */
-		if (pos->attr.type == PERF_TYPE_SOFTWARE)
-			continue;
-		if (pmu_type == PERF_TYPE_SOFTWARE) {
-			pmu_type = pos->attr.type;
-			continue;
-		}
-		if (pmu_type != pos->attr.type)
-			return true;
-	}
-
-	return false;
-}
-
-static void printout(struct perf_stat_config *config, int id, int nr,
-		     struct perf_evsel *counter, double uval,
-		     char *prefix, u64 run, u64 ena, double noise,
-		     struct runtime_stat *st)
-{
-	struct perf_stat_output_ctx out;
-	struct outstate os = {
-		.fh = config->output,
-		.prefix = prefix ? prefix : "",
-		.id = id,
-		.nr = nr,
-		.evsel = counter,
-	};
-	print_metric_t pm = print_metric_std;
-	new_line_t nl;
-
-	if (config->metric_only) {
-		nl = new_line_metric;
-		if (config->csv_output)
-			pm = print_metric_only_csv;
-		else
-			pm = print_metric_only;
-	} else
-		nl = new_line_std;
-
-	if (config->csv_output && !config->metric_only) {
-		static int aggr_fields[] = {
-			[AGGR_GLOBAL] = 0,
-			[AGGR_THREAD] = 1,
-			[AGGR_NONE] = 1,
-			[AGGR_SOCKET] = 2,
-			[AGGR_CORE] = 2,
-		};
-
-		pm = print_metric_csv;
-		nl = new_line_csv;
-		os.nfields = 3;
-		os.nfields += aggr_fields[config->aggr_mode];
-		if (counter->cgrp)
-			os.nfields++;
-	}
-	if (run == 0 || ena == 0 || counter->counts->scaled == -1) {
-		if (config->metric_only) {
-			pm(config, &os, NULL, "", "", 0);
-			return;
-		}
-		aggr_printout(config, counter, id, nr);
-
-		fprintf(config->output, "%*s%s",
-			config->csv_output ? 0 : 18,
-			counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
-			config->csv_sep);
-
-		if (counter->supported) {
-			config->print_free_counters_hint = 1;
-			if (is_mixed_hw_group(counter))
-				config->print_mixed_hw_group_error = 1;
-		}
-
-		fprintf(config->output, "%-*s%s",
-			config->csv_output ? 0 : config->unit_width,
-			counter->unit, config->csv_sep);
-
-		fprintf(config->output, "%*s",
-			config->csv_output ? 0 : -25,
-			perf_evsel__name(counter));
-
-		if (counter->cgrp)
-			fprintf(config->output, "%s%s",
-				config->csv_sep, counter->cgrp->name);
-
-		if (!config->csv_output)
-			pm(config, &os, NULL, NULL, "", 0);
-		print_noise(config, counter, noise);
-		print_running(config, run, ena);
-		if (config->csv_output)
-			pm(config, &os, NULL, NULL, "", 0);
-		return;
-	}
-
-	if (!config->metric_only)
-		abs_printout(config, id, nr, counter, uval);
-
-	out.print_metric = pm;
-	out.new_line = nl;
-	out.ctx = &os;
-	out.force_header = false;
-
-	if (config->csv_output && !config->metric_only) {
-		print_noise(config, counter, noise);
-		print_running(config, run, ena);
-	}
-
-	perf_stat__print_shadow_stats(config, counter, uval,
-				first_shadow_cpu(config, counter, id),
-				&out, &config->metric_events, st);
-	if (!config->csv_output && !config->metric_only) {
-		print_noise(config, counter, noise);
-		print_running(config, run, ena);
-	}
-}
-
-static void aggr_update_shadow(struct perf_stat_config *config,
-			       struct perf_evlist *evlist)
-{
-	int cpu, s2, id, s;
-	u64 val;
-	struct perf_evsel *counter;
-
-	for (s = 0; s < config->aggr_map->nr; s++) {
-		id = config->aggr_map->map[s];
-		evlist__for_each_entry(evlist, counter) {
-			val = 0;
-			for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
-				s2 = config->aggr_get_id(config, evlist->cpus, cpu);
-				if (s2 != id)
-					continue;
-				val += perf_counts(counter->counts, cpu, 0)->val;
-			}
-			perf_stat__update_shadow_stats(counter, val,
-					first_shadow_cpu(config, counter, id),
-					&rt_stat);
-		}
-	}
-}
-
-static void uniquify_event_name(struct perf_evsel *counter)
-{
-	char *new_name;
-	char *config;
-
-	if (counter->uniquified_name ||
-	    !counter->pmu_name || !strncmp(counter->name, counter->pmu_name,
-					   strlen(counter->pmu_name)))
-		return;
-
-	config = strchr(counter->name, '/');
-	if (config) {
-		if (asprintf(&new_name,
-			     "%s%s", counter->pmu_name, config) > 0) {
-			free(counter->name);
-			counter->name = new_name;
-		}
-	} else {
-		if (asprintf(&new_name,
-			     "%s [%s]", counter->name, counter->pmu_name) > 0) {
-			free(counter->name);
-			counter->name = new_name;
-		}
-	}
-
-	counter->uniquified_name = true;
-}
-
-static void collect_all_aliases(struct perf_stat_config *config, struct perf_evsel *counter,
-			    void (*cb)(struct perf_stat_config *config, struct perf_evsel *counter, void *data,
-				       bool first),
-			    void *data)
-{
-	struct perf_evlist *evlist = counter->evlist;
-	struct perf_evsel *alias;
-
-	alias = list_prepare_entry(counter, &(evlist->entries), node);
-	list_for_each_entry_continue (alias, &evlist->entries, node) {
-		if (strcmp(perf_evsel__name(alias), perf_evsel__name(counter)) ||
-		    alias->scale != counter->scale ||
-		    alias->cgrp != counter->cgrp ||
-		    strcmp(alias->unit, counter->unit) ||
-		    perf_evsel__is_clock(alias) != perf_evsel__is_clock(counter))
-			break;
-		alias->merged_stat = true;
-		cb(config, alias, data, false);
-	}
-}
-
-static bool collect_data(struct perf_stat_config *config, struct perf_evsel *counter,
-			    void (*cb)(struct perf_stat_config *config, struct perf_evsel *counter, void *data,
-				       bool first),
-			    void *data)
-{
-	if (counter->merged_stat)
-		return false;
-	cb(config, counter, data, true);
-	if (config->no_merge)
-		uniquify_event_name(counter);
-	else if (counter->auto_merge_stats)
-		collect_all_aliases(config, counter, cb, data);
-	return true;
-}
-
-struct aggr_data {
-	u64 ena, run, val;
-	int id;
-	int nr;
-	int cpu;
-};
-
-static void aggr_cb(struct perf_stat_config *config,
-		    struct perf_evsel *counter, void *data, bool first)
-{
-	struct aggr_data *ad = data;
-	int cpu, s2;
-
-	for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
-		struct perf_counts_values *counts;
-
-		s2 = config->aggr_get_id(config, perf_evsel__cpus(counter), cpu);
-		if (s2 != ad->id)
-			continue;
-		if (first)
-			ad->nr++;
-		counts = perf_counts(counter->counts, cpu, 0);
-		/*
-		 * When any result is bad, make them all to give
-		 * consistent output in interval mode.
-		 */
-		if (counts->ena == 0 || counts->run == 0 ||
-		    counter->counts->scaled == -1) {
-			ad->ena = 0;
-			ad->run = 0;
-			break;
-		}
-		ad->val += counts->val;
-		ad->ena += counts->ena;
-		ad->run += counts->run;
-	}
-}
-
-static void print_aggr(struct perf_stat_config *config,
-		       struct perf_evlist *evlist,
-		       char *prefix)
-{
-	bool metric_only = config->metric_only;
-	FILE *output = config->output;
-	struct perf_evsel *counter;
-	int s, id, nr;
-	double uval;
-	u64 ena, run, val;
-	bool first;
-
-	if (!(config->aggr_map || config->aggr_get_id))
-		return;
-
-	aggr_update_shadow(config, evlist);
-
-	/*
-	 * With metric_only everything is on a single line.
-	 * Without each counter has its own line.
-	 */
-	for (s = 0; s < config->aggr_map->nr; s++) {
-		struct aggr_data ad;
-		if (prefix && metric_only)
-			fprintf(output, "%s", prefix);
-
-		ad.id = id = config->aggr_map->map[s];
-		first = true;
-		evlist__for_each_entry(evlist, counter) {
-			if (is_duration_time(counter))
-				continue;
-
-			ad.val = ad.ena = ad.run = 0;
-			ad.nr = 0;
-			if (!collect_data(config, counter, aggr_cb, &ad))
-				continue;
-			nr = ad.nr;
-			ena = ad.ena;
-			run = ad.run;
-			val = ad.val;
-			if (first && metric_only) {
-				first = false;
-				aggr_printout(config, counter, id, nr);
-			}
-			if (prefix && !metric_only)
-				fprintf(output, "%s", prefix);
-
-			uval = val * counter->scale;
-			printout(config, id, nr, counter, uval, prefix,
-				 run, ena, 1.0, &rt_stat);
-			if (!metric_only)
-				fputc('\n', output);
-		}
-		if (metric_only)
-			fputc('\n', output);
-	}
-}
-
-static int cmp_val(const void *a, const void *b)
-{
-	return ((struct perf_aggr_thread_value *)b)->val -
-		((struct perf_aggr_thread_value *)a)->val;
-}
-
-static struct perf_aggr_thread_value *sort_aggr_thread(
-					struct perf_evsel *counter,
-					int nthreads, int ncpus,
-					int *ret,
-					struct target *_target)
-{
-	int cpu, thread, i = 0;
-	double uval;
-	struct perf_aggr_thread_value *buf;
-
-	buf = calloc(nthreads, sizeof(struct perf_aggr_thread_value));
-	if (!buf)
-		return NULL;
-
-	for (thread = 0; thread < nthreads; thread++) {
-		u64 ena = 0, run = 0, val = 0;
-
-		for (cpu = 0; cpu < ncpus; cpu++) {
-			val += perf_counts(counter->counts, cpu, thread)->val;
-			ena += perf_counts(counter->counts, cpu, thread)->ena;
-			run += perf_counts(counter->counts, cpu, thread)->run;
-		}
-
-		uval = val * counter->scale;
-
-		/*
-		 * Skip value 0 when enabling --per-thread globally,
-		 * otherwise too many 0 output.
-		 */
-		if (uval == 0.0 && target__has_per_thread(_target))
-			continue;
-
-		buf[i].counter = counter;
-		buf[i].id = thread;
-		buf[i].uval = uval;
-		buf[i].val = val;
-		buf[i].run = run;
-		buf[i].ena = ena;
-		i++;
-	}
-
-	qsort(buf, i, sizeof(struct perf_aggr_thread_value), cmp_val);
-
-	if (ret)
-		*ret = i;
-
-	return buf;
-}
-
-static void print_aggr_thread(struct perf_stat_config *config,
-			      struct target *_target,
-			      struct perf_evsel *counter, char *prefix)
-{
-	FILE *output = config->output;
-	int nthreads = thread_map__nr(counter->threads);
-	int ncpus = cpu_map__nr(counter->cpus);
-	int thread, sorted_threads, id;
-	struct perf_aggr_thread_value *buf;
-
-	buf = sort_aggr_thread(counter, nthreads, ncpus, &sorted_threads, _target);
-	if (!buf) {
-		perror("cannot sort aggr thread");
-		return;
-	}
-
-	for (thread = 0; thread < sorted_threads; thread++) {
-		if (prefix)
-			fprintf(output, "%s", prefix);
-
-		id = buf[thread].id;
-		if (config->stats)
-			printout(config, id, 0, buf[thread].counter, buf[thread].uval,
-				 prefix, buf[thread].run, buf[thread].ena, 1.0,
-				 &config->stats[id]);
-		else
-			printout(config, id, 0, buf[thread].counter, buf[thread].uval,
-				 prefix, buf[thread].run, buf[thread].ena, 1.0,
-				 &rt_stat);
-		fputc('\n', output);
-	}
-
-	free(buf);
-}
-
-struct caggr_data {
-	double avg, avg_enabled, avg_running;
-};
-
-static void counter_aggr_cb(struct perf_stat_config *config __maybe_unused,
-			    struct perf_evsel *counter, void *data,
-			    bool first __maybe_unused)
-{
-	struct caggr_data *cd = data;
-	struct perf_stat_evsel *ps = counter->stats;
-
-	cd->avg += avg_stats(&ps->res_stats[0]);
-	cd->avg_enabled += avg_stats(&ps->res_stats[1]);
-	cd->avg_running += avg_stats(&ps->res_stats[2]);
-}
-
-/*
- * Print out the results of a single counter:
- * aggregated counts in system-wide mode
- */
-static void print_counter_aggr(struct perf_stat_config *config,
-			       struct perf_evsel *counter, char *prefix)
-{
-	bool metric_only = config->metric_only;
-	FILE *output = config->output;
-	double uval;
-	struct caggr_data cd = { .avg = 0.0 };
-
-	if (!collect_data(config, counter, counter_aggr_cb, &cd))
-		return;
-
-	if (prefix && !metric_only)
-		fprintf(output, "%s", prefix);
-
-	uval = cd.avg * counter->scale;
-	printout(config, -1, 0, counter, uval, prefix, cd.avg_running, cd.avg_enabled,
-		 cd.avg, &rt_stat);
-	if (!metric_only)
-		fprintf(output, "\n");
-}
-
-static void counter_cb(struct perf_stat_config *config __maybe_unused,
-		       struct perf_evsel *counter, void *data,
-		       bool first __maybe_unused)
-{
-	struct aggr_data *ad = data;
-
-	ad->val += perf_counts(counter->counts, ad->cpu, 0)->val;
-	ad->ena += perf_counts(counter->counts, ad->cpu, 0)->ena;
-	ad->run += perf_counts(counter->counts, ad->cpu, 0)->run;
-}
-
-/*
- * Print out the results of a single counter:
- * does not use aggregated count in system-wide
- */
-static void print_counter(struct perf_stat_config *config,
-			  struct perf_evsel *counter, char *prefix)
-{
-	FILE *output = config->output;
-	u64 ena, run, val;
-	double uval;
-	int cpu;
-
-	for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
-		struct aggr_data ad = { .cpu = cpu };
-
-		if (!collect_data(config, counter, counter_cb, &ad))
-			return;
-		val = ad.val;
-		ena = ad.ena;
-		run = ad.run;
-
-		if (prefix)
-			fprintf(output, "%s", prefix);
-
-		uval = val * counter->scale;
-		printout(config, cpu, 0, counter, uval, prefix, run, ena, 1.0,
-			 &rt_stat);
-
-		fputc('\n', output);
-	}
-}
-
-static void print_no_aggr_metric(struct perf_stat_config *config,
-				 struct perf_evlist *evlist,
-				 char *prefix)
-{
-	int cpu;
-	int nrcpus = 0;
-	struct perf_evsel *counter;
-	u64 ena, run, val;
-	double uval;
-
-	nrcpus = evlist->cpus->nr;
-	for (cpu = 0; cpu < nrcpus; cpu++) {
-		bool first = true;
-
-		if (prefix)
-			fputs(prefix, config->output);
-		evlist__for_each_entry(evlist, counter) {
-			if (is_duration_time(counter))
-				continue;
-			if (first) {
-				aggr_printout(config, counter, cpu, 0);
-				first = false;
-			}
-			val = perf_counts(counter->counts, cpu, 0)->val;
-			ena = perf_counts(counter->counts, cpu, 0)->ena;
-			run = perf_counts(counter->counts, cpu, 0)->run;
-
-			uval = val * counter->scale;
-			printout(config, cpu, 0, counter, uval, prefix, run, ena, 1.0,
-				 &rt_stat);
-		}
-		fputc('\n', config->output);
-	}
-}
-
-static int aggr_header_lens[] = {
-	[AGGR_CORE] = 18,
-	[AGGR_SOCKET] = 12,
-	[AGGR_NONE] = 6,
-	[AGGR_THREAD] = 24,
-	[AGGR_GLOBAL] = 0,
-};
-
-static const char *aggr_header_csv[] = {
-	[AGGR_CORE] 	= 	"core,cpus,",
-	[AGGR_SOCKET] 	= 	"socket,cpus",
-	[AGGR_NONE] 	= 	"cpu,",
-	[AGGR_THREAD] 	= 	"comm-pid,",
-	[AGGR_GLOBAL] 	=	""
-};
-
-static void print_metric_headers(struct perf_stat_config *config,
-				 struct perf_evlist *evlist,
-				 const char *prefix, bool no_indent)
-{
-	struct perf_stat_output_ctx out;
-	struct perf_evsel *counter;
-	struct outstate os = {
-		.fh = config->output
-	};
-
-	if (prefix)
-		fprintf(config->output, "%s", prefix);
-
-	if (!config->csv_output && !no_indent)
-		fprintf(config->output, "%*s",
-			aggr_header_lens[config->aggr_mode], "");
-	if (config->csv_output) {
-		if (config->interval)
-			fputs("time,", config->output);
-		fputs(aggr_header_csv[config->aggr_mode], config->output);
-	}
-
-	/* Print metrics headers only */
-	evlist__for_each_entry(evlist, counter) {
-		if (is_duration_time(counter))
-			continue;
-		os.evsel = counter;
-		out.ctx = &os;
-		out.print_metric = print_metric_header;
-		out.new_line = new_line_metric;
-		out.force_header = true;
-		os.evsel = counter;
-		perf_stat__print_shadow_stats(config, counter, 0,
-					      0,
-					      &out,
-					      &config->metric_events,
-					      &rt_stat);
-	}
-	fputc('\n', config->output);
-}
-
-static void print_interval(struct perf_stat_config *config,
-			   struct perf_evlist *evlist,
-			   char *prefix, struct timespec *ts)
-{
-	bool metric_only = config->metric_only;
-	unsigned int unit_width = config->unit_width;
-	FILE *output = config->output;
-	static int num_print_interval;
-
-	if (config->interval_clear)
-		puts(CONSOLE_CLEAR);
-
-	sprintf(prefix, "%6lu.%09lu%s", ts->tv_sec, ts->tv_nsec, config->csv_sep);
-
-	if ((num_print_interval == 0 && !config->csv_output) || config->interval_clear) {
-		switch (config->aggr_mode) {
-		case AGGR_SOCKET:
-			fprintf(output, "#           time socket cpus");
-			if (!metric_only)
-				fprintf(output, "             counts %*s events\n", unit_width, "unit");
-			break;
-		case AGGR_CORE:
-			fprintf(output, "#           time core         cpus");
-			if (!metric_only)
-				fprintf(output, "             counts %*s events\n", unit_width, "unit");
-			break;
-		case AGGR_NONE:
-			fprintf(output, "#           time CPU    ");
-			if (!metric_only)
-				fprintf(output, "                counts %*s events\n", unit_width, "unit");
-			break;
-		case AGGR_THREAD:
-			fprintf(output, "#           time             comm-pid");
-			if (!metric_only)
-				fprintf(output, "                  counts %*s events\n", unit_width, "unit");
-			break;
-		case AGGR_GLOBAL:
-		default:
-			fprintf(output, "#           time");
-			if (!metric_only)
-				fprintf(output, "             counts %*s events\n", unit_width, "unit");
-		case AGGR_UNSET:
-			break;
-		}
-	}
-
-	if ((num_print_interval == 0 || config->interval_clear) && metric_only)
-		print_metric_headers(config, evlist, " ", true);
-	if (++num_print_interval == 25)
-		num_print_interval = 0;
-}
-
-static void print_header(struct perf_stat_config *config,
-			 struct target *_target,
-			 int argc, const char **argv)
-{
-	FILE *output = config->output;
-	int i;
-
-	fflush(stdout);
-
-	if (!config->csv_output) {
-		fprintf(output, "\n");
-		fprintf(output, " Performance counter stats for ");
-		if (_target->system_wide)
-			fprintf(output, "\'system wide");
-		else if (_target->cpu_list)
-			fprintf(output, "\'CPU(s) %s", _target->cpu_list);
-		else if (!target__has_task(_target)) {
-			fprintf(output, "\'%s", argv ? argv[0] : "pipe");
-			for (i = 1; argv && (i < argc); i++)
-				fprintf(output, " %s", argv[i]);
-		} else if (_target->pid)
-			fprintf(output, "process id \'%s", _target->pid);
-		else
-			fprintf(output, "thread id \'%s", _target->tid);
-
-		fprintf(output, "\'");
-		if (config->run_count > 1)
-			fprintf(output, " (%d runs)", config->run_count);
-		fprintf(output, ":\n\n");
-	}
-}
-
-static int get_precision(double num)
-{
-	if (num > 1)
-		return 0;
-
-	return lround(ceil(-log10(num)));
-}
-
-static void print_table(struct perf_stat_config *config,
-			FILE *output, int precision, double avg)
-{
-	char tmp[64];
-	int idx, indent = 0;
-
-	scnprintf(tmp, 64, " %17.*f", precision, avg);
-	while (tmp[indent] == ' ')
-		indent++;
-
-	fprintf(output, "%*s# Table of individual measurements:\n", indent, "");
-
-	for (idx = 0; idx < config->run_count; idx++) {
-		double run = (double) config->walltime_run[idx] / NSEC_PER_SEC;
-		int h, n = 1 + abs((int) (100.0 * (run - avg)/run) / 5);
-
-		fprintf(output, " %17.*f (%+.*f) ",
-			precision, run, precision, run - avg);
-
-		for (h = 0; h < n; h++)
-			fprintf(output, "#");
-
-		fprintf(output, "\n");
-	}
-
-	fprintf(output, "\n%*s# Final result:\n", indent, "");
-}
-
-static double timeval2double(struct timeval *t)
-{
-	return t->tv_sec + (double) t->tv_usec/USEC_PER_SEC;
-}
-
-static void print_footer(struct perf_stat_config *config)
-{
-	double avg = avg_stats(config->walltime_nsecs_stats) / NSEC_PER_SEC;
-	FILE *output = config->output;
-	int n;
-
-	if (!config->null_run)
-		fprintf(output, "\n");
-
-	if (config->run_count == 1) {
-		fprintf(output, " %17.9f seconds time elapsed", avg);
-
-		if (config->ru_display) {
-			double ru_utime = timeval2double(&config->ru_data.ru_utime);
-			double ru_stime = timeval2double(&config->ru_data.ru_stime);
-
-			fprintf(output, "\n\n");
-			fprintf(output, " %17.9f seconds user\n", ru_utime);
-			fprintf(output, " %17.9f seconds sys\n", ru_stime);
-		}
-	} else {
-		double sd = stddev_stats(config->walltime_nsecs_stats) / NSEC_PER_SEC;
-		/*
-		 * Display at most 2 more significant
-		 * digits than the stddev inaccuracy.
-		 */
-		int precision = get_precision(sd) + 2;
-
-		if (config->walltime_run_table)
-			print_table(config, output, precision, avg);
-
-		fprintf(output, " %17.*f +- %.*f seconds time elapsed",
-			precision, avg, precision, sd);
-
-		print_noise_pct(config, sd, avg);
-	}
-	fprintf(output, "\n\n");
-
-	if (config->print_free_counters_hint &&
-	    sysctl__read_int("kernel/nmi_watchdog", &n) >= 0 &&
-	    n > 0)
-		fprintf(output,
-"Some events weren't counted. Try disabling the NMI watchdog:\n"
-"	echo 0 > /proc/sys/kernel/nmi_watchdog\n"
-"	perf stat ...\n"
-"	echo 1 > /proc/sys/kernel/nmi_watchdog\n");
-
-	if (config->print_mixed_hw_group_error)
-		fprintf(output,
-			"The events in group usually have to be from "
-			"the same PMU. Try reorganizing the group.\n");
-}
-
-static void
-perf_evlist__print_counters(struct perf_evlist *evlist,
-			    struct perf_stat_config *config,
-			    struct target *_target,
-			    struct timespec *ts,
-			    int argc, const char **argv)
-{
-	bool metric_only = config->metric_only;
-	int interval = config->interval;
-	struct perf_evsel *counter;
-	char buf[64], *prefix = NULL;
-
-	if (interval)
-		print_interval(config, evlist, prefix = buf, ts);
-	else
-		print_header(config, _target, argc, argv);
-
-	if (metric_only) {
-		static int num_print_iv;
-
-		if (num_print_iv == 0 && !interval)
-			print_metric_headers(config, evlist, prefix, false);
-		if (num_print_iv++ == 25)
-			num_print_iv = 0;
-		if (config->aggr_mode == AGGR_GLOBAL && prefix)
-			fprintf(config->output, "%s", prefix);
-	}
-
-	switch (config->aggr_mode) {
-	case AGGR_CORE:
-	case AGGR_SOCKET:
-		print_aggr(config, evlist, prefix);
-		break;
-	case AGGR_THREAD:
-		evlist__for_each_entry(evlist, counter) {
-			if (is_duration_time(counter))
-				continue;
-			print_aggr_thread(config, _target, counter, prefix);
-		}
-		break;
-	case AGGR_GLOBAL:
-		evlist__for_each_entry(evlist, counter) {
-			if (is_duration_time(counter))
-				continue;
-			print_counter_aggr(config, counter, prefix);
-		}
-		if (metric_only)
-			fputc('\n', config->output);
-		break;
-	case AGGR_NONE:
-		if (metric_only)
-			print_no_aggr_metric(config, evlist, prefix);
-		else {
-			evlist__for_each_entry(evlist, counter) {
-				if (is_duration_time(counter))
-					continue;
-				print_counter(config, counter, prefix);
-			}
-		}
-		break;
-	case AGGR_UNSET:
-	default:
-		break;
-	}
-
-	if (!interval && !config->csv_output)
-		print_footer(config);
-
-	fflush(config->output);
-}
-
 static void print_counters(struct timespec *ts, int argc, const char **argv)
 {
 	/* Do not print anything if we record to the pipe. */
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 7efe15b9618d..ecd9f9ceda77 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -73,6 +73,7 @@ libperf-y += vdso.o
 libperf-y += counts.o
 libperf-y += stat.o
 libperf-y += stat-shadow.o
+libperf-y += stat-display.o
 libperf-y += record.o
 libperf-y += srcline.o
 libperf-y += data.o
diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c
new file mode 100644
index 000000000000..e7b4c44ebb62
--- /dev/null
+++ b/tools/perf/util/stat-display.c
@@ -0,0 +1,1166 @@
+#include <stdio.h>
+#include <inttypes.h>
+#include <linux/time64.h>
+#include <math.h>
+#include "evlist.h"
+#include "evsel.h"
+#include "stat.h"
+#include "top.h"
+#include "thread_map.h"
+#include "cpumap.h"
+#include "string2.h"
+#include "sane_ctype.h"
+#include "cgroup.h"
+#include <math.h>
+#include <api/fs/fs.h>
+
+#define CNTR_NOT_SUPPORTED	"<not supported>"
+#define CNTR_NOT_COUNTED	"<not counted>"
+
+static bool is_duration_time(struct perf_evsel *evsel)
+{
+	return !strcmp(evsel->name, "duration_time");
+}
+
+static void print_running(struct perf_stat_config *config,
+			  u64 run, u64 ena)
+{
+	if (config->csv_output) {
+		fprintf(config->output, "%s%" PRIu64 "%s%.2f",
+					config->csv_sep,
+					run,
+					config->csv_sep,
+					ena ? 100.0 * run / ena : 100.0);
+	} else if (run != ena) {
+		fprintf(config->output, "  (%.2f%%)", 100.0 * run / ena);
+	}
+}
+
+static void print_noise_pct(struct perf_stat_config *config,
+			    double total, double avg)
+{
+	double pct = rel_stddev_stats(total, avg);
+
+	if (config->csv_output)
+		fprintf(config->output, "%s%.2f%%", config->csv_sep, pct);
+	else if (pct)
+		fprintf(config->output, "  ( +-%6.2f%% )", pct);
+}
+
+static void print_noise(struct perf_stat_config *config,
+			struct perf_evsel *evsel, double avg)
+{
+	struct perf_stat_evsel *ps;
+
+	if (config->run_count == 1)
+		return;
+
+	ps = evsel->stats;
+	print_noise_pct(config, stddev_stats(&ps->res_stats[0]), avg);
+}
+
+static void aggr_printout(struct perf_stat_config *config,
+			  struct perf_evsel *evsel, int id, int nr)
+{
+	switch (config->aggr_mode) {
+	case AGGR_CORE:
+		fprintf(config->output, "S%d-C%*d%s%*d%s",
+			cpu_map__id_to_socket(id),
+			config->csv_output ? 0 : -8,
+			cpu_map__id_to_cpu(id),
+			config->csv_sep,
+			config->csv_output ? 0 : 4,
+			nr,
+			config->csv_sep);
+		break;
+	case AGGR_SOCKET:
+		fprintf(config->output, "S%*d%s%*d%s",
+			config->csv_output ? 0 : -5,
+			id,
+			config->csv_sep,
+			config->csv_output ? 0 : 4,
+			nr,
+			config->csv_sep);
+			break;
+	case AGGR_NONE:
+		fprintf(config->output, "CPU%*d%s",
+			config->csv_output ? 0 : -4,
+			perf_evsel__cpus(evsel)->map[id], config->csv_sep);
+		break;
+	case AGGR_THREAD:
+		fprintf(config->output, "%*s-%*d%s",
+			config->csv_output ? 0 : 16,
+			thread_map__comm(evsel->threads, id),
+			config->csv_output ? 0 : -8,
+			thread_map__pid(evsel->threads, id),
+			config->csv_sep);
+		break;
+	case AGGR_GLOBAL:
+	case AGGR_UNSET:
+	default:
+		break;
+	}
+}
+
+struct outstate {
+	FILE *fh;
+	bool newline;
+	const char *prefix;
+	int  nfields;
+	int  id, nr;
+	struct perf_evsel *evsel;
+};
+
+#define METRIC_LEN  35
+
+static void new_line_std(struct perf_stat_config *config __maybe_unused,
+			 void *ctx)
+{
+	struct outstate *os = ctx;
+
+	os->newline = true;
+}
+
+static void do_new_line_std(struct perf_stat_config *config,
+			    struct outstate *os)
+{
+	fputc('\n', os->fh);
+	fputs(os->prefix, os->fh);
+	aggr_printout(config, os->evsel, os->id, os->nr);
+	if (config->aggr_mode == AGGR_NONE)
+		fprintf(os->fh, "        ");
+	fprintf(os->fh, "                                                 ");
+}
+
+static void print_metric_std(struct perf_stat_config *config,
+			     void *ctx, const char *color, const char *fmt,
+			     const char *unit, double val)
+{
+	struct outstate *os = ctx;
+	FILE *out = os->fh;
+	int n;
+	bool newline = os->newline;
+
+	os->newline = false;
+
+	if (unit == NULL || fmt == NULL) {
+		fprintf(out, "%-*s", METRIC_LEN, "");
+		return;
+	}
+
+	if (newline)
+		do_new_line_std(config, os);
+
+	n = fprintf(out, " # ");
+	if (color)
+		n += color_fprintf(out, color, fmt, val);
+	else
+		n += fprintf(out, fmt, val);
+	fprintf(out, " %-*s", METRIC_LEN - n - 1, unit);
+}
+
+static void new_line_csv(struct perf_stat_config *config, void *ctx)
+{
+	struct outstate *os = ctx;
+	int i;
+
+	fputc('\n', os->fh);
+	if (os->prefix)
+		fprintf(os->fh, "%s%s", os->prefix, config->csv_sep);
+	aggr_printout(config, os->evsel, os->id, os->nr);
+	for (i = 0; i < os->nfields; i++)
+		fputs(config->csv_sep, os->fh);
+}
+
+static void print_metric_csv(struct perf_stat_config *config __maybe_unused,
+			     void *ctx,
+			     const char *color __maybe_unused,
+			     const char *fmt, const char *unit, double val)
+{
+	struct outstate *os = ctx;
+	FILE *out = os->fh;
+	char buf[64], *vals, *ends;
+
+	if (unit == NULL || fmt == NULL) {
+		fprintf(out, "%s%s", config->csv_sep, config->csv_sep);
+		return;
+	}
+	snprintf(buf, sizeof(buf), fmt, val);
+	ends = vals = ltrim(buf);
+	while (isdigit(*ends) || *ends == '.')
+		ends++;
+	*ends = 0;
+	while (isspace(*unit))
+		unit++;
+	fprintf(out, "%s%s%s%s", config->csv_sep, vals, config->csv_sep, unit);
+}
+
+/* Filter out some columns that don't work well in metrics only mode */
+
+static bool valid_only_metric(const char *unit)
+{
+	if (!unit)
+		return false;
+	if (strstr(unit, "/sec") ||
+	    strstr(unit, "hz") ||
+	    strstr(unit, "Hz") ||
+	    strstr(unit, "CPUs utilized"))
+		return false;
+	return true;
+}
+
+static const char *fixunit(char *buf, struct perf_evsel *evsel,
+			   const char *unit)
+{
+	if (!strncmp(unit, "of all", 6)) {
+		snprintf(buf, 1024, "%s %s", perf_evsel__name(evsel),
+			 unit);
+		return buf;
+	}
+	return unit;
+}
+
+static void print_metric_only(struct perf_stat_config *config,
+			      void *ctx, const char *color, const char *fmt,
+			      const char *unit, double val)
+{
+	struct outstate *os = ctx;
+	FILE *out = os->fh;
+	char buf[1024], str[1024];
+	unsigned mlen = config->metric_only_len;
+
+	if (!valid_only_metric(unit))
+		return;
+	unit = fixunit(buf, os->evsel, unit);
+	if (mlen < strlen(unit))
+		mlen = strlen(unit) + 1;
+
+	if (color)
+		mlen += strlen(color) + sizeof(PERF_COLOR_RESET) - 1;
+
+	color_snprintf(str, sizeof(str), color ?: "", fmt, val);
+	fprintf(out, "%*s ", mlen, str);
+}
+
+static void print_metric_only_csv(struct perf_stat_config *config __maybe_unused,
+				  void *ctx, const char *color __maybe_unused,
+				  const char *fmt,
+				  const char *unit, double val)
+{
+	struct outstate *os = ctx;
+	FILE *out = os->fh;
+	char buf[64], *vals, *ends;
+	char tbuf[1024];
+
+	if (!valid_only_metric(unit))
+		return;
+	unit = fixunit(tbuf, os->evsel, unit);
+	snprintf(buf, sizeof buf, fmt, val);
+	ends = vals = ltrim(buf);
+	while (isdigit(*ends) || *ends == '.')
+		ends++;
+	*ends = 0;
+	fprintf(out, "%s%s", vals, config->csv_sep);
+}
+
+static void new_line_metric(struct perf_stat_config *config __maybe_unused,
+			    void *ctx __maybe_unused)
+{
+}
+
+static void print_metric_header(struct perf_stat_config *config,
+				void *ctx, const char *color __maybe_unused,
+				const char *fmt __maybe_unused,
+				const char *unit, double val __maybe_unused)
+{
+	struct outstate *os = ctx;
+	char tbuf[1024];
+
+	if (!valid_only_metric(unit))
+		return;
+	unit = fixunit(tbuf, os->evsel, unit);
+	if (config->csv_output)
+		fprintf(os->fh, "%s%s", unit, config->csv_sep);
+	else
+		fprintf(os->fh, "%*s ", config->metric_only_len, unit);
+}
+
+static int first_shadow_cpu(struct perf_stat_config *config,
+			    struct perf_evsel *evsel, int id)
+{
+	struct perf_evlist *evlist = evsel->evlist;
+	int i;
+
+	if (!config->aggr_get_id)
+		return 0;
+
+	if (config->aggr_mode == AGGR_NONE)
+		return id;
+
+	if (config->aggr_mode == AGGR_GLOBAL)
+		return 0;
+
+	for (i = 0; i < perf_evsel__nr_cpus(evsel); i++) {
+		int cpu2 = perf_evsel__cpus(evsel)->map[i];
+
+		if (config->aggr_get_id(config, evlist->cpus, cpu2) == id)
+			return cpu2;
+	}
+	return 0;
+}
+
+static void abs_printout(struct perf_stat_config *config,
+			 int id, int nr, struct perf_evsel *evsel, double avg)
+{
+	FILE *output = config->output;
+	double sc =  evsel->scale;
+	const char *fmt;
+
+	if (config->csv_output) {
+		fmt = floor(sc) != sc ?  "%.2f%s" : "%.0f%s";
+	} else {
+		if (config->big_num)
+			fmt = floor(sc) != sc ? "%'18.2f%s" : "%'18.0f%s";
+		else
+			fmt = floor(sc) != sc ? "%18.2f%s" : "%18.0f%s";
+	}
+
+	aggr_printout(config, evsel, id, nr);
+
+	fprintf(output, fmt, avg, config->csv_sep);
+
+	if (evsel->unit)
+		fprintf(output, "%-*s%s",
+			config->csv_output ? 0 : config->unit_width,
+			evsel->unit, config->csv_sep);
+
+	fprintf(output, "%-*s", config->csv_output ? 0 : 25, perf_evsel__name(evsel));
+
+	if (evsel->cgrp)
+		fprintf(output, "%s%s", config->csv_sep, evsel->cgrp->name);
+}
+
+static bool is_mixed_hw_group(struct perf_evsel *counter)
+{
+	struct perf_evlist *evlist = counter->evlist;
+	u32 pmu_type = counter->attr.type;
+	struct perf_evsel *pos;
+
+	if (counter->nr_members < 2)
+		return false;
+
+	evlist__for_each_entry(evlist, pos) {
+		/* software events can be part of any hardware group */
+		if (pos->attr.type == PERF_TYPE_SOFTWARE)
+			continue;
+		if (pmu_type == PERF_TYPE_SOFTWARE) {
+			pmu_type = pos->attr.type;
+			continue;
+		}
+		if (pmu_type != pos->attr.type)
+			return true;
+	}
+
+	return false;
+}
+
+static void printout(struct perf_stat_config *config, int id, int nr,
+		     struct perf_evsel *counter, double uval,
+		     char *prefix, u64 run, u64 ena, double noise,
+		     struct runtime_stat *st)
+{
+	struct perf_stat_output_ctx out;
+	struct outstate os = {
+		.fh = config->output,
+		.prefix = prefix ? prefix : "",
+		.id = id,
+		.nr = nr,
+		.evsel = counter,
+	};
+	print_metric_t pm = print_metric_std;
+	new_line_t nl;
+
+	if (config->metric_only) {
+		nl = new_line_metric;
+		if (config->csv_output)
+			pm = print_metric_only_csv;
+		else
+			pm = print_metric_only;
+	} else
+		nl = new_line_std;
+
+	if (config->csv_output && !config->metric_only) {
+		static int aggr_fields[] = {
+			[AGGR_GLOBAL] = 0,
+			[AGGR_THREAD] = 1,
+			[AGGR_NONE] = 1,
+			[AGGR_SOCKET] = 2,
+			[AGGR_CORE] = 2,
+		};
+
+		pm = print_metric_csv;
+		nl = new_line_csv;
+		os.nfields = 3;
+		os.nfields += aggr_fields[config->aggr_mode];
+		if (counter->cgrp)
+			os.nfields++;
+	}
+	if (run == 0 || ena == 0 || counter->counts->scaled == -1) {
+		if (config->metric_only) {
+			pm(config, &os, NULL, "", "", 0);
+			return;
+		}
+		aggr_printout(config, counter, id, nr);
+
+		fprintf(config->output, "%*s%s",
+			config->csv_output ? 0 : 18,
+			counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
+			config->csv_sep);
+
+		if (counter->supported) {
+			config->print_free_counters_hint = 1;
+			if (is_mixed_hw_group(counter))
+				config->print_mixed_hw_group_error = 1;
+		}
+
+		fprintf(config->output, "%-*s%s",
+			config->csv_output ? 0 : config->unit_width,
+			counter->unit, config->csv_sep);
+
+		fprintf(config->output, "%*s",
+			config->csv_output ? 0 : -25,
+			perf_evsel__name(counter));
+
+		if (counter->cgrp)
+			fprintf(config->output, "%s%s",
+				config->csv_sep, counter->cgrp->name);
+
+		if (!config->csv_output)
+			pm(config, &os, NULL, NULL, "", 0);
+		print_noise(config, counter, noise);
+		print_running(config, run, ena);
+		if (config->csv_output)
+			pm(config, &os, NULL, NULL, "", 0);
+		return;
+	}
+
+	if (!config->metric_only)
+		abs_printout(config, id, nr, counter, uval);
+
+	out.print_metric = pm;
+	out.new_line = nl;
+	out.ctx = &os;
+	out.force_header = false;
+
+	if (config->csv_output && !config->metric_only) {
+		print_noise(config, counter, noise);
+		print_running(config, run, ena);
+	}
+
+	perf_stat__print_shadow_stats(config, counter, uval,
+				first_shadow_cpu(config, counter, id),
+				&out, &config->metric_events, st);
+	if (!config->csv_output && !config->metric_only) {
+		print_noise(config, counter, noise);
+		print_running(config, run, ena);
+	}
+}
+
+static void aggr_update_shadow(struct perf_stat_config *config,
+			       struct perf_evlist *evlist)
+{
+	int cpu, s2, id, s;
+	u64 val;
+	struct perf_evsel *counter;
+
+	for (s = 0; s < config->aggr_map->nr; s++) {
+		id = config->aggr_map->map[s];
+		evlist__for_each_entry(evlist, counter) {
+			val = 0;
+			for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
+				s2 = config->aggr_get_id(config, evlist->cpus, cpu);
+				if (s2 != id)
+					continue;
+				val += perf_counts(counter->counts, cpu, 0)->val;
+			}
+			perf_stat__update_shadow_stats(counter, val,
+					first_shadow_cpu(config, counter, id),
+					&rt_stat);
+		}
+	}
+}
+
+static void uniquify_event_name(struct perf_evsel *counter)
+{
+	char *new_name;
+	char *config;
+
+	if (counter->uniquified_name ||
+	    !counter->pmu_name || !strncmp(counter->name, counter->pmu_name,
+					   strlen(counter->pmu_name)))
+		return;
+
+	config = strchr(counter->name, '/');
+	if (config) {
+		if (asprintf(&new_name,
+			     "%s%s", counter->pmu_name, config) > 0) {
+			free(counter->name);
+			counter->name = new_name;
+		}
+	} else {
+		if (asprintf(&new_name,
+			     "%s [%s]", counter->name, counter->pmu_name) > 0) {
+			free(counter->name);
+			counter->name = new_name;
+		}
+	}
+
+	counter->uniquified_name = true;
+}
+
+static void collect_all_aliases(struct perf_stat_config *config, struct perf_evsel *counter,
+			    void (*cb)(struct perf_stat_config *config, struct perf_evsel *counter, void *data,
+				       bool first),
+			    void *data)
+{
+	struct perf_evlist *evlist = counter->evlist;
+	struct perf_evsel *alias;
+
+	alias = list_prepare_entry(counter, &(evlist->entries), node);
+	list_for_each_entry_continue (alias, &evlist->entries, node) {
+		if (strcmp(perf_evsel__name(alias), perf_evsel__name(counter)) ||
+		    alias->scale != counter->scale ||
+		    alias->cgrp != counter->cgrp ||
+		    strcmp(alias->unit, counter->unit) ||
+		    perf_evsel__is_clock(alias) != perf_evsel__is_clock(counter))
+			break;
+		alias->merged_stat = true;
+		cb(config, alias, data, false);
+	}
+}
+
+static bool collect_data(struct perf_stat_config *config, struct perf_evsel *counter,
+			    void (*cb)(struct perf_stat_config *config, struct perf_evsel *counter, void *data,
+				       bool first),
+			    void *data)
+{
+	if (counter->merged_stat)
+		return false;
+	cb(config, counter, data, true);
+	if (config->no_merge)
+		uniquify_event_name(counter);
+	else if (counter->auto_merge_stats)
+		collect_all_aliases(config, counter, cb, data);
+	return true;
+}
+
+struct aggr_data {
+	u64 ena, run, val;
+	int id;
+	int nr;
+	int cpu;
+};
+
+static void aggr_cb(struct perf_stat_config *config,
+		    struct perf_evsel *counter, void *data, bool first)
+{
+	struct aggr_data *ad = data;
+	int cpu, s2;
+
+	for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
+		struct perf_counts_values *counts;
+
+		s2 = config->aggr_get_id(config, perf_evsel__cpus(counter), cpu);
+		if (s2 != ad->id)
+			continue;
+		if (first)
+			ad->nr++;
+		counts = perf_counts(counter->counts, cpu, 0);
+		/*
+		 * When any result is bad, make them all to give
+		 * consistent output in interval mode.
+		 */
+		if (counts->ena == 0 || counts->run == 0 ||
+		    counter->counts->scaled == -1) {
+			ad->ena = 0;
+			ad->run = 0;
+			break;
+		}
+		ad->val += counts->val;
+		ad->ena += counts->ena;
+		ad->run += counts->run;
+	}
+}
+
+static void print_aggr(struct perf_stat_config *config,
+		       struct perf_evlist *evlist,
+		       char *prefix)
+{
+	bool metric_only = config->metric_only;
+	FILE *output = config->output;
+	struct perf_evsel *counter;
+	int s, id, nr;
+	double uval;
+	u64 ena, run, val;
+	bool first;
+
+	if (!(config->aggr_map || config->aggr_get_id))
+		return;
+
+	aggr_update_shadow(config, evlist);
+
+	/*
+	 * With metric_only everything is on a single line.
+	 * Without each counter has its own line.
+	 */
+	for (s = 0; s < config->aggr_map->nr; s++) {
+		struct aggr_data ad;
+		if (prefix && metric_only)
+			fprintf(output, "%s", prefix);
+
+		ad.id = id = config->aggr_map->map[s];
+		first = true;
+		evlist__for_each_entry(evlist, counter) {
+			if (is_duration_time(counter))
+				continue;
+
+			ad.val = ad.ena = ad.run = 0;
+			ad.nr = 0;
+			if (!collect_data(config, counter, aggr_cb, &ad))
+				continue;
+			nr = ad.nr;
+			ena = ad.ena;
+			run = ad.run;
+			val = ad.val;
+			if (first && metric_only) {
+				first = false;
+				aggr_printout(config, counter, id, nr);
+			}
+			if (prefix && !metric_only)
+				fprintf(output, "%s", prefix);
+
+			uval = val * counter->scale;
+			printout(config, id, nr, counter, uval, prefix,
+				 run, ena, 1.0, &rt_stat);
+			if (!metric_only)
+				fputc('\n', output);
+		}
+		if (metric_only)
+			fputc('\n', output);
+	}
+}
+
+static int cmp_val(const void *a, const void *b)
+{
+	return ((struct perf_aggr_thread_value *)b)->val -
+		((struct perf_aggr_thread_value *)a)->val;
+}
+
+static struct perf_aggr_thread_value *sort_aggr_thread(
+					struct perf_evsel *counter,
+					int nthreads, int ncpus,
+					int *ret,
+					struct target *_target)
+{
+	int cpu, thread, i = 0;
+	double uval;
+	struct perf_aggr_thread_value *buf;
+
+	buf = calloc(nthreads, sizeof(struct perf_aggr_thread_value));
+	if (!buf)
+		return NULL;
+
+	for (thread = 0; thread < nthreads; thread++) {
+		u64 ena = 0, run = 0, val = 0;
+
+		for (cpu = 0; cpu < ncpus; cpu++) {
+			val += perf_counts(counter->counts, cpu, thread)->val;
+			ena += perf_counts(counter->counts, cpu, thread)->ena;
+			run += perf_counts(counter->counts, cpu, thread)->run;
+		}
+
+		uval = val * counter->scale;
+
+		/*
+		 * Skip value 0 when enabling --per-thread globally,
+		 * otherwise too many 0 output.
+		 */
+		if (uval == 0.0 && target__has_per_thread(_target))
+			continue;
+
+		buf[i].counter = counter;
+		buf[i].id = thread;
+		buf[i].uval = uval;
+		buf[i].val = val;
+		buf[i].run = run;
+		buf[i].ena = ena;
+		i++;
+	}
+
+	qsort(buf, i, sizeof(struct perf_aggr_thread_value), cmp_val);
+
+	if (ret)
+		*ret = i;
+
+	return buf;
+}
+
+static void print_aggr_thread(struct perf_stat_config *config,
+			      struct target *_target,
+			      struct perf_evsel *counter, char *prefix)
+{
+	FILE *output = config->output;
+	int nthreads = thread_map__nr(counter->threads);
+	int ncpus = cpu_map__nr(counter->cpus);
+	int thread, sorted_threads, id;
+	struct perf_aggr_thread_value *buf;
+
+	buf = sort_aggr_thread(counter, nthreads, ncpus, &sorted_threads, _target);
+	if (!buf) {
+		perror("cannot sort aggr thread");
+		return;
+	}
+
+	for (thread = 0; thread < sorted_threads; thread++) {
+		if (prefix)
+			fprintf(output, "%s", prefix);
+
+		id = buf[thread].id;
+		if (config->stats)
+			printout(config, id, 0, buf[thread].counter, buf[thread].uval,
+				 prefix, buf[thread].run, buf[thread].ena, 1.0,
+				 &config->stats[id]);
+		else
+			printout(config, id, 0, buf[thread].counter, buf[thread].uval,
+				 prefix, buf[thread].run, buf[thread].ena, 1.0,
+				 &rt_stat);
+		fputc('\n', output);
+	}
+
+	free(buf);
+}
+
+struct caggr_data {
+	double avg, avg_enabled, avg_running;
+};
+
+static void counter_aggr_cb(struct perf_stat_config *config __maybe_unused,
+			    struct perf_evsel *counter, void *data,
+			    bool first __maybe_unused)
+{
+	struct caggr_data *cd = data;
+	struct perf_stat_evsel *ps = counter->stats;
+
+	cd->avg += avg_stats(&ps->res_stats[0]);
+	cd->avg_enabled += avg_stats(&ps->res_stats[1]);
+	cd->avg_running += avg_stats(&ps->res_stats[2]);
+}
+
+/*
+ * Print out the results of a single counter:
+ * aggregated counts in system-wide mode
+ */
+static void print_counter_aggr(struct perf_stat_config *config,
+			       struct perf_evsel *counter, char *prefix)
+{
+	bool metric_only = config->metric_only;
+	FILE *output = config->output;
+	double uval;
+	struct caggr_data cd = { .avg = 0.0 };
+
+	if (!collect_data(config, counter, counter_aggr_cb, &cd))
+		return;
+
+	if (prefix && !metric_only)
+		fprintf(output, "%s", prefix);
+
+	uval = cd.avg * counter->scale;
+	printout(config, -1, 0, counter, uval, prefix, cd.avg_running, cd.avg_enabled,
+		 cd.avg, &rt_stat);
+	if (!metric_only)
+		fprintf(output, "\n");
+}
+
+static void counter_cb(struct perf_stat_config *config __maybe_unused,
+		       struct perf_evsel *counter, void *data,
+		       bool first __maybe_unused)
+{
+	struct aggr_data *ad = data;
+
+	ad->val += perf_counts(counter->counts, ad->cpu, 0)->val;
+	ad->ena += perf_counts(counter->counts, ad->cpu, 0)->ena;
+	ad->run += perf_counts(counter->counts, ad->cpu, 0)->run;
+}
+
+/*
+ * Print out the results of a single counter:
+ * does not use aggregated count in system-wide
+ */
+static void print_counter(struct perf_stat_config *config,
+			  struct perf_evsel *counter, char *prefix)
+{
+	FILE *output = config->output;
+	u64 ena, run, val;
+	double uval;
+	int cpu;
+
+	for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
+		struct aggr_data ad = { .cpu = cpu };
+
+		if (!collect_data(config, counter, counter_cb, &ad))
+			return;
+		val = ad.val;
+		ena = ad.ena;
+		run = ad.run;
+
+		if (prefix)
+			fprintf(output, "%s", prefix);
+
+		uval = val * counter->scale;
+		printout(config, cpu, 0, counter, uval, prefix, run, ena, 1.0,
+			 &rt_stat);
+
+		fputc('\n', output);
+	}
+}
+
+static void print_no_aggr_metric(struct perf_stat_config *config,
+				 struct perf_evlist *evlist,
+				 char *prefix)
+{
+	int cpu;
+	int nrcpus = 0;
+	struct perf_evsel *counter;
+	u64 ena, run, val;
+	double uval;
+
+	nrcpus = evlist->cpus->nr;
+	for (cpu = 0; cpu < nrcpus; cpu++) {
+		bool first = true;
+
+		if (prefix)
+			fputs(prefix, config->output);
+		evlist__for_each_entry(evlist, counter) {
+			if (is_duration_time(counter))
+				continue;
+			if (first) {
+				aggr_printout(config, counter, cpu, 0);
+				first = false;
+			}
+			val = perf_counts(counter->counts, cpu, 0)->val;
+			ena = perf_counts(counter->counts, cpu, 0)->ena;
+			run = perf_counts(counter->counts, cpu, 0)->run;
+
+			uval = val * counter->scale;
+			printout(config, cpu, 0, counter, uval, prefix, run, ena, 1.0,
+				 &rt_stat);
+		}
+		fputc('\n', config->output);
+	}
+}
+
+static int aggr_header_lens[] = {
+	[AGGR_CORE] = 18,
+	[AGGR_SOCKET] = 12,
+	[AGGR_NONE] = 6,
+	[AGGR_THREAD] = 24,
+	[AGGR_GLOBAL] = 0,
+};
+
+static const char *aggr_header_csv[] = {
+	[AGGR_CORE] 	= 	"core,cpus,",
+	[AGGR_SOCKET] 	= 	"socket,cpus",
+	[AGGR_NONE] 	= 	"cpu,",
+	[AGGR_THREAD] 	= 	"comm-pid,",
+	[AGGR_GLOBAL] 	=	""
+};
+
+static void print_metric_headers(struct perf_stat_config *config,
+				 struct perf_evlist *evlist,
+				 const char *prefix, bool no_indent)
+{
+	struct perf_stat_output_ctx out;
+	struct perf_evsel *counter;
+	struct outstate os = {
+		.fh = config->output
+	};
+
+	if (prefix)
+		fprintf(config->output, "%s", prefix);
+
+	if (!config->csv_output && !no_indent)
+		fprintf(config->output, "%*s",
+			aggr_header_lens[config->aggr_mode], "");
+	if (config->csv_output) {
+		if (config->interval)
+			fputs("time,", config->output);
+		fputs(aggr_header_csv[config->aggr_mode], config->output);
+	}
+
+	/* Print metrics headers only */
+	evlist__for_each_entry(evlist, counter) {
+		if (is_duration_time(counter))
+			continue;
+		os.evsel = counter;
+		out.ctx = &os;
+		out.print_metric = print_metric_header;
+		out.new_line = new_line_metric;
+		out.force_header = true;
+		os.evsel = counter;
+		perf_stat__print_shadow_stats(config, counter, 0,
+					      0,
+					      &out,
+					      &config->metric_events,
+					      &rt_stat);
+	}
+	fputc('\n', config->output);
+}
+
+static void print_interval(struct perf_stat_config *config,
+			   struct perf_evlist *evlist,
+			   char *prefix, struct timespec *ts)
+{
+	bool metric_only = config->metric_only;
+	unsigned int unit_width = config->unit_width;
+	FILE *output = config->output;
+	static int num_print_interval;
+
+	if (config->interval_clear)
+		puts(CONSOLE_CLEAR);
+
+	sprintf(prefix, "%6lu.%09lu%s", ts->tv_sec, ts->tv_nsec, config->csv_sep);
+
+	if ((num_print_interval == 0 && !config->csv_output) || config->interval_clear) {
+		switch (config->aggr_mode) {
+		case AGGR_SOCKET:
+			fprintf(output, "#           time socket cpus");
+			if (!metric_only)
+				fprintf(output, "             counts %*s events\n", unit_width, "unit");
+			break;
+		case AGGR_CORE:
+			fprintf(output, "#           time core         cpus");
+			if (!metric_only)
+				fprintf(output, "             counts %*s events\n", unit_width, "unit");
+			break;
+		case AGGR_NONE:
+			fprintf(output, "#           time CPU    ");
+			if (!metric_only)
+				fprintf(output, "                counts %*s events\n", unit_width, "unit");
+			break;
+		case AGGR_THREAD:
+			fprintf(output, "#           time             comm-pid");
+			if (!metric_only)
+				fprintf(output, "                  counts %*s events\n", unit_width, "unit");
+			break;
+		case AGGR_GLOBAL:
+		default:
+			fprintf(output, "#           time");
+			if (!metric_only)
+				fprintf(output, "             counts %*s events\n", unit_width, "unit");
+		case AGGR_UNSET:
+			break;
+		}
+	}
+
+	if ((num_print_interval == 0 || config->interval_clear) && metric_only)
+		print_metric_headers(config, evlist, " ", true);
+	if (++num_print_interval == 25)
+		num_print_interval = 0;
+}
+
+static void print_header(struct perf_stat_config *config,
+			 struct target *_target,
+			 int argc, const char **argv)
+{
+	FILE *output = config->output;
+	int i;
+
+	fflush(stdout);
+
+	if (!config->csv_output) {
+		fprintf(output, "\n");
+		fprintf(output, " Performance counter stats for ");
+		if (_target->system_wide)
+			fprintf(output, "\'system wide");
+		else if (_target->cpu_list)
+			fprintf(output, "\'CPU(s) %s", _target->cpu_list);
+		else if (!target__has_task(_target)) {
+			fprintf(output, "\'%s", argv ? argv[0] : "pipe");
+			for (i = 1; argv && (i < argc); i++)
+				fprintf(output, " %s", argv[i]);
+		} else if (_target->pid)
+			fprintf(output, "process id \'%s", _target->pid);
+		else
+			fprintf(output, "thread id \'%s", _target->tid);
+
+		fprintf(output, "\'");
+		if (config->run_count > 1)
+			fprintf(output, " (%d runs)", config->run_count);
+		fprintf(output, ":\n\n");
+	}
+}
+
+static int get_precision(double num)
+{
+	if (num > 1)
+		return 0;
+
+	return lround(ceil(-log10(num)));
+}
+
+static void print_table(struct perf_stat_config *config,
+			FILE *output, int precision, double avg)
+{
+	char tmp[64];
+	int idx, indent = 0;
+
+	scnprintf(tmp, 64, " %17.*f", precision, avg);
+	while (tmp[indent] == ' ')
+		indent++;
+
+	fprintf(output, "%*s# Table of individual measurements:\n", indent, "");
+
+	for (idx = 0; idx < config->run_count; idx++) {
+		double run = (double) config->walltime_run[idx] / NSEC_PER_SEC;
+		int h, n = 1 + abs((int) (100.0 * (run - avg)/run) / 5);
+
+		fprintf(output, " %17.*f (%+.*f) ",
+			precision, run, precision, run - avg);
+
+		for (h = 0; h < n; h++)
+			fprintf(output, "#");
+
+		fprintf(output, "\n");
+	}
+
+	fprintf(output, "\n%*s# Final result:\n", indent, "");
+}
+
+static double timeval2double(struct timeval *t)
+{
+	return t->tv_sec + (double) t->tv_usec/USEC_PER_SEC;
+}
+
+static void print_footer(struct perf_stat_config *config)
+{
+	double avg = avg_stats(config->walltime_nsecs_stats) / NSEC_PER_SEC;
+	FILE *output = config->output;
+	int n;
+
+	if (!config->null_run)
+		fprintf(output, "\n");
+
+	if (config->run_count == 1) {
+		fprintf(output, " %17.9f seconds time elapsed", avg);
+
+		if (config->ru_display) {
+			double ru_utime = timeval2double(&config->ru_data.ru_utime);
+			double ru_stime = timeval2double(&config->ru_data.ru_stime);
+
+			fprintf(output, "\n\n");
+			fprintf(output, " %17.9f seconds user\n", ru_utime);
+			fprintf(output, " %17.9f seconds sys\n", ru_stime);
+		}
+	} else {
+		double sd = stddev_stats(config->walltime_nsecs_stats) / NSEC_PER_SEC;
+		/*
+		 * Display at most 2 more significant
+		 * digits than the stddev inaccuracy.
+		 */
+		int precision = get_precision(sd) + 2;
+
+		if (config->walltime_run_table)
+			print_table(config, output, precision, avg);
+
+		fprintf(output, " %17.*f +- %.*f seconds time elapsed",
+			precision, avg, precision, sd);
+
+		print_noise_pct(config, sd, avg);
+	}
+	fprintf(output, "\n\n");
+
+	if (config->print_free_counters_hint &&
+	    sysctl__read_int("kernel/nmi_watchdog", &n) >= 0 &&
+	    n > 0)
+		fprintf(output,
+"Some events weren't counted. Try disabling the NMI watchdog:\n"
+"	echo 0 > /proc/sys/kernel/nmi_watchdog\n"
+"	perf stat ...\n"
+"	echo 1 > /proc/sys/kernel/nmi_watchdog\n");
+
+	if (config->print_mixed_hw_group_error)
+		fprintf(output,
+			"The events in group usually have to be from "
+			"the same PMU. Try reorganizing the group.\n");
+}
+
+void
+perf_evlist__print_counters(struct perf_evlist *evlist,
+			    struct perf_stat_config *config,
+			    struct target *_target,
+			    struct timespec *ts,
+			    int argc, const char **argv)
+{
+	bool metric_only = config->metric_only;
+	int interval = config->interval;
+	struct perf_evsel *counter;
+	char buf[64], *prefix = NULL;
+
+	if (interval)
+		print_interval(config, evlist, prefix = buf, ts);
+	else
+		print_header(config, _target, argc, argv);
+
+	if (metric_only) {
+		static int num_print_iv;
+
+		if (num_print_iv == 0 && !interval)
+			print_metric_headers(config, evlist, prefix, false);
+		if (num_print_iv++ == 25)
+			num_print_iv = 0;
+		if (config->aggr_mode == AGGR_GLOBAL && prefix)
+			fprintf(config->output, "%s", prefix);
+	}
+
+	switch (config->aggr_mode) {
+	case AGGR_CORE:
+	case AGGR_SOCKET:
+		print_aggr(config, evlist, prefix);
+		break;
+	case AGGR_THREAD:
+		evlist__for_each_entry(evlist, counter) {
+			if (is_duration_time(counter))
+				continue;
+			print_aggr_thread(config, _target, counter, prefix);
+		}
+		break;
+	case AGGR_GLOBAL:
+		evlist__for_each_entry(evlist, counter) {
+			if (is_duration_time(counter))
+				continue;
+			print_counter_aggr(config, counter, prefix);
+		}
+		if (metric_only)
+			fputc('\n', config->output);
+		break;
+	case AGGR_NONE:
+		if (metric_only)
+			print_no_aggr_metric(config, evlist, prefix);
+		else {
+			evlist__for_each_entry(evlist, counter) {
+				if (is_duration_time(counter))
+					continue;
+				print_counter(config, counter, prefix);
+			}
+		}
+		break;
+	case AGGR_UNSET:
+	default:
+		break;
+	}
+
+	if (!interval && !config->csv_output)
+		print_footer(config);
+
+	fflush(config->output);
+}
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 8d3354e21e19..3a13a6dc5a62 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -215,4 +215,10 @@ int perf_stat_synthesize_config(struct perf_stat_config *config,
 				struct perf_evlist *evlist,
 				perf_event__handler_t process,
 				bool attrs);
+void
+perf_evlist__print_counters(struct perf_evlist *evlist,
+			    struct perf_stat_config *config,
+			    struct target *_target,
+			    struct timespec *ts,
+			    int argc, const char **argv);
 #endif

^ permalink raw reply related	[flat|nested] 88+ messages in thread

end of thread, other threads:[~2018-09-06 13:45 UTC | newest]

Thread overview: 88+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-08-30  6:32 [PATCH 00/43] perf stat: Make some of the stat code generic Jiri Olsa
2018-08-30  6:32 ` [PATCH 01/43] perf stat: Use evsel->threads in create_perf_stat_counter Jiri Olsa
2018-09-06 13:21   ` [tip:perf/core] perf stat: Use evsel->threads in create_perf_stat_counter() tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 02/43] perf stat: Move initial_delay into struct perf_stat_config Jiri Olsa
2018-09-06 13:21   ` [tip:perf/core] perf stat: Move 'initial_delay' to 'struct perf_stat_config' tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 03/43] perf stat: Move no_inherit into struct perf_stat_config Jiri Olsa
2018-09-06 13:22   ` [tip:perf/core] perf stat: Move 'no_inherit' to 'struct perf_stat_config' tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 04/43] perf stat: Use local config arg for scale in create_perf_stat_counter Jiri Olsa
2018-09-06 13:22   ` [tip:perf/core] perf stat: Use local config arg for scale in create_perf_stat_counter() tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 05/43] perf stat: Add identifier flag into struct stat_opts Jiri Olsa
2018-09-06 13:23   ` [tip:perf/core] perf stat: Add 'identifier' flag to 'struct perf_stat_config' tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 06/43] perf tools: Switch session argument to evlist in perf_event__synthesize_attrs Jiri Olsa
2018-09-06 13:23   ` [tip:perf/core] perf tools: Switch 'session' argument to 'evlist' in perf_event__synthesize_attrs() tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 07/43] perf tools: Add perf_evsel__store_ids function Jiri Olsa
2018-09-06 13:24   ` [tip:perf/core] perf evsel: Introduce perf_evsel__store_ids() tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 08/43] perf stat: Move create_perf_stat_counter into stat.c Jiri Olsa
2018-09-06 13:24   ` [tip:perf/core] perf stat: Move create_perf_stat_counter() to stat.c tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 09/43] perf stat: Rename is_pipe argument to attrs perf_stat_synthesize_config Jiri Olsa
2018-09-06 13:25   ` [tip:perf/core] perf stat: Rename 'is_pipe' argument to 'attrs' in perf_stat_synthesize_config() tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 10/43] perf stat: Add struct perf_stat_config argument to perf_stat_synthesize_config Jiri Olsa
2018-09-06 13:26   ` [tip:perf/core] perf stat: Add 'struct perf_stat_config' argument to perf_stat_synthesize_config() tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 11/43] perf stat: Add struct perf_tool argument to perf_stat_synthesize_config Jiri Olsa
2018-09-06 13:26   ` [tip:perf/core] perf stat: Add 'struct perf_tool' argument to perf_stat_synthesize_config() tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 12/43] perf stat: Add struct perf_evlist argument to perf_stat_synthesize_config Jiri Olsa
2018-09-06 13:27   ` [tip:perf/core] perf stat: Add 'struct perf_evlist' argument to perf_stat_synthesize_config() tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 13/43] perf stat: Add perf_event__handler_t argument to perf_stat_synthesize_config Jiri Olsa
2018-09-06 13:27   ` [tip:perf/core] perf stat: Add 'perf_event__handler_t' argument to perf_stat_synthesize_config() tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 14/43] perf stat: Move perf_stat_synthesize_config into stat.c Jiri Olsa
2018-09-06 13:28   ` [tip:perf/core] perf stat: Move perf_stat_synthesize_config() to stat.c tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 15/43] perf stat: Add perf_evlist__print_counters function Jiri Olsa
2018-09-06 13:28   ` [tip:perf/core] perf stat: Introduce perf_evlist__print_counters() tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 16/43] perf stat: Move STAT_RECORD out of perf_evlist__print_counters Jiri Olsa
2018-09-06 13:29   ` [tip:perf/core] perf stat: Move STAT_RECORD out of perf_evlist__print_counters() tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 17/43] perf stat: Add stat_config argument to perf_evlist__print_counters Jiri Olsa
2018-09-06 13:29   ` [tip:perf/core] perf stat: Add 'struct perf_stat_config' argument to perf_evlist__print_counters() tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 18/43] perf stat: Pass stat_config argument to local print functions Jiri Olsa
2018-09-06 13:30   ` [tip:perf/core] perf stat: Pass 'struct perf_stat_config' " tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 19/43] perf stat: Pass stat_config argument to global " Jiri Olsa
2018-09-06 13:30   ` [tip:perf/core] perf stat: Pass a 'struct perf_stat_config' " tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 20/43] perf stat: Move csv_* into struct perf_stat_config Jiri Olsa
2018-09-06 13:31   ` [tip:perf/core] perf stat: Move csv_* to 'struct perf_stat_config' tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 21/43] perf stat: Move interval_clear into struct perf_stat_config Jiri Olsa
2018-09-06 13:31   ` [tip:perf/core] perf stat: Move 'interval_clear' to 'struct perf_stat_config' tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 22/43] perf stat: Move metric_only into struct perf_stat_config Jiri Olsa
2018-09-06 13:32   ` [tip:perf/core] perf stat: Move 'metric_only' to 'struct perf_stat_config' tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 23/43] perf stat: Move unit_width into struct perf_stat_config Jiri Olsa
2018-09-06 13:33   ` [tip:perf/core] perf stat: Move 'unit_width' to 'struct perf_stat_config' tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 24/43] perf stat: Add target argument to perf_evlist__print_counters Jiri Olsa
2018-09-06 13:33   ` [tip:perf/core] perf stat: Add 'target' argument to perf_evlist__print_counters() tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 25/43] perf stat: Pass evlist argument to print functions Jiri Olsa
2018-09-06 13:34   ` [tip:perf/core] perf stat: Pass 'evlist' " tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 26/43] perf stat: Use evsel->evlist instead of evsel_list in collect_all_aliases Jiri Olsa
2018-09-06 13:34   ` [tip:perf/core] perf stat: Use 'evsel->evlist' instead of 'evsel_list' in collect_all_aliases() tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 27/43] perf stat: Move run_count into struct perf_stat_config Jiri Olsa
2018-09-06 13:35   ` [tip:perf/core] perf stat: Move 'run_count' to 'struct perf_stat_config' tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 28/43] perf stat: Move metric_only_len into struct perf_stat_config Jiri Olsa
2018-09-06 13:35   ` [tip:perf/core] perf stat: Move 'metric_only_len' to 'struct perf_stat_config' tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 29/43] perf stat: Pass stat_config to first_shadow_cpu Jiri Olsa
2018-09-06 13:36   ` [tip:perf/core] perf stat: Pass 'struct perf_stat_config' to first_shadow_cpu() tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 30/43] perf stat: Pass evlist to aggr_update_shadow Jiri Olsa
2018-09-06 13:37   ` [tip:perf/core] perf stat: Pass 'evlist' to aggr_update_shadow() tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 31/43] perf stat: Add walltime_nsecs_stats pointer into struct perf_stat_config Jiri Olsa
2018-09-06 13:37   ` [tip:perf/core] perf stat: Add 'walltime_nsecs_stats' pointer to 'struct perf_stat_config' tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 32/43] perf stat: Move null_run into struct perf_stat_config Jiri Olsa
2018-09-06 13:38   ` [tip:perf/core] perf stat: Move 'null_run' to 'struct perf_stat_config' tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 33/43] perf stat: Move print_free_counters_hint into struct perf_stat_config Jiri Olsa
2018-09-06 13:38   ` [tip:perf/core] perf stat: Move 'print_free_counters_hint' to 'struct perf_stat_config' tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 34/43] perf stat: Move print_mixed_hw_group_error into struct perf_stat_config Jiri Olsa
2018-09-06 13:39   ` [tip:perf/core] perf stat: Move 'print_mixed_hw_group_error' to 'struct perf_stat_config' tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 35/43] perf stat: Move ru_* data into struct perf_stat_config Jiri Olsa
2018-09-06 13:39   ` [tip:perf/core] perf stat: Move ru_* data to 'struct perf_stat_config' tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 36/43] perf stat: Move *_aggr_* data into struct perf_stat_config Jiri Olsa
2018-09-06 13:40   ` [tip:perf/core] perf stat: Move *_aggr_* data to 'struct perf_stat_config' tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 37/43] perf stat: Do not use glovab evsel_list in print functions Jiri Olsa
2018-09-06 13:40   ` [tip:perf/core] perf stat: Do not use the global 'evsel_list' " tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 38/43] perf stat: Move big_num data into struct perf_stat_config Jiri Olsa
2018-09-06 13:41   ` [tip:perf/core] perf stat: Move 'big_num' data to 'struct perf_stat_config' tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 39/43] perf stat: Move no_merge data into struct perf_stat_config Jiri Olsa
2018-09-06 13:42   ` [tip:perf/core] perf stat: Move 'no_merge' data to 'struct perf_stat_config' tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 40/43] perf stat: Propagate struct target arg to sort_aggr_thread Jiri Olsa
2018-09-06 13:42   ` [tip:perf/core] perf stat: Propagate 'struct target' arg to sort_aggr_thread() tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 41/43] perf stat: Move walltime_* data into struct perf_stat_config Jiri Olsa
2018-09-06 13:43   ` [tip:perf/core] perf stat: Move 'walltime_*' data to 'struct perf_stat_config' tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 42/43] perf stat: Move metric_events into struct perf_stat_config Jiri Olsa
2018-09-06 13:43   ` [tip:perf/core] perf stat: Move 'metric_events' to 'struct perf_stat_config' tip-bot for Jiri Olsa
2018-08-30  6:32 ` [PATCH 43/43] perf stat: Move display functions into stat-display.c Jiri Olsa
2018-09-06 13:44   ` [tip:perf/core] perf stat: Move the display functions to stat-display.c tip-bot for Jiri Olsa
2018-08-30 17:54 ` [PATCH 00/43] perf stat: Make some of the stat code generic Arnaldo Carvalho de Melo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).