Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1236373 > unrolled thread

[PATCHv2 00/45] perf stat: Add scripting support

Started byJiri Olsa <jolsa@kernel.org>
First post2015-09-30 16:20 +0200
Last post2015-09-30 23:40 +0200
Articles 20 on this page of 24 — 3 participants

Back to article view | Back to linux.kernel


Contents

  [PATCHv2 00/45] perf stat: Add scripting support Jiri Olsa <jolsa@kernel.org> - 2015-09-30 16:20 +0200
    [PATCH 44/45] perf script: Add python support for stat events Jiri Olsa <jolsa@kernel.org> - 2015-09-30 16:20 +0200
    [PATCH 40/45] perf script: Process stat config event Jiri Olsa <jolsa@kernel.org> - 2015-09-30 16:20 +0200
    [PATCH 05/45] perf tools: Add cpu_map event synthesize function Jiri Olsa <jolsa@kernel.org> - 2015-09-30 16:20 +0200
    [PATCH 29/45] perf tools: Add data arg to cpu_map__build_map callback Jiri Olsa <jolsa@kernel.org> - 2015-09-30 16:20 +0200
    [PATCH 34/45] perf stat report: Add support to initialize aggr_map from file Jiri Olsa <jolsa@kernel.org> - 2015-09-30 16:20 +0200
    [PATCH 30/45] perf stat report: Cache aggregated map entries in extra cpumap Jiri Olsa <jolsa@kernel.org> - 2015-09-30 16:20 +0200
    [PATCH 09/45] perf tools: Add stat config event read function Jiri Olsa <jolsa@kernel.org> - 2015-09-30 16:30 +0200
    [PATCH 18/45] perf stat: Add AGGR_UNSET mode Jiri Olsa <jolsa@kernel.org> - 2015-09-30 16:30 +0200
    [PATCH 11/45] perf tools: Add stat event synthesize function Jiri Olsa <jolsa@kernel.org> - 2015-09-30 16:30 +0200
    [PATCH 17/45] perf stat: Rename perf_stat struct into perf_stat_evsel Jiri Olsa <jolsa@kernel.org> - 2015-09-30 16:30 +0200
    [PATCH 23/45] perf stat record: Add pipe support for record command Jiri Olsa <jolsa@kernel.org> - 2015-09-30 16:30 +0200
    [PATCH 12/45] perf tools: Add stat event read function Jiri Olsa <jolsa@kernel.org> - 2015-09-30 16:30 +0200
    [PATCH 02/45] perf tools: Add thread_map event synthesize function Jiri Olsa <jolsa@kernel.org> - 2015-09-30 16:30 +0200
    [PATCH 14/45] perf tools: Add stat round event synthesize function Jiri Olsa <jolsa@kernel.org> - 2015-09-30 16:30 +0200
    [PATCH 15/45] perf tools: Introduce stat feature Jiri Olsa <jolsa@kernel.org> - 2015-09-30 16:30 +0200
    [PATCH 04/45] perf tools: Add cpu_map event Jiri Olsa <jolsa@kernel.org> - 2015-09-30 16:30 +0200
    [PATCH 22/45] perf stat record: Store events IDs in perf data file Jiri Olsa <jolsa@kernel.org> - 2015-09-30 16:30 +0200
    [PATCH 08/45] perf tools: Add stat config event synthesize function Jiri Olsa <jolsa@kernel.org> - 2015-09-30 16:30 +0200
    [PATCH 19/45] perf stat record: Add record command Jiri Olsa <jolsa@kernel.org> - 2015-09-30 16:30 +0200
    [PATCH 21/45] perf stat record: Synthesize stat record data Jiri Olsa <jolsa@kernel.org> - 2015-09-30 16:30 +0200
    RE: [PATCHv2 00/45] perf stat: Add scripting support "Liang, Kan" <kan.liang@intel.com> - 2015-09-30 23:20 +0200
      Re: [PATCHv2 00/45] perf stat: Add scripting support Jiri Olsa <jolsa@redhat.com> - 2015-09-30 23:40 +0200
      Re: [PATCHv2 00/45] perf stat: Add scripting support Jiri Olsa <jolsa@redhat.com> - 2015-09-30 23:40 +0200

Page 1 of 2  [1] 2  Next page →


#1236373 — [PATCHv2 00/45] perf stat: Add scripting support

FromJiri Olsa <jolsa@kernel.org>
Date2015-09-30 16:20 +0200
Subject[PATCHv2 00/45] perf stat: Add scripting support
Message-ID<qeqoF-7qA-3@gated-at.bofh.it>
hi,
sending another version of stat scripting.

v2 changes:
  - rebased to latest Arnaldo's perf/core
  - patches 1 to 11 already merged in
  - added --per-core/--per-socket/-A options for perf stat report
    command to allow custom aggregation in stat report, please
    check new examples below
  - couple changelogs changes

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.

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

thanks,
jirka


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

- To display different aggregation in report:

  $ perf stat -e cycles -a -I 1000 record sleep 3 
  #           time             counts unit events
       1.000223609        703,427,617      cycles                   
       2.000443651        609,975,307      cycles                   
       3.000569616        668,479,597      cycles                   
       3.000735323          1,155,816      cycles                 

  $ perf stat report
  #           time             counts unit events
       1.000223609        703,427,617      cycles                   
       2.000443651        609,975,307      cycles                   
       3.000569616        668,479,597      cycles                   
       3.000735323          1,155,816      cycles                   

  $ perf stat report --per-core
  #           time core         cpus             counts unit events
       1.000223609 S0-C0           2        327,612,412      cycles                   
       1.000223609 S0-C1           2        375,815,205      cycles                   
       2.000443651 S0-C0           2        287,462,177      cycles                   
       2.000443651 S0-C1           2        322,513,130      cycles                   
       3.000569616 S0-C0           2        271,571,908      cycles                   
       3.000569616 S0-C1           2        396,907,689      cycles                   
       3.000735323 S0-C0           2            694,977      cycles                   
       3.000735323 S0-C1           2            460,839      cycles                   

  $ perf stat report --per-socket
  #           time socket cpus             counts unit events
       1.000223609 S0        4        703,427,617      cycles                   
       2.000443651 S0        4        609,975,307      cycles                   
       3.000569616 S0        4        668,479,597      cycles                   
       3.000735323 S0        4          1,155,816      cycles                   

  $ perf stat report -A
  #           time CPU                counts unit events
       1.000223609 CPU0           205,431,505      cycles                   
       1.000223609 CPU1           122,180,907      cycles                   
       1.000223609 CPU2           176,649,682      cycles                   
       1.000223609 CPU3           199,165,523      cycles                   
       2.000443651 CPU0           148,447,922      cycles                   
       2.000443651 CPU1           139,014,255      cycles                   
       2.000443651 CPU2           204,436,559      cycles                   
       2.000443651 CPU3           118,076,571      cycles                   
       3.000569616 CPU0           149,788,954      cycles                   
       3.000569616 CPU1           121,782,954      cycles                   
       3.000569616 CPU2           247,277,700      cycles                   
       3.000569616 CPU3           149,629,989      cycles                   
       3.000735323 CPU0               269,675      cycles                   
       3.000735323 CPU1               425,302      cycles                   
       3.000735323 CPU2               364,169      cycles                   
       3.000735323 CPU3                96,670      cycles                   


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>
Cc: Don Zickus <dzickus@redhat.com>
---
Jiri Olsa (45):
      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: Rename perf_stat struct into perf_stat_evsel
      perf stat: Add AGGR_UNSET mode
      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 record: Do not allow record with multiple runs mode
      perf tools: Add cpu_map__empty_new interface
      perf tools: Make cpu_map__build_map global
      perf tools: Add data arg to cpu_map__build_map callback
      perf stat report: Cache aggregated map entries in extra cpumap
      perf stat report: Add report command
      perf stat report: Process cpu/threads maps
      perf stat report: Process stat config event
      perf stat report: Add support to initialize aggr_map from file
      perf stat report: Process stat and stat round events
      perf stat report: Move csv_sep initialization before report command
      perf stat report: Allow to override aggr_mode
      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                 |  34 ++++++
 tools/perf/builtin-record.c                            |   2 +
 tools/perf/builtin-script.c                            | 144 +++++++++++++++++++++++-
 tools/perf/builtin-stat.c                              | 584 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 tools/perf/scripts/python/stat-cpi.py                  |  74 +++++++++++++
 tools/perf/tests/Build                                 |   2 +
 tools/perf/tests/builtin-test.c                        |  21 ++++
 tools/perf/tests/cpumap.c                              |  39 +++++++
 tools/perf/tests/stat.c                                | 111 +++++++++++++++++++
 tools/perf/tests/tests.h                               |   6 +
 tools/perf/tests/thread-map.c                          |  43 +++++++
 tools/perf/tests/topology.c                            |   4 +-
 tools/perf/util/cpumap.c                               |  61 ++++++++--
 tools/perf/util/cpumap.h                               |  11 +-
 tools/perf/util/event.c                                | 172 ++++++++++++++++++++++++++++
 tools/perf/util/event.h                                | 100 ++++++++++++++++-
 tools/perf/util/evlist.c                               |   6 +-
 tools/perf/util/evlist.h                               |   3 +
 tools/perf/util/evsel.h                                |   2 +-
 tools/perf/util/header.c                               |  14 +++
 tools/perf/util/header.h                               |   1 +
 tools/perf/util/scripting-engines/trace-event-python.c | 114 ++++++++++++++++++-
 tools/perf/util/session.c                              | 123 +++++++++++++++++++++
 tools/perf/util/stat.c                                 |  36 +++++-
 tools/perf/util/stat.h                                 |   9 +-
 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 +
 29 files changed, 1708 insertions(+), 49 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
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [next] | [standalone]


#1236374 — [PATCH 44/45] perf script: Add python support for stat events

FromJiri Olsa <jolsa@kernel.org>
Date2015-09-30 16:20 +0200
Subject[PATCH 44/45] perf script: Add python support for stat events
Message-ID<qeqoI-7qA-71@gated-at.bofh.it>
In reply to#1236373
Add support to get stat events data in perf python scripts.

The python script shall implement following
new interface to process stat data:

  def stat__<event_name>_[<modifier>](cpu, thread, time, val, ena, run):

    - is called for every stat event for given counter,
      if user monitors 'cycles,instructions:u" following
      callbacks should be defined:

      def stat__cycles(cpu, thread, time, val, ena, run):
      def stat__instructions_u(cpu, thread, time, val, ena, run):

  def stat__interval(time):

    - is called for every interval with its time,
      in non interval mode it's called after last
      stat event with total meassured time in ns

The rest of the current interface stays untouched..

Please check example CPI metrics script in following patch
with command line examples in changelogs.

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    | 114 +++++++++++++++++++--
 1 file changed, 108 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 a8e825fca42a..8436eb23eb16 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -41,6 +41,9 @@
 #include "../thread-stack.h"
 #include "../trace-event.h"
 #include "../machine.h"
+#include "thread_map.h"
+#include "cpumap.h"
+#include "stat.h"
 
 PyMODINIT_FUNC initperf_trace_context(void);
 
@@ -859,6 +862,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__");
@@ -1201,10 +1301,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

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1236375 — [PATCH 40/45] perf script: Process stat config event

FromJiri Olsa <jolsa@kernel.org>
Date2015-09-30 16:20 +0200
Subject[PATCH 40/45] perf script: Process stat config event
Message-ID<qeqoJ-7qA-79@gated-at.bofh.it>
In reply to#1236373
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 | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 1d0a4469b74c..223ab33233eb 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -36,6 +36,7 @@ static bool			print_flags;
 static bool			nanosecs;
 static const char		*cpu_list;
 static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
+static struct perf_stat_config	stat_config;
 
 unsigned int scripting_max_stack = PERF_MAX_STACK_DEPTH;
 
@@ -1622,6 +1623,14 @@ static void script__setup_sample_type(struct perf_script *script)
 	}
 }
 
+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;
@@ -1707,6 +1716,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

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1236377 — [PATCH 05/45] perf tools: Add cpu_map event synthesize function

FromJiri Olsa <jolsa@kernel.org>
Date2015-09-30 16:20 +0200
Subject[PATCH 05/45] perf tools: Add cpu_map event synthesize function
Message-ID<qeqoJ-7qA-77@gated-at.bofh.it>
In reply to#1236373
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 c6f198ae65fb..1a8d23367b8a 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -34,6 +34,7 @@ perf-y += kmod-path.o
 perf-y += thread-map.o
 perf-y += llvm.o
 perf-y += topology.o
+perf-y += cpumap.o
 
 perf-$(CONFIG_X86) += perf-time-to-tsc.o
 ifdef CONFIG_AUXTRACE
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 7cf131a3f75e..3068ec0c7ecf 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -196,6 +196,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 1c9cb793ae72..c8e4e74830c4 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -66,6 +66,7 @@ int test__llvm(void);
 int test__insn_x86(void);
 int test_session_topology(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 091c5de2a523..d327f0922ae4 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -737,6 +737,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 46162b9c6720..61f8228a90b5 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -405,6 +405,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,
@@ -420,6 +421,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

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1236378 — [PATCH 29/45] perf tools: Add data arg to cpu_map__build_map callback

FromJiri Olsa <jolsa@kernel.org>
Date2015-09-30 16:20 +0200
Subject[PATCH 29/45] perf tools: Add data arg to cpu_map__build_map callback
Message-ID<qeqoJ-7qA-81@gated-at.bofh.it>
In reply to#1236373
Adding data arg to cpu_map__build_map callback, so we could
pass data along to the callback. It'll be needed in following
patches to retrieve topology info from perf.data.

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

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 5d53f7d1a2d4..9982f09dff09 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1099,6 +1099,16 @@ static int stat__set_big_num(const struct option *opt __maybe_unused,
 	return 0;
 }
 
+static int perf_stat__get_socket(struct cpu_map *map, int cpu)
+{
+	return cpu_map__get_socket(map, cpu, NULL);
+}
+
+static int perf_stat__get_core(struct cpu_map *map, int cpu)
+{
+	return cpu_map__get_core(map, cpu, NULL);
+}
+
 static int perf_stat_init_aggr_mode(void)
 {
 	switch (stat_config.aggr_mode) {
@@ -1107,14 +1117,14 @@ static int perf_stat_init_aggr_mode(void)
 			perror("cannot build socket map");
 			return -1;
 		}
-		aggr_get_id = cpu_map__get_socket;
+		aggr_get_id = perf_stat__get_socket;
 		break;
 	case AGGR_CORE:
 		if (cpu_map__build_core_map(evsel_list->cpus, &aggr_map)) {
 			perror("cannot build core map");
 			return -1;
 		}
-		aggr_get_id = cpu_map__get_core;
+		aggr_get_id = perf_stat__get_core;
 		break;
 	case AGGR_NONE:
 	case AGGR_GLOBAL:
diff --git a/tools/perf/tests/topology.c b/tools/perf/tests/topology.c
index c3aff53a976a..f5bb096c3bd9 100644
--- a/tools/perf/tests/topology.c
+++ b/tools/perf/tests/topology.c
@@ -73,10 +73,10 @@ static int check_cpu_topology(char *path, struct cpu_map *map)
 
 	for (i = 0; i < map->nr; i++) {
 		TEST_ASSERT_VAL("Core ID doesn't match",
-			(session->header.env.cpu[map->map[i]].core_id == (cpu_map__get_core(map, i) & 0xffff)));
+			(session->header.env.cpu[map->map[i]].core_id == (cpu_map__get_core(map, i, NULL) & 0xffff)));
 
 		TEST_ASSERT_VAL("Socket ID doesn't match",
-			(session->header.env.cpu[map->map[i]].socket_id == cpu_map__get_socket(map, i)));
+			(session->header.env.cpu[map->map[i]].socket_id == cpu_map__get_socket(map, i, NULL)));
 	}
 
 	perf_session__delete(session);
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index 6d0a2ddf4eba..52d3f8bbf733 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -285,7 +285,7 @@ int cpu_map__get_socket_id(int cpu)
 	return ret ?: value;
 }
 
-int cpu_map__get_socket(struct cpu_map *map, int idx)
+int cpu_map__get_socket(struct cpu_map *map, int idx, void *data __maybe_unused)
 {
 	int cpu;
 
@@ -303,7 +303,8 @@ static int cmp_ids(const void *a, const void *b)
 }
 
 int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res,
-		       int (*f)(struct cpu_map *map, int cpu))
+		       int (*f)(struct cpu_map *map, int cpu, void *data),
+		       void *data)
 {
 	struct cpu_map *c;
 	int nr = cpus->nr;
@@ -315,7 +316,7 @@ int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res,
 		return -1;
 
 	for (cpu = 0; cpu < nr; cpu++) {
-		s1 = f(cpus, cpu);
+		s1 = f(cpus, cpu, data);
 		for (s2 = 0; s2 < c->nr; s2++) {
 			if (s1 == c->map[s2])
 				break;
@@ -339,7 +340,7 @@ int cpu_map__get_core_id(int cpu)
 	return ret ?: value;
 }
 
-int cpu_map__get_core(struct cpu_map *map, int idx)
+int cpu_map__get_core(struct cpu_map *map, int idx, void *data)
 {
 	int cpu, s;
 
@@ -350,7 +351,7 @@ int cpu_map__get_core(struct cpu_map *map, int idx)
 
 	cpu = cpu_map__get_core_id(cpu);
 
-	s = cpu_map__get_socket(map, idx);
+	s = cpu_map__get_socket(map, idx, data);
 	if (s == -1)
 		return -1;
 
@@ -365,12 +366,12 @@ int cpu_map__get_core(struct cpu_map *map, int idx)
 
 int cpu_map__build_socket_map(struct cpu_map *cpus, struct cpu_map **sockp)
 {
-	return cpu_map__build_map(cpus, sockp, cpu_map__get_socket);
+	return cpu_map__build_map(cpus, sockp, cpu_map__get_socket, NULL);
 }
 
 int cpu_map__build_core_map(struct cpu_map *cpus, struct cpu_map **corep)
 {
-	return cpu_map__build_map(cpus, corep, cpu_map__get_core);
+	return cpu_map__build_map(cpus, corep, cpu_map__get_core, NULL);
 }
 
 /* setup simple routines to easily access node numbers given a cpu number */
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index 74f0151c3fab..a44eab0083bd 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -23,9 +23,9 @@ 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_id(int cpu);
-int cpu_map__get_socket(struct cpu_map *map, int idx);
+int cpu_map__get_socket(struct cpu_map *map, int idx, void *data);
 int cpu_map__get_core_id(int cpu);
-int cpu_map__get_core(struct cpu_map *map, int idx);
+int cpu_map__get_core(struct cpu_map *map, int idx, void *data);
 int cpu_map__build_socket_map(struct cpu_map *cpus, struct cpu_map **sockp);
 int cpu_map__build_core_map(struct cpu_map *cpus, struct cpu_map **corep);
 
@@ -92,5 +92,6 @@ static inline int cpu__get_node(int cpu)
 }
 
 int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res,
-		       int (*f)(struct cpu_map *map, int cpu));
+		       int (*f)(struct cpu_map *map, int cpu, void *data),
+		       void *data);
 #endif /* __PERF_CPUMAP_H */
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index 677620acd2bd..40fa99b640f8 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -230,7 +230,7 @@ static int check_per_pkg(struct perf_evsel *counter,
 	if (!(vals->run && vals->ena))
 		return 0;
 
-	s = cpu_map__get_socket(cpus, cpu);
+	s = cpu_map__get_socket(cpus, cpu, NULL);
 	if (s < 0)
 		return -1;
 
-- 
2.4.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1236379 — [PATCH 34/45] perf stat report: Add support to initialize aggr_map from file

FromJiri Olsa <jolsa@kernel.org>
Date2015-09-30 16:20 +0200
Subject[PATCH 34/45] perf stat report: Add support to initialize aggr_map from file
Message-ID<qeqoK-7qA-85@gated-at.bofh.it>
In reply to#1236373
Using perf.data's perf_env data to initialize
aggregate config.

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

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 5a5221437208..6e84794cae00 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1194,6 +1194,89 @@ static int perf_stat_init_aggr_mode(void)
 	return cpus_aggr_map ? 0 : -ENOMEM;
 }
 
+static inline int perf_env__get_cpu(struct perf_env *env, struct cpu_map *map, int idx)
+{
+	int cpu;
+
+	if (idx > map->nr)
+		return -1;
+
+	cpu = map->map[idx];
+
+	if (cpu >= env->nr_cpus_online)
+		return -1;
+
+	return cpu;
+}
+
+static int perf_env__get_socket(struct cpu_map *map, int idx, void *data)
+{
+	struct perf_env *env = data;
+	int cpu = perf_env__get_cpu(env, map, idx);
+
+	return cpu == -1 ? -1 : env->cpu[cpu].socket_id;
+}
+
+static int perf_env__get_core(struct cpu_map *map, int idx, void *data)
+{
+	struct perf_env *env = data;
+	int cpu = perf_env__get_cpu(env, map, idx);
+
+	return cpu == -1 ? -1 : env->cpu[cpu].core_id;
+}
+
+static int perf_env__build_socket_map(struct perf_env *env, struct cpu_map *cpus,
+				      struct cpu_map **sockp)
+{
+	return cpu_map__build_map(cpus, sockp, perf_env__get_socket, env);
+}
+
+static int perf_env__build_core_map(struct perf_env *env, struct cpu_map *cpus,
+				    struct cpu_map **corep)
+{
+	return cpu_map__build_map(cpus, corep, perf_env__get_core, env);
+}
+
+static int perf_stat__get_socket_file(struct cpu_map *map, int idx)
+{
+	return perf_env__get_socket(map, idx, &perf_stat.session->header.env);
+}
+
+static int perf_stat__get_core_file(struct cpu_map *map, int idx)
+{
+	return perf_env__get_core(map, idx, &perf_stat.session->header.env);
+}
+
+static int perf_stat_init_aggr_mode_file(struct perf_stat *stat)
+{
+	struct perf_env *env = &stat->session->header.env;
+
+	switch (stat_config.aggr_mode) {
+	case AGGR_SOCKET:
+		if (perf_env__build_socket_map(env, evsel_list->cpus, &aggr_map)) {
+			perror("cannot build socket map");
+			return -1;
+		}
+		aggr_get_id = perf_stat__get_socket_file;
+		break;
+	case AGGR_CORE:
+		if (perf_env__build_core_map(env, evsel_list->cpus, &aggr_map)) {
+			perror("cannot build core map");
+			return -1;
+		}
+		aggr_get_id = perf_stat__get_core_file;
+		break;
+	case AGGR_NONE:
+	case AGGR_GLOBAL:
+	case AGGR_THREAD:
+	case AGGR_UNSET:
+	default:
+		break;
+	}
+
+	return 0;
+}
+
 /*
  * Add default attributes, if there were no attributes specified or
  * if -d/--detailed, -d -d or -d -d -d is used:
@@ -1407,7 +1490,15 @@ int process_stat_config_event(struct perf_tool *tool __maybe_unused,
 			      union perf_event *event,
 			      struct perf_session *session __maybe_unused)
 {
+	struct perf_stat *stat = container_of(tool, struct perf_stat, tool);
+
 	perf_event__read_stat_config(&stat_config, &event->stat_config);
+
+	if (perf_stat.file.is_pipe)
+		perf_stat_init_aggr_mode();
+	else
+		perf_stat_init_aggr_mode_file(stat);
+
 	return 0;
 }
 
-- 
2.4.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1236380 — [PATCH 30/45] perf stat report: Cache aggregated map entries in extra cpumap

FromJiri Olsa <jolsa@kernel.org>
Date2015-09-30 16:20 +0200
Subject[PATCH 30/45] perf stat report: Cache aggregated map entries in extra cpumap
Message-ID<qeqoJ-7qA-83@gated-at.bofh.it>
In reply to#1236373
Currently any time we need to access socket or core id for
given cpu, we access the sysfs topology file.

Adding cpus_aggr_map cpu_map to cache those entries.

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

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 9982f09dff09..b5297b9a27d5 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -101,6 +101,8 @@ static struct target target = {
 	.uid	= UINT_MAX,
 };
 
+typedef int (*aggr_get_id_t)(struct cpu_map *m, int cpu);
+
 static int			run_count			=  1;
 static bool			no_inherit			= false;
 static volatile pid_t		child_pid			= -1;
@@ -120,7 +122,7 @@ static unsigned int		unit_width			= 4; /* strlen("unit") */
 static bool			forever				= false;
 static struct timespec		ref_time;
 static struct cpu_map		*aggr_map;
-static int			(*aggr_get_id)(struct cpu_map *m, int cpu);
+static aggr_get_id_t		aggr_get_id;
 
 struct perf_stat {
 	bool			 record;
@@ -1099,6 +1101,7 @@ static int stat__set_big_num(const struct option *opt __maybe_unused,
 	return 0;
 }
 
+
 static int perf_stat__get_socket(struct cpu_map *map, int cpu)
 {
 	return cpu_map__get_socket(map, cpu, NULL);
@@ -1109,22 +1112,63 @@ static int perf_stat__get_core(struct cpu_map *map, int cpu)
 	return cpu_map__get_core(map, cpu, NULL);
 }
 
+static int cpu_map__get_max(struct cpu_map *map)
+{
+	int i, max = -1;
+
+	for (i = 0; i < map->nr; i++) {
+		if (map->map[i] > max)
+			max = map->map[i];
+	}
+
+	return max;
+}
+
+static struct cpu_map *cpus_aggr_map;
+
+static int perf_stat__get_aggr(aggr_get_id_t get_id, struct cpu_map *map, int idx)
+{
+	int cpu;
+
+	if (idx > map->nr)
+		return -1;
+
+	cpu = map->map[idx];
+
+	if (cpus_aggr_map->map[cpu] == -1)
+		cpus_aggr_map->map[cpu] = get_id(map, idx);
+
+	return cpus_aggr_map->map[cpu];
+}
+
+static int perf_stat__get_socket_cached(struct cpu_map *map, int idx)
+{
+	return perf_stat__get_aggr(perf_stat__get_socket, map, idx);
+}
+
+static int perf_stat__get_core_cached(struct cpu_map *map, int idx)
+{
+	return perf_stat__get_aggr(perf_stat__get_core, map, idx);
+}
+
 static int perf_stat_init_aggr_mode(void)
 {
+	int nr;
+
 	switch (stat_config.aggr_mode) {
 	case AGGR_SOCKET:
 		if (cpu_map__build_socket_map(evsel_list->cpus, &aggr_map)) {
 			perror("cannot build socket map");
 			return -1;
 		}
-		aggr_get_id = perf_stat__get_socket;
+		aggr_get_id = perf_stat__get_socket_cached;
 		break;
 	case AGGR_CORE:
 		if (cpu_map__build_core_map(evsel_list->cpus, &aggr_map)) {
 			perror("cannot build core map");
 			return -1;
 		}
-		aggr_get_id = perf_stat__get_core;
+		aggr_get_id = perf_stat__get_core_cached;
 		break;
 	case AGGR_NONE:
 	case AGGR_GLOBAL:
@@ -1133,7 +1177,15 @@ static int perf_stat_init_aggr_mode(void)
 	default:
 		break;
 	}
-	return 0;
+
+	/*
+	 * The evsel_list->cpus is the base we operate on,
+	 * taking the highest cpu number to be the size of
+	 * the aggregation translate cpumap.
+	 */
+	nr = cpu_map__get_max(evsel_list->cpus);
+	cpus_aggr_map = cpu_map__empty_new(nr + 1);
+	return cpus_aggr_map ? 0 : -ENOMEM;
 }
 
 /*
-- 
2.4.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1236381 — [PATCH 09/45] perf tools: Add stat config event read function

FromJiri Olsa <jolsa@kernel.org>
Date2015-09-30 16:30 +0200
Subject[PATCH 09/45] perf tools: Add stat config event read function
Message-ID<qeqyl-7BV-1@gated-at.bofh.it>
In reply to#1236373
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 6708cc207c38..bd58b87d8be9 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -806,6 +806,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 da6155dac7d1..c0e7a8035b21 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -457,6 +457,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

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1236384 — [PATCH 18/45] perf stat: Add AGGR_UNSET mode

FromJiri Olsa <jolsa@kernel.org>
Date2015-09-30 16:30 +0200
Subject[PATCH 18/45] perf stat: Add AGGR_UNSET mode
Message-ID<qeqym-7BV-11@gated-at.bofh.it>
In reply to#1236373
Adding AGGR_UNSET mode, so we could distinguish
unset aggr_mode in following patches.

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

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 9beb2fb56475..e1a716e08eb5 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -479,6 +479,7 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr)
 			csv_sep);
 		break;
 	case AGGR_GLOBAL:
+	case AGGR_UNSET:
 	default:
 		break;
 	}
@@ -799,6 +800,8 @@ static void print_interval(char *prefix, struct timespec *ts)
 		case AGGR_GLOBAL:
 		default:
 			fprintf(output, "#           time             counts %*s events\n", unit_width, "unit");
+		case AGGR_UNSET:
+			break;
 		}
 	}
 
@@ -880,6 +883,7 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)
 		evlist__for_each(evsel_list, counter)
 			print_counter(counter, prefix);
 		break;
+	case AGGR_UNSET:
 	default:
 		break;
 	}
@@ -960,6 +964,7 @@ static int perf_stat_init_aggr_mode(void)
 	case AGGR_NONE:
 	case AGGR_GLOBAL:
 	case AGGR_THREAD:
+	case AGGR_UNSET:
 	default:
 		break;
 	}
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index be31184a9a97..677620acd2bd 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -272,6 +272,7 @@ process_counter_values(struct perf_stat_config *config, struct perf_evsel *evsel
 			aggr->ena += count->ena;
 			aggr->run += count->run;
 		}
+	case AGGR_UNSET:
 	default:
 		break;
 	}
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 9d615b082115..afe6844e5219 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -31,6 +31,7 @@ enum aggr_mode {
 	AGGR_SOCKET,
 	AGGR_CORE,
 	AGGR_THREAD,
+	AGGR_UNSET,
 };
 
 struct perf_stat_config {
-- 
2.4.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1236386 — [PATCH 11/45] perf tools: Add stat event synthesize function

FromJiri Olsa <jolsa@kernel.org>
Date2015-09-30 16:30 +0200
Subject[PATCH 11/45] perf tools: Add stat event synthesize function
Message-ID<qeqym-7BV-13@gated-at.bofh.it>
In reply to#1236373
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         | 41 ++++++++++++++++++++++++++++++++++++-----
 tools/perf/tests/tests.h        |  1 +
 tools/perf/util/event.c         | 22 ++++++++++++++++++++++
 tools/perf/util/event.h         |  7 ++++++-
 5 files changed, 69 insertions(+), 6 deletions(-)

diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 23fccd474302..63661c26dae3 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -204,6 +204,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..5918fb74dfd8 100644
--- a/tools/perf/tests/stat.c
+++ b/tools/perf/tests/stat.c
@@ -2,6 +2,7 @@
 #include "event.h"
 #include "tests.h"
 #include "stat.h"
+#include "counts.h"
 #include "debug.h"
 
 static bool has_term(struct stat_config_event *config,
@@ -18,10 +19,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 +54,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 3dc65f5158ed..b9f4bf179649 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -68,6 +68,7 @@ int test_session_topology(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 c0fc12630ba0..46f5518c04e8 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -807,6 +807,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 885a1731ac23..2fa72b88e5e1 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -446,6 +446,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,
@@ -478,7 +479,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

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1236387 — [PATCH 17/45] perf stat: Rename perf_stat struct into perf_stat_evsel

FromJiri Olsa <jolsa@kernel.org>
Date2015-09-30 16:30 +0200
Subject[PATCH 17/45] perf stat: Rename perf_stat struct into perf_stat_evsel
Message-ID<qeqym-7BV-17@gated-at.bofh.it>
In reply to#1236373
It's used as the perf_evsel::priv data, so the name
suits better. Also we'll need the perf_stat name
free for more generic struct.

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

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index a96fb5c3bedb..9beb2fb56475 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -434,7 +434,7 @@ static void print_noise_pct(double total, double avg)
 
 static void print_noise(struct perf_evsel *evsel, double avg)
 {
-	struct perf_stat *ps;
+	struct perf_stat_evsel *ps;
 
 	if (run_count == 1)
 		return;
@@ -671,7 +671,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;
+	struct perf_stat_evsel *ps = counter->priv;
 	double avg = avg_stats(&ps->res_stats[0]);
 	int scaled = counter->counts->scaled;
 	double uval;
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index 0369b4516c29..be31184a9a97 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -67,7 +67,7 @@ double rel_stddev_stats(double stddev, double avg)
 bool __perf_evsel_stat__is(struct perf_evsel *evsel,
 			   enum perf_stat_evsel_id id)
 {
-	struct perf_stat *ps = evsel->priv;
+	struct perf_stat_evsel *ps = evsel->priv;
 
 	return ps->id == id;
 }
@@ -84,7 +84,7 @@ static const char *id_str[PERF_STAT_EVSEL_ID__MAX] = {
 
 void perf_stat_evsel_id_init(struct perf_evsel *evsel)
 {
-	struct perf_stat *ps = evsel->priv;
+	struct perf_stat_evsel *ps = evsel->priv;
 	int i;
 
 	/* ps->id is 0 hence PERF_STAT_EVSEL_ID__NONE by default */
@@ -100,7 +100,7 @@ void perf_stat_evsel_id_init(struct perf_evsel *evsel)
 void perf_evsel__reset_stat_priv(struct perf_evsel *evsel)
 {
 	int i;
-	struct perf_stat *ps = evsel->priv;
+	struct perf_stat_evsel *ps = evsel->priv;
 
 	for (i = 0; i < 3; i++)
 		init_stats(&ps->res_stats[i]);
@@ -110,7 +110,7 @@ void perf_evsel__reset_stat_priv(struct perf_evsel *evsel)
 
 int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)
 {
-	evsel->priv = zalloc(sizeof(struct perf_stat));
+	evsel->priv = zalloc(sizeof(struct perf_stat_evsel));
 	if (evsel->priv == NULL)
 		return -ENOMEM;
 	perf_evsel__reset_stat_priv(evsel);
@@ -304,7 +304,7 @@ 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;
+	struct perf_stat_evsel *ps = counter->priv;
 	u64 *count = counter->counts->aggr.values;
 	int i, ret;
 
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index a61cb0a9f23a..9d615b082115 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -20,7 +20,7 @@ enum perf_stat_evsel_id {
 	PERF_STAT_EVSEL_ID__MAX,
 };
 
-struct perf_stat {
+struct perf_stat_evsel {
 	struct stats		res_stats[3];
 	enum perf_stat_evsel_id	id;
 };
-- 
2.4.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1236388 — [PATCH 23/45] perf stat record: Add pipe support for record command

FromJiri Olsa <jolsa@kernel.org>
Date2015-09-30 16:30 +0200
Subject[PATCH 23/45] perf stat record: Add pipe support for record command
Message-ID<qeqym-7BV-19@gated-at.bofh.it>
In reply to#1236373
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 7bd5bde5fa7c..74aac55ff24a 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -291,10 +291,19 @@ 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;
 
+	if (is_pipe) {
+		err = perf_event__synthesize_attrs(NULL, perf_stat.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 ? perf_stat.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(&perf_stat.file);
 
-		err = perf_session__write_header(perf_stat.session, evsel_list,
-						 fd, false);
+		if (is_pipe) {
+			err = perf_header__write_pipe(perf_data_file__fd(&perf_stat.file));
+		} else {
+			err = perf_session__write_header(perf_stat.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;
 	}
@@ -963,6 +978,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 && perf_stat.file.is_pipe)
+		return;
+
 	if (interval)
 		print_interval(prefix = buf, ts);
 	else
@@ -1268,10 +1287,6 @@ static int __cmd_record(int argc, const char **argv)
 		return -1;
 	}
 
-	/* No pipe support ATM */
-	if (perf_stat.file.is_pipe)
-		return -EINVAL;
-
 	init_features(session);
 
 	session->evlist   = evsel_list;
@@ -1538,8 +1553,10 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 	if (STAT_RECORD) {
 		int fd = perf_data_file__fd(&perf_stat.file);
 
-		perf_stat.session->header.data_size += perf_stat.bytes_written;
-		perf_session__write_header(perf_stat.session, evsel_list, fd, true);
+		if (!perf_stat.file.is_pipe) {
+			perf_stat.session->header.data_size += perf_stat.bytes_written;
+			perf_session__write_header(perf_stat.session, evsel_list, fd, true);
+		}
 
 		perf_session__delete(perf_stat.session);
 	}
-- 
2.4.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1236389 — [PATCH 12/45] perf tools: Add stat event read function

FromJiri Olsa <jolsa@kernel.org>
Date2015-09-30 16:30 +0200
Subject[PATCH 12/45] perf tools: Add stat event read function
Message-ID<qeqym-7BV-21@gated-at.bofh.it>
In reply to#1236373
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 2d065d065b67..0369b4516c29 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -340,3 +340,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 62448c8175d3..a61cb0a9f23a 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -89,4 +89,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

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1236390 — [PATCH 02/45] perf tools: Add thread_map event synthesize function

FromJiri Olsa <jolsa@kernel.org>
Date2015-09-30 16:30 +0200
Subject[PATCH 02/45] perf tools: Add thread_map event synthesize function
Message-ID<qeqym-7BV-23@gated-at.bofh.it>
In reply to#1236373
Introduce perf_event__synthesize_thread_map2 function to
synthesize struct thread_map.

The perf_event__synthesize_thread_map is already taken
for synthesizing complete threads data (comm/mmap/fork).

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 |  5 +++++
 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, 75 insertions(+)

diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index d9bf51dc8cf5..7cf131a3f75e 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -175,6 +175,7 @@ static struct test {
 		.func = test__thread_map,
 	},
 	{
+
 		.desc = "Test LLVM searching and compiling",
 		.func = test__llvm,
 	},
@@ -191,6 +192,10 @@ static struct test {
 		.func = test_session_topology,
 	},
 	{
+		.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 0b3549672c16..1c9cb793ae72 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -65,6 +65,7 @@ int test__thread_map(void);
 int test__llvm(void);
 int test__insn_x86(void);
 int test_session_topology(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 12c409a95f81..57df245b6fa6 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -700,6 +700,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 f075f9ed0051..3ef69fef4497 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -408,6 +408,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

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1236393 — [PATCH 14/45] perf tools: Add stat round event synthesize function

FromJiri Olsa <jolsa@kernel.org>
Date2015-09-30 16:30 +0200
Subject[PATCH 14/45] perf tools: Add stat round event synthesize function
Message-ID<qeqym-7BV-27@gated-at.bofh.it>
In reply to#1236373
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         | 21 +++++++++++++++++++++
 tools/perf/tests/tests.h        |  2 ++
 tools/perf/util/event.c         | 17 +++++++++++++++++
 tools/perf/util/event.h         |  4 ++++
 5 files changed, 48 insertions(+)

diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 63661c26dae3..fb87406f3658 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -208,6 +208,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 5918fb74dfd8..ff42574adfd8 100644
--- a/tools/perf/tests/stat.c
+++ b/tools/perf/tests/stat.c
@@ -88,3 +88,24 @@ 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);
+	TEST_ASSERT_VAL("wrong type", stat_round->type == PERF_STAT_ROUND_TYPE__INTERVAL);
+	return 0;
+}
+
+int test__synthesize_stat_round(void)
+{
+	TEST_ASSERT_VAL("failed to synthesize stat_config",
+		!perf_event__synthesize_stat_round(NULL, 0xdeadbeef, PERF_STAT_ROUND_TYPE__INTERVAL,
+						   process_stat_round_event, NULL));
+
+	return 0;
+}
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index b9f4bf179649..932ad6557b21 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -69,6 +69,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 39aeffd305b3..bbced71fd044 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -830,6 +830,23 @@ 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, u64 type,
+				      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;
+	event.type = type;
+
+	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 9aeac2ab62e8..3cccbd0b5686 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -497,6 +497,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, u64 type,
+				      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

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1236394 — [PATCH 15/45] perf tools: Introduce stat feature

FromJiri Olsa <jolsa@kernel.org>
Date2015-09-30 16:30 +0200
Subject[PATCH 15/45] perf tools: Introduce stat feature
Message-ID<qeqyn-7BV-37@gated-at.bofh.it>
In reply to#1236373
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 a01c8ae1ee07..0592b1cdea8a 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -451,6 +451,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 43838003c1a1..69f143c07f2b 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -868,6 +868,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)
 {
@@ -1159,6 +1166,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)
 {
@@ -1948,6 +1961,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 05f27cb6b7e3..1e3ae09de499 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

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1236395 — [PATCH 04/45] perf tools: Add cpu_map event

FromJiri Olsa <jolsa@kernel.org>
Date2015-09-30 16:30 +0200
Subject[PATCH 04/45] perf tools: Add cpu_map event
Message-ID<qeqyn-7BV-29@gated-at.bofh.it>
In reply to#1236373
Adding cpu_map event to pass/store cpu maps
as data in pipe/perf.data.

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 57df245b6fa6..091c5de2a523 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -38,6 +38,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 3ef69fef4497..46162b9c6720 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			= 71,
 	PERF_RECORD_AUXTRACE_ERROR		= 72,
 	PERF_RECORD_THREAD_MAP			= 73,
+	PERF_RECORD_CPU_MAP			= 74,
 	PERF_RECORD_HEADER_MAX
 };
 
@@ -368,6 +369,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;
@@ -391,6 +398,7 @@ union perf_event {
 	struct itrace_start_event	itrace_start;
 	struct context_switch_event	context_switch;
 	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 bd64c7f2bead..e6d1f1439ad4 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -306,6 +306,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)
@@ -358,6 +367,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);
 
@@ -667,6 +689,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,
 };
 
@@ -1205,6 +1228,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 1af4774960c3..9e5925c78519 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -56,7 +56,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

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1236396 — [PATCH 22/45] perf stat record: Store events IDs in perf data file

FromJiri Olsa <jolsa@kernel.org>
Date2015-09-30 16:30 +0200
Subject[PATCH 22/45] perf stat record: Store events IDs in perf data file
Message-ID<qeqyn-7BV-35@gated-at.bofh.it>
In reply to#1236373
Store event IDs in evlist object so it get stored
into perf.data file.

Also making perf_evlist__id_add_fd global.

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 fa5299db0d2d..7bd5bde5fa7c 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 89546228b8ed..7f27160618a3 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -534,9 +534,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 66bc9d4c0869..36de92e5c8fb 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -97,6 +97,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

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1236397 — [PATCH 08/45] perf tools: Add stat config event synthesize function

FromJiri Olsa <jolsa@kernel.org>
Date2015-09-30 16:30 +0200
Subject[PATCH 08/45] perf tools: Add stat config event synthesize function
Message-ID<qeqyn-7BV-39@gated-at.bofh.it>
In reply to#1236373
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         | 40 +++++++++++++++++++++++++++++++
 tools/perf/util/event.h         |  5 ++++
 6 files changed, 104 insertions(+)
 create mode 100644 tools/perf/tests/stat.c

diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index 1a8d23367b8a..b7bdad4a00cd 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -35,6 +35,7 @@ perf-y += thread-map.o
 perf-y += llvm.o
 perf-y += topology.o
 perf-y += cpumap.o
+perf-y += stat.o
 
 perf-$(CONFIG_X86) += perf-time-to-tsc.o
 ifdef CONFIG_AUXTRACE
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 3068ec0c7ecf..23fccd474302 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -200,6 +200,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 c8e4e74830c4..3dc65f5158ed 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -67,6 +67,7 @@ int test__insn_x86(void);
 int test_session_topology(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 8840d82ca24f..6708cc207c38 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -10,6 +10,8 @@
 #include "thread.h"
 #include "thread_map.h"
 #include "symbol/kallsyms.h"
+#include "asm/bug.h"
+#include "stat.h"
 
 static const char *perf_event__names[] = {
 	[0]					= "TOTAL",
@@ -766,6 +768,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 179eba07889e..da6155dac7d1 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -426,6 +426,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,
@@ -452,6 +453,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

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1236398 — [PATCH 19/45] perf stat record: Add record command

FromJiri Olsa <jolsa@kernel.org>
Date2015-09-30 16:30 +0200
Subject[PATCH 19/45] perf stat record: Add record command
Message-ID<qeqyn-7BV-43@gated-at.bofh.it>
In reply to#1236373
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 e1a716e08eb5..12c48d705f02 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -59,6 +59,7 @@
 #include "util/thread.h"
 #include "util/thread_map.h"
 #include "util/counts.h"
+#include "util/session.h"
 
 #include <stdlib.h>
 #include <sys/prctl.h>
@@ -121,6 +122,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 {
+	bool			 record;
+	struct perf_data_file	 file;
+	struct perf_session	*session;
+	u64			 bytes_written;
+};
+
+static struct perf_stat		perf_stat;
+#define STAT_RECORD		perf_stat.record
+
 static volatile int done = 0;
 
 static struct perf_stat_config stat_config = {
@@ -339,6 +350,15 @@ static int __run_perf_stat(int argc, const char **argv)
 		return -1;
 	}
 
+	if (STAT_RECORD) {
+		int err, fd = perf_data_file__fd(&perf_stat.file);
+
+		err = perf_session__write_header(perf_stat.session, evsel_list,
+						 fd, false);
+		if (err < 0)
+			return err;
+	}
+
 	/*
 	 * Enable counters and exec the command:
 	 */
@@ -1130,6 +1150,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 = &perf_stat.file;
+	const struct option options[] = {
+	OPT_STRING('o', "output", &perf_stat.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 (perf_stat.file.is_pipe)
+		return -EINVAL;
+
+	session->evlist   = evsel_list;
+	perf_stat.session = session;
+	perf_stat.record  = true;
+	return argc;
+}
+
 int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 {
 	bool append_file = false;
@@ -1203,6 +1256,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, "");
 
@@ -1210,8 +1264,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;
 
@@ -1377,6 +1438,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(&perf_stat.file);
+
+		perf_stat.session->header.data_size += perf_stat.bytes_written;
+		perf_session__write_header(perf_stat.session, evsel_list, fd, true);
+
+		perf_session__delete(perf_stat.session);
+	}
+
 	perf_evlist__free_stats(evsel_list);
 out:
 	perf_evlist__delete(evsel_list);
-- 
2.4.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | linux.kernel


csiph-web