All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC 00/47] perf stat: Add scripting support
@ 2015-07-21 12:31 Jiri Olsa
  2015-07-21 12:31 ` [PATCH 01/47] perf test: Check for refcnt in thread_map test Jiri Olsa
                   ` (48 more replies)
  0 siblings, 49 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Andi Kleen, Ulrich Drepper, Will Deacon, Stephane Eranian, lkml,
	David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

hi,
sending RFC on another attempt for stat scripting.

The initial attempt defined its own formula lang and allowed
triggering user's script on the end of the stat command:
  http://marc.info/?l=linux-kernel&m=136742146322273&w=2

This patchset abandons the idea of new formula language
and rather adds support to:
  - store stat data into perf.data file
  - add python support to process stat events

Basically it allows to store stat data into perf.data and
post process it with python scripts in a similar way we
do for sampling data.

Examples:

 To record data for command stat workload:
  $ perf stat record kill
  ...

   Performance counter stats for 'kill':

            0.372007      task-clock (msec)         #    0.613 CPUs utilized          
                   3      context-switches          #    0.008 M/sec                  
                   0      cpu-migrations            #    0.000 K/sec                  
                  62      page-faults               #    0.167 M/sec                  
           1,129,973      cycles                    #    3.038 GHz                    
     <not supported>      stalled-cycles-frontend  
     <not supported>      stalled-cycles-backend   
             813,313      instructions              #    0.72  insns per cycle        
             166,161      branches                  #  446.661 M/sec                  
               8,747      branch-misses             #    5.26% of all branches        

         0.000607287 seconds time elapsed

 To report perf stat data:
  $ perf stat report

   Performance counter stats for '/home/jolsa/bin/perf stat record kill':

            0.372007      task-clock (msec)         #      inf CPUs utilized          
                   3      context-switches          #    0.008 M/sec                  
                   0      cpu-migrations            #    0.000 K/sec                  
                  62      page-faults               #    0.167 M/sec                  
           1,129,973      cycles                    #    3.038 GHz                    
     <not supported>      stalled-cycles-frontend  
     <not supported>      stalled-cycles-backend   
             813,313      instructions              #    0.72  insns per cycle        
             166,161      branches                  #  446.661 M/sec                  
               8,747      branch-misses             #    5.26% of all branches        

         0.000000000 seconds time elapsed

 To store system-wide period stat data:
  $ perf stat -e cycles:u,instructions:u -a -I 1000 record
  #           time             counts unit events
       1.000265471        462,311,482      cycles:u                   (100.00%)
       1.000265471        590,037,440      instructions:u           
       2.000483453        722,532,336      cycles:u                   (100.00%)
       2.000483453        848,678,197      instructions:u           
       3.000759876         75,990,880      cycles:u                   (100.00%)
       3.000759876         86,187,813      instructions:u           
  ^C     3.213960893         85,329,533      cycles:u                   (100.00%)
       3.213960893        135,954,296      instructions:u           

 To report perf stat data:
  $ perf stat report
  #           time             counts unit events
       1.000265471        462,311,482      cycles:u                   (100.00%)
       1.000265471        590,037,440      instructions:u           
       2.000483453        722,532,336      cycles:u                   (100.00%)
       2.000483453        848,678,197      instructions:u           
       3.000759876         75,990,880      cycles:u                   (100.00%)
       3.000759876         86,187,813      instructions:u           
       3.213960893         85,329,533      cycles:u                   (100.00%)
       3.213960893        135,954,296      instructions:u           

 To run stat-cpi.py script over perf.data:
  $ perf script -s scripts/python/stat-cpi.py 
         1.000265: cpu -1, thread -1 -> cpi 0.783529 (462311482/590037440)
         2.000483: cpu -1, thread -1 -> cpi 0.851362 (722532336/848678197)
         3.000760: cpu -1, thread -1 -> cpi 0.881689 (75990880/86187813)
         3.213961: cpu -1, thread -1 -> cpi 0.627634 (85329533/135954296)

 To pipe data from stat to stat-cpi script:
  $ perf stat -e cycles:u,instructions:u -A -C 0 -I 1000 record | perf script -s scripts/python/stat-cpi.py 
         1.000192: cpu 0, thread -1 -> cpi 0.739535 (23921908/32347236)
         2.000376: cpu 0, thread -1 -> cpi 1.663482 (2519340/1514498)
         3.000621: cpu 0, thread -1 -> cpi 1.396308 (16162767/11575362)
         4.000700: cpu 0, thread -1 -> cpi 1.092246 (20077258/18381624)
         5.000867: cpu 0, thread -1 -> cpi 0.473816 (45157586/95306156)
         6.001034: cpu 0, thread -1 -> cpi 0.532792 (43701668/82023818)
         7.001195: cpu 0, thread -1 -> cpi 1.122059 (29890042/26638561)

 Raw script stat data output:
  $ perf stat -e cycles:u,instructions:u -A -C 0 -I 1000 record | perf --no-pager script
  CPU   THREAD             VAL             ENA             RUN            TIME EVENT
    0       -1        12302059      1000811347      1000810712      1000198821 cycles:u
    0       -1         2565362      1000823218      1000823218      1000198821 instructions:u
    0       -1        14453353      1000812704      1000812704      2000382283 cycles:u
    0       -1         4600932      1000799342      1000799342      2000382283 instructions:u
    0       -1        15245106      1000774425      1000774425      3000538255 cycles:u
    0       -1         2624324      1000769310      1000769310      3000538255 instructions:u


The stat data are stored in new stat, stat-round, stat-config user events.
  stat        - stored for each read syscall of the counter
  stat round  - stored for each interval or end of the command invocation
  stat config - stores all the config information needed to process data
                so report tool could restore the same output as record

The python script can now define 'stat__<eventname>_<modifier>' functions
to get stat events data and 'stat__interval' to get stat-round data. See
CPI script example in scripts/python/stat-cpi.py.

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


This patchset still has MANY rough edges and loose ends,
but I think it's better approach than to define our own
formula scripting language.

The patchset is growing and there's still a long way to go,
so I'd like to hear some opinions before I go further ;-)


thanks for comments,
jirka


Cc: Andi Kleen <andi@firstfloor.org>
Cc: Ulrich Drepper <drepper@gmail.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Stephane Eranian <eranian@google.com>
---
Jiri Olsa (47):
      perf test: Check for refcnt in thread_map test
      perf stat: Introduce struct perf_stat_config
      perf stat: Move scale into struct perf_stat_config
      perf stat: Move output into struct perf_stat_config
      perf stat: Move interval into struct perf_stat_config
      perf stat: Pass struct perf_stat_config into process_counter
      perf stat: Move counter processing code into stat object
      perf tools: Use bool instead of target argument in perf_evlist__propagate_maps
      perf tools: Tolerate NULL maps in perf_evlist__propagate_maps
      perf tools: Force perf_evlist__set_maps to propagate maps through events
      perf tools: Use argv style storage for cmdline feature data
      perf tools: Add thread_map event
      perf tools: Add thread_map event sythesize function
      perf tools: Add thread_map__new_event function
      perf tools: Add cpu_map event
      perf tools: Add cpu_map event synthesize function
      perf tools: Add cpu_map__new_event function
      perf tools: Add stat config event
      perf tools: Add stat config event synthesize function
      perf tools: Add stat config event read function
      perf tools: Add stat event
      perf tools: Add stat event synthesize function
      perf tools: Add stat event read function
      perf tools: Add stat round event
      perf tools: Add stat round event synthesize function
      perf tools: Introduce stat feature
      perf tools: Move id_offset out of struct perf_evsel union
      perf stat record: Add record command
      perf stat record: Initialize record features
      perf stat record: Synthesize stat record data
      perf stat record: Store events IDs in perf data file
      perf stat record: Add pipe support for record command
      perf stat record: Write stat events on record
      perf stat record: Write stat round events on record
      perf stat report: Add report command
      perf stat report: Process cpu/threads maps
      perf stat report: Process stat config event
      perf stat report: Process stat and stat round events
      perf stat report: Move csv_sep initialization before report command
      perf script: Check output fields only for samples
      perf script: Process cpu/threads maps
      perf script: Process stat config event
      perf script: Add process_stat/process_stat_interval scripting interface
      perf script: Add stat default handlers
      perf script: Display stat events by default
      perf script: Add python support for stat events
      perf script: Add stat-cpi.py script

 tools/perf/Documentation/perf-stat.txt             |  24 +
 tools/perf/builtin-record.c                        |   2 +
 tools/perf/builtin-script.c                        | 143 ++++-
 tools/perf/builtin-stat.c                          | 579 +++++++++++++++------
 tools/perf/scripts/python/stat-cpi.py              |  74 +++
 tools/perf/tests/Build                             |   2 +
 tools/perf/tests/builtin-test.c                    |  20 +
 tools/perf/tests/cpumap.c                          |  39 ++
 tools/perf/tests/stat.c                            | 108 ++++
 tools/perf/tests/tests.h                           |   6 +
 tools/perf/tests/thread-map.c                      |  47 ++
 tools/perf/util/cpumap.c                           |  27 +
 tools/perf/util/cpumap.h                           |   3 +
 tools/perf/util/event.c                            | 170 ++++++
 tools/perf/util/event.h                            |  94 +++-
 tools/perf/util/evlist.c                           |  34 +-
 tools/perf/util/evlist.h                           |  14 +-
 tools/perf/util/evsel.h                            |   2 +-
 tools/perf/util/header.c                           |  49 +-
 tools/perf/util/header.h                           |   2 +
 .../util/scripting-engines/trace-event-python.c    | 113 +++-
 tools/perf/util/session.c                          | 123 +++++
 tools/perf/util/stat.c                             | 162 ++++++
 tools/perf/util/stat.h                             |  16 +
 tools/perf/util/thread_map.c                       |  27 +
 tools/perf/util/thread_map.h                       |   3 +
 tools/perf/util/tool.h                             |   7 +-
 tools/perf/util/trace-event.h                      |   4 +
 28 files changed, 1686 insertions(+), 208 deletions(-)
 create mode 100644 tools/perf/scripts/python/stat-cpi.py
 create mode 100644 tools/perf/tests/cpumap.c
 create mode 100644 tools/perf/tests/stat.c

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

* [PATCH 01/47] perf test: Check for refcnt in thread_map test
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
@ 2015-07-21 12:31 ` Jiri Olsa
  2015-07-21 17:26   ` Arnaldo Carvalho de Melo
  2015-07-29  8:10   ` [tip:perf/core] " tip-bot for Jiri Olsa
  2015-07-21 12:31 ` [PATCH 02/47] perf stat: Introduce struct perf_stat_config Jiri Olsa
                   ` (47 subsequent siblings)
  48 siblings, 2 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Checking also for refcnt in thread_map test.

Link: http://lkml.kernel.org/n/tip-6fege00q2h2ulx4296921evo@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/tests/thread-map.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/tools/perf/tests/thread-map.c b/tools/perf/tests/thread-map.c
index 5acf000939ea..138a0e3431fa 100644
--- a/tools/perf/tests/thread-map.c
+++ b/tools/perf/tests/thread-map.c
@@ -20,6 +20,8 @@ int test__thread_map(void)
 	TEST_ASSERT_VAL("wrong comm",
 			thread_map__comm(map, 0) &&
 			!strcmp(thread_map__comm(map, 0), "perf"));
+	TEST_ASSERT_VAL("wrong refcnt",
+			atomic_read(&map->refcnt) == 1);
 	thread_map__put(map);
 
 	/* test dummy pid */
@@ -33,6 +35,8 @@ int test__thread_map(void)
 	TEST_ASSERT_VAL("wrong comm",
 			thread_map__comm(map, 0) &&
 			!strcmp(thread_map__comm(map, 0), "dummy"));
+	TEST_ASSERT_VAL("wrong refcnt",
+			atomic_read(&map->refcnt) == 1);
 	thread_map__put(map);
 	return 0;
 }
-- 
2.4.3


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

* [PATCH 02/47] perf stat: Introduce struct perf_stat_config
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
  2015-07-21 12:31 ` [PATCH 01/47] perf test: Check for refcnt in thread_map test Jiri Olsa
@ 2015-07-21 12:31 ` Jiri Olsa
  2015-07-21 17:24   ` Arnaldo Carvalho de Melo
  2015-08-07  7:17   ` [tip:perf/core] " tip-bot for Jiri Olsa
  2015-07-21 12:31 ` [PATCH 03/47] perf stat: Move scale into " Jiri Olsa
                   ` (46 subsequent siblings)
  48 siblings, 2 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Moving aggr_mode into new struct. The point is to centralize
the base stat config so it could be used localy together with
other stat routines in other parts of perf code.

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

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index d99d850e1444..bafb830b1bd9 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -102,7 +102,6 @@ static struct target target = {
 static int			run_count			=  1;
 static bool			no_inherit			= false;
 static bool			scale				=  true;
-static enum aggr_mode		aggr_mode			= AGGR_GLOBAL;
 static volatile pid_t		child_pid			= -1;
 static bool			null_run			=  false;
 static int			detailed_run			=  0;
@@ -126,6 +125,10 @@ static int			(*aggr_get_id)(struct cpu_map *m, int cpu);
 
 static volatile int done = 0;
 
+static struct perf_stat_config stat_config = {
+	.aggr_mode	= AGGR_GLOBAL,
+};
+
 static inline void diff_timespec(struct timespec *r, struct timespec *a,
 				 struct timespec *b)
 {
@@ -230,7 +233,7 @@ process_counter_values(struct perf_evsel *evsel, int cpu, int thread,
 	if (skip)
 		count = &zero;
 
-	switch (aggr_mode) {
+	switch (stat_config.aggr_mode) {
 	case AGGR_THREAD:
 	case AGGR_CORE:
 	case AGGR_SOCKET:
@@ -238,7 +241,7 @@ process_counter_values(struct perf_evsel *evsel, int cpu, int thread,
 		if (!evsel->snapshot)
 			perf_evsel__compute_deltas(evsel, cpu, thread, count);
 		perf_counts_values__scale(count, scale, NULL);
-		if (aggr_mode == AGGR_NONE)
+		if (stat_config.aggr_mode == AGGR_NONE)
 			perf_stat__update_shadow_stats(evsel, count->values, cpu);
 		break;
 	case AGGR_GLOBAL:
@@ -291,7 +294,7 @@ static int process_counter(struct perf_evsel *counter)
 	if (ret)
 		return ret;
 
-	if (aggr_mode != AGGR_GLOBAL)
+	if (stat_config.aggr_mode != AGGR_GLOBAL)
 		return 0;
 
 	if (!counter->snapshot)
@@ -578,7 +581,7 @@ static void print_noise(struct perf_evsel *evsel, double avg)
 
 static void aggr_printout(struct perf_evsel *evsel, int id, int nr)
 {
-	switch (aggr_mode) {
+	switch (stat_config.aggr_mode) {
 	case AGGR_CORE:
 		fprintf(output, "S%d-C%*d%s%*d%s",
 			cpu_map__id_to_socket(id),
@@ -670,7 +673,7 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
 
 	aggr_printout(evsel, id, nr);
 
-	if (aggr_mode == AGGR_GLOBAL)
+	if (stat_config.aggr_mode == AGGR_GLOBAL)
 		cpu = 0;
 
 	fprintf(output, fmt, avg, csv_sep);
@@ -688,7 +691,8 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
 	if (csv_output || interval)
 		return;
 
-	perf_stat__print_shadow_stats(output, evsel, avg, cpu, aggr_mode);
+	perf_stat__print_shadow_stats(output, evsel, avg, cpu,
+				      stat_config.aggr_mode);
 }
 
 static void print_aggr(char *prefix)
@@ -909,7 +913,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) {
-		switch (aggr_mode) {
+		switch (stat_config.aggr_mode) {
 		case AGGR_SOCKET:
 			fprintf(output, "#           time socket cpus             counts %*s events\n", unit_width, "unit");
 			break;
@@ -985,7 +989,7 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)
 	else
 		print_header(argc, argv);
 
-	switch (aggr_mode) {
+	switch (stat_config.aggr_mode) {
 	case AGGR_CORE:
 	case AGGR_SOCKET:
 		print_aggr(prefix);
@@ -1064,7 +1068,7 @@ static int stat__set_big_num(const struct option *opt __maybe_unused,
 
 static int perf_stat_init_aggr_mode(void)
 {
-	switch (aggr_mode) {
+	switch (stat_config.aggr_mode) {
 	case AGGR_SOCKET:
 		if (cpu_map__build_socket_map(evsel_list->cpus, &aggr_map)) {
 			perror("cannot build socket map");
@@ -1286,7 +1290,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 			   stat__set_big_num),
 	OPT_STRING('C', "cpu", &target.cpu_list, "cpu",
 		    "list of cpus to monitor in system-wide"),
-	OPT_SET_UINT('A', "no-aggr", &aggr_mode,
+	OPT_SET_UINT('A', "no-aggr", &stat_config.aggr_mode,
 		    "disable CPU count aggregation", AGGR_NONE),
 	OPT_STRING('x', "field-separator", &csv_sep, "separator",
 		   "print counts with custom separator"),
@@ -1302,11 +1306,11 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 			"command to run after to the measured command"),
 	OPT_UINTEGER('I', "interval-print", &interval,
 		    "print counts at regular interval in ms (>= 100)"),
-	OPT_SET_UINT(0, "per-socket", &aggr_mode,
+	OPT_SET_UINT(0, "per-socket", &stat_config.aggr_mode,
 		     "aggregate counts per processor socket", AGGR_SOCKET),
-	OPT_SET_UINT(0, "per-core", &aggr_mode,
+	OPT_SET_UINT(0, "per-core", &stat_config.aggr_mode,
 		     "aggregate counts per physical processor core", AGGR_CORE),
-	OPT_SET_UINT(0, "per-thread", &aggr_mode,
+	OPT_SET_UINT(0, "per-thread", &stat_config.aggr_mode,
 		     "aggregate counts per thread", AGGR_THREAD),
 	OPT_UINTEGER('D', "delay", &initial_delay,
 		     "ms to wait before starting measurement after program start"),
@@ -1399,7 +1403,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 		run_count = 1;
 	}
 
-	if ((aggr_mode == AGGR_THREAD) && !target__has_task(&target)) {
+	if ((stat_config.aggr_mode == AGGR_THREAD) && !target__has_task(&target)) {
 		fprintf(stderr, "The --per-thread option is only available "
 			"when monitoring via -p -t options.\n");
 		parse_options_usage(NULL, options, "p", 1);
@@ -1411,7 +1415,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 	 * no_aggr, cgroup are for system-wide only
 	 * --per-thread is aggregated per thread, we dont mix it with cpu mode
 	 */
-	if (((aggr_mode != AGGR_GLOBAL && aggr_mode != AGGR_THREAD) || nr_cgroups) &&
+	if (((stat_config.aggr_mode != AGGR_GLOBAL &&
+	      stat_config.aggr_mode != AGGR_THREAD) || nr_cgroups) &&
 	    !target__has_cpu(&target)) {
 		fprintf(stderr, "both cgroup and no-aggregation "
 			"modes only available in system-wide mode\n");
@@ -1444,7 +1449,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 	 * Initialize thread_map with comm names,
 	 * so we could print it out on output.
 	 */
-	if (aggr_mode == AGGR_THREAD)
+	if (stat_config.aggr_mode == AGGR_THREAD)
 		thread_map__read_comms(evsel_list->threads);
 
 	if (interval && interval < 100) {
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 1cfbe0a980ac..078bee49ccad 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -50,6 +50,10 @@ struct perf_counts {
 	struct xyarray		  *values;
 };
 
+struct perf_stat_config {
+	enum aggr_mode	aggr_mode;
+};
+
 static inline struct perf_counts_values*
 perf_counts(struct perf_counts *counts, int cpu, int thread)
 {
-- 
2.4.3


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

* [PATCH 03/47] perf stat: Move scale into struct perf_stat_config
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
  2015-07-21 12:31 ` [PATCH 01/47] perf test: Check for refcnt in thread_map test Jiri Olsa
  2015-07-21 12:31 ` [PATCH 02/47] perf stat: Introduce struct perf_stat_config Jiri Olsa
@ 2015-07-21 12:31 ` Jiri Olsa
  2015-08-07  7:17   ` [tip:perf/core] perf stat: Move 'scale' " tip-bot for Jiri Olsa
  2015-07-21 12:31 ` [PATCH 04/47] perf stat: Move output " Jiri Olsa
                   ` (45 subsequent siblings)
  48 siblings, 1 reply; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Moving scale into struct perf_stat_config. The point is to centralize
the base stat config so it could be used localy together with
other stat routines in other parts of perf code.

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

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index bafb830b1bd9..3fb2865e519a 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -101,7 +101,6 @@ static struct target target = {
 
 static int			run_count			=  1;
 static bool			no_inherit			= false;
-static bool			scale				=  true;
 static volatile pid_t		child_pid			= -1;
 static bool			null_run			=  false;
 static int			detailed_run			=  0;
@@ -127,6 +126,7 @@ static volatile int done = 0;
 
 static struct perf_stat_config stat_config = {
 	.aggr_mode	= AGGR_GLOBAL,
+	.scale		= true,
 };
 
 static inline void diff_timespec(struct timespec *r, struct timespec *a,
@@ -151,7 +151,7 @@ static int create_perf_stat_counter(struct perf_evsel *evsel)
 {
 	struct perf_event_attr *attr = &evsel->attr;
 
-	if (scale)
+	if (stat_config.scale)
 		attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
 				    PERF_FORMAT_TOTAL_TIME_RUNNING;
 
@@ -240,13 +240,13 @@ process_counter_values(struct perf_evsel *evsel, int cpu, int thread,
 	case AGGR_NONE:
 		if (!evsel->snapshot)
 			perf_evsel__compute_deltas(evsel, cpu, thread, count);
-		perf_counts_values__scale(count, scale, NULL);
+		perf_counts_values__scale(count, stat_config.scale, NULL);
 		if (stat_config.aggr_mode == AGGR_NONE)
 			perf_stat__update_shadow_stats(evsel, count->values, cpu);
 		break;
 	case AGGR_GLOBAL:
 		aggr->val += count->val;
-		if (scale) {
+		if (stat_config.scale) {
 			aggr->ena += count->ena;
 			aggr->run += count->run;
 		}
@@ -299,7 +299,7 @@ static int process_counter(struct perf_evsel *counter)
 
 	if (!counter->snapshot)
 		perf_evsel__compute_deltas(counter, -1, -1, aggr);
-	perf_counts_values__scale(aggr, scale, &counter->counts->scaled);
+	perf_counts_values__scale(aggr, stat_config.scale, &counter->counts->scaled);
 
 	for (i = 0; i < 3; i++)
 		update_stats(&ps->res_stats[i], count[i]);
@@ -1274,7 +1274,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 		    "system-wide collection from all CPUs"),
 	OPT_BOOLEAN('g', "group", &group,
 		    "put the counters into a counter group"),
-	OPT_BOOLEAN('c', "scale", &scale, "scale/normalize counters"),
+	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,
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 078bee49ccad..0a1d83faa7b9 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -52,6 +52,7 @@ struct perf_counts {
 
 struct perf_stat_config {
 	enum aggr_mode	aggr_mode;
+	bool		scale;
 };
 
 static inline struct perf_counts_values*
-- 
2.4.3


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

* [PATCH 04/47] perf stat: Move output into struct perf_stat_config
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (2 preceding siblings ...)
  2015-07-21 12:31 ` [PATCH 03/47] perf stat: Move scale into " Jiri Olsa
@ 2015-07-21 12:31 ` Jiri Olsa
  2015-08-07  7:17   ` [tip:perf/core] perf stat: Move 'output' " tip-bot for Jiri Olsa
  2015-07-21 12:31 ` [PATCH 05/47] perf stat: Move interval " Jiri Olsa
                   ` (44 subsequent siblings)
  48 siblings, 1 reply; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Moving output into struct perf_stat_config. The point is to centralize
the base stat config so it could be used localy together with
other stat routines in other parts of perf code.

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

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 3fb2865e519a..e3ea8b67703d 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -110,7 +110,6 @@ static int			big_num_opt			=  -1;
 static const char		*csv_sep			= NULL;
 static bool			csv_output			= false;
 static bool			group				= false;
-static FILE			*output				= NULL;
 static const char		*pre_cmd			= NULL;
 static const char		*post_cmd			= NULL;
 static bool			sync_run			= false;
@@ -305,7 +304,7 @@ static int process_counter(struct perf_evsel *counter)
 		update_stats(&ps->res_stats[i], count[i]);
 
 	if (verbose) {
-		fprintf(output, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
+		fprintf(stat_config.output, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
 			perf_evsel__name(counter), count[0], count[1], count[2]);
 	}
 
@@ -548,13 +547,13 @@ static int run_perf_stat(int argc, const char **argv)
 static void print_running(u64 run, u64 ena)
 {
 	if (csv_output) {
-		fprintf(output, "%s%" PRIu64 "%s%.2f",
+		fprintf(stat_config.output, "%s%" PRIu64 "%s%.2f",
 					csv_sep,
 					run,
 					csv_sep,
 					ena ? 100.0 * run / ena : 100.0);
 	} else if (run != ena) {
-		fprintf(output, "  (%.2f%%)", 100.0 * run / ena);
+		fprintf(stat_config.output, "  (%.2f%%)", 100.0 * run / ena);
 	}
 }
 
@@ -563,9 +562,9 @@ static void print_noise_pct(double total, double avg)
 	double pct = rel_stddev_stats(total, avg);
 
 	if (csv_output)
-		fprintf(output, "%s%.2f%%", csv_sep, pct);
+		fprintf(stat_config.output, "%s%.2f%%", csv_sep, pct);
 	else if (pct)
-		fprintf(output, "  ( +-%6.2f%% )", pct);
+		fprintf(stat_config.output, "  ( +-%6.2f%% )", pct);
 }
 
 static void print_noise(struct perf_evsel *evsel, double avg)
@@ -583,7 +582,7 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr)
 {
 	switch (stat_config.aggr_mode) {
 	case AGGR_CORE:
-		fprintf(output, "S%d-C%*d%s%*d%s",
+		fprintf(stat_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),
@@ -593,7 +592,7 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr)
 			csv_sep);
 		break;
 	case AGGR_SOCKET:
-		fprintf(output, "S%*d%s%*d%s",
+		fprintf(stat_config.output, "S%*d%s%*d%s",
 			csv_output ? 0 : -5,
 			id,
 			csv_sep,
@@ -602,12 +601,12 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr)
 			csv_sep);
 			break;
 	case AGGR_NONE:
-		fprintf(output, "CPU%*d%s",
+		fprintf(stat_config.output, "CPU%*d%s",
 			csv_output ? 0 : -4,
 			perf_evsel__cpus(evsel)->map[id], csv_sep);
 		break;
 	case AGGR_THREAD:
-		fprintf(output, "%*s-%*d%s",
+		fprintf(stat_config.output, "%*s-%*d%s",
 			csv_output ? 0 : 16,
 			thread_map__comm(evsel->threads, id),
 			csv_output ? 0 : -8,
@@ -622,6 +621,7 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr)
 
 static void nsec_printout(int id, int nr, struct perf_evsel *evsel, double avg)
 {
+	FILE *output = stat_config.output;
 	double msecs = avg / 1e6;
 	const char *fmt_v, *fmt_n;
 	char name[25];
@@ -658,6 +658,7 @@ static void nsec_printout(int id, int nr, struct perf_evsel *evsel, double avg)
 
 static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
 {
+	FILE *output = stat_config.output;
 	double sc =  evsel->scale;
 	const char *fmt;
 	int cpu = cpu_map__id_to_cpu(id);
@@ -697,6 +698,7 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
 
 static void print_aggr(char *prefix)
 {
+	FILE *output = stat_config.output;
 	struct perf_evsel *counter;
 	int cpu, cpu2, s, s2, id, nr;
 	double uval;
@@ -765,6 +767,7 @@ static void print_aggr(char *prefix)
 
 static void print_aggr_thread(struct perf_evsel *counter, char *prefix)
 {
+	FILE *output = stat_config.output;
 	int nthreads = thread_map__nr(counter->threads);
 	int ncpus = cpu_map__nr(counter->cpus);
 	int cpu, thread;
@@ -803,6 +806,7 @@ static void print_aggr_thread(struct perf_evsel *counter, char *prefix)
  */
 static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
 {
+	FILE *output = stat_config.output;
 	struct perf_stat *ps = counter->priv;
 	double avg = avg_stats(&ps->res_stats[0]);
 	int scaled = counter->counts->scaled;
@@ -854,6 +858,7 @@ static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
  */
 static void print_counter(struct perf_evsel *counter, char *prefix)
 {
+	FILE *output = stat_config.output;
 	u64 ena, run, val;
 	double uval;
 	int cpu;
@@ -908,6 +913,7 @@ static void print_counter(struct perf_evsel *counter, char *prefix)
 
 static void print_interval(char *prefix, struct timespec *ts)
 {
+	FILE *output = stat_config.output;
 	static int num_print_interval;
 
 	sprintf(prefix, "%6lu.%09lu%s", ts->tv_sec, ts->tv_nsec, csv_sep);
@@ -938,6 +944,7 @@ static void print_interval(char *prefix, struct timespec *ts)
 
 static void print_header(int argc, const char **argv)
 {
+	FILE *output = stat_config.output;
 	int i;
 
 	fflush(stdout);
@@ -967,6 +974,8 @@ static void print_header(int argc, const char **argv)
 
 static void print_footer(void)
 {
+	FILE *output = stat_config.output;
+
 	if (!null_run)
 		fprintf(output, "\n");
 	fprintf(output, " %17.9f seconds time elapsed",
@@ -1013,7 +1022,7 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)
 	if (!interval && !csv_output)
 		print_footer();
 
-	fflush(output);
+	fflush(stat_config.output);
 }
 
 static volatile int signr = -1;
@@ -1322,6 +1331,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 	};
 	int status = -EINVAL, run_idx;
 	const char *mode;
+	FILE *output = stderr;
 
 	setlocale(LC_ALL, "");
 
@@ -1332,7 +1342,6 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 	argc = parse_options(argc, argv, options, stat_usage,
 		PARSE_OPT_STOP_AT_NON_OPTION);
 
-	output = stderr;
 	if (output_name && strcmp(output_name, "-"))
 		output = NULL;
 
@@ -1369,6 +1378,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 		}
 	}
 
+	stat_config.output = output;
+
 	if (csv_sep) {
 		csv_output = true;
 		if (!strcmp(csv_sep, "\\t"))
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 0a1d83faa7b9..ed0e05829cb0 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -53,6 +53,7 @@ struct perf_counts {
 struct perf_stat_config {
 	enum aggr_mode	aggr_mode;
 	bool		scale;
+	FILE		*output;
 };
 
 static inline struct perf_counts_values*
-- 
2.4.3


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

* [PATCH 05/47] perf stat: Move interval into struct perf_stat_config
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (3 preceding siblings ...)
  2015-07-21 12:31 ` [PATCH 04/47] perf stat: Move output " Jiri Olsa
@ 2015-07-21 12:31 ` Jiri Olsa
  2015-08-07  7:18   ` [tip:perf/core] perf stat: Move 'interval' " tip-bot for Jiri Olsa
  2015-07-21 12:31 ` [PATCH 06/47] perf stat: Pass struct perf_stat_config into process_counter Jiri Olsa
                   ` (43 subsequent siblings)
  48 siblings, 1 reply; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Moving interval into struct perf_stat_config. The point is to centralize
the base stat config so it could be used localy together with
other stat routines in other parts of perf code.

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

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index e3ea8b67703d..1bdfec8f5fe6 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -113,7 +113,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		interval			= 0;
 static unsigned int		initial_delay			= 0;
 static unsigned int		unit_width			= 4; /* strlen("unit") */
 static bool			forever				= false;
@@ -404,6 +403,7 @@ static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *inf
 
 static int __run_perf_stat(int argc, const char **argv)
 {
+	int interval = stat_config.interval;
 	char msg[512];
 	unsigned long long t0, t1;
 	struct perf_evsel *counter;
@@ -646,7 +646,7 @@ static void nsec_printout(int id, int nr, struct perf_evsel *evsel, double avg)
 	if (evsel->cgrp)
 		fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
 
-	if (csv_output || interval)
+	if (csv_output || stat_config.interval)
 		return;
 
 	if (perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK))
@@ -689,7 +689,7 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
 	if (evsel->cgrp)
 		fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
 
-	if (csv_output || interval)
+	if (csv_output || stat_config.interval)
 		return;
 
 	perf_stat__print_shadow_stats(output, evsel, avg, cpu,
@@ -990,6 +990,7 @@ static void print_footer(void)
 
 static void print_counters(struct timespec *ts, int argc, const char **argv)
 {
+	int interval = stat_config.interval;
 	struct perf_evsel *counter;
 	char buf[64], *prefix = NULL;
 
@@ -1029,7 +1030,7 @@ static volatile int signr = -1;
 
 static void skip_signal(int signo)
 {
-	if ((child_pid == -1) || interval)
+	if ((child_pid == -1) || stat_config.interval)
 		done = 1;
 
 	signr = signo;
@@ -1313,7 +1314,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 			"command to run prior to the measured command"),
 	OPT_STRING(0, "post", &post_cmd, "command",
 			"command to run after to the measured command"),
-	OPT_UINTEGER('I', "interval-print", &interval,
+	OPT_UINTEGER('I', "interval-print", &stat_config.interval,
 		    "print counts at regular interval in ms (>= 100)"),
 	OPT_SET_UINT(0, "per-socket", &stat_config.aggr_mode,
 		     "aggregate counts per processor socket", AGGR_SOCKET),
@@ -1332,6 +1333,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 	int status = -EINVAL, run_idx;
 	const char *mode;
 	FILE *output = stderr;
+	unsigned int interval;
 
 	setlocale(LC_ALL, "");
 
@@ -1342,6 +1344,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 	argc = parse_options(argc, argv, options, stat_usage,
 		PARSE_OPT_STOP_AT_NON_OPTION);
 
+	interval = stat_config.interval;
+
 	if (output_name && strcmp(output_name, "-"))
 		output = NULL;
 
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index ed0e05829cb0..1da706d848fb 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -54,6 +54,7 @@ struct perf_stat_config {
 	enum aggr_mode	aggr_mode;
 	bool		scale;
 	FILE		*output;
+	unsigned int	interval;
 };
 
 static inline struct perf_counts_values*
-- 
2.4.3


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

* [PATCH 06/47] perf stat: Pass struct perf_stat_config into process_counter
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (4 preceding siblings ...)
  2015-07-21 12:31 ` [PATCH 05/47] perf stat: Move interval " Jiri Olsa
@ 2015-07-21 12:31 ` Jiri Olsa
  2015-08-07  7:18   ` [tip:perf/core] perf stat: Pass 'struct perf_stat_config' into process_counter() tip-bot for Jiri Olsa
  2015-07-21 12:31 ` [PATCH 07/47] perf stat: Move counter processing code into stat object Jiri Olsa
                   ` (42 subsequent siblings)
  48 siblings, 1 reply; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Passing struct perf_stat_config into process_counter, so we could
make process_counter global and use it from other places.

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

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 1bdfec8f5fe6..5a781718c09f 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -216,7 +216,8 @@ static int check_per_pkg(struct perf_evsel *counter, int cpu, bool *skip)
 }
 
 static int
-process_counter_values(struct perf_evsel *evsel, int cpu, int thread,
+process_counter_values(struct perf_stat_config *config, struct perf_evsel *evsel,
+		       int cpu, int thread,
 		       struct perf_counts_values *count)
 {
 	struct perf_counts_values *aggr = &evsel->counts->aggr;
@@ -231,20 +232,20 @@ process_counter_values(struct perf_evsel *evsel, int cpu, int thread,
 	if (skip)
 		count = &zero;
 
-	switch (stat_config.aggr_mode) {
+	switch (config->aggr_mode) {
 	case AGGR_THREAD:
 	case AGGR_CORE:
 	case AGGR_SOCKET:
 	case AGGR_NONE:
 		if (!evsel->snapshot)
 			perf_evsel__compute_deltas(evsel, cpu, thread, count);
-		perf_counts_values__scale(count, stat_config.scale, NULL);
-		if (stat_config.aggr_mode == AGGR_NONE)
+		perf_counts_values__scale(count, config->scale, NULL);
+		if (config->aggr_mode == AGGR_NONE)
 			perf_stat__update_shadow_stats(evsel, count->values, cpu);
 		break;
 	case AGGR_GLOBAL:
 		aggr->val += count->val;
-		if (stat_config.scale) {
+		if (config->scale) {
 			aggr->ena += count->ena;
 			aggr->run += count->run;
 		}
@@ -255,7 +256,8 @@ process_counter_values(struct perf_evsel *evsel, int cpu, int thread,
 	return 0;
 }
 
-static int process_counter_maps(struct perf_evsel *counter)
+static int process_counter_maps(struct perf_stat_config *config,
+				struct perf_evsel *counter)
 {
 	int nthreads = thread_map__nr(counter->threads);
 	int ncpus = perf_evsel__nr_cpus(counter);
@@ -266,7 +268,7 @@ static int process_counter_maps(struct perf_evsel *counter)
 
 	for (thread = 0; thread < nthreads; thread++) {
 		for (cpu = 0; cpu < ncpus; cpu++) {
-			if (process_counter_values(counter, cpu, thread,
+			if (process_counter_values(config, counter, cpu, thread,
 						   perf_counts(counter->counts, cpu, thread)))
 				return -1;
 		}
@@ -275,7 +277,8 @@ static int process_counter_maps(struct perf_evsel *counter)
 	return 0;
 }
 
-static int process_counter(struct perf_evsel *counter)
+static int process_counter(struct perf_stat_config *config,
+			   struct perf_evsel *counter)
 {
 	struct perf_counts_values *aggr = &counter->counts->aggr;
 	struct perf_stat *ps = counter->priv;
@@ -288,22 +291,22 @@ static int process_counter(struct perf_evsel *counter)
 	if (counter->per_pkg)
 		zero_per_pkg(counter);
 
-	ret = process_counter_maps(counter);
+	ret = process_counter_maps(&stat_config, counter);
 	if (ret)
 		return ret;
 
-	if (stat_config.aggr_mode != AGGR_GLOBAL)
+	if (config->aggr_mode != AGGR_GLOBAL)
 		return 0;
 
 	if (!counter->snapshot)
 		perf_evsel__compute_deltas(counter, -1, -1, aggr);
-	perf_counts_values__scale(aggr, stat_config.scale, &counter->counts->scaled);
+	perf_counts_values__scale(aggr, config->scale, &counter->counts->scaled);
 
 	for (i = 0; i < 3; i++)
 		update_stats(&ps->res_stats[i], count[i]);
 
 	if (verbose) {
-		fprintf(stat_config.output, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
+		fprintf(config->output, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
 			perf_evsel__name(counter), count[0], count[1], count[2]);
 	}
 
@@ -352,7 +355,7 @@ static void read_counters(bool close_counters)
 		if (read_counter(counter))
 			pr_warning("failed to read counter %s\n", counter->name);
 
-		if (process_counter(counter))
+		if (process_counter(&stat_config, counter))
 			pr_warning("failed to process counter %s\n", counter->name);
 
 		if (close_counters) {
-- 
2.4.3


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

* [PATCH 07/47] perf stat: Move counter processing code into stat object
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (5 preceding siblings ...)
  2015-07-21 12:31 ` [PATCH 06/47] perf stat: Pass struct perf_stat_config into process_counter Jiri Olsa
@ 2015-07-21 12:31 ` Jiri Olsa
  2015-08-07  7:18   ` [tip:perf/core] " tip-bot for Jiri Olsa
  2015-07-21 12:31 ` [PATCH 08/47] perf tools: Use bool instead of target argument in perf_evlist__propagate_maps Jiri Olsa
                   ` (41 subsequent siblings)
  48 siblings, 1 reply; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Moving counter processing code into stat object
as perf_stat__process_counter.

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

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 5a781718c09f..a054ddc0b2a0 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -179,145 +179,6 @@ static inline int nsec_counter(struct perf_evsel *evsel)
 	return 0;
 }
 
-static void zero_per_pkg(struct perf_evsel *counter)
-{
-	if (counter->per_pkg_mask)
-		memset(counter->per_pkg_mask, 0, MAX_NR_CPUS);
-}
-
-static int check_per_pkg(struct perf_evsel *counter, int cpu, bool *skip)
-{
-	unsigned long *mask = counter->per_pkg_mask;
-	struct cpu_map *cpus = perf_evsel__cpus(counter);
-	int s;
-
-	*skip = false;
-
-	if (!counter->per_pkg)
-		return 0;
-
-	if (cpu_map__empty(cpus))
-		return 0;
-
-	if (!mask) {
-		mask = zalloc(MAX_NR_CPUS);
-		if (!mask)
-			return -ENOMEM;
-
-		counter->per_pkg_mask = mask;
-	}
-
-	s = cpu_map__get_socket(cpus, cpu);
-	if (s < 0)
-		return -1;
-
-	*skip = test_and_set_bit(s, mask) == 1;
-	return 0;
-}
-
-static int
-process_counter_values(struct perf_stat_config *config, struct perf_evsel *evsel,
-		       int cpu, int thread,
-		       struct perf_counts_values *count)
-{
-	struct perf_counts_values *aggr = &evsel->counts->aggr;
-	static struct perf_counts_values zero;
-	bool skip = false;
-
-	if (check_per_pkg(evsel, cpu, &skip)) {
-		pr_err("failed to read per-pkg counter\n");
-		return -1;
-	}
-
-	if (skip)
-		count = &zero;
-
-	switch (config->aggr_mode) {
-	case AGGR_THREAD:
-	case AGGR_CORE:
-	case AGGR_SOCKET:
-	case AGGR_NONE:
-		if (!evsel->snapshot)
-			perf_evsel__compute_deltas(evsel, cpu, thread, count);
-		perf_counts_values__scale(count, config->scale, NULL);
-		if (config->aggr_mode == AGGR_NONE)
-			perf_stat__update_shadow_stats(evsel, count->values, cpu);
-		break;
-	case AGGR_GLOBAL:
-		aggr->val += count->val;
-		if (config->scale) {
-			aggr->ena += count->ena;
-			aggr->run += count->run;
-		}
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-static int process_counter_maps(struct perf_stat_config *config,
-				struct perf_evsel *counter)
-{
-	int nthreads = thread_map__nr(counter->threads);
-	int ncpus = perf_evsel__nr_cpus(counter);
-	int cpu, thread;
-
-	if (counter->system_wide)
-		nthreads = 1;
-
-	for (thread = 0; thread < nthreads; thread++) {
-		for (cpu = 0; cpu < ncpus; cpu++) {
-			if (process_counter_values(config, counter, cpu, thread,
-						   perf_counts(counter->counts, cpu, thread)))
-				return -1;
-		}
-	}
-
-	return 0;
-}
-
-static int process_counter(struct perf_stat_config *config,
-			   struct perf_evsel *counter)
-{
-	struct perf_counts_values *aggr = &counter->counts->aggr;
-	struct perf_stat *ps = counter->priv;
-	u64 *count = counter->counts->aggr.values;
-	int i, ret;
-
-	aggr->val = aggr->ena = aggr->run = 0;
-	init_stats(ps->res_stats);
-
-	if (counter->per_pkg)
-		zero_per_pkg(counter);
-
-	ret = process_counter_maps(&stat_config, counter);
-	if (ret)
-		return ret;
-
-	if (config->aggr_mode != AGGR_GLOBAL)
-		return 0;
-
-	if (!counter->snapshot)
-		perf_evsel__compute_deltas(counter, -1, -1, aggr);
-	perf_counts_values__scale(aggr, config->scale, &counter->counts->scaled);
-
-	for (i = 0; i < 3; i++)
-		update_stats(&ps->res_stats[i], count[i]);
-
-	if (verbose) {
-		fprintf(config->output, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
-			perf_evsel__name(counter), count[0], count[1], count[2]);
-	}
-
-	/*
-	 * Save the full runtime - to allow normalization during printout:
-	 */
-	perf_stat__update_shadow_stats(counter, count, 0);
-
-	return 0;
-}
-
 /*
  * Read out the results of a single counter:
  * do not aggregate counts across CPUs in system-wide mode
@@ -355,7 +216,7 @@ static void read_counters(bool close_counters)
 		if (read_counter(counter))
 			pr_warning("failed to read counter %s\n", counter->name);
 
-		if (process_counter(&stat_config, counter))
+		if (perf_stat_process_counter(&stat_config, counter))
 			pr_warning("failed to process counter %s\n", counter->name);
 
 		if (close_counters) {
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index f2a0d1521e26..c5c709cdc3ce 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -238,3 +238,142 @@ void perf_evlist__reset_stats(struct perf_evlist *evlist)
 		perf_evsel__reset_counts(evsel);
 	}
 }
+
+static void zero_per_pkg(struct perf_evsel *counter)
+{
+	if (counter->per_pkg_mask)
+		memset(counter->per_pkg_mask, 0, MAX_NR_CPUS);
+}
+
+static int check_per_pkg(struct perf_evsel *counter, int cpu, bool *skip)
+{
+	unsigned long *mask = counter->per_pkg_mask;
+	struct cpu_map *cpus = perf_evsel__cpus(counter);
+	int s;
+
+	*skip = false;
+
+	if (!counter->per_pkg)
+		return 0;
+
+	if (cpu_map__empty(cpus))
+		return 0;
+
+	if (!mask) {
+		mask = zalloc(MAX_NR_CPUS);
+		if (!mask)
+			return -ENOMEM;
+
+		counter->per_pkg_mask = mask;
+	}
+
+	s = cpu_map__get_socket(cpus, cpu);
+	if (s < 0)
+		return -1;
+
+	*skip = test_and_set_bit(s, mask) == 1;
+	return 0;
+}
+
+static int
+process_counter_values(struct perf_stat_config *config, struct perf_evsel *evsel,
+		       int cpu, int thread,
+		       struct perf_counts_values *count)
+{
+	struct perf_counts_values *aggr = &evsel->counts->aggr;
+	static struct perf_counts_values zero;
+	bool skip = false;
+
+	if (check_per_pkg(evsel, cpu, &skip)) {
+		pr_err("failed to read per-pkg counter\n");
+		return -1;
+	}
+
+	if (skip)
+		count = &zero;
+
+	switch (config->aggr_mode) {
+	case AGGR_THREAD:
+	case AGGR_CORE:
+	case AGGR_SOCKET:
+	case AGGR_NONE:
+		if (!evsel->snapshot)
+			perf_evsel__compute_deltas(evsel, cpu, thread, count);
+		perf_counts_values__scale(count, config->scale, NULL);
+		if (config->aggr_mode == AGGR_NONE)
+			perf_stat__update_shadow_stats(evsel, count->values, cpu);
+		break;
+	case AGGR_GLOBAL:
+		aggr->val += count->val;
+		if (config->scale) {
+			aggr->ena += count->ena;
+			aggr->run += count->run;
+		}
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int process_counter_maps(struct perf_stat_config *config,
+				struct perf_evsel *counter)
+{
+	int nthreads = thread_map__nr(counter->threads);
+	int ncpus = perf_evsel__nr_cpus(counter);
+	int cpu, thread;
+
+	if (counter->system_wide)
+		nthreads = 1;
+
+	for (thread = 0; thread < nthreads; thread++) {
+		for (cpu = 0; cpu < ncpus; cpu++) {
+			if (process_counter_values(config, counter, cpu, thread,
+						   perf_counts(counter->counts, cpu, thread)))
+				return -1;
+		}
+	}
+
+	return 0;
+}
+
+int perf_stat_process_counter(struct perf_stat_config *config,
+			      struct perf_evsel *counter)
+{
+	struct perf_counts_values *aggr = &counter->counts->aggr;
+	struct perf_stat *ps = counter->priv;
+	u64 *count = counter->counts->aggr.values;
+	int i, ret;
+
+	aggr->val = aggr->ena = aggr->run = 0;
+	init_stats(ps->res_stats);
+
+	if (counter->per_pkg)
+		zero_per_pkg(counter);
+
+	ret = process_counter_maps(config, counter);
+	if (ret)
+		return ret;
+
+	if (config->aggr_mode != AGGR_GLOBAL)
+		return 0;
+
+	if (!counter->snapshot)
+		perf_evsel__compute_deltas(counter, -1, -1, aggr);
+	perf_counts_values__scale(aggr, config->scale, &counter->counts->scaled);
+
+	for (i = 0; i < 3; i++)
+		update_stats(&ps->res_stats[i], count[i]);
+
+	if (verbose) {
+		fprintf(config->output, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
+			perf_evsel__name(counter), count[0], count[1], count[2]);
+	}
+
+	/*
+	 * Save the full runtime - to allow normalization during printout:
+	 */
+	perf_stat__update_shadow_stats(counter, count, 0);
+
+	return 0;
+}
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 1da706d848fb..0b897b083682 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -116,4 +116,7 @@ int perf_evsel__alloc_stats(struct perf_evsel *evsel, bool alloc_raw);
 int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw);
 void perf_evlist__free_stats(struct perf_evlist *evlist);
 void perf_evlist__reset_stats(struct perf_evlist *evlist);
+
+int perf_stat_process_counter(struct perf_stat_config *config,
+			      struct perf_evsel *counter);
 #endif
-- 
2.4.3


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

* [PATCH 08/47] perf tools: Use bool instead of target argument in perf_evlist__propagate_maps
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (6 preceding siblings ...)
  2015-07-21 12:31 ` [PATCH 07/47] perf stat: Move counter processing code into stat object Jiri Olsa
@ 2015-07-21 12:31 ` Jiri Olsa
  2015-07-29  8:10   ` [tip:perf/core] perf evlist: Use bool instead of target argument in propagate_maps() tip-bot for Jiri Olsa
  2015-07-21 12:31 ` [PATCH 09/47] perf tools: Tolerate NULL maps in perf_evlist__propagate_maps Jiri Olsa
                   ` (40 subsequent siblings)
  48 siblings, 1 reply; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

We need only bool info wether user defined her own set of cpus.
Switching target argument to bool so it could be used from
places without target object defined in following patches.

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

diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index f7d9c77ee31b..63bc24dbf03b 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -1102,7 +1102,7 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
 }
 
 static int perf_evlist__propagate_maps(struct perf_evlist *evlist,
-				       struct target *target)
+				       bool has_user_cpus)
 {
 	struct perf_evsel *evsel;
 
@@ -1111,10 +1111,10 @@ static int perf_evlist__propagate_maps(struct perf_evlist *evlist,
 		 * We already have cpus for evsel (via PMU sysfs) so
 		 * keep it, if there's no target cpu list defined.
 		 */
-		if (evsel->cpus && target->cpu_list)
+		if (evsel->cpus && has_user_cpus)
 			cpu_map__put(evsel->cpus);
 
-		if (!evsel->cpus || target->cpu_list)
+		if (!evsel->cpus || has_user_cpus)
 			evsel->cpus = cpu_map__get(evlist->cpus);
 
 		evsel->threads = thread_map__get(evlist->threads);
@@ -1142,7 +1142,7 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)
 	if (evlist->cpus == NULL)
 		goto out_delete_threads;
 
-	return perf_evlist__propagate_maps(evlist, target);
+	return perf_evlist__propagate_maps(evlist, !!target->cpu_list);
 
 out_delete_threads:
 	thread_map__put(evlist->threads);
-- 
2.4.3


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

* [PATCH 09/47] perf tools: Tolerate NULL maps in perf_evlist__propagate_maps
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (7 preceding siblings ...)
  2015-07-21 12:31 ` [PATCH 08/47] perf tools: Use bool instead of target argument in perf_evlist__propagate_maps Jiri Olsa
@ 2015-07-21 12:31 ` Jiri Olsa
  2015-07-21 17:31   ` Arnaldo Carvalho de Melo
  2015-07-29  8:11   ` [tip:perf/core] perf evlist: Tolerate NULL maps in propagate_maps tip-bot for Jiri Olsa
  2015-07-21 12:31 ` [PATCH 10/47] perf tools: Force perf_evlist__set_maps to propagate maps through events Jiri Olsa
                   ` (39 subsequent siblings)
  48 siblings, 2 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Tolerating NULL maps in perf_evlist__propagate_maps,
so we dont need to pass evlist with both cpus and threads
maps defined.

Link: http://lkml.kernel.org/n/tip-y15hjmv6uu8b6gyhkz5v41rw@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/evlist.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 63bc24dbf03b..f1714bedd5de 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -1119,7 +1119,8 @@ static int perf_evlist__propagate_maps(struct perf_evlist *evlist,
 
 		evsel->threads = thread_map__get(evlist->threads);
 
-		if (!evsel->cpus || !evsel->threads)
+		if ((evlist->cpus && !evsel->cpus) ||
+		    (evlist->threads && !evsel->threads))
 			return -ENOMEM;
 	}
 
-- 
2.4.3


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

* [PATCH 10/47] perf tools: Force perf_evlist__set_maps to propagate maps through events
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (8 preceding siblings ...)
  2015-07-21 12:31 ` [PATCH 09/47] perf tools: Tolerate NULL maps in perf_evlist__propagate_maps Jiri Olsa
@ 2015-07-21 12:31 ` Jiri Olsa
  2015-07-21 17:25   ` Arnaldo Carvalho de Melo
  2015-07-29  8:10   ` [tip:perf/core] perf evlist: " tip-bot for Jiri Olsa
  2015-07-21 12:31 ` [PATCH 11/47] perf tools: Use argv style storage for cmdline feature data Jiri Olsa
                   ` (38 subsequent siblings)
  48 siblings, 2 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Forcing perf_evlist__set_maps to propagate maps through events,
so cpu/thread maps get set within evlist.

Link: http://lkml.kernel.org/n/tip-0oqwhvjdr3jgfzkbd3qee5o0@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/evlist.c | 17 +++++++++++++++++
 tools/perf/util/evlist.h | 11 +++--------
 2 files changed, 20 insertions(+), 8 deletions(-)

diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index f1714bedd5de..3b9f411a6b46 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -1151,6 +1151,23 @@ out_delete_threads:
 	return -1;
 }
 
+int perf_evlist__set_maps(struct perf_evlist *evlist,
+			  struct cpu_map *cpus,
+			  struct thread_map *threads)
+{
+	if (evlist->cpus)
+		cpu_map__put(evlist->cpus);
+
+	evlist->cpus = cpus;
+
+	if (evlist->threads)
+		thread_map__put(evlist->threads);
+
+	evlist->threads = threads;
+
+	return perf_evlist__propagate_maps(evlist, false);
+}
+
 int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **err_evsel)
 {
 	struct perf_evsel *evsel;
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 037633c1da9d..406a8216a51e 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -152,14 +152,9 @@ int perf_evlist__enable_event_idx(struct perf_evlist *evlist,
 void perf_evlist__set_selected(struct perf_evlist *evlist,
 			       struct perf_evsel *evsel);
 
-static inline void perf_evlist__set_maps(struct perf_evlist *evlist,
-					 struct cpu_map *cpus,
-					 struct thread_map *threads)
-{
-	evlist->cpus	= cpus;
-	evlist->threads	= threads;
-}
-
+int perf_evlist__set_maps(struct perf_evlist *evlist,
+			  struct cpu_map *cpus,
+			  struct thread_map *threads);
 int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target);
 int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **err_evsel);
 
-- 
2.4.3


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

* [PATCH 11/47] perf tools: Use argv style storage for cmdline feature data
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (9 preceding siblings ...)
  2015-07-21 12:31 ` [PATCH 10/47] perf tools: Force perf_evlist__set_maps to propagate maps through events Jiri Olsa
@ 2015-07-21 12:31 ` Jiri Olsa
  2015-07-21 17:29   ` Arnaldo Carvalho de Melo
  2015-07-29  8:11   ` [tip:perf/core] perf header: " tip-bot for Jiri Olsa
  2015-07-21 12:31 ` [PATCH 12/47] perf tools: Add thread_map event Jiri Olsa
                   ` (37 subsequent siblings)
  48 siblings, 2 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

We will reuse argv style data in following change to display
counters header showing monitored command line.

Link: http://lkml.kernel.org/n/tip-qu64zmm5zbpbkuybusnkg4gl@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/header.c  | 35 ++++++++++++++++++++---------------
 tools/perf/util/header.h  |  1 +
 tools/perf/util/session.c |  1 +
 3 files changed, 22 insertions(+), 15 deletions(-)

diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 03ace57a800c..179b2bdd157d 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -923,17 +923,13 @@ static void print_cmdline(struct perf_header *ph, int fd __maybe_unused,
 			  FILE *fp)
 {
 	int nr, i;
-	char *str;
 
 	nr = ph->env.nr_cmdline;
-	str = ph->env.cmdline;
 
 	fprintf(fp, "# cmdline : ");
 
-	for (i = 0; i < nr; i++) {
-		fprintf(fp, "%s ", str);
-		str += strlen(str) + 1;
-	}
+	for (i = 0; i < nr; i++)
+		fprintf(fp, "%s ", ph->env.cmdline_argv[i]);
 	fputc('\n', fp);
 }
 
@@ -1541,14 +1537,13 @@ process_event_desc(struct perf_file_section *section __maybe_unused,
 	return 0;
 }
 
-static int process_cmdline(struct perf_file_section *section __maybe_unused,
+static int process_cmdline(struct perf_file_section *section,
 			   struct perf_header *ph, int fd,
 			   void *data __maybe_unused)
 {
 	ssize_t ret;
-	char *str;
-	u32 nr, i;
-	struct strbuf sb;
+	char *str, *cmdline = NULL, **argv = NULL;
+	u32 nr, i, len = 0;
 
 	ret = readn(fd, &nr, sizeof(nr));
 	if (ret != sizeof(nr))
@@ -1558,22 +1553,32 @@ static int process_cmdline(struct perf_file_section *section __maybe_unused,
 		nr = bswap_32(nr);
 
 	ph->env.nr_cmdline = nr;
-	strbuf_init(&sb, 128);
+
+	cmdline = zalloc(section->size + nr + 1);
+	if (!cmdline)
+		return -1;
+
+	argv = zalloc(sizeof(char *) * (nr + 1));
+	if (!argv)
+		goto error;
 
 	for (i = 0; i < nr; i++) {
 		str = do_read_string(fd, ph);
 		if (!str)
 			goto error;
 
-		/* include a NULL character at the end */
-		strbuf_add(&sb, str, strlen(str) + 1);
+		argv[i] = cmdline + len;
+		memcpy(argv[i], str, strlen(str) + 1);
+		len += strlen(str) + 1;
 		free(str);
 	}
-	ph->env.cmdline = strbuf_detach(&sb, NULL);
+	ph->env.cmdline = cmdline;
+	ph->env.cmdline_argv = (const char **) argv;
 	return 0;
 
 error:
-	strbuf_release(&sb);
+	free(argv);
+	free(cmdline);
 	return -1;
 }
 
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index d4d57962c591..9b53b6525ce8 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -84,6 +84,7 @@ struct perf_session_env {
 	int			nr_pmu_mappings;
 	int			nr_groups;
 	char			*cmdline;
+	const char		**cmdline_argv;
 	char			*sibling_cores;
 	char			*sibling_threads;
 	char			*numa_nodes;
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index ed9dc2555ec7..fb1d525ca3d0 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -180,6 +180,7 @@ static void perf_session_env__delete(struct perf_session_env *env)
 	zfree(&env->cpuid);
 
 	zfree(&env->cmdline);
+	zfree(&env->cmdline_argv);
 	zfree(&env->sibling_cores);
 	zfree(&env->sibling_threads);
 	zfree(&env->numa_nodes);
-- 
2.4.3


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

* [PATCH 12/47] perf tools: Add thread_map event
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (10 preceding siblings ...)
  2015-07-21 12:31 ` [PATCH 11/47] perf tools: Use argv style storage for cmdline feature data Jiri Olsa
@ 2015-07-21 12:31 ` Jiri Olsa
  2015-07-21 12:31 ` [PATCH 13/47] perf tools: Add thread_map event sythesize function Jiri Olsa
                   ` (36 subsequent siblings)
  48 siblings, 0 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Adding thread_map event to pass/store thread maps.

Link: http://lkml.kernel.org/n/tip-2l07qyf3buhnt83q4ezqz5sj@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/event.c   |  1 +
 tools/perf/util/event.h   | 13 +++++++++++++
 tools/perf/util/session.c | 26 ++++++++++++++++++++++++++
 tools/perf/util/tool.h    |  3 ++-
 4 files changed, 42 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 67a977e5d0ab..1ff4a0bb0feb 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -35,6 +35,7 @@ static const char *perf_event__names[] = {
 	[PERF_RECORD_AUXTRACE_INFO]		= "AUXTRACE_INFO",
 	[PERF_RECORD_AUXTRACE]			= "AUXTRACE",
 	[PERF_RECORD_AUXTRACE_ERROR]		= "AUXTRACE_ERROR",
+	[PERF_RECORD_THREAD_MAP]		= "THREAD_MAP",
 };
 
 const char *perf_event__name(unsigned int id)
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index c53f36384b64..64dc752f3589 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -225,6 +225,7 @@ enum perf_user_event_type { /* above any possible kernel type */
 	PERF_RECORD_AUXTRACE_INFO		= 70,
 	PERF_RECORD_AUXTRACE			= 71,
 	PERF_RECORD_AUXTRACE_ERROR		= 72,
+	PERF_RECORD_THREAD_MAP			= 73,
 	PERF_RECORD_HEADER_MAX
 };
 
@@ -348,6 +349,17 @@ struct itrace_start_event {
 	u32 pid, tid;
 };
 
+struct thread_map_data_event {
+	u64	pid;
+	char	comm[16];
+};
+
+struct thread_map_event {
+	struct perf_event_header	header;
+	u64				nr;
+	struct thread_map_data_event	data[];
+};
+
 union perf_event {
 	struct perf_event_header	header;
 	struct mmap_event		mmap;
@@ -369,6 +381,7 @@ union perf_event {
 	struct auxtrace_error_event	auxtrace_error;
 	struct aux_event		aux;
 	struct itrace_start_event	itrace_start;
+	struct thread_map_event		thread_map;
 };
 
 void perf_event__print_totals(void);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index fb1d525ca3d0..e20cd50a9a8f 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -311,6 +311,16 @@ int process_event_auxtrace_error_stub(struct perf_tool *tool __maybe_unused,
 	return 0;
 }
 
+
+static
+int process_event_thread_map_stub(struct perf_tool *tool __maybe_unused,
+				  union perf_event *event __maybe_unused,
+				  struct perf_session *session __maybe_unused)
+{
+	dump_printf(": unhandled!\n");
+	return 0;
+}
+
 void perf_tool__fill_defaults(struct perf_tool *tool)
 {
 	if (tool->sample == NULL)
@@ -359,6 +369,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
 		tool->auxtrace = process_event_auxtrace_stub;
 	if (tool->auxtrace_error == NULL)
 		tool->auxtrace_error = process_event_auxtrace_error_stub;
+	if (tool->thread_map == NULL)
+		tool->thread_map = process_event_thread_map_stub;
 }
 
 static void swap_sample_id_all(union perf_event *event, void *data)
@@ -616,6 +628,17 @@ static void perf_event__auxtrace_error_swap(union perf_event *event,
 	event->auxtrace_error.ip   = bswap_64(event->auxtrace_error.ip);
 }
 
+static void perf_event__thread_map_swap(union perf_event *event,
+					bool sample_id_all __maybe_unused)
+{
+	unsigned i;
+
+	event->thread_map.nr = bswap_64(event->thread_map.nr);
+
+	for (i = 0; i < event->thread_map.nr; i++)
+		event->thread_map.data[i].pid = bswap_64(event->thread_map.data[i].pid);
+}
+
 typedef void (*perf_event__swap_op)(union perf_event *event,
 				    bool sample_id_all);
 
@@ -641,6 +664,7 @@ static perf_event__swap_op perf_event__swap_ops[] = {
 	[PERF_RECORD_AUXTRACE_INFO]	  = perf_event__auxtrace_info_swap,
 	[PERF_RECORD_AUXTRACE]		  = perf_event__auxtrace_swap,
 	[PERF_RECORD_AUXTRACE_ERROR]	  = perf_event__auxtrace_error_swap,
+	[PERF_RECORD_THREAD_MAP]	  = perf_event__thread_map_swap,
 	[PERF_RECORD_HEADER_MAX]	  = NULL,
 };
 
@@ -1163,6 +1187,8 @@ static s64 perf_session__process_user_event(struct perf_session *session,
 	case PERF_RECORD_AUXTRACE_ERROR:
 		perf_session__auxtrace_error_inc(session, event);
 		return tool->auxtrace_error(tool, event, session);
+	case PERF_RECORD_THREAD_MAP:
+		return tool->thread_map(tool, event, session);
 	default:
 		return -EINVAL;
 	}
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index c307dd438286..cbaffbeb5b18 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -54,7 +54,8 @@ struct perf_tool {
 	event_op2	build_id,
 			id_index,
 			auxtrace_info,
-			auxtrace_error;
+			auxtrace_error,
+			thread_map;
 	event_op3	auxtrace;
 	bool		ordered_events;
 	bool		ordering_requires_timestamps;
-- 
2.4.3


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

* [PATCH 13/47] perf tools: Add thread_map event sythesize function
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (11 preceding siblings ...)
  2015-07-21 12:31 ` [PATCH 12/47] perf tools: Add thread_map event Jiri Olsa
@ 2015-07-21 12:31 ` Jiri Olsa
  2015-07-21 12:31 ` [PATCH 14/47] perf tools: Add thread_map__new_event function Jiri Olsa
                   ` (35 subsequent siblings)
  48 siblings, 0 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Introduce perf_event__synthesize_thread_map2 function to
sythesize struct thread_map.

Link: http://lkml.kernel.org/n/tip-cykuf1v8qb6li8q6w6tbm05w@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/tests/builtin-test.c |  4 ++++
 tools/perf/tests/tests.h        |  1 +
 tools/perf/tests/thread-map.c   | 29 +++++++++++++++++++++++++++++
 tools/perf/util/event.c         | 36 ++++++++++++++++++++++++++++++++++++
 tools/perf/util/event.h         |  4 ++++
 5 files changed, 74 insertions(+)

diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index c1dde733c3a6..7b289d20bd8b 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -175,6 +175,10 @@ static struct test {
 		.func = test__thread_map,
 	},
 	{
+		.desc = "Test thread map synthesize",
+		.func = test__thread_map_synthesize,
+	},
+	{
 		.func = NULL,
 	},
 };
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index ebb47d96bc0b..14e2d821d0fd 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -62,6 +62,7 @@ int test__fdarray__filter(void);
 int test__fdarray__add(void);
 int test__kmod_path__parse(void);
 int test__thread_map(void);
+int test__thread_map_synthesize(void);
 
 #if defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__)
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/tests/thread-map.c b/tools/perf/tests/thread-map.c
index 138a0e3431fa..0facd9fa3458 100644
--- a/tools/perf/tests/thread-map.c
+++ b/tools/perf/tests/thread-map.c
@@ -40,3 +40,32 @@ int test__thread_map(void)
 	thread_map__put(map);
 	return 0;
 }
+
+static int process_event(struct perf_tool *tool __maybe_unused,
+			 union perf_event *event,
+			 struct perf_sample *sample __maybe_unused,
+			 struct machine *machine __maybe_unused)
+{
+	struct thread_map_event *map = &event->thread_map;
+
+	TEST_ASSERT_VAL("wrong nr",   map->nr == 1);
+	TEST_ASSERT_VAL("wrong pid",  map->data[0].pid == (u64) getpid());
+	TEST_ASSERT_VAL("wrong comm", !strcmp(map->data[0].comm, "perf"));
+	return 0;
+}
+
+int test__thread_map_synthesize(void)
+{
+	struct thread_map *threads;
+
+	/* test map on current pid */
+	threads = thread_map__new_by_pid(getpid());
+	TEST_ASSERT_VAL("failed to alloc map", threads);
+
+	thread_map__read_comms(threads);
+
+	TEST_ASSERT_VAL("failed to synthesize map",
+		!perf_event__synthesize_thread_map2(NULL, threads, process_event, NULL));
+
+	return 0;
+}
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 1ff4a0bb0feb..15fb35c6baed 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -698,6 +698,42 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
 	return err;
 }
 
+int perf_event__synthesize_thread_map2(struct perf_tool *tool,
+				      struct thread_map *threads,
+				      perf_event__handler_t process,
+				      struct machine *machine)
+{
+	union perf_event *event;
+	int i, err, size;
+
+	size  = sizeof(event->thread_map);
+	size +=	threads->nr * sizeof(event->thread_map.data[0]);
+
+	event = zalloc(size);
+	if (!event)
+		return -ENOMEM;
+
+	event->header.type = PERF_RECORD_THREAD_MAP;
+	event->header.size = size;
+	event->thread_map.nr = threads->nr;
+
+	for (i = 0; i < threads->nr; i++) {
+		struct thread_map_data_event *data = &event->thread_map.data[i];
+		char *comm = thread_map__comm(threads, i);
+
+		if (!comm)
+			comm = (char *) "";
+
+		data->pid = thread_map__pid(threads, i);
+		strncpy((char *) &data->comm, comm, sizeof(data->comm));
+	}
+
+	err = process(tool, event, NULL, machine);
+
+	free(event);
+	return err;
+}
+
 size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp)
 {
 	const char *s;
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 64dc752f3589..c204dbf7e386 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -399,6 +399,10 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
 				      perf_event__handler_t process,
 				      struct machine *machine, bool mmap_data,
 				      unsigned int proc_map_timeout);
+int perf_event__synthesize_thread_map2(struct perf_tool *tool,
+				      struct thread_map *threads,
+				      perf_event__handler_t process,
+				      struct machine *machine);
 int perf_event__synthesize_threads(struct perf_tool *tool,
 				   perf_event__handler_t process,
 				   struct machine *machine, bool mmap_data,
-- 
2.4.3


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

* [PATCH 14/47] perf tools: Add thread_map__new_event function
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (12 preceding siblings ...)
  2015-07-21 12:31 ` [PATCH 13/47] perf tools: Add thread_map event sythesize function Jiri Olsa
@ 2015-07-21 12:31 ` Jiri Olsa
  2015-07-21 12:31 ` [PATCH 15/47] perf tools: Add cpu_map event Jiri Olsa
                   ` (34 subsequent siblings)
  48 siblings, 0 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Introducing thread_map__new_event function to create
struct thread_map object from thread_map event.

Link: http://lkml.kernel.org/n/tip-0gu5uv3g51p4mzul93bhh2yh@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/tests/thread-map.c | 14 ++++++++++++++
 tools/perf/util/thread_map.c  | 27 +++++++++++++++++++++++++++
 tools/perf/util/thread_map.h  |  3 +++
 3 files changed, 44 insertions(+)

diff --git a/tools/perf/tests/thread-map.c b/tools/perf/tests/thread-map.c
index 0facd9fa3458..da7b047d3ada 100644
--- a/tools/perf/tests/thread-map.c
+++ b/tools/perf/tests/thread-map.c
@@ -47,10 +47,24 @@ static int process_event(struct perf_tool *tool __maybe_unused,
 			 struct machine *machine __maybe_unused)
 {
 	struct thread_map_event *map = &event->thread_map;
+	struct thread_map *threads;
 
 	TEST_ASSERT_VAL("wrong nr",   map->nr == 1);
 	TEST_ASSERT_VAL("wrong pid",  map->data[0].pid == (u64) getpid());
 	TEST_ASSERT_VAL("wrong comm", !strcmp(map->data[0].comm, "perf"));
+
+	threads = thread_map__new_event(&event->thread_map);
+	TEST_ASSERT_VAL("failed to alloc map", threads);
+
+	TEST_ASSERT_VAL("wrong nr", threads->nr == 1);
+	TEST_ASSERT_VAL("wrong pid",
+			thread_map__pid(threads, 0) == getpid());
+	TEST_ASSERT_VAL("wrong comm",
+			thread_map__comm(threads, 0) &&
+			!strcmp(thread_map__comm(threads, 0), "perf"));
+	TEST_ASSERT_VAL("wrong refcnt",
+			atomic_read(&threads->refcnt) == 1);
+	thread_map__put(threads);
 	return 0;
 }
 
diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c
index da7646d767fe..34d44df2fb1e 100644
--- a/tools/perf/util/thread_map.c
+++ b/tools/perf/util/thread_map.c
@@ -13,6 +13,7 @@
 #include "thread_map.h"
 #include "util.h"
 #include "debug.h"
+#include "event.h"
 
 /* Skip "." and ".." directories */
 static int filter(const struct dirent *dir)
@@ -407,3 +408,29 @@ void thread_map__read_comms(struct thread_map *threads)
 	for (i = 0; i < threads->nr; ++i)
 		comm_init(threads, i);
 }
+
+static void thread_map__copy_event(struct thread_map *threads,
+				   struct thread_map_event *event)
+{
+	unsigned i;
+
+	threads->nr = (int) event->nr;
+
+	for (i = 0; i < event->nr; i++) {
+		thread_map__set_pid(threads, i, (pid_t) event->data[i].pid);
+		threads->map[i].comm = strndup(event->data[i].comm, 16);
+	}
+
+	atomic_set(&threads->refcnt, 1);
+}
+
+struct thread_map *thread_map__new_event(struct thread_map_event *event)
+{
+	struct thread_map *threads;
+
+	threads = thread_map__alloc(event->nr);
+	if (threads)
+		thread_map__copy_event(threads, event);
+
+	return threads;
+}
diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h
index af679d8a50f8..85e4c7c4fbde 100644
--- a/tools/perf/util/thread_map.h
+++ b/tools/perf/util/thread_map.h
@@ -16,11 +16,14 @@ struct thread_map {
 	struct thread_map_data map[];
 };
 
+struct thread_map_event;
+
 struct thread_map *thread_map__new_dummy(void);
 struct thread_map *thread_map__new_by_pid(pid_t pid);
 struct thread_map *thread_map__new_by_tid(pid_t tid);
 struct thread_map *thread_map__new_by_uid(uid_t uid);
 struct thread_map *thread_map__new(pid_t pid, pid_t tid, uid_t uid);
+struct thread_map *thread_map__new_event(struct thread_map_event *event);
 
 struct thread_map *thread_map__get(struct thread_map *map);
 void thread_map__put(struct thread_map *map);
-- 
2.4.3


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

* [PATCH 15/47] perf tools: Add cpu_map event
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (13 preceding siblings ...)
  2015-07-21 12:31 ` [PATCH 14/47] perf tools: Add thread_map__new_event function Jiri Olsa
@ 2015-07-21 12:31 ` Jiri Olsa
  2015-07-21 12:31 ` [PATCH 16/47] perf tools: Add cpu_map event synthesize function Jiri Olsa
                   ` (33 subsequent siblings)
  48 siblings, 0 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Adding cpu_map event to pass/store cpu maps.

Link: http://lkml.kernel.org/n/tip-tomgwwohnuxvvalwu4znaa2o@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/event.c   |  1 +
 tools/perf/util/event.h   |  8 ++++++++
 tools/perf/util/session.c | 25 +++++++++++++++++++++++++
 tools/perf/util/tool.h    |  3 ++-
 4 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 15fb35c6baed..9f8ffbfc5cd4 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -36,6 +36,7 @@ static const char *perf_event__names[] = {
 	[PERF_RECORD_AUXTRACE]			= "AUXTRACE",
 	[PERF_RECORD_AUXTRACE_ERROR]		= "AUXTRACE_ERROR",
 	[PERF_RECORD_THREAD_MAP]		= "THREAD_MAP",
+	[PERF_RECORD_CPU_MAP]			= "CPU_MAP",
 };
 
 const char *perf_event__name(unsigned int id)
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index c204dbf7e386..f05c4d868162 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -226,6 +226,7 @@ enum perf_user_event_type { /* above any possible kernel type */
 	PERF_RECORD_AUXTRACE			= 71,
 	PERF_RECORD_AUXTRACE_ERROR		= 72,
 	PERF_RECORD_THREAD_MAP			= 73,
+	PERF_RECORD_CPU_MAP			= 74,
 	PERF_RECORD_HEADER_MAX
 };
 
@@ -360,6 +361,12 @@ struct thread_map_event {
 	struct thread_map_data_event	data[];
 };
 
+struct cpu_map_event {
+	struct perf_event_header	header;
+	u64				nr;
+	u64				cpu[];
+};
+
 union perf_event {
 	struct perf_event_header	header;
 	struct mmap_event		mmap;
@@ -382,6 +389,7 @@ union perf_event {
 	struct aux_event		aux;
 	struct itrace_start_event	itrace_start;
 	struct thread_map_event		thread_map;
+	struct cpu_map_event		cpu_map;
 };
 
 void perf_event__print_totals(void);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index e20cd50a9a8f..9db7cb19e4b4 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -321,6 +321,15 @@ int process_event_thread_map_stub(struct perf_tool *tool __maybe_unused,
 	return 0;
 }
 
+static
+int process_event_cpu_map_stub(struct perf_tool *tool __maybe_unused,
+			       union perf_event *event __maybe_unused,
+			       struct perf_session *session __maybe_unused)
+{
+	dump_printf(": unhandled!\n");
+	return 0;
+}
+
 void perf_tool__fill_defaults(struct perf_tool *tool)
 {
 	if (tool->sample == NULL)
@@ -371,6 +380,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
 		tool->auxtrace_error = process_event_auxtrace_error_stub;
 	if (tool->thread_map == NULL)
 		tool->thread_map = process_event_thread_map_stub;
+	if (tool->cpu_map == NULL)
+		tool->cpu_map = process_event_cpu_map_stub;
 }
 
 static void swap_sample_id_all(union perf_event *event, void *data)
@@ -639,6 +650,17 @@ static void perf_event__thread_map_swap(union perf_event *event,
 		event->thread_map.data[i].pid = bswap_64(event->thread_map.data[i].pid);
 }
 
+static void perf_event__cpu_map_swap(union perf_event *event,
+				     bool sample_id_all __maybe_unused)
+{
+	unsigned i;
+
+	event->cpu_map.nr = bswap_64(event->cpu_map.nr);
+
+	for (i = 0; i < event->cpu_map.nr; i++)
+		event->cpu_map.cpu[i] = bswap_64(event->cpu_map.cpu[i]);
+}
+
 typedef void (*perf_event__swap_op)(union perf_event *event,
 				    bool sample_id_all);
 
@@ -665,6 +687,7 @@ static perf_event__swap_op perf_event__swap_ops[] = {
 	[PERF_RECORD_AUXTRACE]		  = perf_event__auxtrace_swap,
 	[PERF_RECORD_AUXTRACE_ERROR]	  = perf_event__auxtrace_error_swap,
 	[PERF_RECORD_THREAD_MAP]	  = perf_event__thread_map_swap,
+	[PERF_RECORD_CPU_MAP]		  = perf_event__cpu_map_swap,
 	[PERF_RECORD_HEADER_MAX]	  = NULL,
 };
 
@@ -1189,6 +1212,8 @@ static s64 perf_session__process_user_event(struct perf_session *session,
 		return tool->auxtrace_error(tool, event, session);
 	case PERF_RECORD_THREAD_MAP:
 		return tool->thread_map(tool, event, session);
+	case PERF_RECORD_CPU_MAP:
+		return tool->cpu_map(tool, event, session);
 	default:
 		return -EINVAL;
 	}
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index cbaffbeb5b18..ddb88a6e18ee 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -55,7 +55,8 @@ struct perf_tool {
 			id_index,
 			auxtrace_info,
 			auxtrace_error,
-			thread_map;
+			thread_map,
+			cpu_map;
 	event_op3	auxtrace;
 	bool		ordered_events;
 	bool		ordering_requires_timestamps;
-- 
2.4.3


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

* [PATCH 16/47] perf tools: Add cpu_map event synthesize function
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (14 preceding siblings ...)
  2015-07-21 12:31 ` [PATCH 15/47] perf tools: Add cpu_map event Jiri Olsa
@ 2015-07-21 12:31 ` Jiri Olsa
  2015-07-21 12:31 ` [PATCH 17/47] perf tools: Add cpu_map__new_event function Jiri Olsa
                   ` (32 subsequent siblings)
  48 siblings, 0 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Introduce perf_event__synthesize_cpu_map function to
sythesize struct cpu_map.

Link: http://lkml.kernel.org/n/tip-miidn8vqsx3udu4ct8103v5f@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/tests/Build          |  1 +
 tools/perf/tests/builtin-test.c |  4 ++++
 tools/perf/tests/cpumap.c       | 29 +++++++++++++++++++++++++++++
 tools/perf/tests/tests.h        |  1 +
 tools/perf/util/event.c         | 28 ++++++++++++++++++++++++++++
 tools/perf/util/event.h         |  5 +++++
 6 files changed, 68 insertions(+)
 create mode 100644 tools/perf/tests/cpumap.c

diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index d20d6e6ab65b..05faf02ed1ee 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -32,6 +32,7 @@ perf-y += sample-parsing.o
 perf-y += parse-no-sample-id-all.o
 perf-y += kmod-path.o
 perf-y += thread-map.o
+perf-y += cpumap.o
 
 perf-$(CONFIG_X86) += perf-time-to-tsc.o
 
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 7b289d20bd8b..d4cfc0592f6b 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -179,6 +179,10 @@ static struct test {
 		.func = test__thread_map_synthesize,
 	},
 	{
+		.desc = "Test cpu map synthesize",
+		.func = test__cpu_map_synthesize,
+	},
+	{
 		.func = NULL,
 	},
 };
diff --git a/tools/perf/tests/cpumap.c b/tools/perf/tests/cpumap.c
new file mode 100644
index 000000000000..475c040f8a8d
--- /dev/null
+++ b/tools/perf/tests/cpumap.c
@@ -0,0 +1,29 @@
+#include "tests.h"
+#include "cpumap.h"
+
+static int process_event(struct perf_tool *tool __maybe_unused,
+			 union perf_event *event,
+			 struct perf_sample *sample __maybe_unused,
+			 struct machine *machine __maybe_unused)
+{
+	struct cpu_map_event *map = &event->cpu_map;
+
+	TEST_ASSERT_VAL("wrong nr",   map->nr == 3);
+	TEST_ASSERT_VAL("wrong cpu",  map->cpu[0] == 1);
+	TEST_ASSERT_VAL("wrong cpu",  map->cpu[1] == 2);
+	TEST_ASSERT_VAL("wrong cpu",  map->cpu[2] == 4);
+	return 0;
+}
+
+int test__cpu_map_synthesize(void)
+{
+	struct cpu_map *cpus;
+
+	cpus = cpu_map__new("1,2,4");
+
+
+	TEST_ASSERT_VAL("failed to synthesize map",
+		!perf_event__synthesize_cpu_map(NULL, cpus, process_event, NULL));
+
+	return 0;
+}
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 14e2d821d0fd..c251d5a21e0c 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -63,6 +63,7 @@ int test__fdarray__add(void);
 int test__kmod_path__parse(void);
 int test__thread_map(void);
 int test__thread_map_synthesize(void);
+int test__cpu_map_synthesize(void);
 
 #if defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__)
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 9f8ffbfc5cd4..7bbe64c51d85 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -735,6 +735,34 @@ int perf_event__synthesize_thread_map2(struct perf_tool *tool,
 	return err;
 }
 
+int perf_event__synthesize_cpu_map(struct perf_tool *tool,
+				   struct cpu_map *cpus,
+				   perf_event__handler_t process,
+				   struct machine *machine)
+{
+	union perf_event *event;
+	int i, err, size;
+
+	size  = sizeof(event->cpu_map);
+	size +=	cpus->nr * sizeof(event->cpu_map.cpu[0]);
+
+	event = zalloc(size);
+	if (!event)
+		return -ENOMEM;
+
+	event->header.type = PERF_RECORD_CPU_MAP;
+	event->header.size = size;
+	event->cpu_map.nr = cpus->nr;
+
+	for (i = 0; i < cpus->nr; i++)
+		event->cpu_map.cpu[i] = cpus->map[i];
+
+	err = process(tool, event, NULL, machine);
+
+	free(event);
+	return err;
+}
+
 size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp)
 {
 	const char *s;
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index f05c4d868162..6600da608782 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -396,6 +396,7 @@ void perf_event__print_totals(void);
 
 struct perf_tool;
 struct thread_map;
+struct cpu_map;
 
 typedef int (*perf_event__handler_t)(struct perf_tool *tool,
 				     union perf_event *event,
@@ -411,6 +412,10 @@ int perf_event__synthesize_thread_map2(struct perf_tool *tool,
 				      struct thread_map *threads,
 				      perf_event__handler_t process,
 				      struct machine *machine);
+int perf_event__synthesize_cpu_map(struct perf_tool *tool,
+				   struct cpu_map *cpus,
+				   perf_event__handler_t process,
+				   struct machine *machine);
 int perf_event__synthesize_threads(struct perf_tool *tool,
 				   perf_event__handler_t process,
 				   struct machine *machine, bool mmap_data,
-- 
2.4.3


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

* [PATCH 17/47] perf tools: Add cpu_map__new_event function
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (15 preceding siblings ...)
  2015-07-21 12:31 ` [PATCH 16/47] perf tools: Add cpu_map event synthesize function Jiri Olsa
@ 2015-07-21 12:31 ` Jiri Olsa
  2015-07-21 12:31 ` [PATCH 18/47] perf tools: Add stat config event Jiri Olsa
                   ` (31 subsequent siblings)
  48 siblings, 0 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Introducing cpu_map__new_event function to create
struct cpu_map object from cpu_map event.

Link: http://lkml.kernel.org/n/tip-tepv49tbjsqeprmf8k05lc6r@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/tests/cpumap.c | 10 ++++++++++
 tools/perf/util/cpumap.c  | 27 +++++++++++++++++++++++++++
 tools/perf/util/cpumap.h  |  3 +++
 3 files changed, 40 insertions(+)

diff --git a/tools/perf/tests/cpumap.c b/tools/perf/tests/cpumap.c
index 475c040f8a8d..af8a3f520a2a 100644
--- a/tools/perf/tests/cpumap.c
+++ b/tools/perf/tests/cpumap.c
@@ -7,11 +7,21 @@ static int process_event(struct perf_tool *tool __maybe_unused,
 			 struct machine *machine __maybe_unused)
 {
 	struct cpu_map_event *map = &event->cpu_map;
+	struct cpu_map *cpus;
 
 	TEST_ASSERT_VAL("wrong nr",   map->nr == 3);
 	TEST_ASSERT_VAL("wrong cpu",  map->cpu[0] == 1);
 	TEST_ASSERT_VAL("wrong cpu",  map->cpu[1] == 2);
 	TEST_ASSERT_VAL("wrong cpu",  map->cpu[2] == 4);
+
+	cpus = cpu_map__new_event(&event->cpu_map);
+	TEST_ASSERT_VAL("wrong nr",  cpus->nr == 3);
+	TEST_ASSERT_VAL("wrong cpu", cpus->map[0] == 1);
+	TEST_ASSERT_VAL("wrong cpu", cpus->map[1] == 2);
+	TEST_ASSERT_VAL("wrong cpu", cpus->map[2] == 4);
+	TEST_ASSERT_VAL("wrong refcnt",
+			atomic_read(&cpus->refcnt) == 1);
+	cpu_map__put(cpus);
 	return 0;
 }
 
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index 3667e2123e5b..81e82cadda50 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -179,6 +179,33 @@ out:
 	return cpus;
 }
 
+static void cpu_map__copy_event(struct cpu_map *cpus,
+				struct cpu_map_event *event)
+{
+	unsigned i;
+
+	cpus->nr = event->nr;
+
+	for (i = 0; i < event->nr; i++)
+		cpus->map[i] = (int) event->cpu[i];
+
+	atomic_set(&cpus->refcnt, 1);
+}
+
+struct cpu_map *cpu_map__new_event(struct cpu_map_event *event)
+{
+	struct cpu_map *cpus;
+	int size;
+
+	size = sizeof(cpus) + (event->nr * sizeof(cpus->map[0]));
+
+	cpus = zalloc(size);
+	if (cpus)
+		cpu_map__copy_event(cpus, event);
+
+	return cpus;
+}
+
 size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp)
 {
 	int i;
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index 0af9cecb4c51..44a68b63bf48 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -14,8 +14,11 @@ struct cpu_map {
 	int map[];
 };
 
+struct cpu_map_event;
+
 struct cpu_map *cpu_map__new(const char *cpu_list);
 struct cpu_map *cpu_map__dummy_new(void);
+struct cpu_map *cpu_map__new_event(struct cpu_map_event *event);
 struct cpu_map *cpu_map__read(FILE *file);
 size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp);
 int cpu_map__get_socket(struct cpu_map *map, int idx);
-- 
2.4.3


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

* [PATCH 18/47] perf tools: Add stat config event
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (16 preceding siblings ...)
  2015-07-21 12:31 ` [PATCH 17/47] perf tools: Add cpu_map__new_event function Jiri Olsa
@ 2015-07-21 12:31 ` Jiri Olsa
  2015-07-21 12:31 ` [PATCH 19/47] perf tools: Add stat config event synthesize function Jiri Olsa
                   ` (30 subsequent siblings)
  48 siblings, 0 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Adding stat config event to pass/store stat config data,
so report tools (report/script) know how to interpret
stat data.

Link: http://lkml.kernel.org/n/tip-1npdsfez8635vogthpqwtkd0@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/event.c   |  1 +
 tools/perf/util/event.h   | 20 ++++++++++++++++++++
 tools/perf/util/session.c | 24 ++++++++++++++++++++++++
 tools/perf/util/tool.h    |  3 ++-
 4 files changed, 47 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 7bbe64c51d85..e2c6c2df57fb 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -37,6 +37,7 @@ static const char *perf_event__names[] = {
 	[PERF_RECORD_AUXTRACE_ERROR]		= "AUXTRACE_ERROR",
 	[PERF_RECORD_THREAD_MAP]		= "THREAD_MAP",
 	[PERF_RECORD_CPU_MAP]			= "CPU_MAP",
+	[PERF_RECORD_STAT_CONFIG]		= "STAT_CONFIG",
 };
 
 const char *perf_event__name(unsigned int id)
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 6600da608782..a67f4e8e0633 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -227,6 +227,7 @@ enum perf_user_event_type { /* above any possible kernel type */
 	PERF_RECORD_AUXTRACE_ERROR		= 72,
 	PERF_RECORD_THREAD_MAP			= 73,
 	PERF_RECORD_CPU_MAP			= 74,
+	PERF_RECORD_STAT_CONFIG			= 75,
 	PERF_RECORD_HEADER_MAX
 };
 
@@ -367,6 +368,24 @@ struct cpu_map_event {
 	u64				cpu[];
 };
 
+enum {
+	PERF_STAT_CONFIG_TERM__AGGR_MODE	= 0,
+	PERF_STAT_CONFIG_TERM__INTERVAL		= 1,
+	PERF_STAT_CONFIG_TERM__SCALE		= 2,
+	PERF_STAT_CONFIG_TERM__MAX		= 3,
+};
+
+struct stat_config_term_event {
+	u64	tag;
+	u64	val;
+};
+
+struct stat_config_event {
+	struct perf_event_header	header;
+	u64				nr;
+	struct stat_config_term_event	data[];
+};
+
 union perf_event {
 	struct perf_event_header	header;
 	struct mmap_event		mmap;
@@ -390,6 +409,7 @@ union perf_event {
 	struct itrace_start_event	itrace_start;
 	struct thread_map_event		thread_map;
 	struct cpu_map_event		cpu_map;
+	struct stat_config_event	stat_config;
 };
 
 void perf_event__print_totals(void);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 9db7cb19e4b4..d9027593e4a2 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -330,6 +330,15 @@ int process_event_cpu_map_stub(struct perf_tool *tool __maybe_unused,
 	return 0;
 }
 
+static
+int process_event_stat_config_stub(struct perf_tool *tool __maybe_unused,
+				   union perf_event *event __maybe_unused,
+				   struct perf_session *session __maybe_unused)
+{
+	dump_printf(": unhandled!\n");
+	return 0;
+}
+
 void perf_tool__fill_defaults(struct perf_tool *tool)
 {
 	if (tool->sample == NULL)
@@ -382,6 +391,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
 		tool->thread_map = process_event_thread_map_stub;
 	if (tool->cpu_map == NULL)
 		tool->cpu_map = process_event_cpu_map_stub;
+	if (tool->stat_config == NULL)
+		tool->stat_config = process_event_stat_config_stub;
 }
 
 static void swap_sample_id_all(union perf_event *event, void *data)
@@ -661,6 +672,16 @@ static void perf_event__cpu_map_swap(union perf_event *event,
 		event->cpu_map.cpu[i] = bswap_64(event->cpu_map.cpu[i]);
 }
 
+static void perf_event__stat_config_swap(union perf_event *event,
+					 bool sample_id_all __maybe_unused)
+{
+	u64 size;
+
+	size  = event->stat_config.nr * sizeof(event->stat_config.data[0]);
+	size += 1; /* nr item itself */
+	mem_bswap_64(&event->stat_config.nr, size);
+}
+
 typedef void (*perf_event__swap_op)(union perf_event *event,
 				    bool sample_id_all);
 
@@ -688,6 +709,7 @@ static perf_event__swap_op perf_event__swap_ops[] = {
 	[PERF_RECORD_AUXTRACE_ERROR]	  = perf_event__auxtrace_error_swap,
 	[PERF_RECORD_THREAD_MAP]	  = perf_event__thread_map_swap,
 	[PERF_RECORD_CPU_MAP]		  = perf_event__cpu_map_swap,
+	[PERF_RECORD_STAT_CONFIG]	  = perf_event__stat_config_swap,
 	[PERF_RECORD_HEADER_MAX]	  = NULL,
 };
 
@@ -1214,6 +1236,8 @@ static s64 perf_session__process_user_event(struct perf_session *session,
 		return tool->thread_map(tool, event, session);
 	case PERF_RECORD_CPU_MAP:
 		return tool->cpu_map(tool, event, session);
+	case PERF_RECORD_STAT_CONFIG:
+		return tool->stat_config(tool, event, session);
 	default:
 		return -EINVAL;
 	}
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index ddb88a6e18ee..5c209743ad97 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -56,7 +56,8 @@ struct perf_tool {
 			auxtrace_info,
 			auxtrace_error,
 			thread_map,
-			cpu_map;
+			cpu_map,
+			stat_config;
 	event_op3	auxtrace;
 	bool		ordered_events;
 	bool		ordering_requires_timestamps;
-- 
2.4.3


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

* [PATCH 19/47] perf tools: Add stat config event synthesize function
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (17 preceding siblings ...)
  2015-07-21 12:31 ` [PATCH 18/47] perf tools: Add stat config event Jiri Olsa
@ 2015-07-21 12:31 ` Jiri Olsa
  2015-07-21 12:31 ` [PATCH 20/47] perf tools: Add stat config event read function Jiri Olsa
                   ` (29 subsequent siblings)
  48 siblings, 0 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Introduce perf_event__synthesize_stat_config function to
sythesize 'struct perf_stat_config'.

Storing stat config in form of tag-value pairs in a believe
it'll sort out future version issues.

Link: http://lkml.kernel.org/n/tip-zof1adf5flwp38xdzxzn4p2z@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/tests/Build          |  1 +
 tools/perf/tests/builtin-test.c |  4 ++++
 tools/perf/tests/stat.c         | 53 +++++++++++++++++++++++++++++++++++++++++
 tools/perf/tests/tests.h        |  1 +
 tools/perf/util/event.c         | 39 ++++++++++++++++++++++++++++++
 tools/perf/util/event.h         |  5 ++++
 6 files changed, 103 insertions(+)
 create mode 100644 tools/perf/tests/stat.c

diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index 05faf02ed1ee..5c3b9da9c1c3 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -33,6 +33,7 @@ perf-y += parse-no-sample-id-all.o
 perf-y += kmod-path.o
 perf-y += thread-map.o
 perf-y += cpumap.o
+perf-y += stat.o
 
 perf-$(CONFIG_X86) += perf-time-to-tsc.o
 
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index d4cfc0592f6b..203164ad9c82 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -183,6 +183,10 @@ static struct test {
 		.func = test__cpu_map_synthesize,
 	},
 	{
+		.desc = "Test stat config synthesize",
+		.func = test__synthesize_stat_config,
+	},
+	{
 		.func = NULL,
 	},
 };
diff --git a/tools/perf/tests/stat.c b/tools/perf/tests/stat.c
new file mode 100644
index 000000000000..5e6a2441998c
--- /dev/null
+++ b/tools/perf/tests/stat.c
@@ -0,0 +1,53 @@
+#include <linux/compiler.h>
+#include "event.h"
+#include "tests.h"
+#include "stat.h"
+#include "debug.h"
+
+static bool has_term(struct stat_config_event *config,
+		     u64 tag, u64 val)
+{
+	unsigned i;
+
+	for (i = 0; i < config->nr; i++) {
+		if ((config->data[i].tag == tag) &&
+		    (config->data[i].val == val))
+			return true;
+	}
+
+	return false;
+}
+
+static int process_event(struct perf_tool *tool __maybe_unused,
+			 union perf_event *event,
+			 struct perf_sample *sample __maybe_unused,
+			 struct machine *machine __maybe_unused)
+{
+	struct stat_config_event *config = &event->stat_config;
+
+#define HAS(term, val) \
+	has_term(config, PERF_STAT_CONFIG_TERM__##term, val)
+
+	TEST_ASSERT_VAL("wrong nr",        config->nr == PERF_STAT_CONFIG_TERM__MAX);
+	TEST_ASSERT_VAL("wrong aggr_mode", HAS(AGGR_MODE, AGGR_CORE));
+	TEST_ASSERT_VAL("wrong scale",     HAS(SCALE, 1));
+	TEST_ASSERT_VAL("wrong interval",  HAS(INTERVAL, 1));
+
+#undef HAS
+
+	return 0;
+}
+
+int test__synthesize_stat_config(void)
+{
+	struct perf_stat_config stat_config = {
+		.aggr_mode	= AGGR_CORE,
+		.scale		= 1,
+		.interval	= 1,
+	};
+
+	TEST_ASSERT_VAL("failed to synthesize stat_config",
+		!perf_event__synthesize_stat_config(NULL, &stat_config, process_event, NULL));
+
+	return 0;
+}
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index c251d5a21e0c..dfb6db7d8a4d 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -64,6 +64,7 @@ int test__kmod_path__parse(void);
 int test__thread_map(void);
 int test__thread_map_synthesize(void);
 int test__cpu_map_synthesize(void);
+int test__synthesize_stat_config(void);
 
 #if defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__)
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index e2c6c2df57fb..aa166ebf9fc0 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -10,6 +10,7 @@
 #include "thread.h"
 #include "thread_map.h"
 #include "symbol/kallsyms.h"
+#include "asm/bug.h"
 
 static const char *perf_event__names[] = {
 	[0]					= "TOTAL",
@@ -764,6 +765,44 @@ int perf_event__synthesize_cpu_map(struct perf_tool *tool,
 	return err;
 }
 
+int perf_event__synthesize_stat_config(struct perf_tool *tool,
+				       struct perf_stat_config *config,
+				       perf_event__handler_t process,
+				       struct machine *machine)
+{
+	struct stat_config_event *event;
+	int size, i = 0, err;
+
+	size  = sizeof(*event);
+	size += (PERF_STAT_CONFIG_TERM__MAX * sizeof(event->data[0]));
+
+	event = zalloc(size);
+	if (!event)
+		return -ENOMEM;
+
+	event->header.type = PERF_RECORD_STAT_CONFIG;
+	event->header.size = size;
+	event->nr          = PERF_STAT_CONFIG_TERM__MAX;
+
+#define ADD(__term, __val)					\
+	event->data[i].tag = PERF_STAT_CONFIG_TERM__##__term;	\
+	event->data[i].val = __val;				\
+	i++;
+
+	ADD(AGGR_MODE,	config->aggr_mode);
+	ADD(INTERVAL,	config->interval);
+	ADD(SCALE,	config->scale);
+
+	WARN_ONCE(i != PERF_STAT_CONFIG_TERM__MAX,
+		  "stat config terms unbalanced\n");
+#undef ADD
+
+	err = process(tool, (union perf_event *) event, NULL, machine);
+
+	free(event);
+	return err;
+}
+
 size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp)
 {
 	const char *s;
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index a67f4e8e0633..23dba7bb8973 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -417,6 +417,7 @@ void perf_event__print_totals(void);
 struct perf_tool;
 struct thread_map;
 struct cpu_map;
+struct perf_stat_config;
 
 typedef int (*perf_event__handler_t)(struct perf_tool *tool,
 				     union perf_event *event,
@@ -443,6 +444,10 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
 int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
 				       perf_event__handler_t process,
 				       struct machine *machine);
+int perf_event__synthesize_stat_config(struct perf_tool *tool,
+				       struct perf_stat_config *config,
+				       perf_event__handler_t process,
+				       struct machine *machine);
 
 int perf_event__synthesize_modules(struct perf_tool *tool,
 				   perf_event__handler_t process,
-- 
2.4.3


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

* [PATCH 20/47] perf tools: Add stat config event read function
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (18 preceding siblings ...)
  2015-07-21 12:31 ` [PATCH 19/47] perf tools: Add stat config event synthesize function Jiri Olsa
@ 2015-07-21 12:31 ` Jiri Olsa
  2015-07-21 12:31 ` [PATCH 21/47] perf tools: Add stat event Jiri Olsa
                   ` (28 subsequent siblings)
  48 siblings, 0 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Introducing perf_event__read_stat_config function to read
struct perf_stat_config object data from stat config event.

Link: http://lkml.kernel.org/n/tip-62ae08zz97jp2qkhygp8uet5@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/tests/stat.c |  6 ++++++
 tools/perf/util/event.c | 24 ++++++++++++++++++++++++
 tools/perf/util/event.h |  2 ++
 3 files changed, 32 insertions(+)

diff --git a/tools/perf/tests/stat.c b/tools/perf/tests/stat.c
index 5e6a2441998c..2049c5a3e4a2 100644
--- a/tools/perf/tests/stat.c
+++ b/tools/perf/tests/stat.c
@@ -24,6 +24,7 @@ static int process_event(struct perf_tool *tool __maybe_unused,
 			 struct machine *machine __maybe_unused)
 {
 	struct stat_config_event *config = &event->stat_config;
+	struct perf_stat_config stat_config;
 
 #define HAS(term, val) \
 	has_term(config, PERF_STAT_CONFIG_TERM__##term, val)
@@ -35,6 +36,11 @@ static int process_event(struct perf_tool *tool __maybe_unused,
 
 #undef HAS
 
+	perf_event__read_stat_config(&stat_config, config);
+
+	TEST_ASSERT_VAL("wrong aggr_mode", stat_config.aggr_mode == AGGR_CORE);
+	TEST_ASSERT_VAL("wrong scale",     stat_config.scale == 1);
+	TEST_ASSERT_VAL("wrong interval",  stat_config.interval == 1);
 	return 0;
 }
 
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index aa166ebf9fc0..887731b52c40 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -803,6 +803,30 @@ int perf_event__synthesize_stat_config(struct perf_tool *tool,
 	return err;
 }
 
+void perf_event__read_stat_config(struct perf_stat_config *config,
+				  struct stat_config_event *event)
+{
+	unsigned i;
+
+	for (i = 0; i < event->nr; i++) {
+
+		switch (event->data[i].tag) {
+#define CASE(__term, __val)					\
+		case PERF_STAT_CONFIG_TERM__##__term:		\
+			config->__val = event->data[i].val;	\
+			break;
+
+		CASE(AGGR_MODE, aggr_mode);
+		CASE(SCALE,     scale);
+		CASE(INTERVAL,  interval);
+#undef CASE
+		default:
+			pr_warning("unknown stat config term %" PRIu64 "\n",
+				   event->data[i].tag);
+		}
+	}
+}
+
 size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp)
 {
 	const char *s;
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 23dba7bb8973..72da01b30cf9 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -448,6 +448,8 @@ int perf_event__synthesize_stat_config(struct perf_tool *tool,
 				       struct perf_stat_config *config,
 				       perf_event__handler_t process,
 				       struct machine *machine);
+void perf_event__read_stat_config(struct perf_stat_config *config,
+				  struct stat_config_event *event);
 
 int perf_event__synthesize_modules(struct perf_tool *tool,
 				   perf_event__handler_t process,
-- 
2.4.3


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

* [PATCH 21/47] perf tools: Add stat event
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (19 preceding siblings ...)
  2015-07-21 12:31 ` [PATCH 20/47] perf tools: Add stat config event read function Jiri Olsa
@ 2015-07-21 12:31 ` Jiri Olsa
  2015-07-21 12:31 ` [PATCH 22/47] perf tools: Add stat event synthesize function Jiri Olsa
                   ` (27 subsequent siblings)
  48 siblings, 0 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Adding stat event to store 'struct perf_counter_values' for
given event/cpu/thread.

Link: http://lkml.kernel.org/n/tip-56xpt7m6au4d8u39nffoqgx1@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/event.c   |  1 +
 tools/perf/util/event.h   | 19 +++++++++++++++++++
 tools/perf/util/session.c | 26 +++++++++++++++++++++++++-
 tools/perf/util/tool.h    |  3 ++-
 4 files changed, 47 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 887731b52c40..6779ab62ff6a 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -39,6 +39,7 @@ static const char *perf_event__names[] = {
 	[PERF_RECORD_THREAD_MAP]		= "THREAD_MAP",
 	[PERF_RECORD_CPU_MAP]			= "CPU_MAP",
 	[PERF_RECORD_STAT_CONFIG]		= "STAT_CONFIG",
+	[PERF_RECORD_STAT]			= "STAT",
 };
 
 const char *perf_event__name(unsigned int id)
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 72da01b30cf9..ab98be7a9612 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -228,6 +228,7 @@ enum perf_user_event_type { /* above any possible kernel type */
 	PERF_RECORD_THREAD_MAP			= 73,
 	PERF_RECORD_CPU_MAP			= 74,
 	PERF_RECORD_STAT_CONFIG			= 75,
+	PERF_RECORD_STAT			= 76,
 	PERF_RECORD_HEADER_MAX
 };
 
@@ -386,6 +387,23 @@ struct stat_config_event {
 	struct stat_config_term_event	data[];
 };
 
+struct stat_event {
+	struct perf_event_header	header;
+
+	u64	id;
+	u32	cpu;
+	u32	thread;
+
+	union {
+		struct {
+			u64 val;
+			u64 ena;
+			u64 run;
+		};
+		u64 values[3];
+	};
+};
+
 union perf_event {
 	struct perf_event_header	header;
 	struct mmap_event		mmap;
@@ -410,6 +428,7 @@ union perf_event {
 	struct thread_map_event		thread_map;
 	struct cpu_map_event		cpu_map;
 	struct stat_config_event	stat_config;
+	struct stat_event		stat;
 };
 
 void perf_event__print_totals(void);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index d9027593e4a2..e0ad3e691e6a 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -311,7 +311,6 @@ int process_event_auxtrace_error_stub(struct perf_tool *tool __maybe_unused,
 	return 0;
 }
 
-
 static
 int process_event_thread_map_stub(struct perf_tool *tool __maybe_unused,
 				  union perf_event *event __maybe_unused,
@@ -339,6 +338,15 @@ int process_event_stat_config_stub(struct perf_tool *tool __maybe_unused,
 	return 0;
 }
 
+static int process_stat_stub(struct perf_tool *tool __maybe_unused,
+			     union perf_event *event __maybe_unused,
+			     struct perf_session *perf_session
+			     __maybe_unused)
+{
+	dump_printf(": unhandled!\n");
+	return 0;
+}
+
 void perf_tool__fill_defaults(struct perf_tool *tool)
 {
 	if (tool->sample == NULL)
@@ -393,6 +401,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
 		tool->cpu_map = process_event_cpu_map_stub;
 	if (tool->stat_config == NULL)
 		tool->stat_config = process_event_stat_config_stub;
+	if (tool->stat == NULL)
+		tool->stat = process_stat_stub;
 }
 
 static void swap_sample_id_all(union perf_event *event, void *data)
@@ -682,6 +692,17 @@ static void perf_event__stat_config_swap(union perf_event *event,
 	mem_bswap_64(&event->stat_config.nr, size);
 }
 
+static void perf_event__stat_swap(union perf_event *event,
+				  bool sample_id_all __maybe_unused)
+{
+	event->stat.id     = bswap_64(event->stat.id);
+	event->stat.thread = bswap_32(event->stat.thread);
+	event->stat.cpu    = bswap_32(event->stat.cpu);
+	event->stat.val    = bswap_64(event->stat.val);
+	event->stat.ena    = bswap_64(event->stat.ena);
+	event->stat.run    = bswap_64(event->stat.run);
+}
+
 typedef void (*perf_event__swap_op)(union perf_event *event,
 				    bool sample_id_all);
 
@@ -710,6 +731,7 @@ static perf_event__swap_op perf_event__swap_ops[] = {
 	[PERF_RECORD_THREAD_MAP]	  = perf_event__thread_map_swap,
 	[PERF_RECORD_CPU_MAP]		  = perf_event__cpu_map_swap,
 	[PERF_RECORD_STAT_CONFIG]	  = perf_event__stat_config_swap,
+	[PERF_RECORD_STAT]		  = perf_event__stat_swap,
 	[PERF_RECORD_HEADER_MAX]	  = NULL,
 };
 
@@ -1238,6 +1260,8 @@ static s64 perf_session__process_user_event(struct perf_session *session,
 		return tool->cpu_map(tool, event, session);
 	case PERF_RECORD_STAT_CONFIG:
 		return tool->stat_config(tool, event, session);
+	case PERF_RECORD_STAT:
+		return tool->stat(tool, event, session);
 	default:
 		return -EINVAL;
 	}
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index 5c209743ad97..49224232995b 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -57,7 +57,8 @@ struct perf_tool {
 			auxtrace_error,
 			thread_map,
 			cpu_map,
-			stat_config;
+			stat_config,
+			stat;
 	event_op3	auxtrace;
 	bool		ordered_events;
 	bool		ordering_requires_timestamps;
-- 
2.4.3


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

* [PATCH 22/47] perf tools: Add stat event synthesize function
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (20 preceding siblings ...)
  2015-07-21 12:31 ` [PATCH 21/47] perf tools: Add stat event Jiri Olsa
@ 2015-07-21 12:31 ` Jiri Olsa
  2015-07-21 12:31 ` [PATCH 23/47] perf tools: Add stat event read function Jiri Olsa
                   ` (26 subsequent siblings)
  48 siblings, 0 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Introduce perf_event__synthesize_stat function to
synthesize 'struct stat_event'.

Link: http://lkml.kernel.org/n/tip-0jr9x4vwk0nxbs2ueclj7jfy@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/tests/builtin-test.c |  4 ++++
 tools/perf/tests/stat.c         | 40 +++++++++++++++++++++++++++++++++++-----
 tools/perf/tests/tests.h        |  1 +
 tools/perf/util/event.c         | 22 ++++++++++++++++++++++
 tools/perf/util/event.h         |  7 ++++++-
 5 files changed, 68 insertions(+), 6 deletions(-)

diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 203164ad9c82..7d8772c0ea82 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -187,6 +187,10 @@ static struct test {
 		.func = test__synthesize_stat_config,
 	},
 	{
+		.desc = "Test stat synthesize",
+		.func = test__synthesize_stat,
+	},
+	{
 		.func = NULL,
 	},
 };
diff --git a/tools/perf/tests/stat.c b/tools/perf/tests/stat.c
index 2049c5a3e4a2..31b242159e79 100644
--- a/tools/perf/tests/stat.c
+++ b/tools/perf/tests/stat.c
@@ -18,10 +18,10 @@ static bool has_term(struct stat_config_event *config,
 	return false;
 }
 
-static int process_event(struct perf_tool *tool __maybe_unused,
-			 union perf_event *event,
-			 struct perf_sample *sample __maybe_unused,
-			 struct machine *machine __maybe_unused)
+static int process_stat_config_event(struct perf_tool *tool __maybe_unused,
+				     union perf_event *event,
+				     struct perf_sample *sample __maybe_unused,
+				     struct machine *machine __maybe_unused)
 {
 	struct stat_config_event *config = &event->stat_config;
 	struct perf_stat_config stat_config;
@@ -53,7 +53,37 @@ int test__synthesize_stat_config(void)
 	};
 
 	TEST_ASSERT_VAL("failed to synthesize stat_config",
-		!perf_event__synthesize_stat_config(NULL, &stat_config, process_event, NULL));
+		!perf_event__synthesize_stat_config(NULL, &stat_config, process_stat_config_event, NULL));
+
+	return 0;
+}
+
+static int process_stat_event(struct perf_tool *tool __maybe_unused,
+			      union perf_event *event,
+			      struct perf_sample *sample __maybe_unused,
+			      struct machine *machine __maybe_unused)
+{
+	struct stat_event *stat = &event->stat;
+
+	TEST_ASSERT_VAL("wrong cpu",    stat->cpu    == 1);
+	TEST_ASSERT_VAL("wrong thread", stat->thread == 2);
+	TEST_ASSERT_VAL("wrong id",     stat->id     == 3);
+	TEST_ASSERT_VAL("wrong val",    stat->val    == 100);
+	TEST_ASSERT_VAL("wrong run",    stat->ena    == 200);
+	TEST_ASSERT_VAL("wrong ena",    stat->run    == 300);
+	return 0;
+}
+
+int test__synthesize_stat(void)
+{
+	struct perf_counts_values count = {
+		.val = 100,
+		.ena = 200,
+		.run = 300,
+	};
+
+	TEST_ASSERT_VAL("failed to synthesize stat_config",
+		!perf_event__synthesize_stat(NULL, 1, 2, 3, &count, process_stat_event, NULL));
 
 	return 0;
 }
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index dfb6db7d8a4d..98beb2be1e26 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -65,6 +65,7 @@ int test__thread_map(void);
 int test__thread_map_synthesize(void);
 int test__cpu_map_synthesize(void);
 int test__synthesize_stat_config(void);
+int test__synthesize_stat(void);
 
 #if defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__)
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 6779ab62ff6a..02954385ccdc 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -804,6 +804,28 @@ int perf_event__synthesize_stat_config(struct perf_tool *tool,
 	return err;
 }
 
+int perf_event__synthesize_stat(struct perf_tool *tool,
+				u32 cpu, u32 thread, u64 id,
+				struct perf_counts_values *count,
+				perf_event__handler_t process,
+				struct machine *machine)
+{
+	struct stat_event event;
+
+	event.header.type = PERF_RECORD_STAT;
+	event.header.size = sizeof(event);
+	event.header.misc = 0;
+
+	event.id        = id;
+	event.cpu       = cpu;
+	event.thread    = thread;
+	event.val       = count->val;
+	event.ena       = count->ena;
+	event.run       = count->run;
+
+	return process(tool, (union perf_event *) &event, NULL, machine);
+}
+
 void perf_event__read_stat_config(struct perf_stat_config *config,
 				  struct stat_config_event *event)
 {
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index ab98be7a9612..375b1de34cc6 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -437,6 +437,7 @@ struct perf_tool;
 struct thread_map;
 struct cpu_map;
 struct perf_stat_config;
+struct perf_counts_values;
 
 typedef int (*perf_event__handler_t)(struct perf_tool *tool,
 				     union perf_event *event,
@@ -469,7 +470,11 @@ int perf_event__synthesize_stat_config(struct perf_tool *tool,
 				       struct machine *machine);
 void perf_event__read_stat_config(struct perf_stat_config *config,
 				  struct stat_config_event *event);
-
+int perf_event__synthesize_stat(struct perf_tool *tool,
+				u32 cpu, u32 thread, u64 id,
+				struct perf_counts_values *count,
+				perf_event__handler_t process,
+				struct machine *machine);
 int perf_event__synthesize_modules(struct perf_tool *tool,
 				   perf_event__handler_t process,
 				   struct machine *machine);
-- 
2.4.3


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

* [PATCH 23/47] perf tools: Add stat event read function
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (21 preceding siblings ...)
  2015-07-21 12:31 ` [PATCH 22/47] perf tools: Add stat event synthesize function Jiri Olsa
@ 2015-07-21 12:31 ` Jiri Olsa
  2015-07-21 12:31 ` [PATCH 24/47] perf tools: Add stat round event Jiri Olsa
                   ` (25 subsequent siblings)
  48 siblings, 0 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Introducing perf_event__process_stat_event function to process
'struct perf_stat' data from stat event.

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

diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index c5c709cdc3ce..c5d4b15c6c7a 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -377,3 +377,26 @@ int perf_stat_process_counter(struct perf_stat_config *config,
 
 	return 0;
 }
+
+int perf_event__process_stat_event(struct perf_tool *tool __maybe_unused,
+				   union perf_event *event,
+				   struct perf_session *session)
+{
+	struct perf_counts_values count;
+	struct stat_event *stat = &event->stat;
+	struct perf_evsel *counter;
+
+	count.val = stat->val;
+	count.ena = stat->ena;
+	count.run = stat->run;
+
+	counter = perf_evlist__id2evsel(session->evlist, stat->id);
+	if (!counter) {
+		pr_err("Failed to resolve counter for stat event.\n");
+		return -EINVAL;
+	}
+
+	*perf_counts(counter->counts, stat->cpu, stat->thread) = count;
+	counter->supported = true;
+	return 0;
+}
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 0b897b083682..b69246759cfc 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -119,4 +119,10 @@ void perf_evlist__reset_stats(struct perf_evlist *evlist);
 
 int perf_stat_process_counter(struct perf_stat_config *config,
 			      struct perf_evsel *counter);
+struct perf_tool;
+union perf_event;
+struct perf_session;
+int perf_event__process_stat_event(struct perf_tool *tool,
+				   union perf_event *event,
+				   struct perf_session *session);
 #endif
-- 
2.4.3


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

* [PATCH 24/47] perf tools: Add stat round event
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (22 preceding siblings ...)
  2015-07-21 12:31 ` [PATCH 23/47] perf tools: Add stat event read function Jiri Olsa
@ 2015-07-21 12:31 ` Jiri Olsa
  2015-07-21 12:31 ` [PATCH 25/47] perf tools: Add stat round event synthesize function Jiri Olsa
                   ` (24 subsequent siblings)
  48 siblings, 0 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Adding stat round event to be stored afer each stat interval round,
so report tools (report/script) get notified and process interval
data.

Link: http://lkml.kernel.org/n/tip-nqhzuxrv12ulccx11k7x86mr@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/event.c   |  1 +
 tools/perf/util/event.h   |  7 +++++++
 tools/perf/util/session.c | 20 ++++++++++++++++++++
 tools/perf/util/tool.h    |  3 ++-
 4 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 02954385ccdc..658cb81eb27f 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -40,6 +40,7 @@ static const char *perf_event__names[] = {
 	[PERF_RECORD_CPU_MAP]			= "CPU_MAP",
 	[PERF_RECORD_STAT_CONFIG]		= "STAT_CONFIG",
 	[PERF_RECORD_STAT]			= "STAT",
+	[PERF_RECORD_STAT_ROUND]		= "STAT_ROUND",
 };
 
 const char *perf_event__name(unsigned int id)
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 375b1de34cc6..a4d3b3098613 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -229,6 +229,7 @@ enum perf_user_event_type { /* above any possible kernel type */
 	PERF_RECORD_CPU_MAP			= 74,
 	PERF_RECORD_STAT_CONFIG			= 75,
 	PERF_RECORD_STAT			= 76,
+	PERF_RECORD_STAT_ROUND			= 77,
 	PERF_RECORD_HEADER_MAX
 };
 
@@ -404,6 +405,11 @@ struct stat_event {
 	};
 };
 
+struct stat_round_event {
+	struct perf_event_header	header;
+	u64				time;
+};
+
 union perf_event {
 	struct perf_event_header	header;
 	struct mmap_event		mmap;
@@ -429,6 +435,7 @@ union perf_event {
 	struct cpu_map_event		cpu_map;
 	struct stat_config_event	stat_config;
 	struct stat_event		stat;
+	struct stat_round_event		stat_round;
 };
 
 void perf_event__print_totals(void);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index e0ad3e691e6a..4b957c02fffb 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -347,6 +347,15 @@ static int process_stat_stub(struct perf_tool *tool __maybe_unused,
 	return 0;
 }
 
+static int process_stat_round_stub(struct perf_tool *tool __maybe_unused,
+				   union perf_event *event __maybe_unused,
+				   struct perf_session *perf_session
+				   __maybe_unused)
+{
+	dump_printf(": unhandled!\n");
+	return 0;
+}
+
 void perf_tool__fill_defaults(struct perf_tool *tool)
 {
 	if (tool->sample == NULL)
@@ -403,6 +412,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
 		tool->stat_config = process_event_stat_config_stub;
 	if (tool->stat == NULL)
 		tool->stat = process_stat_stub;
+	if (tool->stat_round == NULL)
+		tool->stat_round = process_stat_round_stub;
 }
 
 static void swap_sample_id_all(union perf_event *event, void *data)
@@ -703,6 +714,12 @@ static void perf_event__stat_swap(union perf_event *event,
 	event->stat.run    = bswap_64(event->stat.run);
 }
 
+static void perf_event__stat_round_swap(union perf_event *event,
+					bool sample_id_all __maybe_unused)
+{
+	event->stat_round.time = bswap_64(event->stat_round.time);
+}
+
 typedef void (*perf_event__swap_op)(union perf_event *event,
 				    bool sample_id_all);
 
@@ -732,6 +749,7 @@ static perf_event__swap_op perf_event__swap_ops[] = {
 	[PERF_RECORD_CPU_MAP]		  = perf_event__cpu_map_swap,
 	[PERF_RECORD_STAT_CONFIG]	  = perf_event__stat_config_swap,
 	[PERF_RECORD_STAT]		  = perf_event__stat_swap,
+	[PERF_RECORD_STAT_ROUND]	  = perf_event__stat_round_swap,
 	[PERF_RECORD_HEADER_MAX]	  = NULL,
 };
 
@@ -1262,6 +1280,8 @@ static s64 perf_session__process_user_event(struct perf_session *session,
 		return tool->stat_config(tool, event, session);
 	case PERF_RECORD_STAT:
 		return tool->stat(tool, event, session);
+	case PERF_RECORD_STAT_ROUND:
+		return tool->stat_round(tool, event, session);
 	default:
 		return -EINVAL;
 	}
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index 49224232995b..fca37b3460cb 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -58,7 +58,8 @@ struct perf_tool {
 			thread_map,
 			cpu_map,
 			stat_config,
-			stat;
+			stat,
+			stat_round;
 	event_op3	auxtrace;
 	bool		ordered_events;
 	bool		ordering_requires_timestamps;
-- 
2.4.3


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

* [PATCH 25/47] perf tools: Add stat round event synthesize function
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (23 preceding siblings ...)
  2015-07-21 12:31 ` [PATCH 24/47] perf tools: Add stat round event Jiri Olsa
@ 2015-07-21 12:31 ` Jiri Olsa
  2015-07-21 12:31 ` [PATCH 26/47] perf tools: Introduce stat feature Jiri Olsa
                   ` (23 subsequent siblings)
  48 siblings, 0 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Introduce perf_event__synthesize_stat_round function to
synthesize 'struct stat_round_event'.

Link: http://lkml.kernel.org/n/tip-gl8rk2il9grrnqalrqlo7iym@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/tests/builtin-test.c |  4 ++++
 tools/perf/tests/stat.c         | 19 +++++++++++++++++++
 tools/perf/tests/tests.h        |  2 ++
 tools/perf/util/event.c         | 16 ++++++++++++++++
 tools/perf/util/event.h         |  4 ++++
 5 files changed, 45 insertions(+)

diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 7d8772c0ea82..4dd6483a6c1c 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -191,6 +191,10 @@ static struct test {
 		.func = test__synthesize_stat,
 	},
 	{
+		.desc = "Test stat round synthesize",
+		.func = test__synthesize_stat_round,
+	},
+	{
 		.func = NULL,
 	},
 };
diff --git a/tools/perf/tests/stat.c b/tools/perf/tests/stat.c
index 31b242159e79..862062256cca 100644
--- a/tools/perf/tests/stat.c
+++ b/tools/perf/tests/stat.c
@@ -87,3 +87,22 @@ int test__synthesize_stat(void)
 
 	return 0;
 }
+
+static int process_stat_round_event(struct perf_tool *tool __maybe_unused,
+				    union perf_event *event,
+				    struct perf_sample *sample __maybe_unused,
+				    struct machine *machine __maybe_unused)
+{
+	struct stat_round_event *stat_round = &event->stat_round;
+
+	TEST_ASSERT_VAL("wrong time",    stat_round->time == 0xdeadbeef);
+	return 0;
+}
+
+int test__synthesize_stat_round(void)
+{
+	TEST_ASSERT_VAL("failed to synthesize stat_config",
+		!perf_event__synthesize_stat_round(NULL, 0xdeadbeef, process_stat_round_event, NULL));
+
+	return 0;
+}
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 98beb2be1e26..ae28421a4834 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -66,6 +66,8 @@ int test__thread_map_synthesize(void);
 int test__cpu_map_synthesize(void);
 int test__synthesize_stat_config(void);
 int test__synthesize_stat(void);
+int test__synthesize_stat_round(void);
+
 
 #if defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__)
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 658cb81eb27f..905c6dc21ac8 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -827,6 +827,22 @@ int perf_event__synthesize_stat(struct perf_tool *tool,
 	return process(tool, (union perf_event *) &event, NULL, machine);
 }
 
+int perf_event__synthesize_stat_round(struct perf_tool *tool,
+				      u64 time,
+				      perf_event__handler_t process,
+				      struct machine *machine)
+{
+	struct stat_round_event event;
+
+	event.header.type = PERF_RECORD_STAT_ROUND;
+	event.header.size = sizeof(event);
+	event.header.misc = 0;
+
+	event.time = time;
+
+	return process(tool, (union perf_event *) &event, NULL, machine);
+}
+
 void perf_event__read_stat_config(struct perf_stat_config *config,
 				  struct stat_config_event *event)
 {
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index a4d3b3098613..d5a248b7643a 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -482,6 +482,10 @@ int perf_event__synthesize_stat(struct perf_tool *tool,
 				struct perf_counts_values *count,
 				perf_event__handler_t process,
 				struct machine *machine);
+int perf_event__synthesize_stat_round(struct perf_tool *tool,
+				      u64 time,
+				      perf_event__handler_t process,
+				      struct machine *machine);
 int perf_event__synthesize_modules(struct perf_tool *tool,
 				   perf_event__handler_t process,
 				   struct machine *machine);
-- 
2.4.3


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

* [PATCH 26/47] perf tools: Introduce stat feature
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (24 preceding siblings ...)
  2015-07-21 12:31 ` [PATCH 25/47] perf tools: Add stat round event synthesize function Jiri Olsa
@ 2015-07-21 12:31 ` Jiri Olsa
  2015-07-21 12:31 ` [PATCH 27/47] perf tools: Move id_offset out of struct perf_evsel union Jiri Olsa
                   ` (22 subsequent siblings)
  48 siblings, 0 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Introducing stat feature to mark perf.data as created by
perf stat record command. It contains no data.

It's needed for report tools (report/script) to differentiate
sampling data from stat data, because they need to be treated
in a different way.

Link: http://lkml.kernel.org/n/tip-56xpt7m6au4d8u39nffoqgx1@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-record.c |  2 ++
 tools/perf/util/header.c    | 14 ++++++++++++++
 tools/perf/util/header.h    |  1 +
 3 files changed, 17 insertions(+)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 283fe96bdfc1..68dda0cffc4e 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -449,6 +449,8 @@ static void record__init_features(struct record *rec)
 
 	if (!rec->opts.full_auxtrace)
 		perf_header__clear_feat(&session->header, HEADER_AUXTRACE);
+
+	perf_header__clear_feat(&session->header, HEADER_STAT);
 }
 
 static volatile int workload_exec_errno;
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 179b2bdd157d..1eb17453d78b 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -883,6 +883,13 @@ static int write_auxtrace(int fd, struct perf_header *h,
 	return err;
 }
 
+static int write_stat(int fd __maybe_unused,
+		      struct perf_header *h __maybe_unused,
+		      struct perf_evlist *evlist __maybe_unused)
+{
+	return 0;
+}
+
 static void print_hostname(struct perf_header *ph, int fd __maybe_unused,
 			   FILE *fp)
 {
@@ -1166,6 +1173,12 @@ static void print_auxtrace(struct perf_header *ph __maybe_unused,
 	fprintf(fp, "# contains AUX area data (e.g. instruction trace)\n");
 }
 
+static void print_stat(struct perf_header *ph __maybe_unused,
+		       int fd __maybe_unused, FILE *fp)
+{
+	fprintf(fp, "# contains stat data\n");
+}
+
 static void print_pmu_mappings(struct perf_header *ph, int fd __maybe_unused,
 			       FILE *fp)
 {
@@ -1899,6 +1912,7 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
 	FEAT_OPP(HEADER_PMU_MAPPINGS,	pmu_mappings),
 	FEAT_OPP(HEADER_GROUP_DESC,	group_desc),
 	FEAT_OPP(HEADER_AUXTRACE,	auxtrace),
+	FEAT_OPA(HEADER_STAT,		stat),
 };
 
 struct header_print_data {
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 9b53b6525ce8..5ef500777428 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -31,6 +31,7 @@ enum {
 	HEADER_PMU_MAPPINGS,
 	HEADER_GROUP_DESC,
 	HEADER_AUXTRACE,
+	HEADER_STAT,
 	HEADER_LAST_FEATURE,
 	HEADER_FEAT_BITS	= 256,
 };
-- 
2.4.3


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

* [PATCH 27/47] perf tools: Move id_offset out of struct perf_evsel union
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (25 preceding siblings ...)
  2015-07-21 12:31 ` [PATCH 26/47] perf tools: Introduce stat feature Jiri Olsa
@ 2015-07-21 12:31 ` Jiri Olsa
  2015-07-21 12:31 ` [PATCH 28/47] perf stat record: Add record command Jiri Olsa
                   ` (21 subsequent siblings)
  48 siblings, 0 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Because following stat patches use id_offset together
with priv pointer.

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

diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index fe9f3279632b..6e0bcf74b33b 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -59,9 +59,9 @@ struct perf_evsel {
 	double			scale;
 	const char		*unit;
 	struct event_format	*tp_format;
+	off_t			id_offset;
 	union {
 		void		*priv;
-		off_t		id_offset;
 		u64		db_id;
 	};
 	struct cgroup_sel	*cgrp;
-- 
2.4.3


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

* [PATCH 28/47] perf stat record: Add record command
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (26 preceding siblings ...)
  2015-07-21 12:31 ` [PATCH 27/47] perf tools: Move id_offset out of struct perf_evsel union Jiri Olsa
@ 2015-07-21 12:31 ` Jiri Olsa
  2015-07-21 12:31 ` [PATCH 29/47] perf stat record: Initialize record features Jiri Olsa
                   ` (20 subsequent siblings)
  48 siblings, 0 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Add 'perf stat record' command support. It creates simple
(header only) perf.data file ATM.

Link: http://lkml.kernel.org/n/tip-0av5yfkwyywwgoiali88w4hi@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/Documentation/perf-stat.txt | 12 ++++++
 tools/perf/builtin-stat.c              | 74 +++++++++++++++++++++++++++++++++-
 2 files changed, 84 insertions(+), 2 deletions(-)

diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 47469abdcc1c..0ccce466ad53 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -10,6 +10,7 @@ SYNOPSIS
 [verse]
 'perf stat' [-e <EVENT> | --event=EVENT] [-a] <command>
 'perf stat' [-e <EVENT> | --event=EVENT] [-a] -- <command> [<options>]
+'perf stat' [-e <EVENT> | --event=EVENT] [-a] record [-o file] -- <command> [<options>]
 
 DESCRIPTION
 -----------
@@ -22,6 +23,8 @@ OPTIONS
 <command>...::
 	Any command you can specify in a shell.
 
+record::
+	See STAT RECORD.
 
 -e::
 --event=::
@@ -158,6 +161,15 @@ filter out the startup phase of the program, which is often very different.
 
 Print statistics of transactional execution if supported.
 
+STAT RECORD
+-----------
+Stores stat data into perf data file.
+
+-o file::
+--output file::
+Output file name.
+
+
 EXAMPLES
 --------
 
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index a054ddc0b2a0..f78bd3e22d40 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -58,6 +58,7 @@
 #include "util/cpumap.h"
 #include "util/thread.h"
 #include "util/thread_map.h"
+#include "util/session.h"
 
 #include <stdlib.h>
 #include <sys/prctl.h>
@@ -120,6 +121,16 @@ static struct timespec		ref_time;
 static struct cpu_map		*aggr_map;
 static int			(*aggr_get_id)(struct cpu_map *m, int cpu);
 
+struct perf_stat_record {
+	bool			 enabled;
+	struct perf_data_file	 file;
+	struct perf_session	*session;
+	u64			 bytes_written;
+};
+
+static struct perf_stat_record	stat_record;
+#define STAT_RECORD		stat_record.enabled
+
 static volatile int done = 0;
 
 static struct perf_stat_config stat_config = {
@@ -338,6 +349,15 @@ static int __run_perf_stat(int argc, const char **argv)
 		return -1;
 	}
 
+	if (STAT_RECORD) {
+		int err, fd = perf_data_file__fd(&stat_record.file);
+
+		err = perf_session__write_header(stat_record.session, evsel_list,
+						 fd, false);
+		if (err < 0)
+			return err;
+	}
+
 	/*
 	 * Enable counters and exec the command:
 	 */
@@ -1125,6 +1145,39 @@ static int add_default_attributes(void)
 	return perf_evlist__add_default_attrs(evsel_list, very_very_detailed_attrs);
 }
 
+static const char * const recort_usage[] = {
+	"perf stat record [<options>]",
+	NULL,
+};
+
+static int __cmd_record(int argc, const char **argv)
+{
+	struct perf_session *session;
+	struct perf_data_file *file = &stat_record.file;
+	const struct option options[] = {
+	OPT_STRING('o', "output", &stat_record.file.path, "file", "output file name"),
+	OPT_END()
+	};
+
+	argc = parse_options(argc, argv, options, record_usage,
+			     PARSE_OPT_STOP_AT_NON_OPTION);
+
+	session = perf_session__new(file, false, NULL);
+	if (session == NULL) {
+		pr_err("Perf session creation failed.\n");
+		return -1;
+	}
+
+	/* No pipe support ATM */
+	if (stat_record.file.is_pipe)
+		return -EINVAL;
+
+	session->evlist      = evsel_list;
+	stat_record.session  = session;
+	stat_record.enabled  = true;
+	return argc;
+}
+
 int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 {
 	bool append_file = false;
@@ -1198,6 +1251,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 	const char *mode;
 	FILE *output = stderr;
 	unsigned int interval;
+	const char * const stat_subcommands[] = { "record" };
 
 	setlocale(LC_ALL, "");
 
@@ -1205,8 +1259,15 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 	if (evsel_list == NULL)
 		return -ENOMEM;
 
-	argc = parse_options(argc, argv, options, stat_usage,
-		PARSE_OPT_STOP_AT_NON_OPTION);
+	argc = parse_options_subcommand(argc, argv, options, stat_subcommands,
+					(const char **) stat_usage,
+					PARSE_OPT_STOP_AT_NON_OPTION);
+
+	if (argc && !strncmp(argv[0], "rec", 3)) {
+		argc = __cmd_record(argc, argv);
+		if (argc < 0)
+			return -1;
+	}
 
 	interval = stat_config.interval;
 
@@ -1372,6 +1433,15 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 	if (!forever && status != -1 && !interval)
 		print_counters(NULL, argc, argv);
 
+	if (STAT_RECORD) {
+		int fd = perf_data_file__fd(&stat_record.file);
+
+		stat_record.session->header.data_size += stat_record.bytes_written;
+		perf_session__write_header(stat_record.session, evsel_list, fd, true);
+
+		perf_session__delete(stat_record.session);
+	}
+
 	perf_evlist__free_stats(evsel_list);
 out:
 	perf_evlist__delete(evsel_list);
-- 
2.4.3


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

* [PATCH 29/47] perf stat record: Initialize record features
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (27 preceding siblings ...)
  2015-07-21 12:31 ` [PATCH 28/47] perf stat record: Add record command Jiri Olsa
@ 2015-07-21 12:31 ` Jiri Olsa
  2015-07-21 12:31 ` [PATCH 30/47] perf stat record: Synthesize stat record data Jiri Olsa
                   ` (19 subsequent siblings)
  48 siblings, 0 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Disabling all non stat related features.

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

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index f78bd3e22d40..95030e686bc4 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1150,6 +1150,19 @@ static const char * const recort_usage[] = {
 	NULL,
 };
 
+static void init_features(struct perf_session *session)
+{
+	int feat;
+
+	for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
+		perf_header__set_feat(&session->header, feat);
+
+	perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
+	perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
+	perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
+	perf_header__clear_feat(&session->header, HEADER_AUXTRACE);
+}
+
 static int __cmd_record(int argc, const char **argv)
 {
 	struct perf_session *session;
@@ -1172,6 +1185,8 @@ static int __cmd_record(int argc, const char **argv)
 	if (stat_record.file.is_pipe)
 		return -EINVAL;
 
+	init_features(session);
+
 	session->evlist      = evsel_list;
 	stat_record.session  = session;
 	stat_record.enabled  = true;
-- 
2.4.3


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

* [PATCH 30/47] perf stat record: Synthesize stat record data
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (28 preceding siblings ...)
  2015-07-21 12:31 ` [PATCH 29/47] perf stat record: Initialize record features Jiri Olsa
@ 2015-07-21 12:31 ` Jiri Olsa
  2015-07-21 12:31 ` [PATCH 31/47] perf stat record: Store events IDs in perf data file Jiri Olsa
                   ` (18 subsequent siblings)
  48 siblings, 0 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Synthesizing needed stat record data for report/script:
  - cpu/thread maps
  - stat config

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

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 95030e686bc4..50d7c8ba0e00 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -190,6 +190,20 @@ static inline int nsec_counter(struct perf_evsel *evsel)
 	return 0;
 }
 
+static int process_synthesized_event(struct perf_tool *tool __maybe_unused,
+				     union perf_event *event,
+				     struct perf_sample *sample __maybe_unused,
+				     struct machine *machine __maybe_unused)
+{
+	if (perf_data_file__write(&stat_record.file, event, event->header.size) < 0) {
+		pr_err("failed to write perf data, error: %m\n");
+		return -1;
+	}
+
+	stat_record.bytes_written += event->header.size;
+	return 0;
+}
+
 /*
  * Read out the results of a single counter:
  * do not aggregate counts across CPUs in system-wide mode
@@ -276,6 +290,36 @@ 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(void)
+{
+	int err;
+
+	err = perf_event__synthesize_stat_config(NULL, &stat_config,
+						 process_synthesized_event, NULL);
+	if (err < 0) {
+		pr_err("Couldn't synthesize config.\n");
+		return err;
+	}
+
+	err = perf_event__synthesize_thread_map2(NULL, evsel_list->threads,
+						process_synthesized_event,
+						NULL);
+	if (err < 0) {
+		pr_err("Couldn't synthesize thread map.\n");
+		return err;
+	}
+
+	err = perf_event__synthesize_cpu_map(NULL, evsel_list->cpus,
+					     process_synthesized_event,
+					     NULL);
+	if (err < 0) {
+		pr_err("Couldn't synthesize thread map.\n");
+		return err;
+	}
+
+	return 0;
+}
+
 static int __run_perf_stat(int argc, const char **argv)
 {
 	int interval = stat_config.interval;
@@ -356,6 +400,10 @@ static int __run_perf_stat(int argc, const char **argv)
 						 fd, false);
 		if (err < 0)
 			return err;
+
+		err = perf_stat_synthesize_config();
+		if (err < 0)
+			return err;
 	}
 
 	/*
-- 
2.4.3


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

* [PATCH 31/47] perf stat record: Store events IDs in perf data file
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (29 preceding siblings ...)
  2015-07-21 12:31 ` [PATCH 30/47] perf stat record: Synthesize stat record data Jiri Olsa
@ 2015-07-21 12:31 ` Jiri Olsa
  2015-07-21 12:31 ` [PATCH 32/47] perf stat record: Add pipe support for record command Jiri Olsa
                   ` (17 subsequent siblings)
  48 siblings, 0 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Store event IDs in evlist object so it get stored
into perf.data file.

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

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 50d7c8ba0e00..eba46eeacd91 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -320,6 +320,38 @@ static int perf_stat_synthesize_config(void)
 	return 0;
 }
 
+#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
+
+static int __store_counter_ids(struct perf_evsel *counter,
+			       struct cpu_map *cpus,
+			       struct thread_map *threads)
+{
+	int cpu, thread;
+
+	for (cpu = 0; cpu < cpus->nr; cpu++) {
+		for (thread = 0; thread < threads->nr; 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, cpus, threads);
+}
+
 static int __run_perf_stat(int argc, const char **argv)
 {
 	int interval = stat_config.interval;
@@ -384,6 +416,9 @@ static int __run_perf_stat(int argc, const char **argv)
 		l = strlen(counter->unit);
 		if (l > unit_width)
 			unit_width = l;
+
+		if (STAT_RECORD && store_counter_ids(counter))
+			return -1;
 	}
 
 	if (perf_evlist__apply_filters(evsel_list, &counter)) {
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 3b9f411a6b46..28c2e9b1eab9 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -496,9 +496,9 @@ void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel,
 	evsel->id[evsel->ids++] = id;
 }
 
-static int perf_evlist__id_add_fd(struct perf_evlist *evlist,
-				  struct perf_evsel *evsel,
-				  int cpu, int thread, int fd)
+int perf_evlist__id_add_fd(struct perf_evlist *evlist,
+			   struct perf_evsel *evsel,
+			   int cpu, int thread, int fd)
 {
 	u64 read_data[4] = { 0, };
 	int id_idx = 1; /* The first entry is the counter value */
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 406a8216a51e..c02d7bc64a65 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -94,6 +94,9 @@ perf_evlist__find_tracepoint_by_name(struct perf_evlist *evlist,
 
 void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel,
 			 int cpu, int thread, u64 id);
+int perf_evlist__id_add_fd(struct perf_evlist *evlist,
+			   struct perf_evsel *evsel,
+			   int cpu, int thread, int fd);
 
 int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd);
 int perf_evlist__alloc_pollfd(struct perf_evlist *evlist);
-- 
2.4.3


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

* [PATCH 32/47] perf stat record: Add pipe support for record command
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (30 preceding siblings ...)
  2015-07-21 12:31 ` [PATCH 31/47] perf stat record: Store events IDs in perf data file Jiri Olsa
@ 2015-07-21 12:31 ` Jiri Olsa
  2015-07-21 12:31 ` [PATCH 33/47] perf stat record: Write stat events on record Jiri Olsa
                   ` (16 subsequent siblings)
  48 siblings, 0 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Allowing storing stat record data into pipe, so report
tools (report/script) could read data directly from
record.

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

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index eba46eeacd91..d6ba710e7358 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -290,7 +290,7 @@ 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(void)
+static int perf_stat_synthesize_config(bool is_pipe)
 {
 	int err;
 
@@ -301,6 +301,15 @@ static int perf_stat_synthesize_config(void)
 		return err;
 	}
 
+	if (is_pipe) {
+		err = perf_event__synthesize_attrs(NULL, stat_record.session,
+						   process_synthesized_event);
+		if (err < 0) {
+			pr_err("Couldn't synthesize attrs.\n");
+			return err;
+		}
+	}
+
 	err = perf_event__synthesize_thread_map2(NULL, evsel_list->threads,
 						process_synthesized_event,
 						NULL);
@@ -362,6 +371,7 @@ static int __run_perf_stat(int argc, const char **argv)
 	size_t l;
 	int status = 0;
 	const bool forks = (argc > 0);
+	bool is_pipe = STAT_RECORD ? stat_record.file.is_pipe : false;
 
 	if (interval) {
 		ts.tv_sec  = interval / 1000;
@@ -372,7 +382,7 @@ static int __run_perf_stat(int argc, const char **argv)
 	}
 
 	if (forks) {
-		if (perf_evlist__prepare_workload(evsel_list, &target, argv, false,
+		if (perf_evlist__prepare_workload(evsel_list, &target, argv, is_pipe,
 						  workload_exec_failed_signal) < 0) {
 			perror("failed to prepare workload");
 			return -1;
@@ -431,12 +441,17 @@ static int __run_perf_stat(int argc, const char **argv)
 	if (STAT_RECORD) {
 		int err, fd = perf_data_file__fd(&stat_record.file);
 
-		err = perf_session__write_header(stat_record.session, evsel_list,
-						 fd, false);
+		if (is_pipe) {
+			err = perf_header__write_pipe(perf_data_file__fd(&stat_record.file));
+		} else {
+			err = perf_session__write_header(stat_record.session, evsel_list,
+							 fd, false);
+		}
+
 		if (err < 0)
 			return err;
 
-		err = perf_stat_synthesize_config();
+		err = perf_stat_synthesize_config(is_pipe);
 		if (err < 0)
 			return err;
 	}
@@ -961,6 +976,10 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)
 	struct perf_evsel *counter;
 	char buf[64], *prefix = NULL;
 
+	/* Do not print anything if we record to the pipe. */
+	if (STAT_RECORD && stat_record.file.is_pipe)
+		return;
+
 	if (interval)
 		print_interval(prefix = buf, ts);
 	else
@@ -1264,10 +1283,6 @@ static int __cmd_record(int argc, const char **argv)
 		return -1;
 	}
 
-	/* No pipe support ATM */
-	if (stat_record.file.is_pipe)
-		return -EINVAL;
-
 	init_features(session);
 
 	session->evlist      = evsel_list;
@@ -1534,8 +1549,10 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 	if (STAT_RECORD) {
 		int fd = perf_data_file__fd(&stat_record.file);
 
-		stat_record.session->header.data_size += stat_record.bytes_written;
-		perf_session__write_header(stat_record.session, evsel_list, fd, true);
+		if (!stat_record.file.is_pipe) {
+			stat_record.session->header.data_size += stat_record.bytes_written;
+			perf_session__write_header(stat_record.session, evsel_list, fd, true);
+		}
 
 		perf_session__delete(stat_record.session);
 	}
-- 
2.4.3


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

* [PATCH 33/47] perf stat record: Write stat events on record
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (31 preceding siblings ...)
  2015-07-21 12:31 ` [PATCH 32/47] perf stat record: Add pipe support for record command Jiri Olsa
@ 2015-07-21 12:31 ` Jiri Olsa
  2015-07-21 12:31 ` [PATCH 34/47] perf stat record: Write stat round " Jiri Olsa
                   ` (15 subsequent siblings)
  48 siblings, 0 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Writing stat events on 'perf stat record' at the time
we read counter values from kernel.

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

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index d6ba710e7358..49948be5680f 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -204,6 +204,18 @@ static int process_synthesized_event(struct perf_tool *tool __maybe_unused,
 	return 0;
 }
 
+#define SID(e, x, y) xyarray__entry(e->sample_id, x, y)
+
+static int
+perf_evsel__write_stat_event(struct perf_evsel *counter, u32 cpu, u32 thread,
+			     struct perf_counts_values *count)
+{
+	struct perf_sample_id *sid = SID(counter, cpu, thread);
+
+	return perf_event__synthesize_stat(NULL, cpu, thread, sid->id, count,
+					   process_synthesized_event, NULL);
+}
+
 /*
  * Read out the results of a single counter:
  * do not aggregate counts across CPUs in system-wide mode
@@ -227,6 +239,13 @@ static int read_counter(struct perf_evsel *counter)
 			count = perf_counts(counter->counts, cpu, thread);
 			if (perf_evsel__read(counter, cpu, thread, count))
 				return -1;
+
+			if (STAT_RECORD) {
+				if (perf_evsel__write_stat_event(counter, cpu, thread, count)) {
+					pr_err("failed to write stat event\n");
+					return -1;
+				}
+			}
 		}
 	}
 
-- 
2.4.3


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

* [PATCH 34/47] perf stat record: Write stat round events on record
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (32 preceding siblings ...)
  2015-07-21 12:31 ` [PATCH 33/47] perf stat record: Write stat events on record Jiri Olsa
@ 2015-07-21 12:31 ` Jiri Olsa
  2015-07-21 12:31 ` [PATCH 35/47] perf stat report: Add report command Jiri Olsa
                   ` (14 subsequent siblings)
  48 siblings, 0 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Writing stat round events on 'perf stat record' for
each interval round. In non interval mode we store
round event after the last stat event.

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

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 49948be5680f..8ad497522a0e 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -204,6 +204,13 @@ static int process_synthesized_event(struct perf_tool *tool __maybe_unused,
 	return 0;
 }
 
+static int write_stat_round_event(u64 time)
+{
+	return perf_event__synthesize_stat_round(NULL, time,
+						 process_synthesized_event,
+						 NULL);
+}
+
 #define SID(e, x, y) xyarray__entry(e->sample_id, x, y)
 
 static int
@@ -279,6 +286,11 @@ static void process_interval(void)
 	clock_gettime(CLOCK_MONOTONIC, &ts);
 	diff_timespec(&rs, &ts, &ref_time);
 
+	if (STAT_RECORD) {
+		if (write_stat_round_event(rs.tv_sec * NSECS_PER_SEC + rs.tv_nsec))
+			pr_err("failed to write stat round event\n");
+	}
+
 	print_counters(&rs, 0, NULL);
 }
 
@@ -1568,6 +1580,11 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 	if (STAT_RECORD) {
 		int fd = perf_data_file__fd(&stat_record.file);
 
+		if (!interval) {
+			if (write_stat_round_event(0))
+				pr_err("failed to write stat round event\n");
+		}
+
 		if (!stat_record.file.is_pipe) {
 			stat_record.session->header.data_size += stat_record.bytes_written;
 			perf_session__write_header(stat_record.session, evsel_list, fd, true);
-- 
2.4.3


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

* [PATCH 35/47] perf stat report: Add report command
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (33 preceding siblings ...)
  2015-07-21 12:31 ` [PATCH 34/47] perf stat record: Write stat round " Jiri Olsa
@ 2015-07-21 12:31 ` Jiri Olsa
  2015-07-21 12:31 ` [PATCH 36/47] perf stat report: Process cpu/threads maps Jiri Olsa
                   ` (13 subsequent siblings)
  48 siblings, 0 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Adding 'perf stat report' command support. ATM it only
processes attr events and display nothing.

Link: http://lkml.kernel.org/n/tip-a43rs4c6szofeuo2gjlcpm0h@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/Documentation/perf-stat.txt | 12 ++++++++
 tools/perf/builtin-stat.c              | 54 +++++++++++++++++++++++++++++++---
 tools/perf/util/session.c              |  3 ++
 3 files changed, 65 insertions(+), 4 deletions(-)

diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 0ccce466ad53..f7234c6263c0 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -11,6 +11,7 @@ SYNOPSIS
 'perf stat' [-e <EVENT> | --event=EVENT] [-a] <command>
 'perf stat' [-e <EVENT> | --event=EVENT] [-a] -- <command> [<options>]
 'perf stat' [-e <EVENT> | --event=EVENT] [-a] record [-o file] -- <command> [<options>]
+'perf stat' report [-i file]
 
 DESCRIPTION
 -----------
@@ -26,6 +27,9 @@ OPTIONS
 record::
 	See STAT RECORD.
 
+report::
+	See STAT REPORT.
+
 -e::
 --event=::
 	Select the PMU event. Selection can be:
@@ -169,6 +173,14 @@ Stores stat data into perf data file.
 --output file::
 Output file name.
 
+STAT RECORD
+-----------
+Reads and reports stat data from perf data file.
+
+-i file::
+--input file::
+Input file name.
+
 
 EXAMPLES
 --------
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 8ad497522a0e..aa2352f92878 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -59,6 +59,8 @@
 #include "util/thread.h"
 #include "util/thread_map.h"
 #include "util/session.h"
+#include "util/tool.h"
+#include "asm/bug.h"
 
 #include <stdlib.h>
 #include <sys/prctl.h>
@@ -138,6 +140,10 @@ static struct perf_stat_config stat_config = {
 	.scale		= true,
 };
 
+struct perf_stat_cmd {
+	struct perf_tool	tool;
+};
+
 static inline void diff_timespec(struct timespec *r, struct timespec *a,
 				 struct timespec *b)
 {
@@ -970,8 +976,8 @@ static void print_header(int argc, const char **argv)
 		else if (target.cpu_list)
 			fprintf(output, "\'CPU(s) %s", target.cpu_list);
 		else if (!target__has_task(&target)) {
-			fprintf(output, "\'%s", argv[0]);
-			for (i = 1; i < argc; i++)
+			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);
@@ -1322,6 +1328,45 @@ static int __cmd_record(int argc, const char **argv)
 	return argc;
 }
 
+static const char * const report_usage[] = {
+	"perf stat report [<options>]",
+	NULL,
+};
+
+static int __cmd_report(int argc, const char **argv)
+{
+	struct perf_session *session;
+	const struct option options[] = {
+	OPT_STRING('i', "input", &input_name, "file", "input file name"),
+	OPT_END()
+	};
+	struct perf_data_file file = {
+		.mode  = PERF_DATA_MODE_READ,
+	};
+	struct perf_stat_cmd stat = {
+		.tool = {
+			.attr		= perf_event__process_attr,
+		},
+	};
+	int ret;
+
+	argc = parse_options(argc, argv, options, report_usage, 0);
+
+	session = perf_session__new(&file, false, &stat.tool);
+	if (session == NULL)
+		return -1;
+
+	stat_config.output = stderr;
+	evsel_list         = session->evlist;
+
+	ret = perf_session__process_events(session);
+	if (ret)
+		return ret;
+
+	perf_session__delete(session);
+	return 0;
+}
+
 int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 {
 	bool append_file = false;
@@ -1395,7 +1440,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 	const char *mode;
 	FILE *output = stderr;
 	unsigned int interval;
-	const char * const stat_subcommands[] = { "record" };
+	const char * const stat_subcommands[] = { "record", "report" };
 
 	setlocale(LC_ALL, "");
 
@@ -1411,7 +1456,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 		argc = __cmd_record(argc, argv);
 		if (argc < 0)
 			return -1;
-	}
+	} else if (argc && !strncmp(argv[0], "rep", 3))
+		return __cmd_report(argc, argv);
 
 	interval = stat_config.interval;
 
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 4b957c02fffb..4fdd0458a166 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -36,6 +36,9 @@ static int perf_session__open(struct perf_session *session)
 	if (perf_data_file__is_pipe(file))
 		return 0;
 
+	if (perf_header__has_feat(&session->header, HEADER_STAT))
+		return 0;
+
 	if (!perf_evlist__valid_sample_type(session->evlist)) {
 		pr_err("non matching sample_type");
 		return -1;
-- 
2.4.3


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

* [PATCH 36/47] perf stat report: Process cpu/threads maps
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (34 preceding siblings ...)
  2015-07-21 12:31 ` [PATCH 35/47] perf stat report: Add report command Jiri Olsa
@ 2015-07-21 12:31 ` Jiri Olsa
  2015-07-21 12:31 ` [PATCH 37/47] perf stat report: Process stat config event Jiri Olsa
                   ` (12 subsequent siblings)
  48 siblings, 0 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Adding processing of cpu/threads maps. Configuring session's
evlist with these maps.

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

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index aa2352f92878..a1a5e5b2b69c 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -142,6 +142,9 @@ static struct perf_stat_config stat_config = {
 
 struct perf_stat_cmd {
 	struct perf_tool	tool;
+	bool			allocated;
+	struct cpu_map		*cpus;
+	struct thread_map	*threads;
 };
 
 static inline void diff_timespec(struct timespec *r, struct timespec *a,
@@ -1328,6 +1331,60 @@ static int __cmd_record(int argc, const char **argv)
 	return argc;
 }
 
+static int set_maps(struct perf_stat_cmd *stat)
+{
+	if (!stat->cpus || !stat->threads)
+		return 0;
+
+	if (WARN_ONCE(stat->allocated, "stats double allocation\n"))
+		return -EINVAL;
+
+	if (perf_evlist__set_maps(evsel_list, stat->cpus, stat->threads) ||
+	    perf_evlist__alloc_stats(evsel_list, true))
+		return -ENOMEM;
+
+	stat->allocated = true;
+	return 0;
+}
+
+static
+int process_thread_map_event(struct perf_tool *tool __maybe_unused,
+			     union perf_event *event,
+			     struct perf_session *session __maybe_unused)
+{
+	struct perf_stat_cmd *stat = container_of(tool, struct perf_stat_cmd, tool);
+
+	if (stat->threads) {
+		pr_warning("Extra thread map event, ignoring.\n");
+		return 0;
+	}
+
+	stat->threads = thread_map__new_event(&event->thread_map);
+	if (!stat->threads)
+		return -ENOMEM;
+
+	return set_maps(stat);
+}
+
+static
+int process_cpu_map_event(struct perf_tool *tool __maybe_unused,
+			  union perf_event *event,
+			  struct perf_session *session __maybe_unused)
+{
+	struct perf_stat_cmd *stat = container_of(tool, struct perf_stat_cmd, tool);
+
+	if (stat->cpus) {
+		pr_warning("Extra cpu map event, ignoring.\n");
+		return 0;
+	}
+
+	stat->cpus = cpu_map__new_event(&event->cpu_map);
+	if (!stat->cpus)
+		return -ENOMEM;
+
+	return set_maps(stat);
+}
+
 static const char * const report_usage[] = {
 	"perf stat report [<options>]",
 	NULL,
@@ -1346,6 +1403,8 @@ static int __cmd_report(int argc, const char **argv)
 	struct perf_stat_cmd stat = {
 		.tool = {
 			.attr		= perf_event__process_attr,
+			.thread_map	= process_thread_map_event,
+			.cpu_map	= process_cpu_map_event,
 		},
 	};
 	int ret;
-- 
2.4.3


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

* [PATCH 37/47] perf stat report: Process stat config event
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (35 preceding siblings ...)
  2015-07-21 12:31 ` [PATCH 36/47] perf stat report: Process cpu/threads maps Jiri Olsa
@ 2015-07-21 12:31 ` Jiri Olsa
  2015-07-21 12:31 ` [PATCH 38/47] perf stat report: Process stat and stat round events Jiri Olsa
                   ` (11 subsequent siblings)
  48 siblings, 0 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Adding processing of stat config event and initialize
stat_config object.

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

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index a1a5e5b2b69c..6db3c435539e 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1331,6 +1331,15 @@ static int __cmd_record(int argc, const char **argv)
 	return argc;
 }
 
+static
+int process_stat_config_event(struct perf_tool *tool __maybe_unused,
+			      union perf_event *event,
+			      struct perf_session *session __maybe_unused)
+{
+	perf_event__read_stat_config(&stat_config, &event->stat_config);
+	return 0;
+}
+
 static int set_maps(struct perf_stat_cmd *stat)
 {
 	if (!stat->cpus || !stat->threads)
@@ -1403,6 +1412,7 @@ static int __cmd_report(int argc, const char **argv)
 	struct perf_stat_cmd stat = {
 		.tool = {
 			.attr		= perf_event__process_attr,
+			.stat_config	= process_stat_config_event,
 			.thread_map	= process_thread_map_event,
 			.cpu_map	= process_cpu_map_event,
 		},
-- 
2.4.3


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

* [PATCH 38/47] perf stat report: Process stat and stat round events
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (36 preceding siblings ...)
  2015-07-21 12:31 ` [PATCH 37/47] perf stat report: Process stat config event Jiri Olsa
@ 2015-07-21 12:31 ` Jiri Olsa
  2015-07-21 12:31 ` [PATCH 39/47] perf stat report: Move csv_sep initialization before report command Jiri Olsa
                   ` (10 subsequent siblings)
  48 siblings, 0 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Adding processing of stat and stat round events.

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

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 6db3c435539e..6602323ecd43 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1331,6 +1331,29 @@ static int __cmd_record(int argc, const char **argv)
 	return argc;
 }
 
+static int process_stat_round_event(struct perf_tool *tool __maybe_unused,
+				    union perf_event *event,
+				    struct perf_session *session)
+{
+	struct stat_round_event *round = &event->stat_round;
+	struct perf_evsel *counter;
+	struct timespec tsh, *ts = NULL;
+	const char **argv = session->header.env.cmdline_argv;
+	int argc = session->header.env.nr_cmdline;
+
+	evlist__for_each(evsel_list, counter)
+		perf_stat_process_counter(&stat_config, counter);
+
+	if (stat_config.interval && round->time) {
+		tsh.tv_sec  = round->time / NSECS_PER_SEC;
+		tsh.tv_nsec = round->time % NSECS_PER_SEC;
+		ts = &tsh;
+	}
+
+	print_counters(ts, argc, argv);
+	return 0;
+}
+
 static
 int process_stat_config_event(struct perf_tool *tool __maybe_unused,
 			      union perf_event *event,
@@ -1412,6 +1435,8 @@ static int __cmd_report(int argc, const char **argv)
 	struct perf_stat_cmd stat = {
 		.tool = {
 			.attr		= perf_event__process_attr,
+			.stat		= perf_event__process_stat_event,
+			.stat_round	= process_stat_round_event,
 			.stat_config	= process_stat_config_event,
 			.thread_map	= process_thread_map_event,
 			.cpu_map	= process_cpu_map_event,
-- 
2.4.3


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

* [PATCH 39/47] perf stat report: Move csv_sep initialization before report command
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (37 preceding siblings ...)
  2015-07-21 12:31 ` [PATCH 38/47] perf stat report: Process stat and stat round events Jiri Olsa
@ 2015-07-21 12:31 ` Jiri Olsa
  2015-07-21 12:32 ` [PATCH 40/47] perf script: Check output fields only for samples Jiri Olsa
                   ` (9 subsequent siblings)
  48 siblings, 0 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

So we have csv_sep properly initialized before
report command leg.

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

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 6602323ecd43..a5c831a242a7 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1546,6 +1546,13 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 					(const char **) stat_usage,
 					PARSE_OPT_STOP_AT_NON_OPTION);
 
+	if (csv_sep) {
+		csv_output = true;
+		if (!strcmp(csv_sep, "\\t"))
+			csv_sep = "\t";
+	} else
+		csv_sep = DEFAULT_SEPARATOR;
+
 	if (argc && !strncmp(argv[0], "rec", 3)) {
 		argc = __cmd_record(argc, argv);
 		if (argc < 0)
@@ -1593,13 +1600,6 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 
 	stat_config.output = output;
 
-	if (csv_sep) {
-		csv_output = true;
-		if (!strcmp(csv_sep, "\\t"))
-			csv_sep = "\t";
-	} else
-		csv_sep = DEFAULT_SEPARATOR;
-
 	/*
 	 * let the spreadsheet do the pretty-printing
 	 */
-- 
2.4.3


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

* [PATCH 40/47] perf script: Check output fields only for samples
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (38 preceding siblings ...)
  2015-07-21 12:31 ` [PATCH 39/47] perf stat report: Move csv_sep initialization before report command Jiri Olsa
@ 2015-07-21 12:32 ` Jiri Olsa
  2015-07-21 12:32 ` [PATCH 41/47] perf script: Process cpu/threads maps Jiri Olsa
                   ` (8 subsequent siblings)
  48 siblings, 0 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

There's no need to check sampling output fields
for events without perf_event_attr::sample_type
field set.

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

diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 24809787369f..308c022ae918 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -650,7 +650,10 @@ static int process_attr(struct perf_tool *tool, union perf_event *event,
 
 	set_print_ip_opts(&evsel->attr);
 
-	return perf_evsel__check_attr(evsel, scr->session);
+	if (evsel->attr.sample_type)
+		err = perf_evsel__check_attr(evsel, scr->session);
+
+	return err;
 }
 
 static int process_comm_event(struct perf_tool *tool,
-- 
2.4.3


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

* [PATCH 41/47] perf script: Process cpu/threads maps
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (39 preceding siblings ...)
  2015-07-21 12:32 ` [PATCH 40/47] perf script: Check output fields only for samples Jiri Olsa
@ 2015-07-21 12:32 ` Jiri Olsa
  2015-07-21 12:32 ` [PATCH 42/47] perf script: Process stat config event Jiri Olsa
                   ` (7 subsequent siblings)
  48 siblings, 0 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Adding processing of cpu/threads maps. Configuring session's
evlist with these maps.

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

diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 308c022ae918..051177d5daed 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -17,7 +17,10 @@
 #include "util/sort.h"
 #include "util/data.h"
 #include "util/auxtrace.h"
+#include "util/cpumap.h"
+#include "util/thread_map.h"
 #include <linux/bitmap.h>
+#include "asm/bug.h"
 
 static char const		*script_name;
 static char const		*generate_script_lang;
@@ -623,6 +626,9 @@ struct perf_script {
 	struct perf_session	*session;
 	bool			show_task_events;
 	bool			show_mmap_events;
+	bool			allocated;
+	struct cpu_map		*cpus;
+	struct thread_map	*threads;
 };
 
 static int process_attr(struct perf_tool *tool, union perf_event *event,
@@ -1535,6 +1541,62 @@ static int have_cmd(int argc, const char **argv)
 	return 0;
 }
 
+static int set_maps(struct perf_script *script)
+{
+	struct perf_evlist *evlist = script->session->evlist;
+
+	if (!script->cpus || !script->threads)
+		return 0;
+
+	if (WARN_ONCE(script->allocated, "stats double allocation\n"))
+		return -EINVAL;
+
+	if (perf_evlist__set_maps(evlist, script->cpus, script->threads) ||
+	    perf_evlist__alloc_stats(evlist, true))
+		return -ENOMEM;
+
+	script->allocated = true;
+	return 0;
+}
+
+static
+int process_thread_map_event(struct perf_tool *tool,
+			     union perf_event *event,
+			     struct perf_session *session __maybe_unused)
+{
+	struct perf_script *script = container_of(tool, struct perf_script, tool);
+
+	if (script->threads) {
+		pr_warning("Extra thread map event, ignoring.\n");
+		return 0;
+	}
+
+	script->threads = thread_map__new_event(&event->thread_map);
+	if (!script->threads)
+		return -ENOMEM;
+
+	return set_maps(script);
+}
+
+static
+int process_cpu_map_event(struct perf_tool *tool __maybe_unused,
+			  union perf_event *event,
+			  struct perf_session *session __maybe_unused)
+{
+	struct perf_script *script = container_of(tool, struct perf_script, tool);
+
+	if (script->cpus) {
+		pr_warning("Extra cpu map event, ignoring.\n");
+		return 0;
+	}
+
+	script->cpus = cpu_map__new_event(&event->cpu_map);
+	if (!script->cpus)
+		return -ENOMEM;
+
+	return set_maps(script);
+}
+
 int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
 {
 	bool show_full_info = false;
@@ -1563,6 +1625,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
 			.auxtrace_info	 = perf_event__process_auxtrace_info,
 			.auxtrace	 = perf_event__process_auxtrace,
 			.auxtrace_error	 = perf_event__process_auxtrace_error,
+			.thread_map	 = process_thread_map_event,
+			.cpu_map	 = process_cpu_map_event,
 			.ordered_events	 = true,
 			.ordering_requires_timestamps = true,
 		},
@@ -1892,6 +1956,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
 	flush_scripting();
 
 out_delete:
+	perf_evlist__free_stats(session->evlist);
 	perf_session__delete(session);
 
 	if (script_started)
-- 
2.4.3


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

* [PATCH 42/47] perf script: Process stat config event
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (40 preceding siblings ...)
  2015-07-21 12:32 ` [PATCH 41/47] perf script: Process cpu/threads maps Jiri Olsa
@ 2015-07-21 12:32 ` Jiri Olsa
  2015-07-21 12:32 ` [PATCH 43/47] perf script: Add process_stat/process_stat_interval scripting interface Jiri Olsa
                   ` (6 subsequent siblings)
  48 siblings, 0 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Adding processing of stat config event and initialize
stat_config object.

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

diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 051177d5daed..b64e4cdc29e2 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -19,6 +19,7 @@
 #include "util/auxtrace.h"
 #include "util/cpumap.h"
 #include "util/thread_map.h"
+#include "util/stat.h"
 #include <linux/bitmap.h>
 #include "asm/bug.h"
 
@@ -33,6 +34,7 @@ static bool			system_wide;
 static bool			print_flags;
 static const char		*cpu_list;
 static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
+static struct perf_stat_config	stat_config;
 
 enum perf_output_field {
 	PERF_OUTPUT_COMM            = 1U << 0,
@@ -1541,6 +1543,14 @@ static int have_cmd(int argc, const char **argv)
 	return 0;
 }
 
+static int process_stat_config_event(struct perf_tool *tool __maybe_unused,
+				     union perf_event *event,
+				     struct perf_session *session __maybe_unused)
+{
+	perf_event__read_stat_config(&stat_config, &event->stat_config);
+	return 0;
+}
+
 static int set_maps(struct perf_script *script)
 {
 	struct perf_evlist *evlist = script->session->evlist;
@@ -1625,6 +1635,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
 			.auxtrace_info	 = perf_event__process_auxtrace_info,
 			.auxtrace	 = perf_event__process_auxtrace,
 			.auxtrace_error	 = perf_event__process_auxtrace_error,
+			.stat_config	 = process_stat_config_event,
 			.thread_map	 = process_thread_map_event,
 			.cpu_map	 = process_cpu_map_event,
 			.ordered_events	 = true,
-- 
2.4.3


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

* [PATCH 43/47] perf script: Add process_stat/process_stat_interval scripting interface
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (41 preceding siblings ...)
  2015-07-21 12:32 ` [PATCH 42/47] perf script: Process stat config event Jiri Olsa
@ 2015-07-21 12:32 ` Jiri Olsa
  2015-07-21 12:32 ` [PATCH 44/47] perf script: Add stat default handlers Jiri Olsa
                   ` (5 subsequent siblings)
  48 siblings, 0 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Python and perl scripting code will define those
callbacks and get stat data.

Link: http://lkml.kernel.org/n/tip-6802z3siu5f59wdsmhaym3wm@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/trace-event.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index d5168f0be4ec..d84147deae58 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -63,6 +63,7 @@ int tracing_data_put(struct tracing_data *tdata);
 struct addr_location;
 
 struct perf_session;
+struct perf_stat_config;
 
 struct scripting_ops {
 	const char *name;
@@ -73,6 +74,9 @@ struct scripting_ops {
 			       struct perf_sample *sample,
 			       struct perf_evsel *evsel,
 			       struct addr_location *al);
+	void (*process_stat) (struct perf_stat_config *config,
+			      struct perf_evsel *evsel, u64 time);
+	void (*process_stat_interval) (u64 time);
 	int (*generate_script) (struct pevent *pevent, const char *outfile);
 };
 
-- 
2.4.3


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

* [PATCH 44/47] perf script: Add stat default handlers
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (42 preceding siblings ...)
  2015-07-21 12:32 ` [PATCH 43/47] perf script: Add process_stat/process_stat_interval scripting interface Jiri Olsa
@ 2015-07-21 12:32 ` Jiri Olsa
  2015-07-21 12:32 ` [PATCH 45/47] perf script: Display stat events by default Jiri Olsa
                   ` (4 subsequent siblings)
  48 siblings, 0 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Implement struct scripting_ops::(process_stat|process_stat_interval)
handlers - calling scripting handlers from stat events handlers.

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

diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index b64e4cdc29e2..9171c53f504f 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -199,6 +199,9 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
 	struct perf_event_attr *attr = &evsel->attr;
 	bool allow_user_set;
 
+	if (perf_header__has_feat(&session->header, HEADER_STAT))
+		return 0;
+
 	allow_user_set = perf_header__has_feat(&session->header,
 					       HEADER_AUXTRACE);
 
@@ -533,6 +536,14 @@ static void process_event(union perf_event *event, struct perf_sample *sample,
 	printf("\n");
 }
 
+static void process_stat(struct perf_stat_config *config __maybe_unused,
+			 struct perf_evsel *evsel __maybe_unused,
+			 u64 time __maybe_unused)
+{
+}
+
+static void process_stat_interval(u64 time __maybe_unused) { }
+
 static int default_start_script(const char *script __maybe_unused,
 				int argc __maybe_unused,
 				const char **argv __maybe_unused)
@@ -561,6 +572,8 @@ static struct scripting_ops default_scripting_ops = {
 	.flush_script		= default_flush_script,
 	.stop_script		= default_stop_script,
 	.process_event		= process_event,
+	.process_stat		= process_stat,
+	.process_stat_interval	= process_stat_interval,
 	.generate_script	= default_generate_script,
 };
 
@@ -1543,6 +1556,22 @@ static int have_cmd(int argc, const char **argv)
 	return 0;
 }
 
+static int process_stat_round_event(struct perf_tool *tool __maybe_unused,
+				    union perf_event *event,
+				    struct perf_session *session)
+{
+	struct stat_round_event *round = &event->stat_round;
+	struct perf_evsel *counter;
+
+	evlist__for_each(session->evlist, counter) {
+		perf_stat_process_counter(&stat_config, counter);
+		scripting_ops->process_stat(&stat_config, counter, round->time);
+	}
+
+	scripting_ops->process_stat_interval(round->time);
+	return 0;
+}
+
 static int process_stat_config_event(struct perf_tool *tool __maybe_unused,
 				     union perf_event *event,
 				     struct perf_session *session __maybe_unused)
@@ -1635,6 +1664,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
 			.auxtrace_info	 = perf_event__process_auxtrace_info,
 			.auxtrace	 = perf_event__process_auxtrace,
 			.auxtrace_error	 = perf_event__process_auxtrace_error,
+			.stat		 = perf_event__process_stat_event,
+			.stat_round	 = process_stat_round_event,
 			.stat_config	 = process_stat_config_event,
 			.thread_map	 = process_thread_map_event,
 			.cpu_map	 = process_cpu_map_event,
-- 
2.4.3


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

* [PATCH 45/47] perf script: Display stat events by default
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (43 preceding siblings ...)
  2015-07-21 12:32 ` [PATCH 44/47] perf script: Add stat default handlers Jiri Olsa
@ 2015-07-21 12:32 ` Jiri Olsa
  2015-07-21 12:32 ` [PATCH 46/47] perf script: Add python support for stat events Jiri Olsa
                   ` (3 subsequent siblings)
  48 siblings, 0 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

If no script is specified for stat data, display
stat events in raw form.

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

diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 9171c53f504f..e3f781a400b9 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -537,9 +537,40 @@ static void process_event(union perf_event *event, struct perf_sample *sample,
 }
 
 static void process_stat(struct perf_stat_config *config __maybe_unused,
-			 struct perf_evsel *evsel __maybe_unused,
-			 u64 time __maybe_unused)
+			 struct perf_evsel *counter, u64 time)
 {
+	int nthreads = thread_map__nr(counter->threads);
+	int ncpus = perf_evsel__nr_cpus(counter);
+	int cpu, thread;
+	static int header_printed;
+
+	if (counter->system_wide)
+		nthreads = 1;
+
+	if (!header_printed) {
+		printf("%3s %8s %15s %15s %15s %15s %s\n",
+		       "CPU", "THREAD", "VAL", "ENA", "RUN", "TIME", "EVENT");
+		header_printed = 1;
+	}
+
+	for (thread = 0; thread < nthreads; thread++) {
+		for (cpu = 0; cpu < ncpus; cpu++) {
+			struct perf_counts_values *counts;
+
+			counts = perf_counts(counter->counts, cpu, thread);
+
+			printf("%3d %8d %15" PRIu64 " %15" PRIu64 " %15" PRIu64 " %15" PRIu64 " %s\n",
+				counter->cpus->map[cpu],
+				thread_map__pid(counter->threads, thread),
+				counts->val,
+				counts->ena,
+				counts->run,
+				time,
+				perf_evsel__name(counter));
+		}
+	}
+
+	return;
 }
 
 static void process_stat_interval(u64 time __maybe_unused) { }
-- 
2.4.3


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

* [PATCH 46/47] perf script: Add python support for stat events
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (44 preceding siblings ...)
  2015-07-21 12:32 ` [PATCH 45/47] perf script: Display stat events by default Jiri Olsa
@ 2015-07-21 12:32 ` Jiri Olsa
  2015-07-21 12:32 ` [PATCH 47/47] perf script: Add stat-cpi.py script Jiri Olsa
                   ` (2 subsequent siblings)
  48 siblings, 0 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Add support to get stat events data in perf python scripts.

Link: http://lkml.kernel.org/n/tip-jojiaelyckrw6040wqc06q1j@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 .../util/scripting-engines/trace-event-python.c    | 113 +++++++++++++++++++--
 1 file changed, 107 insertions(+), 6 deletions(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index ace2484985cb..2e771ede9428 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -41,6 +41,8 @@
 #include "../thread-stack.h"
 #include "../trace-event.h"
 #include "../machine.h"
+#include "thread_map.h"
+#include "cpumap.h"
 
 PyMODINIT_FUNC initperf_trace_context(void);
 
@@ -858,6 +860,103 @@ static void python_process_event(union perf_event *event,
 	}
 }
 
+static void get_handler_name(char *str, size_t size,
+			     struct perf_evsel *evsel)
+{
+	char *p = str;
+
+	scnprintf(str, size, "stat__%s", perf_evsel__name(evsel));
+
+	while ((p = strchr(p, ':'))) {
+		*p = '_';
+		p++;
+	}
+}
+
+static void
+process_stat(struct perf_evsel *counter, int cpu, int thread, u64 time,
+	     struct perf_counts_values *count)
+{
+	PyObject *handler, *t;
+	static char handler_name[256];
+	int n = 0;
+
+	t = PyTuple_New(MAX_FIELDS);
+	if (!t)
+		Py_FatalError("couldn't create Python tuple");
+
+	get_handler_name(handler_name, sizeof(handler_name),
+			 counter);
+
+	handler = get_handler(handler_name);
+	if (!handler) {
+		pr_debug("can't find python handler %s\n", handler_name);
+		return;
+	}
+
+	PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
+	PyTuple_SetItem(t, n++, PyInt_FromLong(thread));
+	PyTuple_SetItem(t, n++, PyLong_FromLong(time));
+	PyTuple_SetItem(t, n++, PyLong_FromLong(count->val));
+	PyTuple_SetItem(t, n++, PyLong_FromLong(count->ena));
+	PyTuple_SetItem(t, n++, PyLong_FromLong(count->run));
+
+	if (_PyTuple_Resize(&t, n) == -1)
+		Py_FatalError("error resizing Python tuple");
+
+	call_object(handler, t, handler_name);
+
+	Py_DECREF(t);
+}
+
+static void python_process_stat(struct perf_stat_config *config,
+				struct perf_evsel *counter, u64 time)
+{
+	struct thread_map *threads = counter->threads;
+	struct cpu_map *cpus = counter->cpus;
+	int cpu, thread;
+
+	if (config->aggr_mode == AGGR_GLOBAL) {
+		process_stat(counter, -1, -1, time,
+			     &counter->counts->aggr);
+		return;
+	}
+
+	for (thread = 0; thread < threads->nr; thread++) {
+		for (cpu = 0; cpu < cpus->nr; cpu++) {
+			process_stat(counter, cpus->map[cpu],
+				     thread_map__pid(threads, thread), time,
+				     perf_counts(counter->counts, cpu, thread));
+		}
+	}
+}
+
+static void python_process_stat_interval(u64 time)
+{
+	PyObject *handler, *t;
+	static const char handler_name[] = "stat__interval";
+	int n = 0;
+
+	t = PyTuple_New(MAX_FIELDS);
+	if (!t)
+		Py_FatalError("couldn't create Python tuple");
+
+	handler = get_handler(handler_name);
+	if (!handler) {
+		pr_debug("can't find python handler %s\n", handler_name);
+		return;
+	}
+
+	PyTuple_SetItem(t, n++, PyLong_FromLong(time));
+
+	if (_PyTuple_Resize(&t, n) == -1)
+		Py_FatalError("error resizing Python tuple");
+
+	call_object(handler, t, handler_name);
+
+	Py_DECREF(t);
+}
+
 static int run_start_sub(void)
 {
 	main_module = PyImport_AddModule("__main__");
@@ -1200,10 +1299,12 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
 }
 
 struct scripting_ops python_scripting_ops = {
-	.name = "Python",
-	.start_script = python_start_script,
-	.flush_script = python_flush_script,
-	.stop_script = python_stop_script,
-	.process_event = python_process_event,
-	.generate_script = python_generate_script,
+	.name			= "Python",
+	.start_script		= python_start_script,
+	.flush_script		= python_flush_script,
+	.stop_script		= python_stop_script,
+	.process_event		= python_process_event,
+	.process_stat		= python_process_stat,
+	.process_stat_interval	= python_process_stat_interval,
+	.generate_script	= python_generate_script,
 };
-- 
2.4.3


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

* [PATCH 47/47] perf script: Add stat-cpi.py script
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (45 preceding siblings ...)
  2015-07-21 12:32 ` [PATCH 46/47] perf script: Add python support for stat events Jiri Olsa
@ 2015-07-21 12:32 ` Jiri Olsa
  2015-07-21 14:43 ` [RFC 00/47] perf stat: Add scripting support Andi Kleen
  2015-08-06 19:27 ` Arnaldo Carvalho de Melo
  48 siblings, 0 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-21 12:32 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Link: http://lkml.kernel.org/n/tip-15vwwb4yea15wzz6bqbxdpc0@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/scripts/python/stat-cpi.py | 74 +++++++++++++++++++++++++++++++++++
 1 file changed, 74 insertions(+)
 create mode 100644 tools/perf/scripts/python/stat-cpi.py

diff --git a/tools/perf/scripts/python/stat-cpi.py b/tools/perf/scripts/python/stat-cpi.py
new file mode 100644
index 000000000000..eb3936e99862
--- /dev/null
+++ b/tools/perf/scripts/python/stat-cpi.py
@@ -0,0 +1,74 @@
+#!/bin/python
+
+data    = {}
+times   = []
+threads = []
+cpus    = []
+
+def get_key(time, event, cpu, thread):
+    return "%d-%s-%d-%d" % (time, event, cpu, thread)
+
+def store_key(time, cpu, thread):
+    if (time not in times):
+        times.append(time)
+
+    if (cpu not in cpus):
+        cpus.append(cpu)
+
+    if (thread not in threads):
+        threads.append(thread)
+
+def store(time, event, cpu, thread, val, ena, run):
+    #print "event %s cpu %d, thread %d, time %d, val %d, ena %d, run %d" % \
+    #      (event, cpu, thread, time, val, ena, run)
+
+    store_key(time, cpu, thread)
+    key = get_key(time, event, cpu, thread)
+    data[key] = [ val, ena, run]
+
+def get(time, event, cpu, thread):
+    key = get_key(time, event, cpu, thread)
+    return data[key][0]
+
+def stat__cycles_k(cpu, thread, time, val, ena, run):
+    store(time, "cycles", cpu, thread, val, ena, run);
+
+def stat__instructions_k(cpu, thread, time, val, ena, run):
+    store(time, "instructions", cpu, thread, val, ena, run);
+
+def stat__cycles_u(cpu, thread, time, val, ena, run):
+    store(time, "cycles", cpu, thread, val, ena, run);
+
+def stat__instructions_u(cpu, thread, time, val, ena, run):
+    store(time, "instructions", cpu, thread, val, ena, run);
+
+def stat__cycles(cpu, thread, time, val, ena, run):
+    store(time, "cycles", cpu, thread, val, ena, run);
+
+def stat__instructions(cpu, thread, time, val, ena, run):
+    store(time, "instructions", cpu, thread, val, ena, run);
+
+def stat__interval(time):
+    for cpu in cpus:
+        for thread in threads:
+            cyc = get(time, "cycles", cpu, thread)
+            ins = get(time, "instructions", cpu, thread)
+            cpi = 0
+
+            if ins != 0:
+                cpi = cyc/float(ins)
+
+            print "%15f: cpu %d, thread %d -> cpi %f (%d/%d)" % (time/(float(1000000000)), cpu, thread, cpi, cyc, ins)
+
+def trace_end():
+    pass
+#    for time in times:
+#        for cpu in cpus:
+#            for thread in threads:
+#                cyc = get(time, "cycles", cpu, thread)
+#                ins = get(time, "instructions", cpu, thread)
+#
+#                if ins != 0:
+#                    cpi = cyc/float(ins)
+#
+#                print "time %.9f, cpu %d, thread %d -> cpi %f" % (time/(float(1000000000)), cpu, thread, cpi)
-- 
2.4.3


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

* Re: [RFC 00/47] perf stat: Add scripting support
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (46 preceding siblings ...)
  2015-07-21 12:32 ` [PATCH 47/47] perf script: Add stat-cpi.py script Jiri Olsa
@ 2015-07-21 14:43 ` Andi Kleen
  2015-07-26 13:51   ` Jiri Olsa
  2015-08-06 19:27 ` Arnaldo Carvalho de Melo
  48 siblings, 1 reply; 72+ messages in thread
From: Andi Kleen @ 2015-07-21 14:43 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Arnaldo Carvalho de Melo, Andi Kleen, Ulrich Drepper,
	Will Deacon, Stephane Eranian, lkml, David Ahern, Ingo Molnar,
	Namhyung Kim, Peter Zijlstra, kan.liang

On Tue, Jul 21, 2015 at 02:31:20PM +0200, Jiri Olsa wrote:
> hi,
> sending RFC on another attempt for stat scripting.
> 
> The initial attempt defined its own formula lang and allowed
> triggering user's script on the end of the stat command:
>   http://marc.info/?l=linux-kernel&m=136742146322273&w=2
> 
> This patchset abandons the idea of new formula language
> and rather adds support to:
>   - store stat data into perf.data file
>   - add python support to process stat events
> 
> Basically it allows to store stat data into perf.data and
> post process it with python scripts in a similar way we
> do for sampling data.

I suspect there is some overlap with Kan's patchkit to put
uncore data into perf.data too.

The basic direction seems good just from reading the intro
(haven't read the code so far). I've been thinking about
doing something similar to do native topdown support in perf.
This would require evaluating formulas which are depending
on the CPU.

-Andi

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

* Re: [PATCH 02/47] perf stat: Introduce struct perf_stat_config
  2015-07-21 12:31 ` [PATCH 02/47] perf stat: Introduce struct perf_stat_config Jiri Olsa
@ 2015-07-21 17:24   ` Arnaldo Carvalho de Melo
  2015-07-21 17:37     ` Arnaldo Carvalho de Melo
  2015-08-07  7:17   ` [tip:perf/core] " tip-bot for Jiri Olsa
  1 sibling, 1 reply; 72+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-07-21 17:24 UTC (permalink / raw)
  To: Jiri Olsa; +Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Em Tue, Jul 21, 2015 at 02:31:22PM +0200, Jiri Olsa escreveu:
> Moving aggr_mode into new struct. The point is to centralize
> the base stat config so it could be used localy together with
> other stat routines in other parts of perf code.

Why not use 'struct perf_stat' for that? It is already there and is
supposed to hold the stat tool internal state. Yeah, lots of those
globals should go there as well, just like we have the 'perf_sched',
'perf_top', 'perf_script', etc structs.

- Arnaldo

 
> Link: http://lkml.kernel.org/n/tip-4g1i3m1z6fzsrznn2umi02wa@git.kernel.org
> Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> ---
>  tools/perf/builtin-stat.c | 39 ++++++++++++++++++++++-----------------
>  tools/perf/util/stat.h    |  4 ++++
>  2 files changed, 26 insertions(+), 17 deletions(-)
> 
> diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
> index d99d850e1444..bafb830b1bd9 100644
> --- a/tools/perf/builtin-stat.c
> +++ b/tools/perf/builtin-stat.c
> @@ -102,7 +102,6 @@ static struct target target = {
>  static int			run_count			=  1;
>  static bool			no_inherit			= false;
>  static bool			scale				=  true;
> -static enum aggr_mode		aggr_mode			= AGGR_GLOBAL;
>  static volatile pid_t		child_pid			= -1;
>  static bool			null_run			=  false;
>  static int			detailed_run			=  0;
> @@ -126,6 +125,10 @@ static int			(*aggr_get_id)(struct cpu_map *m, int cpu);
>  
>  static volatile int done = 0;
>  
> +static struct perf_stat_config stat_config = {
> +	.aggr_mode	= AGGR_GLOBAL,
> +};
> +
>  static inline void diff_timespec(struct timespec *r, struct timespec *a,
>  				 struct timespec *b)
>  {
> @@ -230,7 +233,7 @@ process_counter_values(struct perf_evsel *evsel, int cpu, int thread,
>  	if (skip)
>  		count = &zero;
>  
> -	switch (aggr_mode) {
> +	switch (stat_config.aggr_mode) {
>  	case AGGR_THREAD:
>  	case AGGR_CORE:
>  	case AGGR_SOCKET:
> @@ -238,7 +241,7 @@ process_counter_values(struct perf_evsel *evsel, int cpu, int thread,
>  		if (!evsel->snapshot)
>  			perf_evsel__compute_deltas(evsel, cpu, thread, count);
>  		perf_counts_values__scale(count, scale, NULL);
> -		if (aggr_mode == AGGR_NONE)
> +		if (stat_config.aggr_mode == AGGR_NONE)
>  			perf_stat__update_shadow_stats(evsel, count->values, cpu);
>  		break;
>  	case AGGR_GLOBAL:
> @@ -291,7 +294,7 @@ static int process_counter(struct perf_evsel *counter)
>  	if (ret)
>  		return ret;
>  
> -	if (aggr_mode != AGGR_GLOBAL)
> +	if (stat_config.aggr_mode != AGGR_GLOBAL)
>  		return 0;
>  
>  	if (!counter->snapshot)
> @@ -578,7 +581,7 @@ static void print_noise(struct perf_evsel *evsel, double avg)
>  
>  static void aggr_printout(struct perf_evsel *evsel, int id, int nr)
>  {
> -	switch (aggr_mode) {
> +	switch (stat_config.aggr_mode) {
>  	case AGGR_CORE:
>  		fprintf(output, "S%d-C%*d%s%*d%s",
>  			cpu_map__id_to_socket(id),
> @@ -670,7 +673,7 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
>  
>  	aggr_printout(evsel, id, nr);
>  
> -	if (aggr_mode == AGGR_GLOBAL)
> +	if (stat_config.aggr_mode == AGGR_GLOBAL)
>  		cpu = 0;
>  
>  	fprintf(output, fmt, avg, csv_sep);
> @@ -688,7 +691,8 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
>  	if (csv_output || interval)
>  		return;
>  
> -	perf_stat__print_shadow_stats(output, evsel, avg, cpu, aggr_mode);
> +	perf_stat__print_shadow_stats(output, evsel, avg, cpu,
> +				      stat_config.aggr_mode);
>  }
>  
>  static void print_aggr(char *prefix)
> @@ -909,7 +913,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) {
> -		switch (aggr_mode) {
> +		switch (stat_config.aggr_mode) {
>  		case AGGR_SOCKET:
>  			fprintf(output, "#           time socket cpus             counts %*s events\n", unit_width, "unit");
>  			break;
> @@ -985,7 +989,7 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)
>  	else
>  		print_header(argc, argv);
>  
> -	switch (aggr_mode) {
> +	switch (stat_config.aggr_mode) {
>  	case AGGR_CORE:
>  	case AGGR_SOCKET:
>  		print_aggr(prefix);
> @@ -1064,7 +1068,7 @@ static int stat__set_big_num(const struct option *opt __maybe_unused,
>  
>  static int perf_stat_init_aggr_mode(void)
>  {
> -	switch (aggr_mode) {
> +	switch (stat_config.aggr_mode) {
>  	case AGGR_SOCKET:
>  		if (cpu_map__build_socket_map(evsel_list->cpus, &aggr_map)) {
>  			perror("cannot build socket map");
> @@ -1286,7 +1290,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
>  			   stat__set_big_num),
>  	OPT_STRING('C', "cpu", &target.cpu_list, "cpu",
>  		    "list of cpus to monitor in system-wide"),
> -	OPT_SET_UINT('A', "no-aggr", &aggr_mode,
> +	OPT_SET_UINT('A', "no-aggr", &stat_config.aggr_mode,
>  		    "disable CPU count aggregation", AGGR_NONE),
>  	OPT_STRING('x', "field-separator", &csv_sep, "separator",
>  		   "print counts with custom separator"),
> @@ -1302,11 +1306,11 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
>  			"command to run after to the measured command"),
>  	OPT_UINTEGER('I', "interval-print", &interval,
>  		    "print counts at regular interval in ms (>= 100)"),
> -	OPT_SET_UINT(0, "per-socket", &aggr_mode,
> +	OPT_SET_UINT(0, "per-socket", &stat_config.aggr_mode,
>  		     "aggregate counts per processor socket", AGGR_SOCKET),
> -	OPT_SET_UINT(0, "per-core", &aggr_mode,
> +	OPT_SET_UINT(0, "per-core", &stat_config.aggr_mode,
>  		     "aggregate counts per physical processor core", AGGR_CORE),
> -	OPT_SET_UINT(0, "per-thread", &aggr_mode,
> +	OPT_SET_UINT(0, "per-thread", &stat_config.aggr_mode,
>  		     "aggregate counts per thread", AGGR_THREAD),
>  	OPT_UINTEGER('D', "delay", &initial_delay,
>  		     "ms to wait before starting measurement after program start"),
> @@ -1399,7 +1403,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
>  		run_count = 1;
>  	}
>  
> -	if ((aggr_mode == AGGR_THREAD) && !target__has_task(&target)) {
> +	if ((stat_config.aggr_mode == AGGR_THREAD) && !target__has_task(&target)) {
>  		fprintf(stderr, "The --per-thread option is only available "
>  			"when monitoring via -p -t options.\n");
>  		parse_options_usage(NULL, options, "p", 1);
> @@ -1411,7 +1415,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
>  	 * no_aggr, cgroup are for system-wide only
>  	 * --per-thread is aggregated per thread, we dont mix it with cpu mode
>  	 */
> -	if (((aggr_mode != AGGR_GLOBAL && aggr_mode != AGGR_THREAD) || nr_cgroups) &&
> +	if (((stat_config.aggr_mode != AGGR_GLOBAL &&
> +	      stat_config.aggr_mode != AGGR_THREAD) || nr_cgroups) &&
>  	    !target__has_cpu(&target)) {
>  		fprintf(stderr, "both cgroup and no-aggregation "
>  			"modes only available in system-wide mode\n");
> @@ -1444,7 +1449,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
>  	 * Initialize thread_map with comm names,
>  	 * so we could print it out on output.
>  	 */
> -	if (aggr_mode == AGGR_THREAD)
> +	if (stat_config.aggr_mode == AGGR_THREAD)
>  		thread_map__read_comms(evsel_list->threads);
>  
>  	if (interval && interval < 100) {
> diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
> index 1cfbe0a980ac..078bee49ccad 100644
> --- a/tools/perf/util/stat.h
> +++ b/tools/perf/util/stat.h
> @@ -50,6 +50,10 @@ struct perf_counts {
>  	struct xyarray		  *values;
>  };
>  
> +struct perf_stat_config {
> +	enum aggr_mode	aggr_mode;
> +};
> +
>  static inline struct perf_counts_values*
>  perf_counts(struct perf_counts *counts, int cpu, int thread)
>  {
> -- 
> 2.4.3

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

* Re: [PATCH 10/47] perf tools: Force perf_evlist__set_maps to propagate maps through events
  2015-07-21 12:31 ` [PATCH 10/47] perf tools: Force perf_evlist__set_maps to propagate maps through events Jiri Olsa
@ 2015-07-21 17:25   ` Arnaldo Carvalho de Melo
  2015-07-29  8:10   ` [tip:perf/core] perf evlist: " tip-bot for Jiri Olsa
  1 sibling, 0 replies; 72+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-07-21 17:25 UTC (permalink / raw)
  To: Jiri Olsa; +Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Em Tue, Jul 21, 2015 at 02:31:30PM +0200, Jiri Olsa escreveu:
> Forcing perf_evlist__set_maps to propagate maps through events,
> so cpu/thread maps get set within evlist.

Applied
 
> Link: http://lkml.kernel.org/n/tip-0oqwhvjdr3jgfzkbd3qee5o0@git.kernel.org
> Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> ---
>  tools/perf/util/evlist.c | 17 +++++++++++++++++
>  tools/perf/util/evlist.h | 11 +++--------
>  2 files changed, 20 insertions(+), 8 deletions(-)
> 
> diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
> index f1714bedd5de..3b9f411a6b46 100644
> --- a/tools/perf/util/evlist.c
> +++ b/tools/perf/util/evlist.c
> @@ -1151,6 +1151,23 @@ out_delete_threads:
>  	return -1;
>  }
>  
> +int perf_evlist__set_maps(struct perf_evlist *evlist,
> +			  struct cpu_map *cpus,
> +			  struct thread_map *threads)
> +{
> +	if (evlist->cpus)
> +		cpu_map__put(evlist->cpus);
> +
> +	evlist->cpus = cpus;
> +
> +	if (evlist->threads)
> +		thread_map__put(evlist->threads);
> +
> +	evlist->threads = threads;
> +
> +	return perf_evlist__propagate_maps(evlist, false);
> +}
> +
>  int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **err_evsel)
>  {
>  	struct perf_evsel *evsel;
> diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
> index 037633c1da9d..406a8216a51e 100644
> --- a/tools/perf/util/evlist.h
> +++ b/tools/perf/util/evlist.h
> @@ -152,14 +152,9 @@ int perf_evlist__enable_event_idx(struct perf_evlist *evlist,
>  void perf_evlist__set_selected(struct perf_evlist *evlist,
>  			       struct perf_evsel *evsel);
>  
> -static inline void perf_evlist__set_maps(struct perf_evlist *evlist,
> -					 struct cpu_map *cpus,
> -					 struct thread_map *threads)
> -{
> -	evlist->cpus	= cpus;
> -	evlist->threads	= threads;
> -}
> -
> +int perf_evlist__set_maps(struct perf_evlist *evlist,
> +			  struct cpu_map *cpus,
> +			  struct thread_map *threads);
>  int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target);
>  int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **err_evsel);
>  
> -- 
> 2.4.3

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

* Re: [PATCH 01/47] perf test: Check for refcnt in thread_map test
  2015-07-21 12:31 ` [PATCH 01/47] perf test: Check for refcnt in thread_map test Jiri Olsa
@ 2015-07-21 17:26   ` Arnaldo Carvalho de Melo
  2015-07-29  8:10   ` [tip:perf/core] " tip-bot for Jiri Olsa
  1 sibling, 0 replies; 72+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-07-21 17:26 UTC (permalink / raw)
  To: Jiri Olsa; +Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Em Tue, Jul 21, 2015 at 02:31:21PM +0200, Jiri Olsa escreveu:
> Checking also for refcnt in thread_map test.

Applied.
 
> Link: http://lkml.kernel.org/n/tip-6fege00q2h2ulx4296921evo@git.kernel.org
> Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> ---
>  tools/perf/tests/thread-map.c | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/tools/perf/tests/thread-map.c b/tools/perf/tests/thread-map.c
> index 5acf000939ea..138a0e3431fa 100644
> --- a/tools/perf/tests/thread-map.c
> +++ b/tools/perf/tests/thread-map.c
> @@ -20,6 +20,8 @@ int test__thread_map(void)
>  	TEST_ASSERT_VAL("wrong comm",
>  			thread_map__comm(map, 0) &&
>  			!strcmp(thread_map__comm(map, 0), "perf"));
> +	TEST_ASSERT_VAL("wrong refcnt",
> +			atomic_read(&map->refcnt) == 1);
>  	thread_map__put(map);
>  
>  	/* test dummy pid */
> @@ -33,6 +35,8 @@ int test__thread_map(void)
>  	TEST_ASSERT_VAL("wrong comm",
>  			thread_map__comm(map, 0) &&
>  			!strcmp(thread_map__comm(map, 0), "dummy"));
> +	TEST_ASSERT_VAL("wrong refcnt",
> +			atomic_read(&map->refcnt) == 1);
>  	thread_map__put(map);
>  	return 0;
>  }
> -- 
> 2.4.3

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

* Re: [PATCH 11/47] perf tools: Use argv style storage for cmdline feature data
  2015-07-21 12:31 ` [PATCH 11/47] perf tools: Use argv style storage for cmdline feature data Jiri Olsa
@ 2015-07-21 17:29   ` Arnaldo Carvalho de Melo
  2015-07-29  8:11   ` [tip:perf/core] perf header: " tip-bot for Jiri Olsa
  1 sibling, 0 replies; 72+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-07-21 17:29 UTC (permalink / raw)
  To: Jiri Olsa; +Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Em Tue, Jul 21, 2015 at 02:31:31PM +0200, Jiri Olsa escreveu:
> We will reuse argv style data in following change to display
> counters header showing monitored command line.

Applied
 
> Link: http://lkml.kernel.org/n/tip-qu64zmm5zbpbkuybusnkg4gl@git.kernel.org
> Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> ---
>  tools/perf/util/header.c  | 35 ++++++++++++++++++++---------------
>  tools/perf/util/header.h  |  1 +
>  tools/perf/util/session.c |  1 +
>  3 files changed, 22 insertions(+), 15 deletions(-)
> 
> diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
> index 03ace57a800c..179b2bdd157d 100644
> --- a/tools/perf/util/header.c
> +++ b/tools/perf/util/header.c
> @@ -923,17 +923,13 @@ static void print_cmdline(struct perf_header *ph, int fd __maybe_unused,
>  			  FILE *fp)
>  {
>  	int nr, i;
> -	char *str;
>  
>  	nr = ph->env.nr_cmdline;
> -	str = ph->env.cmdline;
>  
>  	fprintf(fp, "# cmdline : ");
>  
> -	for (i = 0; i < nr; i++) {
> -		fprintf(fp, "%s ", str);
> -		str += strlen(str) + 1;
> -	}
> +	for (i = 0; i < nr; i++)
> +		fprintf(fp, "%s ", ph->env.cmdline_argv[i]);
>  	fputc('\n', fp);
>  }
>  
> @@ -1541,14 +1537,13 @@ process_event_desc(struct perf_file_section *section __maybe_unused,
>  	return 0;
>  }
>  
> -static int process_cmdline(struct perf_file_section *section __maybe_unused,
> +static int process_cmdline(struct perf_file_section *section,
>  			   struct perf_header *ph, int fd,
>  			   void *data __maybe_unused)
>  {
>  	ssize_t ret;
> -	char *str;
> -	u32 nr, i;
> -	struct strbuf sb;
> +	char *str, *cmdline = NULL, **argv = NULL;
> +	u32 nr, i, len = 0;
>  
>  	ret = readn(fd, &nr, sizeof(nr));
>  	if (ret != sizeof(nr))
> @@ -1558,22 +1553,32 @@ static int process_cmdline(struct perf_file_section *section __maybe_unused,
>  		nr = bswap_32(nr);
>  
>  	ph->env.nr_cmdline = nr;
> -	strbuf_init(&sb, 128);
> +
> +	cmdline = zalloc(section->size + nr + 1);
> +	if (!cmdline)
> +		return -1;
> +
> +	argv = zalloc(sizeof(char *) * (nr + 1));
> +	if (!argv)
> +		goto error;
>  
>  	for (i = 0; i < nr; i++) {
>  		str = do_read_string(fd, ph);
>  		if (!str)
>  			goto error;
>  
> -		/* include a NULL character at the end */
> -		strbuf_add(&sb, str, strlen(str) + 1);
> +		argv[i] = cmdline + len;
> +		memcpy(argv[i], str, strlen(str) + 1);
> +		len += strlen(str) + 1;
>  		free(str);
>  	}
> -	ph->env.cmdline = strbuf_detach(&sb, NULL);
> +	ph->env.cmdline = cmdline;
> +	ph->env.cmdline_argv = (const char **) argv;
>  	return 0;
>  
>  error:
> -	strbuf_release(&sb);
> +	free(argv);
> +	free(cmdline);
>  	return -1;
>  }
>  
> diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
> index d4d57962c591..9b53b6525ce8 100644
> --- a/tools/perf/util/header.h
> +++ b/tools/perf/util/header.h
> @@ -84,6 +84,7 @@ struct perf_session_env {
>  	int			nr_pmu_mappings;
>  	int			nr_groups;
>  	char			*cmdline;
> +	const char		**cmdline_argv;
>  	char			*sibling_cores;
>  	char			*sibling_threads;
>  	char			*numa_nodes;
> diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
> index ed9dc2555ec7..fb1d525ca3d0 100644
> --- a/tools/perf/util/session.c
> +++ b/tools/perf/util/session.c
> @@ -180,6 +180,7 @@ static void perf_session_env__delete(struct perf_session_env *env)
>  	zfree(&env->cpuid);
>  
>  	zfree(&env->cmdline);
> +	zfree(&env->cmdline_argv);
>  	zfree(&env->sibling_cores);
>  	zfree(&env->sibling_threads);
>  	zfree(&env->numa_nodes);
> -- 
> 2.4.3

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

* Re: [PATCH 09/47] perf tools: Tolerate NULL maps in perf_evlist__propagate_maps
  2015-07-21 12:31 ` [PATCH 09/47] perf tools: Tolerate NULL maps in perf_evlist__propagate_maps Jiri Olsa
@ 2015-07-21 17:31   ` Arnaldo Carvalho de Melo
  2015-07-29  8:11   ` [tip:perf/core] perf evlist: Tolerate NULL maps in propagate_maps tip-bot for Jiri Olsa
  1 sibling, 0 replies; 72+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-07-21 17:31 UTC (permalink / raw)
  To: Jiri Olsa; +Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Em Tue, Jul 21, 2015 at 02:31:29PM +0200, Jiri Olsa escreveu:
> Tolerating NULL maps in perf_evlist__propagate_maps,
> so we dont need to pass evlist with both cpus and threads
> maps defined.

Applied
 
> Link: http://lkml.kernel.org/n/tip-y15hjmv6uu8b6gyhkz5v41rw@git.kernel.org
> Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> ---
>  tools/perf/util/evlist.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
> index 63bc24dbf03b..f1714bedd5de 100644
> --- a/tools/perf/util/evlist.c
> +++ b/tools/perf/util/evlist.c
> @@ -1119,7 +1119,8 @@ static int perf_evlist__propagate_maps(struct perf_evlist *evlist,
>  
>  		evsel->threads = thread_map__get(evlist->threads);
>  
> -		if (!evsel->cpus || !evsel->threads)
> +		if ((evlist->cpus && !evsel->cpus) ||
> +		    (evlist->threads && !evsel->threads))
>  			return -ENOMEM;
>  	}
>  
> -- 
> 2.4.3

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

* Re: [PATCH 02/47] perf stat: Introduce struct perf_stat_config
  2015-07-21 17:24   ` Arnaldo Carvalho de Melo
@ 2015-07-21 17:37     ` Arnaldo Carvalho de Melo
  2015-07-22  8:38       ` Jiri Olsa
  0 siblings, 1 reply; 72+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-07-21 17:37 UTC (permalink / raw)
  To: Jiri Olsa; +Cc: lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Em Tue, Jul 21, 2015 at 02:24:19PM -0300, Arnaldo Carvalho de Melo escreveu:
> Em Tue, Jul 21, 2015 at 02:31:22PM +0200, Jiri Olsa escreveu:
> > Moving aggr_mode into new struct. The point is to centralize
> > the base stat config so it could be used localy together with
> > other stat routines in other parts of perf code.
> 
> Why not use 'struct perf_stat' for that? It is already there and is
> supposed to hold the stat tool internal state. Yeah, lots of those
> globals should go there as well, just like we have the 'perf_sched',
> 'perf_top', 'perf_script',y etc structs.

Erm, saw some more patches, this stuff gets marshalled into perf.data,
continuing to read... Probably you made this somehow extensible...

- Arnaldo

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

* Re: [PATCH 02/47] perf stat: Introduce struct perf_stat_config
  2015-07-21 17:37     ` Arnaldo Carvalho de Melo
@ 2015-07-22  8:38       ` Jiri Olsa
  0 siblings, 0 replies; 72+ messages in thread
From: Jiri Olsa @ 2015-07-22  8:38 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Jiri Olsa, lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

On Tue, Jul 21, 2015 at 02:37:26PM -0300, Arnaldo Carvalho de Melo wrote:
> Em Tue, Jul 21, 2015 at 02:24:19PM -0300, Arnaldo Carvalho de Melo escreveu:
> > Em Tue, Jul 21, 2015 at 02:31:22PM +0200, Jiri Olsa escreveu:
> > > Moving aggr_mode into new struct. The point is to centralize
> > > the base stat config so it could be used localy together with
> > > other stat routines in other parts of perf code.
> > 
> > Why not use 'struct perf_stat' for that? It is already there and is
> > supposed to hold the stat tool internal state. Yeah, lots of those
> > globals should go there as well, just like we have the 'perf_sched',
> > 'perf_top', 'perf_script',y etc structs.

hm, but it's used as perf_evsel priv data.. 

the 'struct perf_stat_config' is coupled with the same event,
we could switch the name for:

  'struct perf_stat'     -> 'struct perf_evsel_stat'
  'struct perf_stat_cmd' -> 'struct perf_stat'

and move 'struct perf_stat_record' under 'struct perf_stat' ;-)

> 
> Erm, saw some more patches, this stuff gets marshalled into perf.data,
> continuing to read... Probably you made this somehow extensible...

yep, I'm storing it in 'tag-value' way, it's mentioned in the changelog

jirka

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

* Re: [RFC 00/47] perf stat: Add scripting support
  2015-07-21 14:43 ` [RFC 00/47] perf stat: Add scripting support Andi Kleen
@ 2015-07-26 13:51   ` Jiri Olsa
  2015-07-27 12:46     ` Liang, Kan
  0 siblings, 1 reply; 72+ messages in thread
From: Jiri Olsa @ 2015-07-26 13:51 UTC (permalink / raw)
  To: Andi Kleen
  Cc: Jiri Olsa, Arnaldo Carvalho de Melo, Ulrich Drepper, Will Deacon,
	Stephane Eranian, lkml, David Ahern, Ingo Molnar, Namhyung Kim,
	Peter Zijlstra, kan.liang

On Tue, Jul 21, 2015 at 04:43:08PM +0200, Andi Kleen wrote:
> On Tue, Jul 21, 2015 at 02:31:20PM +0200, Jiri Olsa wrote:
> > hi,
> > sending RFC on another attempt for stat scripting.
> > 
> > The initial attempt defined its own formula lang and allowed
> > triggering user's script on the end of the stat command:
> >   http://marc.info/?l=linux-kernel&m=136742146322273&w=2
> > 
> > This patchset abandons the idea of new formula language
> > and rather adds support to:
> >   - store stat data into perf.data file
> >   - add python support to process stat events
> > 
> > Basically it allows to store stat data into perf.data and
> > post process it with python scripts in a similar way we
> > do for sampling data.
> 
> I suspect there is some overlap with Kan's patchkit to put
> uncore data into perf.data too.

hum, haven't seen this, was it posted already?

jirka

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

* RE: [RFC 00/47] perf stat: Add scripting support
  2015-07-26 13:51   ` Jiri Olsa
@ 2015-07-27 12:46     ` Liang, Kan
  0 siblings, 0 replies; 72+ messages in thread
From: Liang, Kan @ 2015-07-27 12:46 UTC (permalink / raw)
  To: Jiri Olsa, Andi Kleen
  Cc: Jiri Olsa, Arnaldo Carvalho de Melo, Ulrich Drepper, Will Deacon,
	Stephane Eranian, lkml, David Ahern, Ingo Molnar, Namhyung Kim,
	Peter Zijlstra

> 
> On Tue, Jul 21, 2015 at 04:43:08PM +0200, Andi Kleen wrote:
> > On Tue, Jul 21, 2015 at 02:31:20PM +0200, Jiri Olsa wrote:
> > > hi,
> > > sending RFC on another attempt for stat scripting.
> > >
> > > The initial attempt defined its own formula lang and allowed
> > > triggering user's script on the end of the stat command:
> > >   http://marc.info/?l=linux-kernel&m=136742146322273&w=2
> > >
> > > This patchset abandons the idea of new formula language and rather
> > > adds support to:
> > >   - store stat data into perf.data file
> > >   - add python support to process stat events
> > >
> > > Basically it allows to store stat data into perf.data and post
> > > process it with python scripts in a similar way we do for sampling
> > > data.
> >
> > I suspect there is some overlap with Kan's patchkit to put uncore data
> > into perf.data too.
> 
> hum, haven't seen this, was it posted already?
> 
Not yet.
But I think the proposal is different as yours.  
It intends to regularly read (10-20ms interval) counter during perf sampling.
So I modified the perf record, added a timer to read counter regularly, and
wrote the delta results into perf.data.
We want to do that is because we can read memory bandwidth from uncore 
event during cpu PMU event is sampling. The sophisticated bandwidth
analysis requires fine granularity.
We cannot use sample read, because we need stable interval. 
We tried to run perf record and perf stat together by script. But the script
way have various issue and complex to parses the output.
So I propose to change the perf record and regularly write the counter
value into perf.data
I will send them to review soon.

Thanks,
Kan

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

* [tip:perf/core] perf test: Check for refcnt in thread_map test
  2015-07-21 12:31 ` [PATCH 01/47] perf test: Check for refcnt in thread_map test Jiri Olsa
  2015-07-21 17:26   ` Arnaldo Carvalho de Melo
@ 2015-07-29  8:10   ` tip-bot for Jiri Olsa
  1 sibling, 0 replies; 72+ messages in thread
From: tip-bot for Jiri Olsa @ 2015-07-29  8:10 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: hpa, a.p.zijlstra, mingo, tglx, dsahern, namhyung, linux-kernel,
	jolsa, acme

Commit-ID:  35318d204db83f5c1f24c281839763b271b9b323
Gitweb:     http://git.kernel.org/tip/35318d204db83f5c1f24c281839763b271b9b323
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Tue, 21 Jul 2015 14:31:21 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Tue, 21 Jul 2015 14:20:32 -0300

perf test: Check for refcnt in thread_map test

Checking also for refcnt in thread_map test.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1437481927-29538-2-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/tests/thread-map.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/tools/perf/tests/thread-map.c b/tools/perf/tests/thread-map.c
index 5acf000..138a0e3 100644
--- a/tools/perf/tests/thread-map.c
+++ b/tools/perf/tests/thread-map.c
@@ -20,6 +20,8 @@ int test__thread_map(void)
 	TEST_ASSERT_VAL("wrong comm",
 			thread_map__comm(map, 0) &&
 			!strcmp(thread_map__comm(map, 0), "perf"));
+	TEST_ASSERT_VAL("wrong refcnt",
+			atomic_read(&map->refcnt) == 1);
 	thread_map__put(map);
 
 	/* test dummy pid */
@@ -33,6 +35,8 @@ int test__thread_map(void)
 	TEST_ASSERT_VAL("wrong comm",
 			thread_map__comm(map, 0) &&
 			!strcmp(thread_map__comm(map, 0), "dummy"));
+	TEST_ASSERT_VAL("wrong refcnt",
+			atomic_read(&map->refcnt) == 1);
 	thread_map__put(map);
 	return 0;
 }

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

* [tip:perf/core] perf evlist: Force perf_evlist__set_maps to propagate maps through events
  2015-07-21 12:31 ` [PATCH 10/47] perf tools: Force perf_evlist__set_maps to propagate maps through events Jiri Olsa
  2015-07-21 17:25   ` Arnaldo Carvalho de Melo
@ 2015-07-29  8:10   ` tip-bot for Jiri Olsa
  1 sibling, 0 replies; 72+ messages in thread
From: tip-bot for Jiri Olsa @ 2015-07-29  8:10 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: namhyung, tglx, hpa, mingo, acme, dsahern, linux-kernel,
	a.p.zijlstra, jolsa

Commit-ID:  3de5cfb04435b82aa427d0285df996ba73d2f426
Gitweb:     http://git.kernel.org/tip/3de5cfb04435b82aa427d0285df996ba73d2f426
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Tue, 21 Jul 2015 14:31:30 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Tue, 21 Jul 2015 14:25:12 -0300

perf evlist: Force perf_evlist__set_maps to propagate maps through events

Forcing perf_evlist__set_maps to propagate maps through events, so
cpu/thread maps get set within evlist.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1437481927-29538-11-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/evlist.c | 17 +++++++++++++++++
 tools/perf/util/evlist.h | 11 +++--------
 2 files changed, 20 insertions(+), 8 deletions(-)

diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index f7d9c77..6bfcab9b 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -1150,6 +1150,23 @@ out_delete_threads:
 	return -1;
 }
 
+int perf_evlist__set_maps(struct perf_evlist *evlist,
+			  struct cpu_map *cpus,
+			  struct thread_map *threads)
+{
+	if (evlist->cpus)
+		cpu_map__put(evlist->cpus);
+
+	evlist->cpus = cpus;
+
+	if (evlist->threads)
+		thread_map__put(evlist->threads);
+
+	evlist->threads = threads;
+
+	return perf_evlist__propagate_maps(evlist, false);
+}
+
 int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **err_evsel)
 {
 	struct perf_evsel *evsel;
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 037633c..406a821 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -152,14 +152,9 @@ int perf_evlist__enable_event_idx(struct perf_evlist *evlist,
 void perf_evlist__set_selected(struct perf_evlist *evlist,
 			       struct perf_evsel *evsel);
 
-static inline void perf_evlist__set_maps(struct perf_evlist *evlist,
-					 struct cpu_map *cpus,
-					 struct thread_map *threads)
-{
-	evlist->cpus	= cpus;
-	evlist->threads	= threads;
-}
-
+int perf_evlist__set_maps(struct perf_evlist *evlist,
+			  struct cpu_map *cpus,
+			  struct thread_map *threads);
 int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target);
 int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **err_evsel);
 

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

* [tip:perf/core] perf evlist: Use bool instead of target argument in propagate_maps()
  2015-07-21 12:31 ` [PATCH 08/47] perf tools: Use bool instead of target argument in perf_evlist__propagate_maps Jiri Olsa
@ 2015-07-29  8:10   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 72+ messages in thread
From: tip-bot for Jiri Olsa @ 2015-07-29  8:10 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: a.p.zijlstra, hpa, namhyung, acme, dsahern, mingo, linux-kernel,
	tglx, jolsa

Commit-ID:  52361ff093c807464f5a32a587a370b360bd399a
Gitweb:     http://git.kernel.org/tip/52361ff093c807464f5a32a587a370b360bd399a
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Tue, 21 Jul 2015 14:31:28 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Tue, 21 Jul 2015 14:34:07 -0300

perf evlist: Use bool instead of target argument in propagate_maps()

We need only bool info wether user defined her own set of cpus.

Switching target argument to bool so it could be used from places
without target object defined in following patches.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1437481927-29538-9-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/evlist.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 6bfcab9b..80ab942 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -1102,7 +1102,7 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
 }
 
 static int perf_evlist__propagate_maps(struct perf_evlist *evlist,
-				       struct target *target)
+				       bool has_user_cpus)
 {
 	struct perf_evsel *evsel;
 
@@ -1111,10 +1111,10 @@ static int perf_evlist__propagate_maps(struct perf_evlist *evlist,
 		 * We already have cpus for evsel (via PMU sysfs) so
 		 * keep it, if there's no target cpu list defined.
 		 */
-		if (evsel->cpus && target->cpu_list)
+		if (evsel->cpus && has_user_cpus)
 			cpu_map__put(evsel->cpus);
 
-		if (!evsel->cpus || target->cpu_list)
+		if (!evsel->cpus || has_user_cpus)
 			evsel->cpus = cpu_map__get(evlist->cpus);
 
 		evsel->threads = thread_map__get(evlist->threads);
@@ -1142,7 +1142,7 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)
 	if (evlist->cpus == NULL)
 		goto out_delete_threads;
 
-	return perf_evlist__propagate_maps(evlist, target);
+	return perf_evlist__propagate_maps(evlist, !!target->cpu_list);
 
 out_delete_threads:
 	thread_map__put(evlist->threads);

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

* [tip:perf/core] perf evlist: Tolerate NULL maps in propagate_maps
  2015-07-21 12:31 ` [PATCH 09/47] perf tools: Tolerate NULL maps in perf_evlist__propagate_maps Jiri Olsa
  2015-07-21 17:31   ` Arnaldo Carvalho de Melo
@ 2015-07-29  8:11   ` tip-bot for Jiri Olsa
  1 sibling, 0 replies; 72+ messages in thread
From: tip-bot for Jiri Olsa @ 2015-07-29  8:11 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: mingo, hpa, linux-kernel, a.p.zijlstra, jolsa, namhyung, dsahern,
	tglx, acme

Commit-ID:  0e5ffb317d7f861c309b0ab679ed2f59e9f72adf
Gitweb:     http://git.kernel.org/tip/0e5ffb317d7f861c309b0ab679ed2f59e9f72adf
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Tue, 21 Jul 2015 14:31:29 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Tue, 21 Jul 2015 14:34:07 -0300

perf evlist: Tolerate NULL maps in propagate_maps

Tolerating NULL maps in perf_evlist__propagate_maps, so we dont need to
pass evlist with both cpus and threads maps defined.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1437481927-29538-10-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/evlist.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 80ab942..3b9f411 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -1119,7 +1119,8 @@ static int perf_evlist__propagate_maps(struct perf_evlist *evlist,
 
 		evsel->threads = thread_map__get(evlist->threads);
 
-		if (!evsel->cpus || !evsel->threads)
+		if ((evlist->cpus && !evsel->cpus) ||
+		    (evlist->threads && !evsel->threads))
 			return -ENOMEM;
 	}
 

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

* [tip:perf/core] perf header: Use argv style storage for cmdline feature data
  2015-07-21 12:31 ` [PATCH 11/47] perf tools: Use argv style storage for cmdline feature data Jiri Olsa
  2015-07-21 17:29   ` Arnaldo Carvalho de Melo
@ 2015-07-29  8:11   ` tip-bot for Jiri Olsa
  1 sibling, 0 replies; 72+ messages in thread
From: tip-bot for Jiri Olsa @ 2015-07-29  8:11 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: hpa, namhyung, a.p.zijlstra, linux-kernel, tglx, mingo, jolsa,
	acme, dsahern

Commit-ID:  768dd3f3a6af25730ed1eec458e47a3c481bc3e5
Gitweb:     http://git.kernel.org/tip/768dd3f3a6af25730ed1eec458e47a3c481bc3e5
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Tue, 21 Jul 2015 14:31:31 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Tue, 21 Jul 2015 14:34:08 -0300

perf header: Use argv style storage for cmdline feature data

We will reuse argv style data in following change to display counters
header showing monitored command line.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1437481927-29538-12-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/header.c  | 35 ++++++++++++++++++++---------------
 tools/perf/util/header.h  |  1 +
 tools/perf/util/session.c |  1 +
 3 files changed, 22 insertions(+), 15 deletions(-)

diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 03ace57..179b2bd 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -923,17 +923,13 @@ static void print_cmdline(struct perf_header *ph, int fd __maybe_unused,
 			  FILE *fp)
 {
 	int nr, i;
-	char *str;
 
 	nr = ph->env.nr_cmdline;
-	str = ph->env.cmdline;
 
 	fprintf(fp, "# cmdline : ");
 
-	for (i = 0; i < nr; i++) {
-		fprintf(fp, "%s ", str);
-		str += strlen(str) + 1;
-	}
+	for (i = 0; i < nr; i++)
+		fprintf(fp, "%s ", ph->env.cmdline_argv[i]);
 	fputc('\n', fp);
 }
 
@@ -1541,14 +1537,13 @@ process_event_desc(struct perf_file_section *section __maybe_unused,
 	return 0;
 }
 
-static int process_cmdline(struct perf_file_section *section __maybe_unused,
+static int process_cmdline(struct perf_file_section *section,
 			   struct perf_header *ph, int fd,
 			   void *data __maybe_unused)
 {
 	ssize_t ret;
-	char *str;
-	u32 nr, i;
-	struct strbuf sb;
+	char *str, *cmdline = NULL, **argv = NULL;
+	u32 nr, i, len = 0;
 
 	ret = readn(fd, &nr, sizeof(nr));
 	if (ret != sizeof(nr))
@@ -1558,22 +1553,32 @@ static int process_cmdline(struct perf_file_section *section __maybe_unused,
 		nr = bswap_32(nr);
 
 	ph->env.nr_cmdline = nr;
-	strbuf_init(&sb, 128);
+
+	cmdline = zalloc(section->size + nr + 1);
+	if (!cmdline)
+		return -1;
+
+	argv = zalloc(sizeof(char *) * (nr + 1));
+	if (!argv)
+		goto error;
 
 	for (i = 0; i < nr; i++) {
 		str = do_read_string(fd, ph);
 		if (!str)
 			goto error;
 
-		/* include a NULL character at the end */
-		strbuf_add(&sb, str, strlen(str) + 1);
+		argv[i] = cmdline + len;
+		memcpy(argv[i], str, strlen(str) + 1);
+		len += strlen(str) + 1;
 		free(str);
 	}
-	ph->env.cmdline = strbuf_detach(&sb, NULL);
+	ph->env.cmdline = cmdline;
+	ph->env.cmdline_argv = (const char **) argv;
 	return 0;
 
 error:
-	strbuf_release(&sb);
+	free(argv);
+	free(cmdline);
 	return -1;
 }
 
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index d4d5796..9b53b65 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -84,6 +84,7 @@ struct perf_session_env {
 	int			nr_pmu_mappings;
 	int			nr_groups;
 	char			*cmdline;
+	const char		**cmdline_argv;
 	char			*sibling_cores;
 	char			*sibling_threads;
 	char			*numa_nodes;
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index ed9dc25..fb1d525 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -180,6 +180,7 @@ static void perf_session_env__delete(struct perf_session_env *env)
 	zfree(&env->cpuid);
 
 	zfree(&env->cmdline);
+	zfree(&env->cmdline_argv);
 	zfree(&env->sibling_cores);
 	zfree(&env->sibling_threads);
 	zfree(&env->numa_nodes);

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

* Re: [RFC 00/47] perf stat: Add scripting support
  2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
                   ` (47 preceding siblings ...)
  2015-07-21 14:43 ` [RFC 00/47] perf stat: Add scripting support Andi Kleen
@ 2015-08-06 19:27 ` Arnaldo Carvalho de Melo
  2015-08-07  7:45   ` Jiri Olsa
  48 siblings, 1 reply; 72+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-08-06 19:27 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Andi Kleen, Ulrich Drepper, Will Deacon, Stephane Eranian, lkml,
	David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra

Em Tue, Jul 21, 2015 at 02:31:20PM +0200, Jiri Olsa escreveu:
> hi,
> sending RFC on another attempt for stat scripting.
> 
> The initial attempt defined its own formula lang and allowed
> triggering user's script on the end of the stat command:
>   http://marc.info/?l=linux-kernel&m=136742146322273&w=2
> 
> This patchset abandons the idea of new formula language
> and rather adds support to:
>   - store stat data into perf.data file
>   - add python support to process stat events

Applied the first 11, some in a previous pull req, the ones moving stuff
to perf_stat_config now, but the 12nd fails, please check when I get
these merged by Ingo.

Also do you intend to do some rework on this due to the conversation
with Kan? The ones I merged are good anyway, merged.

Thanks,

- Arnaldo

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

* [tip:perf/core] perf stat: Introduce struct perf_stat_config
  2015-07-21 12:31 ` [PATCH 02/47] perf stat: Introduce struct perf_stat_config Jiri Olsa
  2015-07-21 17:24   ` Arnaldo Carvalho de Melo
@ 2015-08-07  7:17   ` tip-bot for Jiri Olsa
  1 sibling, 0 replies; 72+ messages in thread
From: tip-bot for Jiri Olsa @ 2015-08-07  7:17 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, acme, jolsa, namhyung, dsahern, mingo, hpa, tglx,
	a.p.zijlstra

Commit-ID:  421a50f3fafaf271bb3293378eaafca71337dfec
Gitweb:     http://git.kernel.org/tip/421a50f3fafaf271bb3293378eaafca71337dfec
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Tue, 21 Jul 2015 14:31:22 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 6 Aug 2015 16:02:29 -0300

perf stat: Introduce struct perf_stat_config

Moving 'aggr_mode' into new struct. The point is to centralize the base
stat config so it could be used localy together with other stat routines
in other parts of perf code.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1437481927-29538-3-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 39 ++++++++++++++++++++++-----------------
 tools/perf/util/stat.h    |  4 ++++
 2 files changed, 26 insertions(+), 17 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index d99d850..bafb830 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -102,7 +102,6 @@ static struct target target = {
 static int			run_count			=  1;
 static bool			no_inherit			= false;
 static bool			scale				=  true;
-static enum aggr_mode		aggr_mode			= AGGR_GLOBAL;
 static volatile pid_t		child_pid			= -1;
 static bool			null_run			=  false;
 static int			detailed_run			=  0;
@@ -126,6 +125,10 @@ static int			(*aggr_get_id)(struct cpu_map *m, int cpu);
 
 static volatile int done = 0;
 
+static struct perf_stat_config stat_config = {
+	.aggr_mode	= AGGR_GLOBAL,
+};
+
 static inline void diff_timespec(struct timespec *r, struct timespec *a,
 				 struct timespec *b)
 {
@@ -230,7 +233,7 @@ process_counter_values(struct perf_evsel *evsel, int cpu, int thread,
 	if (skip)
 		count = &zero;
 
-	switch (aggr_mode) {
+	switch (stat_config.aggr_mode) {
 	case AGGR_THREAD:
 	case AGGR_CORE:
 	case AGGR_SOCKET:
@@ -238,7 +241,7 @@ process_counter_values(struct perf_evsel *evsel, int cpu, int thread,
 		if (!evsel->snapshot)
 			perf_evsel__compute_deltas(evsel, cpu, thread, count);
 		perf_counts_values__scale(count, scale, NULL);
-		if (aggr_mode == AGGR_NONE)
+		if (stat_config.aggr_mode == AGGR_NONE)
 			perf_stat__update_shadow_stats(evsel, count->values, cpu);
 		break;
 	case AGGR_GLOBAL:
@@ -291,7 +294,7 @@ static int process_counter(struct perf_evsel *counter)
 	if (ret)
 		return ret;
 
-	if (aggr_mode != AGGR_GLOBAL)
+	if (stat_config.aggr_mode != AGGR_GLOBAL)
 		return 0;
 
 	if (!counter->snapshot)
@@ -578,7 +581,7 @@ static void print_noise(struct perf_evsel *evsel, double avg)
 
 static void aggr_printout(struct perf_evsel *evsel, int id, int nr)
 {
-	switch (aggr_mode) {
+	switch (stat_config.aggr_mode) {
 	case AGGR_CORE:
 		fprintf(output, "S%d-C%*d%s%*d%s",
 			cpu_map__id_to_socket(id),
@@ -670,7 +673,7 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
 
 	aggr_printout(evsel, id, nr);
 
-	if (aggr_mode == AGGR_GLOBAL)
+	if (stat_config.aggr_mode == AGGR_GLOBAL)
 		cpu = 0;
 
 	fprintf(output, fmt, avg, csv_sep);
@@ -688,7 +691,8 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
 	if (csv_output || interval)
 		return;
 
-	perf_stat__print_shadow_stats(output, evsel, avg, cpu, aggr_mode);
+	perf_stat__print_shadow_stats(output, evsel, avg, cpu,
+				      stat_config.aggr_mode);
 }
 
 static void print_aggr(char *prefix)
@@ -909,7 +913,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) {
-		switch (aggr_mode) {
+		switch (stat_config.aggr_mode) {
 		case AGGR_SOCKET:
 			fprintf(output, "#           time socket cpus             counts %*s events\n", unit_width, "unit");
 			break;
@@ -985,7 +989,7 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)
 	else
 		print_header(argc, argv);
 
-	switch (aggr_mode) {
+	switch (stat_config.aggr_mode) {
 	case AGGR_CORE:
 	case AGGR_SOCKET:
 		print_aggr(prefix);
@@ -1064,7 +1068,7 @@ static int stat__set_big_num(const struct option *opt __maybe_unused,
 
 static int perf_stat_init_aggr_mode(void)
 {
-	switch (aggr_mode) {
+	switch (stat_config.aggr_mode) {
 	case AGGR_SOCKET:
 		if (cpu_map__build_socket_map(evsel_list->cpus, &aggr_map)) {
 			perror("cannot build socket map");
@@ -1286,7 +1290,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 			   stat__set_big_num),
 	OPT_STRING('C', "cpu", &target.cpu_list, "cpu",
 		    "list of cpus to monitor in system-wide"),
-	OPT_SET_UINT('A', "no-aggr", &aggr_mode,
+	OPT_SET_UINT('A', "no-aggr", &stat_config.aggr_mode,
 		    "disable CPU count aggregation", AGGR_NONE),
 	OPT_STRING('x', "field-separator", &csv_sep, "separator",
 		   "print counts with custom separator"),
@@ -1302,11 +1306,11 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 			"command to run after to the measured command"),
 	OPT_UINTEGER('I', "interval-print", &interval,
 		    "print counts at regular interval in ms (>= 100)"),
-	OPT_SET_UINT(0, "per-socket", &aggr_mode,
+	OPT_SET_UINT(0, "per-socket", &stat_config.aggr_mode,
 		     "aggregate counts per processor socket", AGGR_SOCKET),
-	OPT_SET_UINT(0, "per-core", &aggr_mode,
+	OPT_SET_UINT(0, "per-core", &stat_config.aggr_mode,
 		     "aggregate counts per physical processor core", AGGR_CORE),
-	OPT_SET_UINT(0, "per-thread", &aggr_mode,
+	OPT_SET_UINT(0, "per-thread", &stat_config.aggr_mode,
 		     "aggregate counts per thread", AGGR_THREAD),
 	OPT_UINTEGER('D', "delay", &initial_delay,
 		     "ms to wait before starting measurement after program start"),
@@ -1399,7 +1403,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 		run_count = 1;
 	}
 
-	if ((aggr_mode == AGGR_THREAD) && !target__has_task(&target)) {
+	if ((stat_config.aggr_mode == AGGR_THREAD) && !target__has_task(&target)) {
 		fprintf(stderr, "The --per-thread option is only available "
 			"when monitoring via -p -t options.\n");
 		parse_options_usage(NULL, options, "p", 1);
@@ -1411,7 +1415,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 	 * no_aggr, cgroup are for system-wide only
 	 * --per-thread is aggregated per thread, we dont mix it with cpu mode
 	 */
-	if (((aggr_mode != AGGR_GLOBAL && aggr_mode != AGGR_THREAD) || nr_cgroups) &&
+	if (((stat_config.aggr_mode != AGGR_GLOBAL &&
+	      stat_config.aggr_mode != AGGR_THREAD) || nr_cgroups) &&
 	    !target__has_cpu(&target)) {
 		fprintf(stderr, "both cgroup and no-aggregation "
 			"modes only available in system-wide mode\n");
@@ -1444,7 +1449,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 	 * Initialize thread_map with comm names,
 	 * so we could print it out on output.
 	 */
-	if (aggr_mode == AGGR_THREAD)
+	if (stat_config.aggr_mode == AGGR_THREAD)
 		thread_map__read_comms(evsel_list->threads);
 
 	if (interval && interval < 100) {
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 1cfbe0a..078bee4 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -50,6 +50,10 @@ struct perf_counts {
 	struct xyarray		  *values;
 };
 
+struct perf_stat_config {
+	enum aggr_mode	aggr_mode;
+};
+
 static inline struct perf_counts_values*
 perf_counts(struct perf_counts *counts, int cpu, int thread)
 {

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

* [tip:perf/core] perf stat: Move 'scale' into struct perf_stat_config
  2015-07-21 12:31 ` [PATCH 03/47] perf stat: Move scale into " Jiri Olsa
@ 2015-08-07  7:17   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 72+ messages in thread
From: tip-bot for Jiri Olsa @ 2015-08-07  7:17 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, a.p.zijlstra, namhyung, jolsa, acme, mingo, hpa,
	tglx, dsahern

Commit-ID:  711a572ea8ae7e9ab6575403c6d632d058d5cb3d
Gitweb:     http://git.kernel.org/tip/711a572ea8ae7e9ab6575403c6d632d058d5cb3d
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Tue, 21 Jul 2015 14:31:23 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 6 Aug 2015 16:02:39 -0300

perf stat: Move 'scale' into struct perf_stat_config

Moving 'scale' into struct perf_stat_config. The point is to centralize
the base stat config so it could be used localy together with other stat
routines in other parts of perf code.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1437481927-29538-4-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 12 ++++++------
 tools/perf/util/stat.h    |  1 +
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index bafb830..3fb2865 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -101,7 +101,6 @@ static struct target target = {
 
 static int			run_count			=  1;
 static bool			no_inherit			= false;
-static bool			scale				=  true;
 static volatile pid_t		child_pid			= -1;
 static bool			null_run			=  false;
 static int			detailed_run			=  0;
@@ -127,6 +126,7 @@ static volatile int done = 0;
 
 static struct perf_stat_config stat_config = {
 	.aggr_mode	= AGGR_GLOBAL,
+	.scale		= true,
 };
 
 static inline void diff_timespec(struct timespec *r, struct timespec *a,
@@ -151,7 +151,7 @@ static int create_perf_stat_counter(struct perf_evsel *evsel)
 {
 	struct perf_event_attr *attr = &evsel->attr;
 
-	if (scale)
+	if (stat_config.scale)
 		attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
 				    PERF_FORMAT_TOTAL_TIME_RUNNING;
 
@@ -240,13 +240,13 @@ process_counter_values(struct perf_evsel *evsel, int cpu, int thread,
 	case AGGR_NONE:
 		if (!evsel->snapshot)
 			perf_evsel__compute_deltas(evsel, cpu, thread, count);
-		perf_counts_values__scale(count, scale, NULL);
+		perf_counts_values__scale(count, stat_config.scale, NULL);
 		if (stat_config.aggr_mode == AGGR_NONE)
 			perf_stat__update_shadow_stats(evsel, count->values, cpu);
 		break;
 	case AGGR_GLOBAL:
 		aggr->val += count->val;
-		if (scale) {
+		if (stat_config.scale) {
 			aggr->ena += count->ena;
 			aggr->run += count->run;
 		}
@@ -299,7 +299,7 @@ static int process_counter(struct perf_evsel *counter)
 
 	if (!counter->snapshot)
 		perf_evsel__compute_deltas(counter, -1, -1, aggr);
-	perf_counts_values__scale(aggr, scale, &counter->counts->scaled);
+	perf_counts_values__scale(aggr, stat_config.scale, &counter->counts->scaled);
 
 	for (i = 0; i < 3; i++)
 		update_stats(&ps->res_stats[i], count[i]);
@@ -1274,7 +1274,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 		    "system-wide collection from all CPUs"),
 	OPT_BOOLEAN('g', "group", &group,
 		    "put the counters into a counter group"),
-	OPT_BOOLEAN('c', "scale", &scale, "scale/normalize counters"),
+	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,
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 078bee4..0a1d83f 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -52,6 +52,7 @@ struct perf_counts {
 
 struct perf_stat_config {
 	enum aggr_mode	aggr_mode;
+	bool		scale;
 };
 
 static inline struct perf_counts_values*

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

* [tip:perf/core] perf stat: Move 'output' into struct perf_stat_config
  2015-07-21 12:31 ` [PATCH 04/47] perf stat: Move output " Jiri Olsa
@ 2015-08-07  7:17   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 72+ messages in thread
From: tip-bot for Jiri Olsa @ 2015-08-07  7:17 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: namhyung, a.p.zijlstra, hpa, mingo, acme, dsahern, linux-kernel,
	jolsa, tglx

Commit-ID:  5821522e9484a8b503f89aa546085900b99589e9
Gitweb:     http://git.kernel.org/tip/5821522e9484a8b503f89aa546085900b99589e9
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Tue, 21 Jul 2015 14:31:24 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 6 Aug 2015 16:02:51 -0300

perf stat: Move 'output' into struct perf_stat_config

Moving 'output' into struct perf_stat_config. The point is to centralize
the base stat config so it could be used localy together with other stat
routines in other parts of perf code.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1437481927-29538-5-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 35 +++++++++++++++++++++++------------
 tools/perf/util/stat.h    |  1 +
 2 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 3fb2865..e3ea8b6 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -110,7 +110,6 @@ static int			big_num_opt			=  -1;
 static const char		*csv_sep			= NULL;
 static bool			csv_output			= false;
 static bool			group				= false;
-static FILE			*output				= NULL;
 static const char		*pre_cmd			= NULL;
 static const char		*post_cmd			= NULL;
 static bool			sync_run			= false;
@@ -305,7 +304,7 @@ static int process_counter(struct perf_evsel *counter)
 		update_stats(&ps->res_stats[i], count[i]);
 
 	if (verbose) {
-		fprintf(output, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
+		fprintf(stat_config.output, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
 			perf_evsel__name(counter), count[0], count[1], count[2]);
 	}
 
@@ -548,13 +547,13 @@ static int run_perf_stat(int argc, const char **argv)
 static void print_running(u64 run, u64 ena)
 {
 	if (csv_output) {
-		fprintf(output, "%s%" PRIu64 "%s%.2f",
+		fprintf(stat_config.output, "%s%" PRIu64 "%s%.2f",
 					csv_sep,
 					run,
 					csv_sep,
 					ena ? 100.0 * run / ena : 100.0);
 	} else if (run != ena) {
-		fprintf(output, "  (%.2f%%)", 100.0 * run / ena);
+		fprintf(stat_config.output, "  (%.2f%%)", 100.0 * run / ena);
 	}
 }
 
@@ -563,9 +562,9 @@ static void print_noise_pct(double total, double avg)
 	double pct = rel_stddev_stats(total, avg);
 
 	if (csv_output)
-		fprintf(output, "%s%.2f%%", csv_sep, pct);
+		fprintf(stat_config.output, "%s%.2f%%", csv_sep, pct);
 	else if (pct)
-		fprintf(output, "  ( +-%6.2f%% )", pct);
+		fprintf(stat_config.output, "  ( +-%6.2f%% )", pct);
 }
 
 static void print_noise(struct perf_evsel *evsel, double avg)
@@ -583,7 +582,7 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr)
 {
 	switch (stat_config.aggr_mode) {
 	case AGGR_CORE:
-		fprintf(output, "S%d-C%*d%s%*d%s",
+		fprintf(stat_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),
@@ -593,7 +592,7 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr)
 			csv_sep);
 		break;
 	case AGGR_SOCKET:
-		fprintf(output, "S%*d%s%*d%s",
+		fprintf(stat_config.output, "S%*d%s%*d%s",
 			csv_output ? 0 : -5,
 			id,
 			csv_sep,
@@ -602,12 +601,12 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr)
 			csv_sep);
 			break;
 	case AGGR_NONE:
-		fprintf(output, "CPU%*d%s",
+		fprintf(stat_config.output, "CPU%*d%s",
 			csv_output ? 0 : -4,
 			perf_evsel__cpus(evsel)->map[id], csv_sep);
 		break;
 	case AGGR_THREAD:
-		fprintf(output, "%*s-%*d%s",
+		fprintf(stat_config.output, "%*s-%*d%s",
 			csv_output ? 0 : 16,
 			thread_map__comm(evsel->threads, id),
 			csv_output ? 0 : -8,
@@ -622,6 +621,7 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr)
 
 static void nsec_printout(int id, int nr, struct perf_evsel *evsel, double avg)
 {
+	FILE *output = stat_config.output;
 	double msecs = avg / 1e6;
 	const char *fmt_v, *fmt_n;
 	char name[25];
@@ -658,6 +658,7 @@ static void nsec_printout(int id, int nr, struct perf_evsel *evsel, double avg)
 
 static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
 {
+	FILE *output = stat_config.output;
 	double sc =  evsel->scale;
 	const char *fmt;
 	int cpu = cpu_map__id_to_cpu(id);
@@ -697,6 +698,7 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
 
 static void print_aggr(char *prefix)
 {
+	FILE *output = stat_config.output;
 	struct perf_evsel *counter;
 	int cpu, cpu2, s, s2, id, nr;
 	double uval;
@@ -765,6 +767,7 @@ static void print_aggr(char *prefix)
 
 static void print_aggr_thread(struct perf_evsel *counter, char *prefix)
 {
+	FILE *output = stat_config.output;
 	int nthreads = thread_map__nr(counter->threads);
 	int ncpus = cpu_map__nr(counter->cpus);
 	int cpu, thread;
@@ -803,6 +806,7 @@ static void print_aggr_thread(struct perf_evsel *counter, char *prefix)
  */
 static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
 {
+	FILE *output = stat_config.output;
 	struct perf_stat *ps = counter->priv;
 	double avg = avg_stats(&ps->res_stats[0]);
 	int scaled = counter->counts->scaled;
@@ -854,6 +858,7 @@ static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
  */
 static void print_counter(struct perf_evsel *counter, char *prefix)
 {
+	FILE *output = stat_config.output;
 	u64 ena, run, val;
 	double uval;
 	int cpu;
@@ -908,6 +913,7 @@ static void print_counter(struct perf_evsel *counter, char *prefix)
 
 static void print_interval(char *prefix, struct timespec *ts)
 {
+	FILE *output = stat_config.output;
 	static int num_print_interval;
 
 	sprintf(prefix, "%6lu.%09lu%s", ts->tv_sec, ts->tv_nsec, csv_sep);
@@ -938,6 +944,7 @@ static void print_interval(char *prefix, struct timespec *ts)
 
 static void print_header(int argc, const char **argv)
 {
+	FILE *output = stat_config.output;
 	int i;
 
 	fflush(stdout);
@@ -967,6 +974,8 @@ static void print_header(int argc, const char **argv)
 
 static void print_footer(void)
 {
+	FILE *output = stat_config.output;
+
 	if (!null_run)
 		fprintf(output, "\n");
 	fprintf(output, " %17.9f seconds time elapsed",
@@ -1013,7 +1022,7 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)
 	if (!interval && !csv_output)
 		print_footer();
 
-	fflush(output);
+	fflush(stat_config.output);
 }
 
 static volatile int signr = -1;
@@ -1322,6 +1331,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 	};
 	int status = -EINVAL, run_idx;
 	const char *mode;
+	FILE *output = stderr;
 
 	setlocale(LC_ALL, "");
 
@@ -1332,7 +1342,6 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 	argc = parse_options(argc, argv, options, stat_usage,
 		PARSE_OPT_STOP_AT_NON_OPTION);
 
-	output = stderr;
 	if (output_name && strcmp(output_name, "-"))
 		output = NULL;
 
@@ -1369,6 +1378,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 		}
 	}
 
+	stat_config.output = output;
+
 	if (csv_sep) {
 		csv_output = true;
 		if (!strcmp(csv_sep, "\\t"))
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 0a1d83f..ed0e058 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -53,6 +53,7 @@ struct perf_counts {
 struct perf_stat_config {
 	enum aggr_mode	aggr_mode;
 	bool		scale;
+	FILE		*output;
 };
 
 static inline struct perf_counts_values*

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

* [tip:perf/core] perf stat: Move 'interval' into struct perf_stat_config
  2015-07-21 12:31 ` [PATCH 05/47] perf stat: Move interval " Jiri Olsa
@ 2015-08-07  7:18   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 72+ messages in thread
From: tip-bot for Jiri Olsa @ 2015-08-07  7:18 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, a.p.zijlstra, tglx, namhyung, mingo, hpa, dsahern,
	acme, jolsa

Commit-ID:  ec0d3d1fd292adb80372193c03d859e9cbefd367
Gitweb:     http://git.kernel.org/tip/ec0d3d1fd292adb80372193c03d859e9cbefd367
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Tue, 21 Jul 2015 14:31:25 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 6 Aug 2015 16:03:04 -0300

perf stat: Move 'interval' into struct perf_stat_config

Moving 'interval' into struct perf_stat_config. The point is to
centralize the base stat config so it could be used localy together with
other stat routines in other parts of perf code.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1437481927-29538-6-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 14 +++++++++-----
 tools/perf/util/stat.h    |  1 +
 2 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index e3ea8b6..1bdfec8 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -113,7 +113,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		interval			= 0;
 static unsigned int		initial_delay			= 0;
 static unsigned int		unit_width			= 4; /* strlen("unit") */
 static bool			forever				= false;
@@ -404,6 +403,7 @@ static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *inf
 
 static int __run_perf_stat(int argc, const char **argv)
 {
+	int interval = stat_config.interval;
 	char msg[512];
 	unsigned long long t0, t1;
 	struct perf_evsel *counter;
@@ -646,7 +646,7 @@ static void nsec_printout(int id, int nr, struct perf_evsel *evsel, double avg)
 	if (evsel->cgrp)
 		fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
 
-	if (csv_output || interval)
+	if (csv_output || stat_config.interval)
 		return;
 
 	if (perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK))
@@ -689,7 +689,7 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
 	if (evsel->cgrp)
 		fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
 
-	if (csv_output || interval)
+	if (csv_output || stat_config.interval)
 		return;
 
 	perf_stat__print_shadow_stats(output, evsel, avg, cpu,
@@ -990,6 +990,7 @@ static void print_footer(void)
 
 static void print_counters(struct timespec *ts, int argc, const char **argv)
 {
+	int interval = stat_config.interval;
 	struct perf_evsel *counter;
 	char buf[64], *prefix = NULL;
 
@@ -1029,7 +1030,7 @@ static volatile int signr = -1;
 
 static void skip_signal(int signo)
 {
-	if ((child_pid == -1) || interval)
+	if ((child_pid == -1) || stat_config.interval)
 		done = 1;
 
 	signr = signo;
@@ -1313,7 +1314,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 			"command to run prior to the measured command"),
 	OPT_STRING(0, "post", &post_cmd, "command",
 			"command to run after to the measured command"),
-	OPT_UINTEGER('I', "interval-print", &interval,
+	OPT_UINTEGER('I', "interval-print", &stat_config.interval,
 		    "print counts at regular interval in ms (>= 100)"),
 	OPT_SET_UINT(0, "per-socket", &stat_config.aggr_mode,
 		     "aggregate counts per processor socket", AGGR_SOCKET),
@@ -1332,6 +1333,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 	int status = -EINVAL, run_idx;
 	const char *mode;
 	FILE *output = stderr;
+	unsigned int interval;
 
 	setlocale(LC_ALL, "");
 
@@ -1342,6 +1344,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 	argc = parse_options(argc, argv, options, stat_usage,
 		PARSE_OPT_STOP_AT_NON_OPTION);
 
+	interval = stat_config.interval;
+
 	if (output_name && strcmp(output_name, "-"))
 		output = NULL;
 
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index ed0e058..1da706d 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -54,6 +54,7 @@ struct perf_stat_config {
 	enum aggr_mode	aggr_mode;
 	bool		scale;
 	FILE		*output;
+	unsigned int	interval;
 };
 
 static inline struct perf_counts_values*

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

* [tip:perf/core] perf stat: Pass 'struct perf_stat_config' into process_counter()
  2015-07-21 12:31 ` [PATCH 06/47] perf stat: Pass struct perf_stat_config into process_counter Jiri Olsa
@ 2015-08-07  7:18   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 72+ messages in thread
From: tip-bot for Jiri Olsa @ 2015-08-07  7:18 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: hpa, mingo, tglx, acme, a.p.zijlstra, namhyung, linux-kernel,
	jolsa, dsahern

Commit-ID:  5e5fe748bec771a810b1f44ec9c19e4b92685246
Gitweb:     http://git.kernel.org/tip/5e5fe748bec771a810b1f44ec9c19e4b92685246
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Tue, 21 Jul 2015 14:31:26 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 6 Aug 2015 16:07:36 -0300

perf stat: Pass 'struct perf_stat_config' into process_counter()

Passing 'struct perf_stat_config' into process_counter(), so that we can
make process_counter() non static and use it from other places.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1437481927-29538-7-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 29 ++++++++++++++++-------------
 1 file changed, 16 insertions(+), 13 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 1bdfec8..5a78171 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -216,7 +216,8 @@ static int check_per_pkg(struct perf_evsel *counter, int cpu, bool *skip)
 }
 
 static int
-process_counter_values(struct perf_evsel *evsel, int cpu, int thread,
+process_counter_values(struct perf_stat_config *config, struct perf_evsel *evsel,
+		       int cpu, int thread,
 		       struct perf_counts_values *count)
 {
 	struct perf_counts_values *aggr = &evsel->counts->aggr;
@@ -231,20 +232,20 @@ process_counter_values(struct perf_evsel *evsel, int cpu, int thread,
 	if (skip)
 		count = &zero;
 
-	switch (stat_config.aggr_mode) {
+	switch (config->aggr_mode) {
 	case AGGR_THREAD:
 	case AGGR_CORE:
 	case AGGR_SOCKET:
 	case AGGR_NONE:
 		if (!evsel->snapshot)
 			perf_evsel__compute_deltas(evsel, cpu, thread, count);
-		perf_counts_values__scale(count, stat_config.scale, NULL);
-		if (stat_config.aggr_mode == AGGR_NONE)
+		perf_counts_values__scale(count, config->scale, NULL);
+		if (config->aggr_mode == AGGR_NONE)
 			perf_stat__update_shadow_stats(evsel, count->values, cpu);
 		break;
 	case AGGR_GLOBAL:
 		aggr->val += count->val;
-		if (stat_config.scale) {
+		if (config->scale) {
 			aggr->ena += count->ena;
 			aggr->run += count->run;
 		}
@@ -255,7 +256,8 @@ process_counter_values(struct perf_evsel *evsel, int cpu, int thread,
 	return 0;
 }
 
-static int process_counter_maps(struct perf_evsel *counter)
+static int process_counter_maps(struct perf_stat_config *config,
+				struct perf_evsel *counter)
 {
 	int nthreads = thread_map__nr(counter->threads);
 	int ncpus = perf_evsel__nr_cpus(counter);
@@ -266,7 +268,7 @@ static int process_counter_maps(struct perf_evsel *counter)
 
 	for (thread = 0; thread < nthreads; thread++) {
 		for (cpu = 0; cpu < ncpus; cpu++) {
-			if (process_counter_values(counter, cpu, thread,
+			if (process_counter_values(config, counter, cpu, thread,
 						   perf_counts(counter->counts, cpu, thread)))
 				return -1;
 		}
@@ -275,7 +277,8 @@ static int process_counter_maps(struct perf_evsel *counter)
 	return 0;
 }
 
-static int process_counter(struct perf_evsel *counter)
+static int process_counter(struct perf_stat_config *config,
+			   struct perf_evsel *counter)
 {
 	struct perf_counts_values *aggr = &counter->counts->aggr;
 	struct perf_stat *ps = counter->priv;
@@ -288,22 +291,22 @@ static int process_counter(struct perf_evsel *counter)
 	if (counter->per_pkg)
 		zero_per_pkg(counter);
 
-	ret = process_counter_maps(counter);
+	ret = process_counter_maps(&stat_config, counter);
 	if (ret)
 		return ret;
 
-	if (stat_config.aggr_mode != AGGR_GLOBAL)
+	if (config->aggr_mode != AGGR_GLOBAL)
 		return 0;
 
 	if (!counter->snapshot)
 		perf_evsel__compute_deltas(counter, -1, -1, aggr);
-	perf_counts_values__scale(aggr, stat_config.scale, &counter->counts->scaled);
+	perf_counts_values__scale(aggr, config->scale, &counter->counts->scaled);
 
 	for (i = 0; i < 3; i++)
 		update_stats(&ps->res_stats[i], count[i]);
 
 	if (verbose) {
-		fprintf(stat_config.output, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
+		fprintf(config->output, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
 			perf_evsel__name(counter), count[0], count[1], count[2]);
 	}
 
@@ -352,7 +355,7 @@ static void read_counters(bool close_counters)
 		if (read_counter(counter))
 			pr_warning("failed to read counter %s\n", counter->name);
 
-		if (process_counter(counter))
+		if (process_counter(&stat_config, counter))
 			pr_warning("failed to process counter %s\n", counter->name);
 
 		if (close_counters) {

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

* [tip:perf/core] perf stat: Move counter processing code into stat object
  2015-07-21 12:31 ` [PATCH 07/47] perf stat: Move counter processing code into stat object Jiri Olsa
@ 2015-08-07  7:18   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 72+ messages in thread
From: tip-bot for Jiri Olsa @ 2015-08-07  7:18 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: hpa, namhyung, linux-kernel, jolsa, dsahern, acme, tglx,
	a.p.zijlstra, mingo

Commit-ID:  f80010eb230b94e8d9cf5bf83373a097fb5b2dcc
Gitweb:     http://git.kernel.org/tip/f80010eb230b94e8d9cf5bf83373a097fb5b2dcc
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Tue, 21 Jul 2015 14:31:27 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 6 Aug 2015 16:08:16 -0300

perf stat: Move counter processing code into stat object

Moving counter processing code into stat object as
perf_stat__process_counter.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1437481927-29538-8-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 141 +---------------------------------------------
 tools/perf/util/stat.c    | 139 +++++++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/stat.h    |   3 +
 3 files changed, 143 insertions(+), 140 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 5a78171..a054ddc 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -179,145 +179,6 @@ static inline int nsec_counter(struct perf_evsel *evsel)
 	return 0;
 }
 
-static void zero_per_pkg(struct perf_evsel *counter)
-{
-	if (counter->per_pkg_mask)
-		memset(counter->per_pkg_mask, 0, MAX_NR_CPUS);
-}
-
-static int check_per_pkg(struct perf_evsel *counter, int cpu, bool *skip)
-{
-	unsigned long *mask = counter->per_pkg_mask;
-	struct cpu_map *cpus = perf_evsel__cpus(counter);
-	int s;
-
-	*skip = false;
-
-	if (!counter->per_pkg)
-		return 0;
-
-	if (cpu_map__empty(cpus))
-		return 0;
-
-	if (!mask) {
-		mask = zalloc(MAX_NR_CPUS);
-		if (!mask)
-			return -ENOMEM;
-
-		counter->per_pkg_mask = mask;
-	}
-
-	s = cpu_map__get_socket(cpus, cpu);
-	if (s < 0)
-		return -1;
-
-	*skip = test_and_set_bit(s, mask) == 1;
-	return 0;
-}
-
-static int
-process_counter_values(struct perf_stat_config *config, struct perf_evsel *evsel,
-		       int cpu, int thread,
-		       struct perf_counts_values *count)
-{
-	struct perf_counts_values *aggr = &evsel->counts->aggr;
-	static struct perf_counts_values zero;
-	bool skip = false;
-
-	if (check_per_pkg(evsel, cpu, &skip)) {
-		pr_err("failed to read per-pkg counter\n");
-		return -1;
-	}
-
-	if (skip)
-		count = &zero;
-
-	switch (config->aggr_mode) {
-	case AGGR_THREAD:
-	case AGGR_CORE:
-	case AGGR_SOCKET:
-	case AGGR_NONE:
-		if (!evsel->snapshot)
-			perf_evsel__compute_deltas(evsel, cpu, thread, count);
-		perf_counts_values__scale(count, config->scale, NULL);
-		if (config->aggr_mode == AGGR_NONE)
-			perf_stat__update_shadow_stats(evsel, count->values, cpu);
-		break;
-	case AGGR_GLOBAL:
-		aggr->val += count->val;
-		if (config->scale) {
-			aggr->ena += count->ena;
-			aggr->run += count->run;
-		}
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-static int process_counter_maps(struct perf_stat_config *config,
-				struct perf_evsel *counter)
-{
-	int nthreads = thread_map__nr(counter->threads);
-	int ncpus = perf_evsel__nr_cpus(counter);
-	int cpu, thread;
-
-	if (counter->system_wide)
-		nthreads = 1;
-
-	for (thread = 0; thread < nthreads; thread++) {
-		for (cpu = 0; cpu < ncpus; cpu++) {
-			if (process_counter_values(config, counter, cpu, thread,
-						   perf_counts(counter->counts, cpu, thread)))
-				return -1;
-		}
-	}
-
-	return 0;
-}
-
-static int process_counter(struct perf_stat_config *config,
-			   struct perf_evsel *counter)
-{
-	struct perf_counts_values *aggr = &counter->counts->aggr;
-	struct perf_stat *ps = counter->priv;
-	u64 *count = counter->counts->aggr.values;
-	int i, ret;
-
-	aggr->val = aggr->ena = aggr->run = 0;
-	init_stats(ps->res_stats);
-
-	if (counter->per_pkg)
-		zero_per_pkg(counter);
-
-	ret = process_counter_maps(&stat_config, counter);
-	if (ret)
-		return ret;
-
-	if (config->aggr_mode != AGGR_GLOBAL)
-		return 0;
-
-	if (!counter->snapshot)
-		perf_evsel__compute_deltas(counter, -1, -1, aggr);
-	perf_counts_values__scale(aggr, config->scale, &counter->counts->scaled);
-
-	for (i = 0; i < 3; i++)
-		update_stats(&ps->res_stats[i], count[i]);
-
-	if (verbose) {
-		fprintf(config->output, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
-			perf_evsel__name(counter), count[0], count[1], count[2]);
-	}
-
-	/*
-	 * Save the full runtime - to allow normalization during printout:
-	 */
-	perf_stat__update_shadow_stats(counter, count, 0);
-
-	return 0;
-}
-
 /*
  * Read out the results of a single counter:
  * do not aggregate counts across CPUs in system-wide mode
@@ -355,7 +216,7 @@ static void read_counters(bool close_counters)
 		if (read_counter(counter))
 			pr_warning("failed to read counter %s\n", counter->name);
 
-		if (process_counter(&stat_config, counter))
+		if (perf_stat_process_counter(&stat_config, counter))
 			pr_warning("failed to process counter %s\n", counter->name);
 
 		if (close_counters) {
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index f2a0d15..c5c709c 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -238,3 +238,142 @@ void perf_evlist__reset_stats(struct perf_evlist *evlist)
 		perf_evsel__reset_counts(evsel);
 	}
 }
+
+static void zero_per_pkg(struct perf_evsel *counter)
+{
+	if (counter->per_pkg_mask)
+		memset(counter->per_pkg_mask, 0, MAX_NR_CPUS);
+}
+
+static int check_per_pkg(struct perf_evsel *counter, int cpu, bool *skip)
+{
+	unsigned long *mask = counter->per_pkg_mask;
+	struct cpu_map *cpus = perf_evsel__cpus(counter);
+	int s;
+
+	*skip = false;
+
+	if (!counter->per_pkg)
+		return 0;
+
+	if (cpu_map__empty(cpus))
+		return 0;
+
+	if (!mask) {
+		mask = zalloc(MAX_NR_CPUS);
+		if (!mask)
+			return -ENOMEM;
+
+		counter->per_pkg_mask = mask;
+	}
+
+	s = cpu_map__get_socket(cpus, cpu);
+	if (s < 0)
+		return -1;
+
+	*skip = test_and_set_bit(s, mask) == 1;
+	return 0;
+}
+
+static int
+process_counter_values(struct perf_stat_config *config, struct perf_evsel *evsel,
+		       int cpu, int thread,
+		       struct perf_counts_values *count)
+{
+	struct perf_counts_values *aggr = &evsel->counts->aggr;
+	static struct perf_counts_values zero;
+	bool skip = false;
+
+	if (check_per_pkg(evsel, cpu, &skip)) {
+		pr_err("failed to read per-pkg counter\n");
+		return -1;
+	}
+
+	if (skip)
+		count = &zero;
+
+	switch (config->aggr_mode) {
+	case AGGR_THREAD:
+	case AGGR_CORE:
+	case AGGR_SOCKET:
+	case AGGR_NONE:
+		if (!evsel->snapshot)
+			perf_evsel__compute_deltas(evsel, cpu, thread, count);
+		perf_counts_values__scale(count, config->scale, NULL);
+		if (config->aggr_mode == AGGR_NONE)
+			perf_stat__update_shadow_stats(evsel, count->values, cpu);
+		break;
+	case AGGR_GLOBAL:
+		aggr->val += count->val;
+		if (config->scale) {
+			aggr->ena += count->ena;
+			aggr->run += count->run;
+		}
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int process_counter_maps(struct perf_stat_config *config,
+				struct perf_evsel *counter)
+{
+	int nthreads = thread_map__nr(counter->threads);
+	int ncpus = perf_evsel__nr_cpus(counter);
+	int cpu, thread;
+
+	if (counter->system_wide)
+		nthreads = 1;
+
+	for (thread = 0; thread < nthreads; thread++) {
+		for (cpu = 0; cpu < ncpus; cpu++) {
+			if (process_counter_values(config, counter, cpu, thread,
+						   perf_counts(counter->counts, cpu, thread)))
+				return -1;
+		}
+	}
+
+	return 0;
+}
+
+int perf_stat_process_counter(struct perf_stat_config *config,
+			      struct perf_evsel *counter)
+{
+	struct perf_counts_values *aggr = &counter->counts->aggr;
+	struct perf_stat *ps = counter->priv;
+	u64 *count = counter->counts->aggr.values;
+	int i, ret;
+
+	aggr->val = aggr->ena = aggr->run = 0;
+	init_stats(ps->res_stats);
+
+	if (counter->per_pkg)
+		zero_per_pkg(counter);
+
+	ret = process_counter_maps(config, counter);
+	if (ret)
+		return ret;
+
+	if (config->aggr_mode != AGGR_GLOBAL)
+		return 0;
+
+	if (!counter->snapshot)
+		perf_evsel__compute_deltas(counter, -1, -1, aggr);
+	perf_counts_values__scale(aggr, config->scale, &counter->counts->scaled);
+
+	for (i = 0; i < 3; i++)
+		update_stats(&ps->res_stats[i], count[i]);
+
+	if (verbose) {
+		fprintf(config->output, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
+			perf_evsel__name(counter), count[0], count[1], count[2]);
+	}
+
+	/*
+	 * Save the full runtime - to allow normalization during printout:
+	 */
+	perf_stat__update_shadow_stats(counter, count, 0);
+
+	return 0;
+}
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 1da706d..0b897b0 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -116,4 +116,7 @@ int perf_evsel__alloc_stats(struct perf_evsel *evsel, bool alloc_raw);
 int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw);
 void perf_evlist__free_stats(struct perf_evlist *evlist);
 void perf_evlist__reset_stats(struct perf_evlist *evlist);
+
+int perf_stat_process_counter(struct perf_stat_config *config,
+			      struct perf_evsel *counter);
 #endif

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

* Re: [RFC 00/47] perf stat: Add scripting support
  2015-08-06 19:27 ` Arnaldo Carvalho de Melo
@ 2015-08-07  7:45   ` Jiri Olsa
  2015-08-07 13:10     ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 72+ messages in thread
From: Jiri Olsa @ 2015-08-07  7:45 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Jiri Olsa, Andi Kleen, Ulrich Drepper, Will Deacon,
	Stephane Eranian, lkml, David Ahern, Ingo Molnar, Namhyung Kim,
	Peter Zijlstra

On Thu, Aug 06, 2015 at 04:27:56PM -0300, Arnaldo Carvalho de Melo wrote:
> Em Tue, Jul 21, 2015 at 02:31:20PM +0200, Jiri Olsa escreveu:
> > hi,
> > sending RFC on another attempt for stat scripting.
> > 
> > The initial attempt defined its own formula lang and allowed
> > triggering user's script on the end of the stat command:
> >   http://marc.info/?l=linux-kernel&m=136742146322273&w=2
> > 
> > This patchset abandons the idea of new formula language
> > and rather adds support to:
> >   - store stat data into perf.data file
> >   - add python support to process stat events
> 
> Applied the first 11, some in a previous pull req, the ones moving stuff
> to perf_stat_config now, but the 12nd fails, please check when I get
> these merged by Ingo.

thanks

> 
> Also do you intend to do some rework on this due to the conversation
> with Kan? The ones I merged are good anyway, merged.

Kan still did not send his code.. I'll send new version
with review comments and with some enhancements soon

jirka

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

* Re: [RFC 00/47] perf stat: Add scripting support
  2015-08-07  7:45   ` Jiri Olsa
@ 2015-08-07 13:10     ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 72+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-08-07 13:10 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Jiri Olsa, Andi Kleen, Ulrich Drepper, Will Deacon,
	Stephane Eranian, lkml, David Ahern, Ingo Molnar, Namhyung Kim,
	Peter Zijlstra

Em Fri, Aug 07, 2015 at 09:45:56AM +0200, Jiri Olsa escreveu:
> On Thu, Aug 06, 2015 at 04:27:56PM -0300, Arnaldo Carvalho de Melo wrote:
> > Applied the first 11, some in a previous pull req, the ones moving stuff
> > to perf_stat_config now, but the 12nd fails, please check when I get
> > these merged by Ingo.
 
> thanks

> > Also do you intend to do some rework on this due to the conversation
> > with Kan? The ones I merged are good anyway, merged.
 
> Kan still did not send his code.. I'll send new version
> with review comments and with some enhancements soon

Ok, this is all in tip.git now, BTW.

- Arnaldo

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

end of thread, other threads:[~2015-08-07 13:10 UTC | newest]

Thread overview: 72+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-07-21 12:31 [RFC 00/47] perf stat: Add scripting support Jiri Olsa
2015-07-21 12:31 ` [PATCH 01/47] perf test: Check for refcnt in thread_map test Jiri Olsa
2015-07-21 17:26   ` Arnaldo Carvalho de Melo
2015-07-29  8:10   ` [tip:perf/core] " tip-bot for Jiri Olsa
2015-07-21 12:31 ` [PATCH 02/47] perf stat: Introduce struct perf_stat_config Jiri Olsa
2015-07-21 17:24   ` Arnaldo Carvalho de Melo
2015-07-21 17:37     ` Arnaldo Carvalho de Melo
2015-07-22  8:38       ` Jiri Olsa
2015-08-07  7:17   ` [tip:perf/core] " tip-bot for Jiri Olsa
2015-07-21 12:31 ` [PATCH 03/47] perf stat: Move scale into " Jiri Olsa
2015-08-07  7:17   ` [tip:perf/core] perf stat: Move 'scale' " tip-bot for Jiri Olsa
2015-07-21 12:31 ` [PATCH 04/47] perf stat: Move output " Jiri Olsa
2015-08-07  7:17   ` [tip:perf/core] perf stat: Move 'output' " tip-bot for Jiri Olsa
2015-07-21 12:31 ` [PATCH 05/47] perf stat: Move interval " Jiri Olsa
2015-08-07  7:18   ` [tip:perf/core] perf stat: Move 'interval' " tip-bot for Jiri Olsa
2015-07-21 12:31 ` [PATCH 06/47] perf stat: Pass struct perf_stat_config into process_counter Jiri Olsa
2015-08-07  7:18   ` [tip:perf/core] perf stat: Pass 'struct perf_stat_config' into process_counter() tip-bot for Jiri Olsa
2015-07-21 12:31 ` [PATCH 07/47] perf stat: Move counter processing code into stat object Jiri Olsa
2015-08-07  7:18   ` [tip:perf/core] " tip-bot for Jiri Olsa
2015-07-21 12:31 ` [PATCH 08/47] perf tools: Use bool instead of target argument in perf_evlist__propagate_maps Jiri Olsa
2015-07-29  8:10   ` [tip:perf/core] perf evlist: Use bool instead of target argument in propagate_maps() tip-bot for Jiri Olsa
2015-07-21 12:31 ` [PATCH 09/47] perf tools: Tolerate NULL maps in perf_evlist__propagate_maps Jiri Olsa
2015-07-21 17:31   ` Arnaldo Carvalho de Melo
2015-07-29  8:11   ` [tip:perf/core] perf evlist: Tolerate NULL maps in propagate_maps tip-bot for Jiri Olsa
2015-07-21 12:31 ` [PATCH 10/47] perf tools: Force perf_evlist__set_maps to propagate maps through events Jiri Olsa
2015-07-21 17:25   ` Arnaldo Carvalho de Melo
2015-07-29  8:10   ` [tip:perf/core] perf evlist: " tip-bot for Jiri Olsa
2015-07-21 12:31 ` [PATCH 11/47] perf tools: Use argv style storage for cmdline feature data Jiri Olsa
2015-07-21 17:29   ` Arnaldo Carvalho de Melo
2015-07-29  8:11   ` [tip:perf/core] perf header: " tip-bot for Jiri Olsa
2015-07-21 12:31 ` [PATCH 12/47] perf tools: Add thread_map event Jiri Olsa
2015-07-21 12:31 ` [PATCH 13/47] perf tools: Add thread_map event sythesize function Jiri Olsa
2015-07-21 12:31 ` [PATCH 14/47] perf tools: Add thread_map__new_event function Jiri Olsa
2015-07-21 12:31 ` [PATCH 15/47] perf tools: Add cpu_map event Jiri Olsa
2015-07-21 12:31 ` [PATCH 16/47] perf tools: Add cpu_map event synthesize function Jiri Olsa
2015-07-21 12:31 ` [PATCH 17/47] perf tools: Add cpu_map__new_event function Jiri Olsa
2015-07-21 12:31 ` [PATCH 18/47] perf tools: Add stat config event Jiri Olsa
2015-07-21 12:31 ` [PATCH 19/47] perf tools: Add stat config event synthesize function Jiri Olsa
2015-07-21 12:31 ` [PATCH 20/47] perf tools: Add stat config event read function Jiri Olsa
2015-07-21 12:31 ` [PATCH 21/47] perf tools: Add stat event Jiri Olsa
2015-07-21 12:31 ` [PATCH 22/47] perf tools: Add stat event synthesize function Jiri Olsa
2015-07-21 12:31 ` [PATCH 23/47] perf tools: Add stat event read function Jiri Olsa
2015-07-21 12:31 ` [PATCH 24/47] perf tools: Add stat round event Jiri Olsa
2015-07-21 12:31 ` [PATCH 25/47] perf tools: Add stat round event synthesize function Jiri Olsa
2015-07-21 12:31 ` [PATCH 26/47] perf tools: Introduce stat feature Jiri Olsa
2015-07-21 12:31 ` [PATCH 27/47] perf tools: Move id_offset out of struct perf_evsel union Jiri Olsa
2015-07-21 12:31 ` [PATCH 28/47] perf stat record: Add record command Jiri Olsa
2015-07-21 12:31 ` [PATCH 29/47] perf stat record: Initialize record features Jiri Olsa
2015-07-21 12:31 ` [PATCH 30/47] perf stat record: Synthesize stat record data Jiri Olsa
2015-07-21 12:31 ` [PATCH 31/47] perf stat record: Store events IDs in perf data file Jiri Olsa
2015-07-21 12:31 ` [PATCH 32/47] perf stat record: Add pipe support for record command Jiri Olsa
2015-07-21 12:31 ` [PATCH 33/47] perf stat record: Write stat events on record Jiri Olsa
2015-07-21 12:31 ` [PATCH 34/47] perf stat record: Write stat round " Jiri Olsa
2015-07-21 12:31 ` [PATCH 35/47] perf stat report: Add report command Jiri Olsa
2015-07-21 12:31 ` [PATCH 36/47] perf stat report: Process cpu/threads maps Jiri Olsa
2015-07-21 12:31 ` [PATCH 37/47] perf stat report: Process stat config event Jiri Olsa
2015-07-21 12:31 ` [PATCH 38/47] perf stat report: Process stat and stat round events Jiri Olsa
2015-07-21 12:31 ` [PATCH 39/47] perf stat report: Move csv_sep initialization before report command Jiri Olsa
2015-07-21 12:32 ` [PATCH 40/47] perf script: Check output fields only for samples Jiri Olsa
2015-07-21 12:32 ` [PATCH 41/47] perf script: Process cpu/threads maps Jiri Olsa
2015-07-21 12:32 ` [PATCH 42/47] perf script: Process stat config event Jiri Olsa
2015-07-21 12:32 ` [PATCH 43/47] perf script: Add process_stat/process_stat_interval scripting interface Jiri Olsa
2015-07-21 12:32 ` [PATCH 44/47] perf script: Add stat default handlers Jiri Olsa
2015-07-21 12:32 ` [PATCH 45/47] perf script: Display stat events by default Jiri Olsa
2015-07-21 12:32 ` [PATCH 46/47] perf script: Add python support for stat events Jiri Olsa
2015-07-21 12:32 ` [PATCH 47/47] perf script: Add stat-cpi.py script Jiri Olsa
2015-07-21 14:43 ` [RFC 00/47] perf stat: Add scripting support Andi Kleen
2015-07-26 13:51   ` Jiri Olsa
2015-07-27 12:46     ` Liang, Kan
2015-08-06 19:27 ` Arnaldo Carvalho de Melo
2015-08-07  7:45   ` Jiri Olsa
2015-08-07 13:10     ` Arnaldo Carvalho de Melo

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.