All of lore.kernel.org
 help / color / mirror / Atom feed
* [GIT PULL 00/43] perf/core new feature: 'perf stat record/report'
@ 2015-12-17 19:46 Arnaldo Carvalho de Melo
  2015-12-17 19:46 ` [PATCH 01/43] perf thread_map: Add thread_map user level event Arnaldo Carvalho de Melo
                   ` (43 more replies)
  0 siblings, 44 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:46 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Arnaldo Carvalho de Melo, David Ahern, Jiri Olsa,
	Kan Liang, Namhyung Kim, Peter Zijlstra, Wang Nan

From: Arnaldo Carvalho de Melo <acme@redhat.com>

Hi Ingo,

	Please consider pulling, cool new feature! This is on top of the
perf-core-for-mingo-2.1 tag, with that RHEL6.7 bugfix, I had also to go
over this one fixing stuff in many spots :-\

- Arnaldo

The following changes since commit 1843b4e057b7717db21a3ad96fa16d6b4ee8f6c4:

  tools subcmd: Rename subcmd header include guards (2015-12-17 14:27:14 -0300)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-core-for-mingo-3

for you to fetch changes up to 89af4e05c21d68f22e07fe66940ea675615a49ed:

  perf stat report: Allow to override aggr_mode (2015-12-17 16:30:30 -0300)

----------------------------------------------------------------
perf/core improvement.

User visible:

- Generate perf.data files from 'perf stat', to tap into the scripting
  capabilities perf has instead of defining a 'perf stat' specific scripting
  support to calculate event ratios, etc. Simple example:

  $ perf stat record -e cycles usleep 1

   Performance counter stats for 'usleep 1':

         1,134,996      cycles

       0.000670644 seconds time elapsed

  $ perf stat report

   Performance counter stats for '/home/acme/bin/perf stat record -e cycles usleep 1':

         1,134,996      cycles

       0.000670644 seconds time elapsed

  $

  It generates PERF_RECORD_ userspace records to store the details:

  $ perf report -D | grep PERF_RECORD
  0xf0 [0x28]: PERF_RECORD_THREAD_MAP nr: 1 thread: 27637
  0x118 [0x12]: PERF_RECORD_CPU_MAP nr: 1 cpu: 65535
  0x12a [0x40]: PERF_RECORD_STAT_CONFIG
  0x16a [0x30]: PERF_RECORD_STAT
  -1 -1 0x19a [0x40]: PERF_RECORD_MMAP -1/0: [0xffffffff81000000(0x1f000000) @ 0xffffffff81000000]: x [kernel.kallsyms]_text
  0x1da [0x18]: PERF_RECORD_STAT_ROUND
  [acme@ssdandy linux]$

  An effort was made to make perf.data files generated like this to not
  generate cryptic messages when processed by older tools.

  The 'perf script' bits need rebasing, will go up later.

Jiri's cover letter for this series:

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.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

----------------------------------------------------------------
Jiri Olsa (43):
      perf thread_map: Add thread_map user level event
      perf thread_map: Add thread_map event sythesize function
      perf thread_map: Add thread_map__new_event function
      perf thread_map: Add perf_event__fprintf_thread_map function
      perf cpu_map: Add cpu_map user level event
      perf cpu_map: Add cpu_map event synthesize function
      perf cpu_map: Add cpu_map__new_event function
      perf cpu_map: Add perf_event__fprintf_cpu_map function
      perf tools: Add stat config user level event
      perf tools: Add stat config event synthesize function
      perf tools: Add stat config event read function
      perf tools: Add stat user level event
      perf tools: Add stat event synthesize function
      perf tools: Add stat event read function
      perf tools: Add stat round user level event
      perf tools: Add stat round event synthesize function
      perf tools: Add stat events fprintf functions
      perf tools: Add event_update user level event
      perf tools: Add event_update event unit type
      perf tools: Add event_update event scale type
      perf tools: Add event_update event name type
      perf tools: Add event_update event cpus type
      perf tools: Add perf_event__fprintf_event_update function
      perf report: Display newly added events in raw dump
      perf tools: Introduce stat perf.data header feature
      perf stat record: Add record command
      perf stat record: Initialize record features
      perf stat record: Synthesize stat record data
      perf evlist: Export id_add_fd()
      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 stat record: Synthesize event update events
      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: Move csv_sep initialization before report command
      perf stat report: Process stat and stat round events
      perf stat report: Process event update events
      perf stat report: Allow to override aggr_mode

 tools/perf/Documentation/perf-stat.txt |  34 ++
 tools/perf/builtin-record.c            |   2 +
 tools/perf/builtin-stat.c              | 614 ++++++++++++++++++++++++++++++++-
 tools/perf/tests/Build                 |   3 +
 tools/perf/tests/builtin-test.c        |  24 ++
 tools/perf/tests/cpumap.c              |  88 +++++
 tools/perf/tests/event_update.c        | 117 +++++++
 tools/perf/tests/stat.c                | 111 ++++++
 tools/perf/tests/tests.h               |   6 +
 tools/perf/tests/thread-map.c          |  43 +++
 tools/perf/util/cpumap.c               |  42 +++
 tools/perf/util/cpumap.h               |   1 +
 tools/perf/util/event.c                | 308 +++++++++++++++++
 tools/perf/util/event.h                | 150 +++++++-
 tools/perf/util/evlist.c               |   6 +-
 tools/perf/util/evlist.h               |   3 +
 tools/perf/util/header.c               | 205 +++++++++++
 tools/perf/util/header.h               |  17 +
 tools/perf/util/session.c              | 189 ++++++++++
 tools/perf/util/stat.c                 |  62 ++++
 tools/perf/util/stat.h                 |  10 +
 tools/perf/util/thread_map.c           |  27 ++
 tools/perf/util/thread_map.h           |   3 +
 tools/perf/util/tool.h                 |   8 +-
 24 files changed, 2054 insertions(+), 19 deletions(-)
 create mode 100644 tools/perf/tests/cpumap.c
 create mode 100644 tools/perf/tests/event_update.c
 create mode 100644 tools/perf/tests/stat.c

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

* [PATCH 01/43] perf thread_map: Add thread_map user level event
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
@ 2015-12-17 19:46 ` Arnaldo Carvalho de Melo
  2015-12-17 19:46 ` [PATCH 02/43] perf thread_map: Add thread_map event sythesize function Arnaldo Carvalho de Melo
                   ` (42 subsequent siblings)
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:46 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

Adding the thread_map event to pass/store thread maps as data in
the pipe/perf.data.

Storing the thread ID along with the standard comm[16] thread name string.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Kan Liang <kan.liang@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1445784728-21732-4-git-send-email-jolsa@kernel.org
[ Renamed thread_map_data_event to thread_map_event_entry ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/event.c   |  1 +
 tools/perf/util/event.h   | 13 +++++++++++++
 tools/perf/util/session.c | 26 ++++++++++++++++++++++++++
 tools/perf/util/tool.h    |  3 ++-
 4 files changed, 42 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 8b10621b415c..771545a27b9b 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -37,6 +37,7 @@ static const char *perf_event__names[] = {
 	[PERF_RECORD_AUXTRACE_INFO]		= "AUXTRACE_INFO",
 	[PERF_RECORD_AUXTRACE]			= "AUXTRACE",
 	[PERF_RECORD_AUXTRACE_ERROR]		= "AUXTRACE_ERROR",
+	[PERF_RECORD_THREAD_MAP]		= "THREAD_MAP",
 };
 
 const char *perf_event__name(unsigned int id)
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index a0dbcbd4f6d8..66f303e69c4d 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -226,6 +226,7 @@ enum perf_user_event_type { /* above any possible kernel type */
 	PERF_RECORD_AUXTRACE_INFO		= 70,
 	PERF_RECORD_AUXTRACE			= 71,
 	PERF_RECORD_AUXTRACE_ERROR		= 72,
+	PERF_RECORD_THREAD_MAP			= 73,
 	PERF_RECORD_HEADER_MAX
 };
 
@@ -356,6 +357,17 @@ struct context_switch_event {
 	u32 next_prev_tid;
 };
 
+struct thread_map_event_entry {
+	u64	pid;
+	char	comm[16];
+};
+
+struct thread_map_event {
+	struct perf_event_header	header;
+	u64				nr;
+	struct thread_map_event_entry	entries[];
+};
+
 union perf_event {
 	struct perf_event_header	header;
 	struct mmap_event		mmap;
@@ -378,6 +390,7 @@ union perf_event {
 	struct aux_event		aux;
 	struct itrace_start_event	itrace_start;
 	struct context_switch_event	context_switch;
+	struct thread_map_event		thread_map;
 };
 
 void perf_event__print_totals(void);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 9774686525b4..36b07b22392d 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -296,6 +296,16 @@ int process_event_auxtrace_error_stub(struct perf_tool *tool __maybe_unused,
 	return 0;
 }
 
+
+static
+int process_event_thread_map_stub(struct perf_tool *tool __maybe_unused,
+				  union perf_event *event __maybe_unused,
+				  struct perf_session *session __maybe_unused)
+{
+	dump_printf(": unhandled!\n");
+	return 0;
+}
+
 void perf_tool__fill_defaults(struct perf_tool *tool)
 {
 	if (tool->sample == NULL)
@@ -346,6 +356,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
 		tool->auxtrace = process_event_auxtrace_stub;
 	if (tool->auxtrace_error == NULL)
 		tool->auxtrace_error = process_event_auxtrace_error_stub;
+	if (tool->thread_map == NULL)
+		tool->thread_map = process_event_thread_map_stub;
 }
 
 static void swap_sample_id_all(union perf_event *event, void *data)
@@ -616,6 +628,17 @@ static void perf_event__auxtrace_error_swap(union perf_event *event,
 	event->auxtrace_error.ip   = bswap_64(event->auxtrace_error.ip);
 }
 
+static void perf_event__thread_map_swap(union perf_event *event,
+					bool sample_id_all __maybe_unused)
+{
+	unsigned i;
+
+	event->thread_map.nr = bswap_64(event->thread_map.nr);
+
+	for (i = 0; i < event->thread_map.nr; i++)
+		event->thread_map.entries[i].pid = bswap_64(event->thread_map.entries[i].pid);
+}
+
 typedef void (*perf_event__swap_op)(union perf_event *event,
 				    bool sample_id_all);
 
@@ -643,6 +666,7 @@ static perf_event__swap_op perf_event__swap_ops[] = {
 	[PERF_RECORD_AUXTRACE_INFO]	  = perf_event__auxtrace_info_swap,
 	[PERF_RECORD_AUXTRACE]		  = perf_event__auxtrace_swap,
 	[PERF_RECORD_AUXTRACE_ERROR]	  = perf_event__auxtrace_error_swap,
+	[PERF_RECORD_THREAD_MAP]	  = perf_event__thread_map_swap,
 	[PERF_RECORD_HEADER_MAX]	  = NULL,
 };
 
@@ -1179,6 +1203,8 @@ static s64 perf_session__process_user_event(struct perf_session *session,
 	case PERF_RECORD_AUXTRACE_ERROR:
 		perf_session__auxtrace_error_inc(session, event);
 		return tool->auxtrace_error(tool, event, session);
+	case PERF_RECORD_THREAD_MAP:
+		return tool->thread_map(tool, event, session);
 	default:
 		return -EINVAL;
 	}
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index cab8cc24831b..1af4774960c3 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -55,7 +55,8 @@ struct perf_tool {
 	event_op2	build_id,
 			id_index,
 			auxtrace_info,
-			auxtrace_error;
+			auxtrace_error,
+			thread_map;
 	event_op3	auxtrace;
 	bool		ordered_events;
 	bool		ordering_requires_timestamps;
-- 
2.1.0


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

* [PATCH 02/43] perf thread_map: Add thread_map event sythesize function
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
  2015-12-17 19:46 ` [PATCH 01/43] perf thread_map: Add thread_map user level event Arnaldo Carvalho de Melo
@ 2015-12-17 19:46 ` Arnaldo Carvalho de Melo
  2015-12-17 19:46 ` [PATCH 03/43] perf thread_map: Add thread_map__new_event function Arnaldo Carvalho de Melo
                   ` (41 subsequent siblings)
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:46 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

Introduce the perf_event__synthesize_thread_map2 function to synthesize
struct thread_map.

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

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Kan Liang <kan.liang@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1445784728-21732-5-git-send-email-jolsa@kernel.org
[ Rename thread_map_data_event to thread_map_event_entry ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/tests/builtin-test.c |  4 ++++
 tools/perf/tests/tests.h        |  1 +
 tools/perf/tests/thread-map.c   | 29 +++++++++++++++++++++++++++++
 tools/perf/util/event.c         | 36 ++++++++++++++++++++++++++++++++++++
 tools/perf/util/event.h         |  4 ++++
 5 files changed, 74 insertions(+)

diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 0372d5945910..745bdb02d22b 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -180,6 +180,10 @@ static struct test generic_tests[] = {
 		},
 	},
 	{
+		.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 a0733aaad081..3fe52ccc4d05 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -79,6 +79,7 @@ int test__bpf(int subtest);
 const char *test__bpf_subtest_get_desc(int subtest);
 int test__bpf_subtest_get_nr(void);
 int test_session_topology(int subtest);
+int test__thread_map_synthesize(int subtest);
 
 #if 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 2be02d303e82..ac5be2578367 100644
--- a/tools/perf/tests/thread-map.c
+++ b/tools/perf/tests/thread-map.c
@@ -40,3 +40,32 @@ int test__thread_map(int subtest __maybe_unused)
 	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->entries[0].pid == (u64) getpid());
+	TEST_ASSERT_VAL("wrong comm", !strcmp(map->entries[0].comm, "perf"));
+	return 0;
+}
+
+int test__thread_map_synthesize(int subtest __maybe_unused)
+{
+	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 771545a27b9b..b13373a60337 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.entries[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_event_entry *entry = &event->thread_map.entries[i];
+		char *comm = thread_map__comm(threads, i);
+
+		if (!comm)
+			comm = (char *) "";
+
+		entry->pid = thread_map__pid(threads, i);
+		strncpy((char *) &entry->comm, comm, sizeof(entry->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 66f303e69c4d..952dd4d83f81 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.1.0


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

* [PATCH 03/43] perf thread_map: Add thread_map__new_event function
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
  2015-12-17 19:46 ` [PATCH 01/43] perf thread_map: Add thread_map user level event Arnaldo Carvalho de Melo
  2015-12-17 19:46 ` [PATCH 02/43] perf thread_map: Add thread_map event sythesize function Arnaldo Carvalho de Melo
@ 2015-12-17 19:46 ` Arnaldo Carvalho de Melo
  2015-12-17 19:46 ` [PATCH 04/43] perf thread_map: Add perf_event__fprintf_thread_map function Arnaldo Carvalho de Melo
                   ` (40 subsequent siblings)
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:46 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

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

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Kan Liang <kan.liang@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1445784728-21732-6-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/tests/thread-map.c | 14 ++++++++++++++
 tools/perf/util/thread_map.c  | 27 +++++++++++++++++++++++++++
 tools/perf/util/thread_map.h  |  3 +++
 3 files changed, 44 insertions(+)

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


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

* [PATCH 04/43] perf thread_map: Add perf_event__fprintf_thread_map function
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
                   ` (2 preceding siblings ...)
  2015-12-17 19:46 ` [PATCH 03/43] perf thread_map: Add thread_map__new_event function Arnaldo Carvalho de Melo
@ 2015-12-17 19:46 ` Arnaldo Carvalho de Melo
  2015-12-17 19:46 ` [PATCH 05/43] perf cpu_map: Add cpu_map user level event Arnaldo Carvalho de Melo
                   ` (39 subsequent siblings)
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:46 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

To display a thread_map event for a raw dump.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Kan Liang <kan.liang@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1445784728-21732-7-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/event.c | 16 ++++++++++++++++
 tools/perf/util/event.h |  1 +
 2 files changed, 17 insertions(+)

diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index b13373a60337..938f006c758e 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -820,6 +820,22 @@ size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp)
 		       event->mmap2.filename);
 }
 
+size_t perf_event__fprintf_thread_map(union perf_event *event, FILE *fp)
+{
+	struct thread_map *threads = thread_map__new_event(&event->thread_map);
+	size_t ret;
+
+	ret = fprintf(fp, " nr: ");
+
+	if (threads)
+		ret += thread_map__fprintf(threads, fp);
+	else
+		ret += fprintf(fp, "failed to get threads from event\n");
+
+	thread_map__put(threads);
+	return ret;
+}
+
 int perf_event__process_mmap(struct perf_tool *tool __maybe_unused,
 			     union perf_event *event,
 			     struct perf_sample *sample,
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 952dd4d83f81..b7ad896d1317 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -516,6 +516,7 @@ size_t perf_event__fprintf_task(union perf_event *event, FILE *fp);
 size_t perf_event__fprintf_aux(union perf_event *event, FILE *fp);
 size_t perf_event__fprintf_itrace_start(union perf_event *event, FILE *fp);
 size_t perf_event__fprintf_switch(union perf_event *event, FILE *fp);
+size_t perf_event__fprintf_thread_map(union perf_event *event, FILE *fp);
 size_t perf_event__fprintf(union perf_event *event, FILE *fp);
 
 u64 kallsyms__get_function_start(const char *kallsyms_filename,
-- 
2.1.0


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

* [PATCH 05/43] perf cpu_map: Add cpu_map user level event
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
                   ` (3 preceding siblings ...)
  2015-12-17 19:46 ` [PATCH 04/43] perf thread_map: Add perf_event__fprintf_thread_map function Arnaldo Carvalho de Melo
@ 2015-12-17 19:46 ` Arnaldo Carvalho de Melo
  2015-12-17 19:46 ` [PATCH 06/43] perf cpu_map: Add cpu_map event synthesize function Arnaldo Carvalho de Melo
                   ` (38 subsequent siblings)
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:46 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

Adding the cpu_map event to pass/store cpu maps as data in
a pipe/perf.data.

We store maps in 2 formats:
  - list of cpus
  - mask of cpus

The format that takes less space is selected transparently in the
following patch.

The interface is made generic, so we could add the cpumap event data
into another event in the following patches.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Kan Liang <kan.liang@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1445784728-21732-8-git-send-email-jolsa@kernel.org
[ cpu_map_data_cpus -> cpu_map_entries, cpu_map_data_mask -> cpu_map_mask ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/event.c   |  1 +
 tools/perf/util/event.h   | 28 ++++++++++++++++++++++++++
 tools/perf/util/session.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/tool.h    |  3 ++-
 4 files changed, 81 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 938f006c758e..719c0781a82a 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 b7ad896d1317..1c82a0ebda73 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
 };
 
@@ -271,6 +272,32 @@ struct events_stats {
 	u32 nr_proc_map_timeout;
 };
 
+enum {
+	PERF_CPU_MAP__CPUS = 0,
+	PERF_CPU_MAP__MASK = 1,
+};
+
+struct cpu_map_entries {
+	u16	nr;
+	u16	cpu[];
+};
+
+struct cpu_map_mask {
+	u16	nr;
+	u16	long_size;
+	unsigned long mask[];
+};
+
+struct cpu_map_data {
+	u16	type;
+	char	data[];
+};
+
+struct cpu_map_event {
+	struct perf_event_header	header;
+	struct cpu_map_data		data;
+};
+
 struct attr_event {
 	struct perf_event_header header;
 	struct perf_event_attr attr;
@@ -391,6 +418,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 36b07b22392d..4350f5e85bf5 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,42 @@ static void perf_event__thread_map_swap(union perf_event *event,
 		event->thread_map.entries[i].pid = bswap_64(event->thread_map.entries[i].pid);
 }
 
+static void perf_event__cpu_map_swap(union perf_event *event,
+				     bool sample_id_all __maybe_unused)
+{
+	struct cpu_map_data *data = &event->cpu_map.data;
+	struct cpu_map_entries *cpus;
+	struct cpu_map_mask *mask;
+	unsigned i;
+
+	data->type = bswap_64(data->type);
+
+	switch (data->type) {
+	case PERF_CPU_MAP__CPUS:
+		cpus = (struct cpu_map_entries *)data->data;
+
+		cpus->nr = bswap_16(cpus->nr);
+
+		for (i = 0; i < cpus->nr; i++)
+			cpus->cpu[i] = bswap_16(cpus->cpu[i]);
+		break;
+	case PERF_CPU_MAP__MASK:
+		mask = (struct cpu_map_mask *) data->data;
+
+		mask->nr = bswap_16(mask->nr);
+		mask->long_size = bswap_16(mask->long_size);
+
+		switch (mask->long_size) {
+		case 4: mem_bswap_32(&mask->mask, mask->nr); break;
+		case 8: mem_bswap_64(&mask->mask, mask->nr); break;
+		default:
+			pr_err("cpu_map swap: unsupported long size\n");
+		}
+	default:
+		break;
+	}
+}
+
 typedef void (*perf_event__swap_op)(union perf_event *event,
 				    bool sample_id_all);
 
@@ -667,6 +714,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 +1253,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.1.0


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

* [PATCH 06/43] perf cpu_map: Add cpu_map event synthesize function
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
                   ` (4 preceding siblings ...)
  2015-12-17 19:46 ` [PATCH 05/43] perf cpu_map: Add cpu_map user level event Arnaldo Carvalho de Melo
@ 2015-12-17 19:46 ` Arnaldo Carvalho de Melo
  2015-12-17 19:46 ` [PATCH 07/43] perf cpu_map: Add cpu_map__new_event function Arnaldo Carvalho de Melo
                   ` (37 subsequent siblings)
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:46 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

Introduce the perf_event__synthesize_cpu_map function to synthesize a
struct cpu_map.

Added generic interface:
  cpu_map_data__alloc
  cpu_map_data__synthesize

to make the cpu_map synthesizing usable for other events.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Kan Liang <kan.liang@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1445784728-21732-9-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/tests/Build          |   1 +
 tools/perf/tests/builtin-test.c |   4 ++
 tools/perf/tests/cpumap.c       |  71 ++++++++++++++++++++++
 tools/perf/tests/tests.h        |   1 +
 tools/perf/util/event.c         | 131 ++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/event.h         |   8 +++
 6 files changed, 216 insertions(+)
 create mode 100644 tools/perf/tests/cpumap.c

diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index f23fb7ed4400..7abad28fe17e 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -34,6 +34,7 @@ perf-y += thread-map.o
 perf-y += llvm.o llvm-src-base.o llvm-src-kbuild.o llvm-src-prologue.o
 perf-y += bpf.o
 perf-y += topology.o
+perf-y += cpumap.o
 
 $(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build
 	$(call rule_mkdir)
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 745bdb02d22b..0c3fe2846de8 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -184,6 +184,10 @@ static struct test generic_tests[] = {
 		.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..715480558088
--- /dev/null
+++ b/tools/perf/tests/cpumap.c
@@ -0,0 +1,71 @@
+#include "tests.h"
+#include "cpumap.h"
+
+static int process_event_mask(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;
+	struct cpu_map_mask *mask;
+	struct cpu_map_data *data;
+	int i;
+
+	data = &map->data;
+
+	TEST_ASSERT_VAL("wrong type", data->type == PERF_CPU_MAP__MASK);
+
+	mask = (struct cpu_map_mask *)data->data;
+
+	TEST_ASSERT_VAL("wrong nr",   mask->nr == 1);
+
+	for (i = 0; i < 20; i++) {
+		TEST_ASSERT_VAL("wrong cpu", test_bit(i, mask->mask));
+	}
+
+	return 0;
+}
+
+static int process_event_cpus(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;
+	struct cpu_map_entries *cpus;
+	struct cpu_map_data *data;
+
+	data = &map->data;
+
+	TEST_ASSERT_VAL("wrong type", data->type == PERF_CPU_MAP__CPUS);
+
+	cpus = (struct cpu_map_entries *)data->data;
+
+	TEST_ASSERT_VAL("wrong nr",   cpus->nr == 2);
+	TEST_ASSERT_VAL("wrong cpu",  cpus->cpu[0] == 1);
+	TEST_ASSERT_VAL("wrong cpu",  cpus->cpu[1] == 256);
+	return 0;
+}
+
+
+int test__cpu_map_synthesize(int subtest __maybe_unused)
+{
+	struct cpu_map *cpus;
+
+	/* This one is better stores in mask. */
+	cpus = cpu_map__new("0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19");
+
+	TEST_ASSERT_VAL("failed to synthesize map",
+		!perf_event__synthesize_cpu_map(NULL, cpus, process_event_mask, NULL));
+
+	cpu_map__put(cpus);
+
+	/* This one is better stores in cpu values. */
+	cpus = cpu_map__new("1,256");
+
+	TEST_ASSERT_VAL("failed to synthesize map",
+		!perf_event__synthesize_cpu_map(NULL, cpus, process_event_cpus, NULL));
+
+	cpu_map__put(cpus);
+	return 0;
+}
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 3fe52ccc4d05..f85160f6ebb8 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -80,6 +80,7 @@ const char *test__bpf_subtest_get_desc(int subtest);
 int test__bpf_subtest_get_nr(void);
 int test_session_topology(int subtest);
 int test__thread_map_synthesize(int subtest);
+int test__cpu_map_synthesize(int subtest);
 
 #if defined(__arm__) || defined(__aarch64__)
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 719c0781a82a..15d6466a4b8f 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -737,6 +737,137 @@ int perf_event__synthesize_thread_map2(struct perf_tool *tool,
 	return err;
 }
 
+static void synthesize_cpus(struct cpu_map_entries *cpus,
+			    struct cpu_map *map)
+{
+	int i;
+
+	cpus->nr = map->nr;
+
+	for (i = 0; i < map->nr; i++)
+		cpus->cpu[i] = map->map[i];
+}
+
+static void synthesize_mask(struct cpu_map_mask *mask,
+			    struct cpu_map *map, int max)
+{
+	int i;
+
+	mask->nr = BITS_TO_LONGS(max);
+	mask->long_size = sizeof(long);
+
+	for (i = 0; i < map->nr; i++)
+		set_bit(map->map[i], mask->mask);
+}
+
+static size_t cpus_size(struct cpu_map *map)
+{
+	return sizeof(struct cpu_map_entries) + map->nr * sizeof(u16);
+}
+
+static size_t mask_size(struct cpu_map *map, int *max)
+{
+	int i;
+
+	*max = 0;
+
+	for (i = 0; i < map->nr; i++) {
+		/* bit possition of the cpu is + 1 */
+		int bit = map->map[i] + 1;
+
+		if (bit > *max)
+			*max = bit;
+	}
+
+	return sizeof(struct cpu_map_mask) + BITS_TO_LONGS(*max) * sizeof(long);
+}
+
+void *cpu_map_data__alloc(struct cpu_map *map, size_t *size, u16 *type, int *max)
+{
+	size_t size_cpus, size_mask;
+	bool is_dummy = cpu_map__empty(map);
+
+	/*
+	 * Both array and mask data have variable size based
+	 * on the number of cpus and their actual values.
+	 * The size of the 'struct cpu_map_data' is:
+	 *
+	 *   array = size of 'struct cpu_map_entries' +
+	 *           number of cpus * sizeof(u64)
+	 *
+	 *   mask  = size of 'struct cpu_map_mask' +
+	 *           maximum cpu bit converted to size of longs
+	 *
+	 * and finaly + the size of 'struct cpu_map_data'.
+	 */
+	size_cpus = cpus_size(map);
+	size_mask = mask_size(map, max);
+
+	if (is_dummy || (size_cpus < size_mask)) {
+		*size += size_cpus;
+		*type  = PERF_CPU_MAP__CPUS;
+	} else {
+		*size += size_mask;
+		*type  = PERF_CPU_MAP__MASK;
+	}
+
+	*size += sizeof(struct cpu_map_data);
+	return zalloc(*size);
+}
+
+void cpu_map_data__synthesize(struct cpu_map_data *data, struct cpu_map *map,
+			      u16 type, int max)
+{
+	data->type = type;
+
+	switch (type) {
+	case PERF_CPU_MAP__CPUS:
+		synthesize_cpus((struct cpu_map_entries *) data->data, map);
+		break;
+	case PERF_CPU_MAP__MASK:
+		synthesize_mask((struct cpu_map_mask *) data->data, map, max);
+	default:
+		break;
+	};
+}
+
+static struct cpu_map_event* cpu_map_event__new(struct cpu_map *map)
+{
+	size_t size = sizeof(struct cpu_map_event);
+	struct cpu_map_event *event;
+	int max;
+	u16 type;
+
+	event = cpu_map_data__alloc(map, &size, &type, &max);
+	if (!event)
+		return NULL;
+
+	event->header.type = PERF_RECORD_CPU_MAP;
+	event->header.size = size;
+	event->data.type   = type;
+
+	cpu_map_data__synthesize(&event->data, map, type, max);
+	return event;
+}
+
+int perf_event__synthesize_cpu_map(struct perf_tool *tool,
+				   struct cpu_map *map,
+				   perf_event__handler_t process,
+				   struct machine *machine)
+{
+	struct cpu_map_event *event;
+	int err;
+
+	event = cpu_map_event__new(map);
+	if (!event)
+		return -ENOMEM;
+
+	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 1c82a0ebda73..de18ee0e9c96 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -425,6 +425,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,
@@ -440,6 +441,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,
@@ -550,4 +555,7 @@ size_t perf_event__fprintf(union perf_event *event, FILE *fp);
 u64 kallsyms__get_function_start(const char *kallsyms_filename,
 				 const char *symbol_name);
 
+void *cpu_map_data__alloc(struct cpu_map *map, size_t *size, u16 *type, int *max);
+void  cpu_map_data__synthesize(struct cpu_map_data *data, struct cpu_map *map,
+			       u16 type, int max);
 #endif /* __PERF_RECORD_H */
-- 
2.1.0


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

* [PATCH 07/43] perf cpu_map: Add cpu_map__new_event function
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
                   ` (5 preceding siblings ...)
  2015-12-17 19:46 ` [PATCH 06/43] perf cpu_map: Add cpu_map event synthesize function Arnaldo Carvalho de Melo
@ 2015-12-17 19:46 ` Arnaldo Carvalho de Melo
  2015-12-17 19:46 ` [PATCH 08/43] perf cpu_map: Add perf_event__fprintf_cpu_map function Arnaldo Carvalho de Melo
                   ` (36 subsequent siblings)
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:46 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

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

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Kan Liang <kan.liang@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1445784728-21732-10-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/tests/cpumap.c | 25 +++++++++++++++++++++----
 tools/perf/util/cpumap.c  | 42 ++++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/cpumap.h  |  1 +
 3 files changed, 64 insertions(+), 4 deletions(-)

diff --git a/tools/perf/tests/cpumap.c b/tools/perf/tests/cpumap.c
index 715480558088..4cb6418a8ffc 100644
--- a/tools/perf/tests/cpumap.c
+++ b/tools/perf/tests/cpumap.c
@@ -6,12 +6,13 @@ static int process_event_mask(struct perf_tool *tool __maybe_unused,
 			 struct perf_sample *sample __maybe_unused,
 			 struct machine *machine __maybe_unused)
 {
-	struct cpu_map_event *map = &event->cpu_map;
+	struct cpu_map_event *map_event = &event->cpu_map;
 	struct cpu_map_mask *mask;
 	struct cpu_map_data *data;
+	struct cpu_map *map;
 	int i;
 
-	data = &map->data;
+	data = &map_event->data;
 
 	TEST_ASSERT_VAL("wrong type", data->type == PERF_CPU_MAP__MASK);
 
@@ -23,6 +24,14 @@ static int process_event_mask(struct perf_tool *tool __maybe_unused,
 		TEST_ASSERT_VAL("wrong cpu", test_bit(i, mask->mask));
 	}
 
+	map = cpu_map__new_data(data);
+	TEST_ASSERT_VAL("wrong nr",  map->nr == 20);
+
+	for (i = 0; i < 20; i++) {
+		TEST_ASSERT_VAL("wrong cpu", map->map[i] == i);
+	}
+
+	cpu_map__put(map);
 	return 0;
 }
 
@@ -31,11 +40,12 @@ static int process_event_cpus(struct perf_tool *tool __maybe_unused,
 			 struct perf_sample *sample __maybe_unused,
 			 struct machine *machine __maybe_unused)
 {
-	struct cpu_map_event *map = &event->cpu_map;
+	struct cpu_map_event *map_event = &event->cpu_map;
 	struct cpu_map_entries *cpus;
 	struct cpu_map_data *data;
+	struct cpu_map *map;
 
-	data = &map->data;
+	data = &map_event->data;
 
 	TEST_ASSERT_VAL("wrong type", data->type == PERF_CPU_MAP__CPUS);
 
@@ -44,6 +54,13 @@ static int process_event_cpus(struct perf_tool *tool __maybe_unused,
 	TEST_ASSERT_VAL("wrong nr",   cpus->nr == 2);
 	TEST_ASSERT_VAL("wrong cpu",  cpus->cpu[0] == 1);
 	TEST_ASSERT_VAL("wrong cpu",  cpus->cpu[1] == 256);
+
+	map = cpu_map__new_data(data);
+	TEST_ASSERT_VAL("wrong nr",  map->nr == 2);
+	TEST_ASSERT_VAL("wrong cpu", map->map[0] == 1);
+	TEST_ASSERT_VAL("wrong cpu", map->map[1] == 256);
+	TEST_ASSERT_VAL("wrong refcnt", atomic_read(&map->refcnt) == 1);
+	cpu_map__put(map);
 	return 0;
 }
 
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index 10af1e7524fb..a0717b93d8f5 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -5,6 +5,7 @@
 #include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <linux/bitmap.h>
 #include "asm/bug.h"
 
 static struct cpu_map *cpu_map__default_new(void)
@@ -179,6 +180,47 @@ out:
 	return cpus;
 }
 
+static struct cpu_map *cpu_map__from_entries(struct cpu_map_entries *cpus)
+{
+	struct cpu_map *map;
+
+	map = cpu_map__empty_new(cpus->nr);
+	if (map) {
+		unsigned i;
+
+		for (i = 0; i < cpus->nr; i++)
+			map->map[i] = (int)cpus->cpu[i];
+	}
+
+	return map;
+}
+
+static struct cpu_map *cpu_map__from_mask(struct cpu_map_mask *mask)
+{
+	struct cpu_map *map;
+	int nr, nbits = mask->nr * mask->long_size * BITS_PER_BYTE;
+
+	nr = bitmap_weight(mask->mask, nbits);
+
+	map = cpu_map__empty_new(nr);
+	if (map) {
+		int cpu, i = 0;
+
+		for_each_set_bit(cpu, mask->mask, nbits)
+			map->map[i++] = cpu;
+	}
+	return map;
+
+}
+
+struct cpu_map *cpu_map__new_data(struct cpu_map_data *data)
+{
+	if (data->type == PERF_CPU_MAP__CPUS)
+		return cpu_map__from_entries((struct cpu_map_entries *)data->data);
+	else
+		return cpu_map__from_mask((struct cpu_map_mask *)data->data);
+}
+
 size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp)
 {
 	int i;
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index 85f7772457fa..71c41b9efabb 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -17,6 +17,7 @@ struct cpu_map {
 struct cpu_map *cpu_map__new(const char *cpu_list);
 struct cpu_map *cpu_map__empty_new(int nr);
 struct cpu_map *cpu_map__dummy_new(void);
+struct cpu_map *cpu_map__new_data(struct cpu_map_data *data);
 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);
-- 
2.1.0


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

* [PATCH 08/43] perf cpu_map: Add perf_event__fprintf_cpu_map function
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
                   ` (6 preceding siblings ...)
  2015-12-17 19:46 ` [PATCH 07/43] perf cpu_map: Add cpu_map__new_event function Arnaldo Carvalho de Melo
@ 2015-12-17 19:46 ` Arnaldo Carvalho de Melo
  2015-12-17 19:46 ` [PATCH 09/43] perf tools: Add stat config user level event Arnaldo Carvalho de Melo
                   ` (35 subsequent siblings)
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:46 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

To display a cpu_map event for raw dump.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Kan Liang <kan.liang@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1445784728-21732-11-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/event.c | 16 ++++++++++++++++
 tools/perf/util/event.h |  1 +
 2 files changed, 17 insertions(+)

diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 15d6466a4b8f..f31ab3b8f918 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -968,6 +968,22 @@ size_t perf_event__fprintf_thread_map(union perf_event *event, FILE *fp)
 	return ret;
 }
 
+size_t perf_event__fprintf_cpu_map(union perf_event *event, FILE *fp)
+{
+	struct cpu_map *cpus = cpu_map__new_data(&event->cpu_map.data);
+	size_t ret;
+
+	ret = fprintf(fp, " nr: ");
+
+	if (cpus)
+		ret += cpu_map__fprintf(cpus, fp);
+	else
+		ret += fprintf(fp, "failed to get cpumap from event\n");
+
+	cpu_map__put(cpus);
+	return ret;
+}
+
 int perf_event__process_mmap(struct perf_tool *tool __maybe_unused,
 			     union perf_event *event,
 			     struct perf_sample *sample,
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index de18ee0e9c96..74a434116b2c 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -550,6 +550,7 @@ size_t perf_event__fprintf_aux(union perf_event *event, FILE *fp);
 size_t perf_event__fprintf_itrace_start(union perf_event *event, FILE *fp);
 size_t perf_event__fprintf_switch(union perf_event *event, FILE *fp);
 size_t perf_event__fprintf_thread_map(union perf_event *event, FILE *fp);
+size_t perf_event__fprintf_cpu_map(union perf_event *event, FILE *fp);
 size_t perf_event__fprintf(union perf_event *event, FILE *fp);
 
 u64 kallsyms__get_function_start(const char *kallsyms_filename,
-- 
2.1.0


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

* [PATCH 09/43] perf tools: Add stat config user level event
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
                   ` (7 preceding siblings ...)
  2015-12-17 19:46 ` [PATCH 08/43] perf cpu_map: Add perf_event__fprintf_cpu_map function Arnaldo Carvalho de Melo
@ 2015-12-17 19:46 ` Arnaldo Carvalho de Melo
  2015-12-17 19:46 ` [PATCH 10/43] perf tools: Add stat config event synthesize function Arnaldo Carvalho de Melo
                   ` (34 subsequent siblings)
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:46 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

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

The config data is stored in a 'tag|value' way to allow for easy
extension and backwards compatibility.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Kan Liang <kan.liang@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1445784728-21732-12-git-send-email-jolsa@kernel.org
[ stat_config_term_event -> stat_config_event_entry ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/event.c   |  1 +
 tools/perf/util/event.h   | 20 ++++++++++++++++++++
 tools/perf/util/session.c | 24 ++++++++++++++++++++++++
 tools/perf/util/tool.h    |  3 ++-
 4 files changed, 47 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index f31ab3b8f918..43e2dfc2c73b 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -39,6 +39,7 @@ static const char *perf_event__names[] = {
 	[PERF_RECORD_AUXTRACE_ERROR]		= "AUXTRACE_ERROR",
 	[PERF_RECORD_THREAD_MAP]		= "THREAD_MAP",
 	[PERF_RECORD_CPU_MAP]			= "CPU_MAP",
+	[PERF_RECORD_STAT_CONFIG]		= "STAT_CONFIG",
 };
 
 const char *perf_event__name(unsigned int id)
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 74a434116b2c..16cee44de56b 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -228,6 +228,7 @@ enum perf_user_event_type { /* above any possible kernel type */
 	PERF_RECORD_AUXTRACE_ERROR		= 72,
 	PERF_RECORD_THREAD_MAP			= 73,
 	PERF_RECORD_CPU_MAP			= 74,
+	PERF_RECORD_STAT_CONFIG			= 75,
 	PERF_RECORD_HEADER_MAX
 };
 
@@ -395,6 +396,24 @@ struct thread_map_event {
 	struct thread_map_event_entry	entries[];
 };
 
+enum {
+	PERF_STAT_CONFIG_TERM__AGGR_MODE	= 0,
+	PERF_STAT_CONFIG_TERM__INTERVAL		= 1,
+	PERF_STAT_CONFIG_TERM__SCALE		= 2,
+	PERF_STAT_CONFIG_TERM__MAX		= 3,
+};
+
+struct stat_config_event_entry {
+	u64	tag;
+	u64	val;
+};
+
+struct stat_config_event {
+	struct perf_event_header	header;
+	u64				nr;
+	struct stat_config_event_entry	data[];
+};
+
 union perf_event {
 	struct perf_event_header	header;
 	struct mmap_event		mmap;
@@ -419,6 +438,7 @@ union perf_event {
 	struct context_switch_event	context_switch;
 	struct thread_map_event		thread_map;
 	struct cpu_map_event		cpu_map;
+	struct stat_config_event	stat_config;
 };
 
 void perf_event__print_totals(void);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 4350f5e85bf5..fbc52ab3eb75 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -315,6 +315,15 @@ int process_event_cpu_map_stub(struct perf_tool *tool __maybe_unused,
 	return 0;
 }
 
+static
+int process_event_stat_config_stub(struct perf_tool *tool __maybe_unused,
+				   union perf_event *event __maybe_unused,
+				   struct perf_session *session __maybe_unused)
+{
+	dump_printf(": unhandled!\n");
+	return 0;
+}
+
 void perf_tool__fill_defaults(struct perf_tool *tool)
 {
 	if (tool->sample == NULL)
@@ -369,6 +378,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
 		tool->thread_map = process_event_thread_map_stub;
 	if (tool->cpu_map == NULL)
 		tool->cpu_map = process_event_cpu_map_stub;
+	if (tool->stat_config == NULL)
+		tool->stat_config = process_event_stat_config_stub;
 }
 
 static void swap_sample_id_all(union perf_event *event, void *data)
@@ -686,6 +697,16 @@ static void perf_event__cpu_map_swap(union perf_event *event,
 	}
 }
 
+static void perf_event__stat_config_swap(union perf_event *event,
+					 bool sample_id_all __maybe_unused)
+{
+	u64 size;
+
+	size  = event->stat_config.nr * sizeof(event->stat_config.data[0]);
+	size += 1; /* nr item itself */
+	mem_bswap_64(&event->stat_config.nr, size);
+}
+
 typedef void (*perf_event__swap_op)(union perf_event *event,
 				    bool sample_id_all);
 
@@ -715,6 +736,7 @@ static perf_event__swap_op perf_event__swap_ops[] = {
 	[PERF_RECORD_AUXTRACE_ERROR]	  = perf_event__auxtrace_error_swap,
 	[PERF_RECORD_THREAD_MAP]	  = perf_event__thread_map_swap,
 	[PERF_RECORD_CPU_MAP]		  = perf_event__cpu_map_swap,
+	[PERF_RECORD_STAT_CONFIG]	  = perf_event__stat_config_swap,
 	[PERF_RECORD_HEADER_MAX]	  = NULL,
 };
 
@@ -1255,6 +1277,8 @@ static s64 perf_session__process_user_event(struct perf_session *session,
 		return tool->thread_map(tool, event, session);
 	case PERF_RECORD_CPU_MAP:
 		return tool->cpu_map(tool, event, session);
+	case PERF_RECORD_STAT_CONFIG:
+		return tool->stat_config(tool, event, session);
 	default:
 		return -EINVAL;
 	}
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index 9e5925c78519..aa7ae73d76b4 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -57,7 +57,8 @@ struct perf_tool {
 			auxtrace_info,
 			auxtrace_error,
 			thread_map,
-			cpu_map;
+			cpu_map,
+			stat_config;
 	event_op3	auxtrace;
 	bool		ordered_events;
 	bool		ordering_requires_timestamps;
-- 
2.1.0


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

* [PATCH 10/43] perf tools: Add stat config event synthesize function
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
                   ` (8 preceding siblings ...)
  2015-12-17 19:46 ` [PATCH 09/43] perf tools: Add stat config user level event Arnaldo Carvalho de Melo
@ 2015-12-17 19:46 ` Arnaldo Carvalho de Melo
  2015-12-17 19:46 ` [PATCH 11/43] perf tools: Add stat config event read function Arnaldo Carvalho de Melo
                   ` (33 subsequent siblings)
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:46 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

Introduce the perf_event__synthesize_stat_config to synthesize a 'struct
perf_stat_config'.

Storing the stat config in the form of tag-value pairs will, I believe,
sort out future version extensibility issues.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Kan Liang <kan.liang@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1445784728-21732-13-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 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 7abad28fe17e..fc0293150f93 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -35,6 +35,7 @@ perf-y += llvm.o llvm-src-base.o llvm-src-kbuild.o llvm-src-prologue.o
 perf-y += bpf.o
 perf-y += topology.o
 perf-y += cpumap.o
+perf-y += stat.o
 
 $(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build
 	$(call rule_mkdir)
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 0c3fe2846de8..ed8402f339fa 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -188,6 +188,10 @@ static struct test generic_tests[] = {
 		.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..c7a2bdb97708
--- /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(int subtest __maybe_unused)
+{
+	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 f85160f6ebb8..319757a3ca69 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -81,6 +81,7 @@ int test__bpf_subtest_get_nr(void);
 int test_session_topology(int subtest);
 int test__thread_map_synthesize(int subtest);
 int test__cpu_map_synthesize(int subtest);
+int test__synthesize_stat_config(int subtest);
 
 #if defined(__arm__) || defined(__aarch64__)
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 43e2dfc2c73b..1ea693c2a14b 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",
@@ -869,6 +871,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 16cee44de56b..39014c7c5a5b 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -446,6 +446,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,
@@ -472,6 +473,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.1.0


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

* [PATCH 11/43] perf tools: Add stat config event read function
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
                   ` (9 preceding siblings ...)
  2015-12-17 19:46 ` [PATCH 10/43] perf tools: Add stat config event synthesize function Arnaldo Carvalho de Melo
@ 2015-12-17 19:46 ` Arnaldo Carvalho de Melo
  2015-12-17 19:46 ` [PATCH 12/43] perf tools: Add stat user level event Arnaldo Carvalho de Melo
                   ` (32 subsequent siblings)
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:46 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

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

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Kan Liang <kan.liang@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1445784728-21732-14-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 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 c7a2bdb97708..aa35d28294a0 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 1ea693c2a14b..223deaf2fba7 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -909,6 +909,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 39014c7c5a5b..4e87be2e1afa 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -477,6 +477,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.1.0


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

* [PATCH 12/43] perf tools: Add stat user level event
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
                   ` (10 preceding siblings ...)
  2015-12-17 19:46 ` [PATCH 11/43] perf tools: Add stat config event read function Arnaldo Carvalho de Melo
@ 2015-12-17 19:46 ` Arnaldo Carvalho de Melo
  2015-12-17 19:46 ` [PATCH 13/43] perf tools: Add stat event synthesize function Arnaldo Carvalho de Melo
                   ` (31 subsequent siblings)
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:46 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

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

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Kan Liang <kan.liang@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1445784728-21732-15-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/event.c   |  1 +
 tools/perf/util/event.h   | 19 +++++++++++++++++++
 tools/perf/util/session.c | 25 +++++++++++++++++++++++++
 tools/perf/util/tool.h    |  3 ++-
 4 files changed, 47 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 223deaf2fba7..670123fee60a 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -42,6 +42,7 @@ static const char *perf_event__names[] = {
 	[PERF_RECORD_THREAD_MAP]		= "THREAD_MAP",
 	[PERF_RECORD_CPU_MAP]			= "CPU_MAP",
 	[PERF_RECORD_STAT_CONFIG]		= "STAT_CONFIG",
+	[PERF_RECORD_STAT]			= "STAT",
 };
 
 const char *perf_event__name(unsigned int id)
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 4e87be2e1afa..f23f464c680a 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -229,6 +229,7 @@ enum perf_user_event_type { /* above any possible kernel type */
 	PERF_RECORD_THREAD_MAP			= 73,
 	PERF_RECORD_CPU_MAP			= 74,
 	PERF_RECORD_STAT_CONFIG			= 75,
+	PERF_RECORD_STAT			= 76,
 	PERF_RECORD_HEADER_MAX
 };
 
@@ -414,6 +415,23 @@ struct stat_config_event {
 	struct stat_config_event_entry	data[];
 };
 
+struct stat_event {
+	struct perf_event_header	header;
+
+	u64	id;
+	u32	cpu;
+	u32	thread;
+
+	union {
+		struct {
+			u64 val;
+			u64 ena;
+			u64 run;
+		};
+		u64 values[3];
+	};
+};
+
 union perf_event {
 	struct perf_event_header	header;
 	struct mmap_event		mmap;
@@ -439,6 +457,7 @@ union perf_event {
 	struct thread_map_event		thread_map;
 	struct cpu_map_event		cpu_map;
 	struct stat_config_event	stat_config;
+	struct stat_event		stat;
 };
 
 void perf_event__print_totals(void);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index fbc52ab3eb75..663a2fdab42c 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -324,6 +324,15 @@ int process_event_stat_config_stub(struct perf_tool *tool __maybe_unused,
 	return 0;
 }
 
+static int process_stat_stub(struct perf_tool *tool __maybe_unused,
+			     union perf_event *event __maybe_unused,
+			     struct perf_session *perf_session
+			     __maybe_unused)
+{
+	dump_printf(": unhandled!\n");
+	return 0;
+}
+
 void perf_tool__fill_defaults(struct perf_tool *tool)
 {
 	if (tool->sample == NULL)
@@ -380,6 +389,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
 		tool->cpu_map = process_event_cpu_map_stub;
 	if (tool->stat_config == NULL)
 		tool->stat_config = process_event_stat_config_stub;
+	if (tool->stat == NULL)
+		tool->stat = process_stat_stub;
 }
 
 static void swap_sample_id_all(union perf_event *event, void *data)
@@ -707,6 +718,17 @@ static void perf_event__stat_config_swap(union perf_event *event,
 	mem_bswap_64(&event->stat_config.nr, size);
 }
 
+static void perf_event__stat_swap(union perf_event *event,
+				  bool sample_id_all __maybe_unused)
+{
+	event->stat.id     = bswap_64(event->stat.id);
+	event->stat.thread = bswap_32(event->stat.thread);
+	event->stat.cpu    = bswap_32(event->stat.cpu);
+	event->stat.val    = bswap_64(event->stat.val);
+	event->stat.ena    = bswap_64(event->stat.ena);
+	event->stat.run    = bswap_64(event->stat.run);
+}
+
 typedef void (*perf_event__swap_op)(union perf_event *event,
 				    bool sample_id_all);
 
@@ -737,6 +759,7 @@ static perf_event__swap_op perf_event__swap_ops[] = {
 	[PERF_RECORD_THREAD_MAP]	  = perf_event__thread_map_swap,
 	[PERF_RECORD_CPU_MAP]		  = perf_event__cpu_map_swap,
 	[PERF_RECORD_STAT_CONFIG]	  = perf_event__stat_config_swap,
+	[PERF_RECORD_STAT]		  = perf_event__stat_swap,
 	[PERF_RECORD_HEADER_MAX]	  = NULL,
 };
 
@@ -1279,6 +1302,8 @@ static s64 perf_session__process_user_event(struct perf_session *session,
 		return tool->cpu_map(tool, event, session);
 	case PERF_RECORD_STAT_CONFIG:
 		return tool->stat_config(tool, event, session);
+	case PERF_RECORD_STAT:
+		return tool->stat(tool, event, session);
 	default:
 		return -EINVAL;
 	}
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index aa7ae73d76b4..f0b9da0c166a 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -58,7 +58,8 @@ struct perf_tool {
 			auxtrace_error,
 			thread_map,
 			cpu_map,
-			stat_config;
+			stat_config,
+			stat;
 	event_op3	auxtrace;
 	bool		ordered_events;
 	bool		ordering_requires_timestamps;
-- 
2.1.0


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

* [PATCH 13/43] perf tools: Add stat event synthesize function
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
                   ` (11 preceding siblings ...)
  2015-12-17 19:46 ` [PATCH 12/43] perf tools: Add stat user level event Arnaldo Carvalho de Melo
@ 2015-12-17 19:46 ` Arnaldo Carvalho de Melo
  2015-12-17 19:46 ` [PATCH 14/43] perf tools: Add stat event read function Arnaldo Carvalho de Melo
                   ` (30 subsequent siblings)
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:46 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

Introduce the perf_event__synthesize_stat function to synthesize a
'struct stat_event'.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Kan Liang <kan.liang@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1445784728-21732-16-git-send-email-jolsa@kernel.org
[ Renamed 'stat' parameter to 'st' to fix 'already defined' build error with older distros (e.g. RHEL6.7) ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 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 ed8402f339fa..4a7d9989e1c3 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -192,6 +192,10 @@ static struct test generic_tests[] = {
 		.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 aa35d28294a0..d319875a5e7c 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(int subtest __maybe_unused)
 	};
 
 	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 *st = &event->stat;
+
+	TEST_ASSERT_VAL("wrong cpu",    st->cpu    == 1);
+	TEST_ASSERT_VAL("wrong thread", st->thread == 2);
+	TEST_ASSERT_VAL("wrong id",     st->id     == 3);
+	TEST_ASSERT_VAL("wrong val",    st->val    == 100);
+	TEST_ASSERT_VAL("wrong run",    st->ena    == 200);
+	TEST_ASSERT_VAL("wrong ena",    st->run    == 300);
+	return 0;
+}
+
+int test__synthesize_stat(int subtest __maybe_unused)
+{
+	struct perf_counts_values count;
+
+	count.val = 100;
+	count.ena = 200;
+	count.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 319757a3ca69..d36eda17a5f5 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -82,6 +82,7 @@ int test_session_topology(int subtest);
 int test__thread_map_synthesize(int subtest);
 int test__cpu_map_synthesize(int subtest);
 int test__synthesize_stat_config(int subtest);
+int test__synthesize_stat(int subtest);
 
 #if defined(__arm__) || defined(__aarch64__)
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 670123fee60a..eb8243ab6ab1 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -910,6 +910,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 f23f464c680a..336eb44babf8 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -466,6 +466,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,
@@ -498,7 +499,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.1.0


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

* [PATCH 14/43] perf tools: Add stat event read function
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
                   ` (12 preceding siblings ...)
  2015-12-17 19:46 ` [PATCH 13/43] perf tools: Add stat event synthesize function Arnaldo Carvalho de Melo
@ 2015-12-17 19:46 ` Arnaldo Carvalho de Melo
  2015-12-17 19:46 ` [PATCH 15/43] perf tools: Add stat round user level event Arnaldo Carvalho de Melo
                   ` (29 subsequent siblings)
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:46 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

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

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Kan Liang <kan.liang@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1445784728-21732-17-git-send-email-jolsa@kernel.org
[ Renamed 'stat' parameter to 'st' to fix 'already defined' build error with older distros (e.g. RHEL6.7) ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 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 2d9d8306dbd3..0ad59cea318c 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -341,3 +341,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 *st = &event->stat;
+	struct perf_evsel *counter;
+
+	count.val = st->val;
+	count.ena = st->ena;
+	count.run = st->run;
+
+	counter = perf_evlist__id2evsel(session->evlist, st->id);
+	if (!counter) {
+		pr_err("Failed to resolve counter for stat event.\n");
+		return -EINVAL;
+	}
+
+	*perf_counts(counter->counts, st->cpu, st->thread) = count;
+	counter->supported = true;
+	return 0;
+}
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index da1d11c4f8c1..afe6844e5219 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -90,4 +90,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.1.0


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

* [PATCH 15/43] perf tools: Add stat round user level event
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
                   ` (13 preceding siblings ...)
  2015-12-17 19:46 ` [PATCH 14/43] perf tools: Add stat event read function Arnaldo Carvalho de Melo
@ 2015-12-17 19:46 ` Arnaldo Carvalho de Melo
  2015-12-17 19:46 ` [PATCH 16/43] perf tools: Add stat round event synthesize function Arnaldo Carvalho de Melo
                   ` (28 subsequent siblings)
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:46 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

Adding the stat round event to be stored after each stat interval round,
so that report tools (report/script) gets notified and process interval
data.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Kan Liang <kan.liang@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1445784728-21732-18-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/event.c   |  1 +
 tools/perf/util/event.h   | 13 +++++++++++++
 tools/perf/util/session.c | 21 +++++++++++++++++++++
 tools/perf/util/tool.h    |  3 ++-
 4 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index eb8243ab6ab1..725db548c7d5 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -43,6 +43,7 @@ static const char *perf_event__names[] = {
 	[PERF_RECORD_CPU_MAP]			= "CPU_MAP",
 	[PERF_RECORD_STAT_CONFIG]		= "STAT_CONFIG",
 	[PERF_RECORD_STAT]			= "STAT",
+	[PERF_RECORD_STAT_ROUND]		= "STAT_ROUND",
 };
 
 const char *perf_event__name(unsigned int id)
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 336eb44babf8..5eb4f55a141d 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -230,6 +230,7 @@ enum perf_user_event_type { /* above any possible kernel type */
 	PERF_RECORD_CPU_MAP			= 74,
 	PERF_RECORD_STAT_CONFIG			= 75,
 	PERF_RECORD_STAT			= 76,
+	PERF_RECORD_STAT_ROUND			= 77,
 	PERF_RECORD_HEADER_MAX
 };
 
@@ -432,6 +433,17 @@ struct stat_event {
 	};
 };
 
+enum {
+	PERF_STAT_ROUND_TYPE__INTERVAL	= 0,
+	PERF_STAT_ROUND_TYPE__FINAL	= 1,
+};
+
+struct stat_round_event {
+	struct perf_event_header	header;
+	u64				type;
+	u64				time;
+};
+
 union perf_event {
 	struct perf_event_header	header;
 	struct mmap_event		mmap;
@@ -458,6 +470,7 @@ union perf_event {
 	struct cpu_map_event		cpu_map;
 	struct stat_config_event	stat_config;
 	struct stat_event		stat;
+	struct stat_round_event		stat_round;
 };
 
 void perf_event__print_totals(void);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 663a2fdab42c..5b3a81a6b795 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -333,6 +333,15 @@ static int process_stat_stub(struct perf_tool *tool __maybe_unused,
 	return 0;
 }
 
+static int process_stat_round_stub(struct perf_tool *tool __maybe_unused,
+				   union perf_event *event __maybe_unused,
+				   struct perf_session *perf_session
+				   __maybe_unused)
+{
+	dump_printf(": unhandled!\n");
+	return 0;
+}
+
 void perf_tool__fill_defaults(struct perf_tool *tool)
 {
 	if (tool->sample == NULL)
@@ -391,6 +400,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
 		tool->stat_config = process_event_stat_config_stub;
 	if (tool->stat == NULL)
 		tool->stat = process_stat_stub;
+	if (tool->stat_round == NULL)
+		tool->stat_round = process_stat_round_stub;
 }
 
 static void swap_sample_id_all(union perf_event *event, void *data)
@@ -729,6 +740,13 @@ static void perf_event__stat_swap(union perf_event *event,
 	event->stat.run    = bswap_64(event->stat.run);
 }
 
+static void perf_event__stat_round_swap(union perf_event *event,
+					bool sample_id_all __maybe_unused)
+{
+	event->stat_round.type = bswap_64(event->stat_round.type);
+	event->stat_round.time = bswap_64(event->stat_round.time);
+}
+
 typedef void (*perf_event__swap_op)(union perf_event *event,
 				    bool sample_id_all);
 
@@ -760,6 +778,7 @@ static perf_event__swap_op perf_event__swap_ops[] = {
 	[PERF_RECORD_CPU_MAP]		  = perf_event__cpu_map_swap,
 	[PERF_RECORD_STAT_CONFIG]	  = perf_event__stat_config_swap,
 	[PERF_RECORD_STAT]		  = perf_event__stat_swap,
+	[PERF_RECORD_STAT_ROUND]	  = perf_event__stat_round_swap,
 	[PERF_RECORD_HEADER_MAX]	  = NULL,
 };
 
@@ -1304,6 +1323,8 @@ static s64 perf_session__process_user_event(struct perf_session *session,
 		return tool->stat_config(tool, event, session);
 	case PERF_RECORD_STAT:
 		return tool->stat(tool, event, session);
+	case PERF_RECORD_STAT_ROUND:
+		return tool->stat_round(tool, event, session);
 	default:
 		return -EINVAL;
 	}
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index f0b9da0c166a..d04d9e5f444a 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -59,7 +59,8 @@ struct perf_tool {
 			thread_map,
 			cpu_map,
 			stat_config,
-			stat;
+			stat,
+			stat_round;
 	event_op3	auxtrace;
 	bool		ordered_events;
 	bool		ordering_requires_timestamps;
-- 
2.1.0


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

* [PATCH 16/43] perf tools: Add stat round event synthesize function
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
                   ` (14 preceding siblings ...)
  2015-12-17 19:46 ` [PATCH 15/43] perf tools: Add stat round user level event Arnaldo Carvalho de Melo
@ 2015-12-17 19:46 ` Arnaldo Carvalho de Melo
  2015-12-17 19:46 ` [PATCH 17/43] perf tools: Add stat events fprintf functions Arnaldo Carvalho de Melo
                   ` (27 subsequent siblings)
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:46 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

Introduce the perf_event__synthesize_stat_round function to
synthesize a 'struct stat_round_event'.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Kan Liang <kan.liang@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1445784728-21732-19-git-send-email-jolsa@kernel.org
[ Renamed 'time' parameter to 'evtime' to fix build on older systems ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/tests/builtin-test.c |  4 ++++
 tools/perf/tests/stat.c         | 21 +++++++++++++++++++++
 tools/perf/tests/tests.h        |  1 +
 tools/perf/util/event.c         | 17 +++++++++++++++++
 tools/perf/util/event.h         |  4 ++++
 5 files changed, 47 insertions(+)

diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 4a7d9989e1c3..6a3519814492 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -196,6 +196,10 @@ static struct test generic_tests[] = {
 		.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 d319875a5e7c..6a20ff2326bb 100644
--- a/tools/perf/tests/stat.c
+++ b/tools/perf/tests/stat.c
@@ -88,3 +88,24 @@ int test__synthesize_stat(int subtest __maybe_unused)
 
 	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(int subtest __maybe_unused)
+{
+	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 d36eda17a5f5..a82ab9c4c0ca 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -83,6 +83,7 @@ int test__thread_map_synthesize(int subtest);
 int test__cpu_map_synthesize(int subtest);
 int test__synthesize_stat_config(int subtest);
 int test__synthesize_stat(int subtest);
+int test__synthesize_stat_round(int subtest);
 
 #if defined(__arm__) || defined(__aarch64__)
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 725db548c7d5..e4c68ba79974 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -933,6 +933,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 evtime, 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 = evtime;
+	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 5eb4f55a141d..1afaa21eeebe 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -517,6 +517,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.1.0


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

* [PATCH 17/43] perf tools: Add stat events fprintf functions
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
                   ` (15 preceding siblings ...)
  2015-12-17 19:46 ` [PATCH 16/43] perf tools: Add stat round event synthesize function Arnaldo Carvalho de Melo
@ 2015-12-17 19:46 ` Arnaldo Carvalho de Melo
  2015-12-17 19:46 ` [PATCH 18/43] perf tools: Add event_update user level event Arnaldo Carvalho de Melo
                   ` (26 subsequent siblings)
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:46 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

Introducing the following functions to display the stat events for raw
dump.

  perf_event__fprintf_stat
  perf_event__fprintf_stat_round
  perf_event__fprintf_stat_config

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Kan Liang <kan.liang@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1445784728-21732-20-git-send-email-jolsa@kernel.org
[ s/stat/st/g and s/round/rd/g parameters to fix 'already defined' build error with older distros (e.g. RHEL6.7) ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/stat.c | 39 +++++++++++++++++++++++++++++++++++++++
 tools/perf/util/stat.h |  4 ++++
 2 files changed, 43 insertions(+)

diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index 0ad59cea318c..2f901d15e063 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -364,3 +364,42 @@ int perf_event__process_stat_event(struct perf_tool *tool __maybe_unused,
 	counter->supported = true;
 	return 0;
 }
+
+size_t perf_event__fprintf_stat(union perf_event *event, FILE *fp)
+{
+	struct stat_event *st = (struct stat_event *) event;
+	size_t ret;
+
+	ret  = fprintf(fp, "\n... id %" PRIu64 ", cpu %d, thread %d\n",
+		       st->id, st->cpu, st->thread);
+	ret += fprintf(fp, "... value %" PRIu64 ", enabled %" PRIu64 ", running %" PRIu64 "\n",
+		       st->val, st->ena, st->run);
+
+	return ret;
+}
+
+size_t perf_event__fprintf_stat_round(union perf_event *event, FILE *fp)
+{
+	struct stat_round_event *rd = (struct stat_round_event *)event;
+	size_t ret;
+
+	ret = fprintf(fp, "\n... time %" PRIu64 ", type %s\n", rd->time,
+		      rd->type == PERF_STAT_ROUND_TYPE__FINAL ? "FINAL" : "INTERVAL");
+
+	return ret;
+}
+
+size_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp)
+{
+	struct perf_stat_config sc;
+	size_t ret;
+
+	perf_event__read_stat_config(&sc, &event->stat_config);
+
+	ret  = fprintf(fp, "\n");
+	ret += fprintf(fp, "... aggr_mode %d\n", sc.aggr_mode);
+	ret += fprintf(fp, "... scale     %d\n", sc.scale);
+	ret += fprintf(fp, "... interval  %u\n", sc.interval);
+
+	return ret;
+}
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index afe6844e5219..086f4e128d63 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -96,4 +96,8 @@ struct perf_session;
 int perf_event__process_stat_event(struct perf_tool *tool,
 				   union perf_event *event,
 				   struct perf_session *session);
+
+size_t perf_event__fprintf_stat(union perf_event *event, FILE *fp);
+size_t perf_event__fprintf_stat_round(union perf_event *event, FILE *fp);
+size_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp);
 #endif
-- 
2.1.0


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

* [PATCH 18/43] perf tools: Add event_update user level event
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
                   ` (16 preceding siblings ...)
  2015-12-17 19:46 ` [PATCH 17/43] perf tools: Add stat events fprintf functions Arnaldo Carvalho de Melo
@ 2015-12-17 19:46 ` Arnaldo Carvalho de Melo
  2015-12-17 19:47 ` [PATCH 19/43] perf tools: Add event_update event unit type Arnaldo Carvalho de Melo
                   ` (25 subsequent siblings)
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:46 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

It'll serve as a base event for additional event attributes details,
that are not part of the attr event.

At the moment this event is just a dummy one without any specific
functionality. The type value will distinguish the update event details.
It'll come in the following patches.

The idea for this event is to be extensible for any update that the
event might need in the future.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Kan Liang <kan.liang@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1445784728-21732-21-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/event.c   |  1 +
 tools/perf/util/event.h   | 10 ++++++++++
 tools/perf/util/header.c  | 20 ++++++++++++++++++++
 tools/perf/util/header.h  |  3 +++
 tools/perf/util/session.c | 21 +++++++++++++++++++++
 tools/perf/util/tool.h    |  1 +
 6 files changed, 56 insertions(+)

diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index e4c68ba79974..cd61bb1f3917 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -44,6 +44,7 @@ static const char *perf_event__names[] = {
 	[PERF_RECORD_STAT_CONFIG]		= "STAT_CONFIG",
 	[PERF_RECORD_STAT]			= "STAT",
 	[PERF_RECORD_STAT_ROUND]		= "STAT_ROUND",
+	[PERF_RECORD_EVENT_UPDATE]		= "EVENT_UPDATE",
 };
 
 const char *perf_event__name(unsigned int id)
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 1afaa21eeebe..6966a4b7c0f0 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -231,6 +231,7 @@ enum perf_user_event_type { /* above any possible kernel type */
 	PERF_RECORD_STAT_CONFIG			= 75,
 	PERF_RECORD_STAT			= 76,
 	PERF_RECORD_STAT_ROUND			= 77,
+	PERF_RECORD_EVENT_UPDATE		= 78,
 	PERF_RECORD_HEADER_MAX
 };
 
@@ -307,6 +308,14 @@ struct attr_event {
 	u64 id[];
 };
 
+struct event_update_event {
+	struct perf_event_header header;
+	u64 type;
+	u64 id;
+
+	char data[];
+};
+
 #define MAX_EVENT_NAME 64
 
 struct perf_trace_event_type {
@@ -456,6 +465,7 @@ union perf_event {
 	struct throttle_event		throttle;
 	struct sample_event		sample;
 	struct attr_event		attr;
+	struct event_update_event	event_update;
 	struct event_type_event		event_type;
 	struct tracing_data_event	tracing_data;
 	struct build_id_event		build_id;
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 5ac7bdb0dff7..6b4e00220a5a 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2745,6 +2745,26 @@ int perf_event__process_attr(struct perf_tool *tool __maybe_unused,
 	return 0;
 }
 
+int perf_event__process_event_update(struct perf_tool *tool __maybe_unused,
+				     union perf_event *event,
+				     struct perf_evlist **pevlist)
+{
+	struct event_update_event *ev = &event->event_update;
+	struct perf_evlist *evlist;
+	struct perf_evsel *evsel;
+
+	if (!pevlist || *pevlist == NULL)
+		return -EINVAL;
+
+	evlist = *pevlist;
+
+	evsel = perf_evlist__id2evsel(evlist, ev->id);
+	if (evsel == NULL)
+		return -EINVAL;
+
+	return 0;
+}
+
 int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd,
 					struct perf_evlist *evlist,
 					perf_event__handler_t process)
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 05f27cb6b7e3..1e843c67a4ff 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -107,6 +107,9 @@ int perf_event__synthesize_attrs(struct perf_tool *tool,
 				 perf_event__handler_t process);
 int perf_event__process_attr(struct perf_tool *tool, union perf_event *event,
 			     struct perf_evlist **pevlist);
+int perf_event__process_event_update(struct perf_tool *tool __maybe_unused,
+				     union perf_event *event,
+				     struct perf_evlist **pevlist);
 
 int perf_event__synthesize_tracing_data(struct perf_tool *tool,
 					int fd, struct perf_evlist *evlist,
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 5b3a81a6b795..49e5cdc4cc5a 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -205,6 +205,15 @@ static int process_event_synth_attr_stub(struct perf_tool *tool __maybe_unused,
 	return 0;
 }
 
+static int process_event_synth_event_update_stub(struct perf_tool *tool __maybe_unused,
+						 union perf_event *event __maybe_unused,
+						 struct perf_evlist **pevlist
+						 __maybe_unused)
+{
+	dump_printf(": unhandled!\n");
+	return 0;
+}
+
 static int process_event_sample_stub(struct perf_tool *tool __maybe_unused,
 				     union perf_event *event __maybe_unused,
 				     struct perf_sample *sample __maybe_unused,
@@ -374,6 +383,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
 		tool->unthrottle = process_event_stub;
 	if (tool->attr == NULL)
 		tool->attr = process_event_synth_attr_stub;
+	if (tool->event_update == NULL)
+		tool->event_update = process_event_synth_event_update_stub;
 	if (tool->tracing_data == NULL)
 		tool->tracing_data = process_event_synth_tracing_data_stub;
 	if (tool->build_id == NULL)
@@ -625,6 +636,13 @@ static void perf_event__hdr_attr_swap(union perf_event *event,
 	mem_bswap_64(event->attr.id, size);
 }
 
+static void perf_event__event_update_swap(union perf_event *event,
+					  bool sample_id_all __maybe_unused)
+{
+	event->event_update.type = bswap_64(event->event_update.type);
+	event->event_update.id   = bswap_64(event->event_update.id);
+}
+
 static void perf_event__event_type_swap(union perf_event *event,
 					bool sample_id_all __maybe_unused)
 {
@@ -779,6 +797,7 @@ static perf_event__swap_op perf_event__swap_ops[] = {
 	[PERF_RECORD_STAT_CONFIG]	  = perf_event__stat_config_swap,
 	[PERF_RECORD_STAT]		  = perf_event__stat_swap,
 	[PERF_RECORD_STAT_ROUND]	  = perf_event__stat_round_swap,
+	[PERF_RECORD_EVENT_UPDATE]	  = perf_event__event_update_swap,
 	[PERF_RECORD_HEADER_MAX]	  = NULL,
 };
 
@@ -1290,6 +1309,8 @@ static s64 perf_session__process_user_event(struct perf_session *session,
 			perf_session__set_comm_exec(session);
 		}
 		return err;
+	case PERF_RECORD_EVENT_UPDATE:
+		return tool->event_update(tool, event, &session->evlist);
 	case PERF_RECORD_HEADER_EVENT_TYPE:
 		/*
 		 * Depreceated, but we need to handle it for sake
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index d04d9e5f444a..55de4cffcd4e 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -50,6 +50,7 @@ struct perf_tool {
 			throttle,
 			unthrottle;
 	event_attr_op	attr;
+	event_attr_op	event_update;
 	event_op2	tracing_data;
 	event_oe	finished_round;
 	event_op2	build_id,
-- 
2.1.0


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

* [PATCH 19/43] perf tools: Add event_update event unit type
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
                   ` (17 preceding siblings ...)
  2015-12-17 19:46 ` [PATCH 18/43] perf tools: Add event_update user level event Arnaldo Carvalho de Melo
@ 2015-12-17 19:47 ` Arnaldo Carvalho de Melo
  2015-12-17 19:47 ` [PATCH 20/43] perf tools: Add event_update event scale type Arnaldo Carvalho de Melo
                   ` (24 subsequent siblings)
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:47 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

Adding unit type 'event update' event, that stores/transfer events unit
name. The unit name is part of the perf stat output data.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Kan Liang <kan.liang@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1445784728-21732-22-git-send-email-jolsa@kernel.org
[ Rename __alloc() to __new() for consistency ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/tests/Build          |  1 +
 tools/perf/tests/builtin-test.c |  4 ++++
 tools/perf/tests/event_update.c | 42 +++++++++++++++++++++++++++++++++++++++
 tools/perf/tests/tests.h        |  1 +
 tools/perf/util/event.h         |  4 ++++
 tools/perf/util/header.c        | 44 +++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/header.h        |  3 +++
 7 files changed, 99 insertions(+)
 create mode 100644 tools/perf/tests/event_update.c

diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index fc0293150f93..614899b88b37 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -36,6 +36,7 @@ perf-y += bpf.o
 perf-y += topology.o
 perf-y += cpumap.o
 perf-y += stat.o
+perf-y += event_update.o
 
 $(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build
 	$(call rule_mkdir)
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 6a3519814492..f2b1dcac45d3 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -200,6 +200,10 @@ static struct test generic_tests[] = {
 		.func = test__synthesize_stat_round,
 	},
 	{
+		.desc = "Test attr update synthesize",
+		.func = test__event_update,
+	},
+	{
 		.func = NULL,
 	},
 };
diff --git a/tools/perf/tests/event_update.c b/tools/perf/tests/event_update.c
new file mode 100644
index 000000000000..9cdf4c934977
--- /dev/null
+++ b/tools/perf/tests/event_update.c
@@ -0,0 +1,42 @@
+#include <linux/compiler.h>
+#include "evlist.h"
+#include "evsel.h"
+#include "machine.h"
+#include "tests.h"
+#include "debug.h"
+
+static int process_event_unit(struct perf_tool *tool __maybe_unused,
+			      union perf_event *event,
+			      struct perf_sample *sample __maybe_unused,
+			      struct machine *machine __maybe_unused)
+{
+	struct event_update_event *ev = (struct event_update_event *) event;
+
+	TEST_ASSERT_VAL("wrong id", ev->id == 123);
+	TEST_ASSERT_VAL("wrong id", ev->type == PERF_EVENT_UPDATE__UNIT);
+	TEST_ASSERT_VAL("wrong unit", !strcmp(ev->data, "KRAVA"));
+	return 0;
+}
+
+int test__event_update(int subtest __maybe_unused)
+{
+	struct perf_evlist *evlist;
+	struct perf_evsel *evsel;
+
+	evlist = perf_evlist__new_default();
+	TEST_ASSERT_VAL("failed to get evlist", evlist);
+
+	evsel = perf_evlist__first(evlist);
+
+	TEST_ASSERT_VAL("failed to allos ids",
+			!perf_evsel__alloc_id(evsel, 1, 1));
+
+	perf_evlist__id_add(evlist, evsel, 0, 0, 123);
+
+	evsel->unit = strdup("KRAVA");
+
+	TEST_ASSERT_VAL("failed to synthesize attr update unit",
+			!perf_event__synthesize_event_update_unit(NULL, evsel, process_event_unit));
+
+	return 0;
+}
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index a82ab9c4c0ca..82b2b5e6ba7c 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -84,6 +84,7 @@ int test__cpu_map_synthesize(int subtest);
 int test__synthesize_stat_config(int subtest);
 int test__synthesize_stat(int subtest);
 int test__synthesize_stat_round(int subtest);
+int test__event_update(int subtest);
 
 #if defined(__arm__) || defined(__aarch64__)
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 6966a4b7c0f0..64c4cdf5aada 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -308,6 +308,10 @@ struct attr_event {
 	u64 id[];
 };
 
+enum {
+	PERF_EVENT_UPDATE__UNIT  = 0,
+};
+
 struct event_update_event {
 	struct perf_event_header header;
 	u64 type;
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 6b4e00220a5a..5759ebfde666 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2686,6 +2686,43 @@ int perf_event__synthesize_attr(struct perf_tool *tool,
 	return err;
 }
 
+static struct event_update_event *
+event_update_event__new(size_t size, u64 type, u64 id)
+{
+	struct event_update_event *ev;
+
+	size += sizeof(*ev);
+	size  = PERF_ALIGN(size, sizeof(u64));
+
+	ev = zalloc(size);
+	if (ev) {
+		ev->header.type = PERF_RECORD_EVENT_UPDATE;
+		ev->header.size = (u16)size;
+		ev->type = type;
+		ev->id = id;
+	}
+	return ev;
+}
+
+int
+perf_event__synthesize_event_update_unit(struct perf_tool *tool,
+					 struct perf_evsel *evsel,
+					 perf_event__handler_t process)
+{
+	struct event_update_event *ev;
+	size_t size = strlen(evsel->unit);
+	int err;
+
+	ev = event_update_event__new(size + 1, PERF_EVENT_UPDATE__UNIT, evsel->id[0]);
+	if (ev == NULL)
+		return -ENOMEM;
+
+	strncpy(ev->data, evsel->unit, size);
+	err = process(tool, (union perf_event *)ev, NULL, NULL);
+	free(ev);
+	return err;
+}
+
 int perf_event__synthesize_attrs(struct perf_tool *tool,
 				   struct perf_session *session,
 				   perf_event__handler_t process)
@@ -2762,6 +2799,13 @@ int perf_event__process_event_update(struct perf_tool *tool __maybe_unused,
 	if (evsel == NULL)
 		return -EINVAL;
 
+	switch (ev->type) {
+	case PERF_EVENT_UPDATE__UNIT:
+		evsel->unit = strdup(ev->data);
+	default:
+		break;
+	}
+
 	return 0;
 }
 
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 1e843c67a4ff..6aa2b9242fc1 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -105,6 +105,9 @@ int perf_event__synthesize_attr(struct perf_tool *tool,
 int perf_event__synthesize_attrs(struct perf_tool *tool,
 				 struct perf_session *session,
 				 perf_event__handler_t process);
+int perf_event__synthesize_event_update_unit(struct perf_tool *tool,
+					     struct perf_evsel *evsel,
+					     perf_event__handler_t process);
 int perf_event__process_attr(struct perf_tool *tool, union perf_event *event,
 			     struct perf_evlist **pevlist);
 int perf_event__process_event_update(struct perf_tool *tool __maybe_unused,
-- 
2.1.0


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

* [PATCH 20/43] perf tools: Add event_update event scale type
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
                   ` (18 preceding siblings ...)
  2015-12-17 19:47 ` [PATCH 19/43] perf tools: Add event_update event unit type Arnaldo Carvalho de Melo
@ 2015-12-17 19:47 ` Arnaldo Carvalho de Melo
  2015-12-17 19:47 ` [PATCH 21/43] perf tools: Add event_update event name type Arnaldo Carvalho de Melo
                   ` (23 subsequent siblings)
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:47 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

A__allocdding scale type 'event update' event, that stores/transfer
events scale value. The PMU events can define the scale
value which is used to multiply events data.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Kan Liang <kan.liang@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1445784728-21732-23-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/tests/event_update.c | 21 +++++++++++++++++++++
 tools/perf/util/event.h         |  5 +++++
 tools/perf/util/header.c        | 26 ++++++++++++++++++++++++++
 tools/perf/util/header.h        |  3 +++
 4 files changed, 55 insertions(+)

diff --git a/tools/perf/tests/event_update.c b/tools/perf/tests/event_update.c
index 9cdf4c934977..a91fcefc9f67 100644
--- a/tools/perf/tests/event_update.c
+++ b/tools/perf/tests/event_update.c
@@ -18,6 +18,22 @@ static int process_event_unit(struct perf_tool *tool __maybe_unused,
 	return 0;
 }
 
+static int process_event_scale(struct perf_tool *tool __maybe_unused,
+			       union perf_event *event,
+			       struct perf_sample *sample __maybe_unused,
+			       struct machine *machine __maybe_unused)
+{
+	struct event_update_event *ev = (struct event_update_event *) event;
+	struct event_update_event_scale *ev_data;
+
+	ev_data = (struct event_update_event_scale *) ev->data;
+
+	TEST_ASSERT_VAL("wrong id", ev->id == 123);
+	TEST_ASSERT_VAL("wrong id", ev->type == PERF_EVENT_UPDATE__SCALE);
+	TEST_ASSERT_VAL("wrong scale", ev_data->scale = 0.123);
+	return 0;
+}
+
 int test__event_update(int subtest __maybe_unused)
 {
 	struct perf_evlist *evlist;
@@ -38,5 +54,10 @@ int test__event_update(int subtest __maybe_unused)
 	TEST_ASSERT_VAL("failed to synthesize attr update unit",
 			!perf_event__synthesize_event_update_unit(NULL, evsel, process_event_unit));
 
+	evsel->scale = 0.123;
+
+	TEST_ASSERT_VAL("failed to synthesize attr update scale",
+			!perf_event__synthesize_event_update_scale(NULL, evsel, process_event_scale));
+
 	return 0;
 }
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 64c4cdf5aada..44198e8550e4 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -310,6 +310,11 @@ struct attr_event {
 
 enum {
 	PERF_EVENT_UPDATE__UNIT  = 0,
+	PERF_EVENT_UPDATE__SCALE = 1,
+};
+
+struct event_update_event_scale {
+	double scale;
 };
 
 struct event_update_event {
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 5759ebfde666..30edb4ba258e 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2723,6 +2723,27 @@ perf_event__synthesize_event_update_unit(struct perf_tool *tool,
 	return err;
 }
 
+int
+perf_event__synthesize_event_update_scale(struct perf_tool *tool,
+					  struct perf_evsel *evsel,
+					  perf_event__handler_t process)
+{
+	struct event_update_event *ev;
+	struct event_update_event_scale *ev_data;
+	int err;
+
+	ev = event_update_event__new(sizeof(*ev_data), PERF_EVENT_UPDATE__SCALE, evsel->id[0]);
+	if (ev == NULL)
+		return -ENOMEM;
+
+	ev_data = (struct event_update_event_scale *) ev->data;
+	ev_data->scale = evsel->scale;
+	err = process(tool, (union perf_event*) ev, NULL, NULL);
+	free(ev);
+	return err;
+}
+
+
 int perf_event__synthesize_attrs(struct perf_tool *tool,
 				   struct perf_session *session,
 				   perf_event__handler_t process)
@@ -2787,6 +2808,7 @@ int perf_event__process_event_update(struct perf_tool *tool __maybe_unused,
 				     struct perf_evlist **pevlist)
 {
 	struct event_update_event *ev = &event->event_update;
+	struct event_update_event_scale *ev_scale;
 	struct perf_evlist *evlist;
 	struct perf_evsel *evsel;
 
@@ -2802,6 +2824,10 @@ int perf_event__process_event_update(struct perf_tool *tool __maybe_unused,
 	switch (ev->type) {
 	case PERF_EVENT_UPDATE__UNIT:
 		evsel->unit = strdup(ev->data);
+		break;
+	case PERF_EVENT_UPDATE__SCALE:
+		ev_scale = (struct event_update_event_scale *) ev->data;
+		evsel->scale = ev_scale->scale;
 	default:
 		break;
 	}
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 6aa2b9242fc1..fad04cbab666 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -108,6 +108,9 @@ int perf_event__synthesize_attrs(struct perf_tool *tool,
 int perf_event__synthesize_event_update_unit(struct perf_tool *tool,
 					     struct perf_evsel *evsel,
 					     perf_event__handler_t process);
+int perf_event__synthesize_event_update_scale(struct perf_tool *tool,
+					      struct perf_evsel *evsel,
+					      perf_event__handler_t process);
 int perf_event__process_attr(struct perf_tool *tool, union perf_event *event,
 			     struct perf_evlist **pevlist);
 int perf_event__process_event_update(struct perf_tool *tool __maybe_unused,
-- 
2.1.0


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

* [PATCH 21/43] perf tools: Add event_update event name type
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
                   ` (19 preceding siblings ...)
  2015-12-17 19:47 ` [PATCH 20/43] perf tools: Add event_update event scale type Arnaldo Carvalho de Melo
@ 2015-12-17 19:47 ` Arnaldo Carvalho de Melo
  2015-12-17 19:47 ` [PATCH 22/43] perf tools: Add event_update event cpus type Arnaldo Carvalho de Melo
                   ` (22 subsequent siblings)
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:47 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

Adding name type 'event update' event, that stores/transfer events name.
Event's name is stored within perf.data's EVENT_DESC feature, but we
don't have it if we get the report data from pipe.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Kan Liang <kan.liang@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1445784728-21732-24-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/tests/event_update.c | 25 +++++++++++++++++++++++++
 tools/perf/util/event.h         |  1 +
 tools/perf/util/header.c        | 21 +++++++++++++++++++++
 tools/perf/util/header.h        |  3 +++
 4 files changed, 50 insertions(+)

diff --git a/tools/perf/tests/event_update.c b/tools/perf/tests/event_update.c
index a91fcefc9f67..482b89650bbe 100644
--- a/tools/perf/tests/event_update.c
+++ b/tools/perf/tests/event_update.c
@@ -34,10 +34,30 @@ static int process_event_scale(struct perf_tool *tool __maybe_unused,
 	return 0;
 }
 
+struct event_name {
+	struct perf_tool tool;
+	const char *name;
+};
+
+static int process_event_name(struct perf_tool *tool,
+			      union perf_event *event,
+			      struct perf_sample *sample __maybe_unused,
+			      struct machine *machine __maybe_unused)
+{
+	struct event_name *tmp = container_of(tool, struct event_name, tool);
+	struct event_update_event *ev = (struct event_update_event*) event;
+
+	TEST_ASSERT_VAL("wrong id", ev->id == 123);
+	TEST_ASSERT_VAL("wrong id", ev->type == PERF_EVENT_UPDATE__NAME);
+	TEST_ASSERT_VAL("wrong name", !strcmp(ev->data, tmp->name));
+	return 0;
+}
+
 int test__event_update(int subtest __maybe_unused)
 {
 	struct perf_evlist *evlist;
 	struct perf_evsel *evsel;
+	struct event_name tmp;
 
 	evlist = perf_evlist__new_default();
 	TEST_ASSERT_VAL("failed to get evlist", evlist);
@@ -59,5 +79,10 @@ int test__event_update(int subtest __maybe_unused)
 	TEST_ASSERT_VAL("failed to synthesize attr update scale",
 			!perf_event__synthesize_event_update_scale(NULL, evsel, process_event_scale));
 
+	tmp.name = perf_evsel__name(evsel);
+
+	TEST_ASSERT_VAL("failed to synthesize attr update name",
+			!perf_event__synthesize_event_update_name(&tmp.tool, evsel, process_event_name));
+
 	return 0;
 }
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 44198e8550e4..235196b575d6 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -311,6 +311,7 @@ struct attr_event {
 enum {
 	PERF_EVENT_UPDATE__UNIT  = 0,
 	PERF_EVENT_UPDATE__SCALE = 1,
+	PERF_EVENT_UPDATE__NAME  = 2,
 };
 
 struct event_update_event_scale {
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 30edb4ba258e..cd3d005a34af 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2743,6 +2743,24 @@ perf_event__synthesize_event_update_scale(struct perf_tool *tool,
 	return err;
 }
 
+int
+perf_event__synthesize_event_update_name(struct perf_tool *tool,
+					 struct perf_evsel *evsel,
+					 perf_event__handler_t process)
+{
+	struct event_update_event *ev;
+	size_t len = strlen(evsel->name);
+	int err;
+
+	ev = event_update_event__new(len + 1, PERF_EVENT_UPDATE__NAME, evsel->id[0]);
+	if (ev == NULL)
+		return -ENOMEM;
+
+	strncpy(ev->data, evsel->name, len);
+	err = process(tool, (union perf_event*) ev, NULL, NULL);
+	free(ev);
+	return err;
+}
 
 int perf_event__synthesize_attrs(struct perf_tool *tool,
 				   struct perf_session *session,
@@ -2825,6 +2843,9 @@ int perf_event__process_event_update(struct perf_tool *tool __maybe_unused,
 	case PERF_EVENT_UPDATE__UNIT:
 		evsel->unit = strdup(ev->data);
 		break;
+	case PERF_EVENT_UPDATE__NAME:
+		evsel->name = strdup(ev->data);
+		break;
 	case PERF_EVENT_UPDATE__SCALE:
 		ev_scale = (struct event_update_event_scale *) ev->data;
 		evsel->scale = ev_scale->scale;
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index fad04cbab666..51cf566a0835 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -111,6 +111,9 @@ int perf_event__synthesize_event_update_unit(struct perf_tool *tool,
 int perf_event__synthesize_event_update_scale(struct perf_tool *tool,
 					      struct perf_evsel *evsel,
 					      perf_event__handler_t process);
+int perf_event__synthesize_event_update_name(struct perf_tool *tool,
+					     struct perf_evsel *evsel,
+					     perf_event__handler_t process);
 int perf_event__process_attr(struct perf_tool *tool, union perf_event *event,
 			     struct perf_evlist **pevlist);
 int perf_event__process_event_update(struct perf_tool *tool __maybe_unused,
-- 
2.1.0


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

* [PATCH 22/43] perf tools: Add event_update event cpus type
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
                   ` (20 preceding siblings ...)
  2015-12-17 19:47 ` [PATCH 21/43] perf tools: Add event_update event name type Arnaldo Carvalho de Melo
@ 2015-12-17 19:47 ` Arnaldo Carvalho de Melo
  2015-12-17 19:47 ` [PATCH 23/43] perf tools: Add perf_event__fprintf_event_update function Arnaldo Carvalho de Melo
                   ` (21 subsequent siblings)
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:47 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

Adding the cpumask 'event update' event, that stores/transfer the
cpumask for a event.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Kan Liang <kan.liang@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1445784728-21732-25-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/tests/event_update.c | 29 ++++++++++++++++++++++++++++
 tools/perf/util/event.h         |  5 +++++
 tools/perf/util/header.c        | 42 +++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/header.h        |  3 +++
 4 files changed, 79 insertions(+)

diff --git a/tools/perf/tests/event_update.c b/tools/perf/tests/event_update.c
index 482b89650bbe..012eab5d1df1 100644
--- a/tools/perf/tests/event_update.c
+++ b/tools/perf/tests/event_update.c
@@ -53,6 +53,29 @@ static int process_event_name(struct perf_tool *tool,
 	return 0;
 }
 
+static int process_event_cpus(struct perf_tool *tool __maybe_unused,
+			      union perf_event *event,
+			      struct perf_sample *sample __maybe_unused,
+			      struct machine *machine __maybe_unused)
+{
+	struct event_update_event *ev = (struct event_update_event*) event;
+	struct event_update_event_cpus *ev_data;
+	struct cpu_map *map;
+
+	ev_data = (struct event_update_event_cpus*) ev->data;
+
+	map = cpu_map__new_data(&ev_data->cpus);
+
+	TEST_ASSERT_VAL("wrong id", ev->id == 123);
+	TEST_ASSERT_VAL("wrong type", ev->type == PERF_EVENT_UPDATE__CPUS);
+	TEST_ASSERT_VAL("wrong cpus", map->nr == 3);
+	TEST_ASSERT_VAL("wrong cpus", map->map[0] == 1);
+	TEST_ASSERT_VAL("wrong cpus", map->map[1] == 2);
+	TEST_ASSERT_VAL("wrong cpus", map->map[2] == 3);
+	cpu_map__put(map);
+	return 0;
+}
+
 int test__event_update(int subtest __maybe_unused)
 {
 	struct perf_evlist *evlist;
@@ -84,5 +107,11 @@ int test__event_update(int subtest __maybe_unused)
 	TEST_ASSERT_VAL("failed to synthesize attr update name",
 			!perf_event__synthesize_event_update_name(&tmp.tool, evsel, process_event_name));
 
+	evsel->own_cpus = cpu_map__new("1,2,3");
+
+	TEST_ASSERT_VAL("failed to synthesize attr update cpus",
+			!perf_event__synthesize_event_update_cpus(&tmp.tool, evsel, process_event_cpus));
+
+	cpu_map__put(evsel->own_cpus);
 	return 0;
 }
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 235196b575d6..b7ffb7ee9971 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -312,6 +312,11 @@ enum {
 	PERF_EVENT_UPDATE__UNIT  = 0,
 	PERF_EVENT_UPDATE__SCALE = 1,
 	PERF_EVENT_UPDATE__NAME  = 2,
+	PERF_EVENT_UPDATE__CPUS  = 3,
+};
+
+struct event_update_event_cpus {
+	struct cpu_map_data cpus;
 };
 
 struct event_update_event_scale {
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index cd3d005a34af..79d3eb984db7 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2762,6 +2762,38 @@ perf_event__synthesize_event_update_name(struct perf_tool *tool,
 	return err;
 }
 
+int
+perf_event__synthesize_event_update_cpus(struct perf_tool *tool,
+					struct perf_evsel *evsel,
+					perf_event__handler_t process)
+{
+	size_t size = sizeof(struct event_update_event);
+	struct event_update_event *ev;
+	int max, err;
+	u16 type;
+
+	if (!evsel->own_cpus)
+		return 0;
+
+	ev = cpu_map_data__alloc(evsel->own_cpus, &size, &type, &max);
+	if (!ev)
+		return -ENOMEM;
+
+	ev->header.type = PERF_RECORD_EVENT_UPDATE;
+	ev->header.size = (u16)size;
+	ev->type = PERF_EVENT_UPDATE__CPUS;
+	ev->id   = evsel->id[0];
+
+	cpu_map_data__synthesize((struct cpu_map_data *) ev->data,
+				 evsel->own_cpus,
+				 type, max);
+
+	err = process(tool, (union perf_event*) ev, NULL, NULL);
+	free(ev);
+	return err;
+}
+
+
 int perf_event__synthesize_attrs(struct perf_tool *tool,
 				   struct perf_session *session,
 				   perf_event__handler_t process)
@@ -2827,8 +2859,10 @@ int perf_event__process_event_update(struct perf_tool *tool __maybe_unused,
 {
 	struct event_update_event *ev = &event->event_update;
 	struct event_update_event_scale *ev_scale;
+	struct event_update_event_cpus *ev_cpus;
 	struct perf_evlist *evlist;
 	struct perf_evsel *evsel;
+	struct cpu_map *map;
 
 	if (!pevlist || *pevlist == NULL)
 		return -EINVAL;
@@ -2849,6 +2883,14 @@ int perf_event__process_event_update(struct perf_tool *tool __maybe_unused,
 	case PERF_EVENT_UPDATE__SCALE:
 		ev_scale = (struct event_update_event_scale *) ev->data;
 		evsel->scale = ev_scale->scale;
+	case PERF_EVENT_UPDATE__CPUS:
+		ev_cpus = (struct event_update_event_cpus *) ev->data;
+
+		map = cpu_map__new_data(&ev_cpus->cpus);
+		if (map)
+			evsel->own_cpus = map;
+		else
+			pr_err("failed to get event_update cpus\n");
 	default:
 		break;
 	}
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 51cf566a0835..a1bc0c5706a3 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -114,6 +114,9 @@ int perf_event__synthesize_event_update_scale(struct perf_tool *tool,
 int perf_event__synthesize_event_update_name(struct perf_tool *tool,
 					     struct perf_evsel *evsel,
 					     perf_event__handler_t process);
+int perf_event__synthesize_event_update_cpus(struct perf_tool *tool,
+					     struct perf_evsel *evsel,
+					     perf_event__handler_t process);
 int perf_event__process_attr(struct perf_tool *tool, union perf_event *event,
 			     struct perf_evlist **pevlist);
 int perf_event__process_event_update(struct perf_tool *tool __maybe_unused,
-- 
2.1.0


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

* [PATCH 23/43] perf tools: Add perf_event__fprintf_event_update function
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
                   ` (21 preceding siblings ...)
  2015-12-17 19:47 ` [PATCH 22/43] perf tools: Add event_update event cpus type Arnaldo Carvalho de Melo
@ 2015-12-17 19:47 ` Arnaldo Carvalho de Melo
  2015-12-17 19:47 ` [PATCH 24/43] perf report: Display newly added events in raw dump Arnaldo Carvalho de Melo
                   ` (20 subsequent siblings)
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:47 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

To display a 'event update' event for raw dump.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Kan Liang <kan.liang@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1445784728-21732-26-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/header.c | 38 ++++++++++++++++++++++++++++++++++++++
 tools/perf/util/header.h |  1 +
 2 files changed, 39 insertions(+)

diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 79d3eb984db7..49676c14c8ae 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2793,6 +2793,44 @@ perf_event__synthesize_event_update_cpus(struct perf_tool *tool,
 	return err;
 }
 
+size_t perf_event__fprintf_event_update(union perf_event *event, FILE *fp)
+{
+	struct event_update_event *ev = &event->event_update;
+	struct event_update_event_scale *ev_scale;
+	struct event_update_event_cpus *ev_cpus;
+	struct cpu_map *map;
+	size_t ret;
+
+	ret = fprintf(fp, "\n... id:    %" PRIu64 "\n", ev->id);
+
+	switch (ev->type) {
+	case PERF_EVENT_UPDATE__SCALE:
+		ev_scale = (struct event_update_event_scale *) ev->data;
+		ret += fprintf(fp, "... scale: %f\n", ev_scale->scale);
+		break;
+	case PERF_EVENT_UPDATE__UNIT:
+		ret += fprintf(fp, "... unit:  %s\n", ev->data);
+		break;
+	case PERF_EVENT_UPDATE__NAME:
+		ret += fprintf(fp, "... name:  %s\n", ev->data);
+		break;
+	case PERF_EVENT_UPDATE__CPUS:
+		ev_cpus = (struct event_update_event_cpus *) ev->data;
+		ret += fprintf(fp, "... ");
+
+		map = cpu_map__new_data(&ev_cpus->cpus);
+		if (map)
+			ret += cpu_map__fprintf(map, fp);
+		else
+			ret += fprintf(fp, "failed to get cpus\n");
+		break;
+	default:
+		ret += fprintf(fp, "... unknown type\n");
+		break;
+	}
+
+	return ret;
+}
 
 int perf_event__synthesize_attrs(struct perf_tool *tool,
 				   struct perf_session *session,
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index a1bc0c5706a3..710deecf8f80 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -122,6 +122,7 @@ int perf_event__process_attr(struct perf_tool *tool, union perf_event *event,
 int perf_event__process_event_update(struct perf_tool *tool __maybe_unused,
 				     union perf_event *event,
 				     struct perf_evlist **pevlist);
+size_t perf_event__fprintf_event_update(union perf_event *event, FILE *fp);
 
 int perf_event__synthesize_tracing_data(struct perf_tool *tool,
 					int fd, struct perf_evlist *evlist,
-- 
2.1.0


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

* [PATCH 24/43] perf report: Display newly added events in raw dump
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
                   ` (22 preceding siblings ...)
  2015-12-17 19:47 ` [PATCH 23/43] perf tools: Add perf_event__fprintf_event_update function Arnaldo Carvalho de Melo
@ 2015-12-17 19:47 ` Arnaldo Carvalho de Melo
  2015-12-17 19:47 ` [PATCH 25/43] perf tools: Introduce stat perf.data header feature Arnaldo Carvalho de Melo
                   ` (19 subsequent siblings)
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:47 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

The 'perf report -D' command will now display detailed output for these
newly added events:

  event_update
  thread_map
  cpu_map
  stat
  stat_config
  stat_round

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Kan Liang <kan.liang@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1445784728-21732-27-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/session.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 49e5cdc4cc5a..a90c74b67e43 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -17,6 +17,7 @@
 #include "asm/bug.h"
 #include "auxtrace.h"
 #include "thread-stack.h"
+#include "stat.h"
 
 static int perf_session__deliver_event(struct perf_session *session,
 				       union perf_event *event,
@@ -210,6 +211,9 @@ static int process_event_synth_event_update_stub(struct perf_tool *tool __maybe_
 						 struct perf_evlist **pevlist
 						 __maybe_unused)
 {
+	if (dump_trace)
+		perf_event__fprintf_event_update(event, stdout);
+
 	dump_printf(": unhandled!\n");
 	return 0;
 }
@@ -311,6 +315,9 @@ int process_event_thread_map_stub(struct perf_tool *tool __maybe_unused,
 				  union perf_event *event __maybe_unused,
 				  struct perf_session *session __maybe_unused)
 {
+	if (dump_trace)
+		perf_event__fprintf_thread_map(event, stdout);
+
 	dump_printf(": unhandled!\n");
 	return 0;
 }
@@ -320,6 +327,9 @@ int process_event_cpu_map_stub(struct perf_tool *tool __maybe_unused,
 			       union perf_event *event __maybe_unused,
 			       struct perf_session *session __maybe_unused)
 {
+	if (dump_trace)
+		perf_event__fprintf_cpu_map(event, stdout);
+
 	dump_printf(": unhandled!\n");
 	return 0;
 }
@@ -329,6 +339,9 @@ int process_event_stat_config_stub(struct perf_tool *tool __maybe_unused,
 				   union perf_event *event __maybe_unused,
 				   struct perf_session *session __maybe_unused)
 {
+	if (dump_trace)
+		perf_event__fprintf_stat_config(event, stdout);
+
 	dump_printf(": unhandled!\n");
 	return 0;
 }
@@ -338,6 +351,9 @@ static int process_stat_stub(struct perf_tool *tool __maybe_unused,
 			     struct perf_session *perf_session
 			     __maybe_unused)
 {
+	if (dump_trace)
+		perf_event__fprintf_stat(event, stdout);
+
 	dump_printf(": unhandled!\n");
 	return 0;
 }
@@ -347,6 +363,9 @@ static int process_stat_round_stub(struct perf_tool *tool __maybe_unused,
 				   struct perf_session *perf_session
 				   __maybe_unused)
 {
+	if (dump_trace)
+		perf_event__fprintf_stat_round(event, stdout);
+
 	dump_printf(": unhandled!\n");
 	return 0;
 }
-- 
2.1.0


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

* [PATCH 25/43] perf tools: Introduce stat perf.data header feature
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
                   ` (23 preceding siblings ...)
  2015-12-17 19:47 ` [PATCH 24/43] perf report: Display newly added events in raw dump Arnaldo Carvalho de Melo
@ 2015-12-17 19:47 ` Arnaldo Carvalho de Melo
  2015-12-17 19:47 ` [PATCH 26/43] perf stat record: Add record command Arnaldo Carvalho de Melo
                   ` (18 subsequent siblings)
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:47 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

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

It's needed so that the report tools (report/script) can differentiate
sampling data from counting data, because they need to be treated in a
different way.

In the future it might be used to store the version of the stat storage
system used.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Kan Liang <kan.liang@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1445784728-21732-28-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 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 1435ef6265b6..9c5cdc2c4471 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -452,6 +452,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 49676c14c8ae..f50b7235ecb6 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 710deecf8f80..cff9892452ee 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.1.0


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

* [PATCH 26/43] perf stat record: Add record command
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
                   ` (24 preceding siblings ...)
  2015-12-17 19:47 ` [PATCH 25/43] perf tools: Introduce stat perf.data header feature Arnaldo Carvalho de Melo
@ 2015-12-17 19:47 ` Arnaldo Carvalho de Melo
  2015-12-17 19:47 ` [PATCH 27/43] perf stat record: Initialize record features Arnaldo Carvalho de Melo
                   ` (17 subsequent siblings)
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:47 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

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

The record command could be specified anywhere among stat options. All
stat command options are valid for stat record command with '-o' option
exception. If specified for record command it denotes the perf data file
name.

Committer note:

Set sample_type to PERF_SAMPLE_IDENTIFIER, which should be harmless
while avoiding that older tools show confusing messages, for instance,
with sample_type = 0, we get:

  $ perf stat record usleep 1

   Performance counter stats for 'usleep 1':

          0.630237      task-clock (msec)         #    0.528 CPUs utilized
                 1      context-switches          #    0.002 M/sec
                 0      cpu-migrations            #    0.000 K/sec
                52      page-faults               #    0.083 M/sec
           978,312      cycles                    #    1.552 GHz
           671,931      stalled-cycles-frontend   #   68.68% frontend cycles idle
   <not supported>      stalled-cycles-backend
           646,379      instructions              #    0.66  insns per cycle
                                                  #    1.04  stalled cycles per insn
           131,046      branches                  #  207.931 M/sec
             7,073      branch-misses             #    5.40% of all branches

       0.001193240 seconds time elapsed

  $ oldperf evlist
  WARNING: The perf.data file's data size field is 0 which is unexpected.
  Was the 'perf record' command properly terminated?
  non matching sample_type
  $

While with sample_type set to PERF_SAMPLE_IDENTIFIER, after we re-run 'perf
stat record usleep' we get:

  $ oldperf evlist
  WARNING: The perf.data file's data size field is 0 which is unexpected.
  Was the 'perf record' command properly terminated?
  task-clock
  context-switches
  cpu-migrations
  page-faults
  cycles
  stalled-cycles-frontend
  stalled-cycles-backend
  instructions
  branches
  branch-misses
  $

Which at least shows the names of the events in the perf.data file.

Additionally, such files, when passed to 'perf report' will produce:

  $ oldperf report --stdio
  WARNING: The perf.data file's data size field is 0 which is unexpected.
  Was the 'perf record' command properly terminated?
  Warning:
  Kernel address maps (/proc/{kallsyms,modules}) were restricted.

  Check /proc/sys/kernel/kptr_restrict before running 'perf record'.

  As no suitable kallsyms nor vmlinux was found, kernel samples
  can't be resolved.

  Samples in kernel modules can't be resolved as well.

  Error:
  The perf.data file has no samples!
  # To display the perf.data header info, please use --header/--header-only options.
  #
  $

Which is confusing and can be solved by just adding the kernel mmap record,
which will also remove that warning about the data size field being equal to
zero, after generating the mmap record:

  $ perf stat record usleep 1

   Performance counter stats for 'usleep 1':

          0.600796      task-clock (msec)         #    0.478 CPUs utilized
                 1      context-switches          #    0.002 M/sec
                 0      cpu-migrations            #    0.000 K/sec
                54      page-faults               #    0.090 M/sec
           886,844      cycles                    #    1.476 GHz
           582,169      stalled-cycles-frontend   #   65.65% frontend cycles idle
   <not supported>      stalled-cycles-backend
           638,344      instructions              #    0.72  insns per cycle
                                                  #    0.91  stalled cycles per insn
           130,204      branches                  #  216.719 M/sec
             7,500      branch-misses             #    5.76% of all branches

       0.001255897 seconds time elapsed

  $ oldperf evlist
  task-clock
  context-switches
  cpu-migrations
  page-faults
  cycles
  stalled-cycles-frontend
  stalled-cycles-backend
  instructions
  branches
  branch-misses
  $ oldperf report --stdio
  Error:
  The perf.data file has no samples!
  # To display the perf.data header info, please use --header/--header-only options.
  #
  [acme@zoo linux]$

No warnings, sensible output about what are the events in the perf.data file and also
a "file has no samples" message, which indeed it doesn't.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Tested-by: Kan Liang <kan.liang@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: htp://lkml.kernel.org/r/1446734469-11352-3-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/Documentation/perf-stat.txt |  12 ++++
 tools/perf/builtin-stat.c              | 120 +++++++++++++++++++++++++++++++--
 2 files changed, 128 insertions(+), 4 deletions(-)

diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 4e074a660826..70eee1c2c444 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=::
@@ -159,6 +162,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 bbf42eefd5e5..af2a3bf659f7 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>
@@ -126,6 +127,16 @@ static bool			append_file;
 static const char		*output_name;
 static int			output_fd;
 
+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 = {
@@ -166,7 +177,11 @@ static int create_perf_stat_counter(struct perf_evsel *evsel)
 	 * like tracepoints. Clear it up for counting.
 	 */
 	attr->sample_period = 0;
-	attr->sample_type   = 0;
+	/*
+	 * But set sample_type to PERF_SAMPLE_IDENTIFIER, which should be harmless
+	 * while avoiding that older tools show confusing messages.
+	 */
+	attr->sample_type   = PERF_SAMPLE_IDENTIFIER;
 
 	/*
 	 * Disabling all counters initially, they will be enabled
@@ -202,6 +217,26 @@ static inline int nsec_counter(struct perf_evsel *evsel)
 	return 0;
 }
 
+static int perf_stat__write(struct perf_stat *stat, void *bf, size_t size)
+{
+	if (perf_data_file__write(stat->session->file, bf, size) < 0) {
+		pr_err("failed to write perf data, error: %m\n");
+		return -1;
+	}
+
+	stat->bytes_written += size;
+	return 0;
+}
+
+static int process_synthesized_event(struct perf_tool *tool,
+				     union perf_event *event,
+				     struct perf_sample *sample __maybe_unused,
+				     struct machine *machine __maybe_unused)
+{
+	struct perf_stat *stat = (void *)tool;
+	return perf_stat__write(stat, event, event->header.size);
+}
+
 /*
  * Read out the results of a single counter:
  * do not aggregate counts across CPUs in system-wide mode
@@ -361,6 +396,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:
 	 */
@@ -1261,6 +1305,38 @@ 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;
+
+	argc = parse_options(argc, argv, stat_options, record_usage,
+			     PARSE_OPT_STOP_AT_NON_OPTION);
+
+	if (output_name)
+		file->path = output_name;
+
+	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)
 {
 	const char * const stat_usage[] = {
@@ -1271,6 +1347,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, "");
 
@@ -1278,12 +1355,22 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 	if (evsel_list == NULL)
 		return -ENOMEM;
 
-	argc = parse_options(argc, argv, stat_options, stat_usage,
-		PARSE_OPT_STOP_AT_NON_OPTION);
+	argc = parse_options_subcommand(argc, argv, stat_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;
 
-	if (output_name && strcmp(output_name, "-"))
+	/*
+	 * For record command the -o is already taken care of.
+	 */
+	if (!STAT_RECORD && output_name && strcmp(output_name, "-"))
 		output = NULL;
 
 	if (output_name && output_fd) {
@@ -1450,6 +1537,31 @@ 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) {
+		/*
+		 * We synthesize the kernel mmap record just so that older tools
+		 * don't emit warnings about not being able to resolve symbols
+		 * due to /proc/sys/kernel/kptr_restrict settings and instear provide
+		 * a saner message about no samples being in the perf.data file.
+		 *
+		 * This also serves to suppress a warning about f_header.data.size == 0
+		 * in header.c.  -acme
+		 */
+		int fd = perf_data_file__fd(&perf_stat.file);
+		int err = perf_event__synthesize_kernel_mmap((void *)&perf_stat,
+							     process_synthesized_event,
+							     &perf_stat.session->machines.host);
+		if (err) {
+			pr_warning("Couldn't synthesize the kernel mmap record, harmless, "
+				   "older tools may produce warnings about this file\n.");
+		}
+
+		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_stat__exit_aggr_mode();
 	perf_evlist__free_stats(evsel_list);
 out:
-- 
2.1.0


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

* [PATCH 27/43] perf stat record: Initialize record features
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
                   ` (25 preceding siblings ...)
  2015-12-17 19:47 ` [PATCH 26/43] perf stat record: Add record command Arnaldo Carvalho de Melo
@ 2015-12-17 19:47 ` Arnaldo Carvalho de Melo
  2015-12-17 19:47 ` [PATCH 28/43] perf stat record: Synthesize stat record data Arnaldo Carvalho de Melo
                   ` (16 subsequent siblings)
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:47 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

Disabling all non stat related features.

Also as we now enable STAT feature in the data file, adding code to
instruct session open to skip sample type checking for stat data files.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Tested-by: Kan Liang <kan.liang@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1446734469-11352-4-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 15 +++++++++++++++
 tools/perf/util/session.c |  3 +++
 2 files changed, 18 insertions(+)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index af2a3bf659f7..c9c896a94fee 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1310,6 +1310,19 @@ static const char * const recort_usage[] = {
 	NULL,
 };
 
+static void init_features(struct perf_session *session)
+{
+	int feat;
+
+	for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
+		perf_header__set_feat(&session->header, feat);
+
+	perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
+	perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
+	perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
+	perf_header__clear_feat(&session->header, HEADER_AUXTRACE);
+}
+
 static int __cmd_record(int argc, const char **argv)
 {
 	struct perf_session *session;
@@ -1331,6 +1344,8 @@ static int __cmd_record(int argc, const char **argv)
 	if (perf_stat.file.is_pipe)
 		return -EINVAL;
 
+	init_features(session);
+
 	session->evlist   = evsel_list;
 	perf_stat.session = session;
 	perf_stat.record  = true;
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index a90c74b67e43..d5636ba94b20 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -37,6 +37,9 @@ static int perf_session__open(struct perf_session *session)
 	if (perf_data_file__is_pipe(file))
 		return 0;
 
+	if (perf_header__has_feat(&session->header, HEADER_STAT))
+		return 0;
+
 	if (!perf_evlist__valid_sample_type(session->evlist)) {
 		pr_err("non matching sample_type\n");
 		return -1;
-- 
2.1.0


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

* [PATCH 28/43] perf stat record: Synthesize stat record data
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
                   ` (26 preceding siblings ...)
  2015-12-17 19:47 ` [PATCH 27/43] perf stat record: Initialize record features Arnaldo Carvalho de Melo
@ 2015-12-17 19:47 ` Arnaldo Carvalho de Melo
  2015-12-17 19:47 ` [PATCH 29/43] perf evlist: Export id_add_fd() Arnaldo Carvalho de Melo
                   ` (15 subsequent siblings)
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:47 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

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

Committer note:

New records generated on a perf.data file with this patch:

  $ perf report -D | grep PERF_RECORD_
  0x568 [0x28]: PERF_RECORD_THREAD_MAP nr: 1 thread: 29097
  0x590 [0x12]: PERF_RECORD_CPU_MAP nr: 1 cpu: 65535
  0x5a2 [0x40]: PERF_RECORD_STAT_CONFIG
  $

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Tested-by: Kan Liang <kan.liang@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1446734469-11352-5-git-send-email-jolsa@kernel.org
[ Adjusted wrt kernel PERF_RECORD_MMAP added when introducing 'perf stat record' ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 56 ++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 43 insertions(+), 13 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index c9c896a94fee..45bf4d2caebe 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -217,26 +217,20 @@ static inline int nsec_counter(struct perf_evsel *evsel)
 	return 0;
 }
 
-static int perf_stat__write(struct perf_stat *stat, void *bf, size_t size)
+static int process_synthesized_event(struct perf_tool *tool __maybe_unused,
+				     union perf_event *event,
+				     struct perf_sample *sample __maybe_unused,
+				     struct machine *machine __maybe_unused)
 {
-	if (perf_data_file__write(stat->session->file, bf, size) < 0) {
+	if (perf_data_file__write(&perf_stat.file, event, event->header.size) < 0) {
 		pr_err("failed to write perf data, error: %m\n");
 		return -1;
 	}
 
-	stat->bytes_written += size;
+	perf_stat.bytes_written += event->header.size;
 	return 0;
 }
 
-static int process_synthesized_event(struct perf_tool *tool,
-				     union perf_event *event,
-				     struct perf_sample *sample __maybe_unused,
-				     struct machine *machine __maybe_unused)
-{
-	struct perf_stat *stat = (void *)tool;
-	return perf_stat__write(stat, event, event->header.size);
-}
-
 /*
  * Read out the results of a single counter:
  * do not aggregate counts across CPUs in system-wide mode
@@ -323,6 +317,35 @@ static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *inf
 	workload_exec_errno = info->si_value.sival_int;
 }
 
+static int perf_stat_synthesize_config(void)
+{
+	int err;
+
+	err = perf_event__synthesize_thread_map2(NULL, evsel_list->threads,
+						process_synthesized_event,
+						NULL);
+	if (err < 0) {
+		pr_err("Couldn't synthesize thread map.\n");
+		return err;
+	}
+
+	err = perf_event__synthesize_cpu_map(NULL, evsel_list->cpus,
+					     process_synthesized_event, NULL);
+	if (err < 0) {
+		pr_err("Couldn't synthesize thread map.\n");
+		return err;
+	}
+
+	err = perf_event__synthesize_stat_config(NULL, &stat_config,
+						 process_synthesized_event, NULL);
+	if (err < 0) {
+		pr_err("Couldn't synthesize config.\n");
+		return err;
+	}
+
+	return 0;
+}
+
 static int __run_perf_stat(int argc, const char **argv)
 {
 	int interval = stat_config.interval;
@@ -403,6 +426,10 @@ static int __run_perf_stat(int argc, const char **argv)
 						 fd, false);
 		if (err < 0)
 			return err;
+
+		err = perf_stat_synthesize_config();
+		if (err < 0)
+			return err;
 	}
 
 	/*
@@ -1560,7 +1587,10 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 		 * a saner message about no samples being in the perf.data file.
 		 *
 		 * This also serves to suppress a warning about f_header.data.size == 0
-		 * in header.c.  -acme
+		 * in header.c at the moment 'perf stat record' gets introduced, which
+		 * is not really needed once we start adding the stat specific PERF_RECORD_
+		 * records, but the need to suppress the kptr_restrict messages in older
+		 * tools remain  -acme
 		 */
 		int fd = perf_data_file__fd(&perf_stat.file);
 		int err = perf_event__synthesize_kernel_mmap((void *)&perf_stat,
-- 
2.1.0


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

* [PATCH 29/43] perf evlist: Export id_add_fd()
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
                   ` (27 preceding siblings ...)
  2015-12-17 19:47 ` [PATCH 28/43] perf stat record: Synthesize stat record data Arnaldo Carvalho de Melo
@ 2015-12-17 19:47 ` Arnaldo Carvalho de Melo
  2015-12-17 19:47 ` [PATCH 30/43] perf stat record: Store events IDs in perf data file Arnaldo Carvalho de Melo
                   ` (14 subsequent siblings)
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:47 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

Will be used to storing the event IDs in evlist object so it get stored
into perf.data file.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Kan Liang <kan.liang@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1446734469-11352-6-git-send-email-jolsa@kernel.org
[ Split from the patch storing the ids in the perf.data file ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/evlist.c | 6 +++---
 tools/perf/util/evlist.h | 3 +++
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 8c44aadb9810..b9eac0daa0b9 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 a459fe71b452..139a50038097 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.1.0


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

* [PATCH 30/43] perf stat record: Store events IDs in perf data file
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
                   ` (28 preceding siblings ...)
  2015-12-17 19:47 ` [PATCH 29/43] perf evlist: Export id_add_fd() Arnaldo Carvalho de Melo
@ 2015-12-17 19:47 ` Arnaldo Carvalho de Melo
  2015-12-17 19:47 ` [PATCH 31/43] perf stat record: Add pipe support for record command Arnaldo Carvalho de Melo
                   ` (13 subsequent siblings)
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:47 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

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

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Kan Liang <kan.liang@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1446734469-11352-6-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 45bf4d2caebe..39d0c30f0f59 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -346,6 +346,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;
@@ -410,6 +442,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)) {
-- 
2.1.0


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

* [PATCH 31/43] perf stat record: Add pipe support for record command
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
                   ` (29 preceding siblings ...)
  2015-12-17 19:47 ` [PATCH 30/43] perf stat record: Store events IDs in perf data file Arnaldo Carvalho de Melo
@ 2015-12-17 19:47 ` Arnaldo Carvalho de Melo
  2015-12-17 19:47 ` [PATCH 32/43] perf stat record: Write stat events on record Arnaldo Carvalho de Melo
                   ` (12 subsequent siblings)
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:47 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

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

Committer note:

Before this patch:

  $ perf stat record -o - usleep 1 | perf report -i -
  incompatible file format (rerun with -v to learn more)
  $ perf stat record -o - usleep 1 | perf script -i -
  incompatible file format (rerun with -v to learn more)
  $ ls -la perf.data
  ls: cannot access perf.data: No such file or directory
  $

After:

  $ perf stat record -o - usleep 1 | perf report -i -
  # To display the perf.data header info, please use
  # --header/--header-only options.
  #
  Error:
  The - file has no samples!
  $ perf stat record -o - usleep 1 | perf script -i -
  Display of symbols requested but neither sample IP nor sample address
  is selected. Hence, no addresses to convert to symbols.
  0 [0x80]: failed to process type: 64
  $ ls -la perf.data
  ls: cannot access perf.data: No such file or directory
  $

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Tested-by: Kan Liang <kan.liang@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1446734469-11352-7-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 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 39d0c30f0f59..8a2f9ce677e7 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -317,10 +317,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);
@@ -388,6 +397,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;
@@ -398,7 +408,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;
@@ -457,12 +467,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;
 	}
@@ -970,6 +985,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
@@ -1402,10 +1421,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;
@@ -1636,8 +1651,10 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 				   "older tools may produce warnings about this file\n.");
 		}
 
-		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.1.0


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

* [PATCH 32/43] perf stat record: Write stat events on record
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
                   ` (30 preceding siblings ...)
  2015-12-17 19:47 ` [PATCH 31/43] perf stat record: Add pipe support for record command Arnaldo Carvalho de Melo
@ 2015-12-17 19:47 ` Arnaldo Carvalho de Melo
  2015-12-17 19:47 ` [PATCH 33/43] perf stat record: Write stat round " Arnaldo Carvalho de Melo
                   ` (11 subsequent siblings)
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:47 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

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

Committer note:

After the patch:

  $ perf stat record usleep 1

   Performance counter stats for 'usleep 1':

          0.598006      task-clock (msec)         #    0.484 CPUs utilized
                 1      context-switches          #    0.002 M/sec
                 0      cpu-migrations            #    0.000 K/sec
                52      page-faults               #    0.087 M/sec
           882,744      cycles                    #    1.476 GHz
           581,416      stalled-cycles-frontend   #   65.86% frontend cycles idle
   <not supported>      stalled-cycles-backend
           636,479      instructions              #    0.72  insns per cycle
                                                  #    0.91  stalled cycles per insn
           129,334      branches                  #  216.275 M/sec
             7,512      branch-misses             #    5.81% of all branches

       0.001235157 seconds time elapsed

  $ oldperf evlist
  task-clock
  context-switches
  cpu-migrations
  page-faults
  cycles
  stalled-cycles-frontend
  stalled-cycles-backend
  instructions
  branches
  branch-misses
  $ oldperf report --stdio
  Error:
  The perf.data file has no samples!
  # To display the perf.data header info, please use --header/--header-only options.
  #
  $ perf report -D | grep PERF_RECORD
  0x5b0 [0x28]: PERF_RECORD_THREAD_MAP nr: 1 thread: 5504
  0x5d8 [0x12]: PERF_RECORD_CPU_MAP nr: 1 cpu: 65535
  0x5ea [0x40]: PERF_RECORD_STAT_CONFIG
  0x62a [0x30]: PERF_RECORD_STAT
  0x65a [0x30]: PERF_RECORD_STAT
  0x68a [0x30]: PERF_RECORD_STAT
  0x6ba [0x30]: PERF_RECORD_STAT
  0x6ea [0x30]: PERF_RECORD_STAT
  0x71a [0x30]: PERF_RECORD_STAT
  0x74a [0x30]: PERF_RECORD_STAT
  0x77a [0x30]: PERF_RECORD_STAT
  0x7aa [0x30]: PERF_RECORD_STAT
  -1 -1 0x7da [0x40]: PERF_RECORD_MMAP -1/0: [0xffffffff81000000(0x1f000000) @ 0xffffffff81000000]: x [kernel.kallsyms]_text
  $

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Kan Liang <kan.liang@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1446734469-11352-8-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

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


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

* [PATCH 33/43] perf stat record: Write stat round events on record
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
                   ` (31 preceding siblings ...)
  2015-12-17 19:47 ` [PATCH 32/43] perf stat record: Write stat events on record Arnaldo Carvalho de Melo
@ 2015-12-17 19:47 ` Arnaldo Carvalho de Melo
  2015-12-17 19:47 ` [PATCH 34/43] perf stat record: Do not allow record with multiple runs mode Arnaldo Carvalho de Melo
                   ` (10 subsequent siblings)
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:47 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

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

Committer note:

After the patch:

  $ perf report -D | grep PERF_RECORD | grep ROUND
  0x852 [0x18]: PERF_RECORD_STAT_ROUND
  $

Reported-by: Kan Liang <kan.liang@intel.com>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1446734469-11352-9-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 32aa2ea1c553..fcece42c2611 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -231,6 +231,16 @@ static int process_synthesized_event(struct perf_tool *tool __maybe_unused,
 	return 0;
 }
 
+static int write_stat_round_event(u64 time, u64 type)
+{
+	return perf_event__synthesize_stat_round(NULL, time, type,
+						 process_synthesized_event,
+						 NULL);
+}
+
+#define WRITE_STAT_ROUND_EVENT(time, interval) \
+	write_stat_round_event(time, PERF_STAT_ROUND_TYPE__ ## interval)
+
 #define SID(e, x, y) xyarray__entry(e->sample_id, x, y)
 
 static int
@@ -306,6 +316,11 @@ static void process_interval(void)
 	clock_gettime(CLOCK_MONOTONIC, &ts);
 	diff_timespec(&rs, &ts, &ref_time);
 
+	if (STAT_RECORD) {
+		if (WRITE_STAT_ROUND_EVENT(rs.tv_sec * NSECS_PER_SEC + rs.tv_nsec, INTERVAL))
+			pr_err("failed to write stat round event\n");
+	}
+
 	print_counters(&rs, 0, NULL);
 }
 
@@ -1670,6 +1685,11 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 				   "older tools may produce warnings about this file\n.");
 		}
 
+		if (!interval) {
+			if (WRITE_STAT_ROUND_EVENT(walltime_nsecs_stats.max, FINAL))
+				pr_err("failed to write stat round event\n");
+		}
+
 		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);
-- 
2.1.0


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

* [PATCH 34/43] perf stat record: Do not allow record with multiple runs mode
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
                   ` (32 preceding siblings ...)
  2015-12-17 19:47 ` [PATCH 33/43] perf stat record: Write stat round " Arnaldo Carvalho de Melo
@ 2015-12-17 19:47 ` Arnaldo Carvalho de Melo
  2015-12-17 19:47 ` [PATCH 35/43] perf stat record: Synthesize event update events Arnaldo Carvalho de Melo
                   ` (9 subsequent siblings)
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:47 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

We currently don't support storing multiple session in perf.data,
so we can't allow -r option in stat record.

  $ perf stat -e cycles -r 2 record ls
  Cannot use -r option with perf stat record.

Committer note:

Before this patch we would a perf.data file such as:

  $ perf stat -e cycles -r 2 record ls
  <SNIP>

   Performance counter stats for 'ls' (2 runs):

         3,935,236      cycles

       0.002353261 seconds time elapsed                                          ( +-  4.76% )

  $ perf report -D | grep PERF_RECORD | grep ROUND
  0xf0 [0]: failed to process type: 16
  Error:
  failed to process sample
  $

Reported-by: Kan Liang <kan.liang@intel.com>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1446734469-11352-10-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index fcece42c2611..10f86a6d7b15 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1449,6 +1449,11 @@ static int __cmd_record(int argc, const char **argv)
 	if (output_name)
 		file->path = output_name;
 
+	if (run_count != 1 || forever) {
+		pr_err("Cannot use -r option with perf stat record.\n");
+		return -1;
+	}
+
 	session = perf_session__new(file, false, NULL);
 	if (session == NULL) {
 		pr_err("Perf session creation failed.\n");
-- 
2.1.0


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

* [PATCH 35/43] perf stat record: Synthesize event update events
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
                   ` (33 preceding siblings ...)
  2015-12-17 19:47 ` [PATCH 34/43] perf stat record: Do not allow record with multiple runs mode Arnaldo Carvalho de Melo
@ 2015-12-17 19:47 ` Arnaldo Carvalho de Melo
  2015-12-17 19:47 ` [PATCH 36/43] perf stat report: Add report command Arnaldo Carvalho de Melo
                   ` (8 subsequent siblings)
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:47 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

Synthesize other events stuff not carried within attr event - unit,
scale, name.

Reported-by: Kan Liang <kan.liang@intel.com>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1446734469-11352-11-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 59 insertions(+)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 10f86a6d7b15..575e2535ea03 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -351,8 +351,19 @@ static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *inf
 	workload_exec_errno = info->si_value.sival_int;
 }
 
+static bool has_unit(struct perf_evsel *counter)
+{
+	return counter->unit && *counter->unit;
+}
+
+static bool has_scale(struct perf_evsel *counter)
+{
+	return counter->scale != 1;
+}
+
 static int perf_stat_synthesize_config(bool is_pipe)
 {
+	struct perf_evsel *counter;
 	int err;
 
 	if (is_pipe) {
@@ -364,6 +375,54 @@ static int perf_stat_synthesize_config(bool is_pipe)
 		}
 	}
 
+	/*
+	 * Synthesize other events stuff not carried within
+	 * attr event - unit, scale, name
+	 */
+	evlist__for_each(evsel_list, counter) {
+		if (!counter->supported)
+			continue;
+
+		/*
+		 * Synthesize unit and scale only if it's defined.
+		 */
+		if (has_unit(counter)) {
+			err = perf_event__synthesize_event_update_unit(NULL, counter, process_synthesized_event);
+			if (err < 0) {
+				pr_err("Couldn't synthesize evsel unit.\n");
+				return err;
+			}
+		}
+
+		if (has_scale(counter)) {
+			err = perf_event__synthesize_event_update_scale(NULL, counter, process_synthesized_event);
+			if (err < 0) {
+				pr_err("Couldn't synthesize evsel scale.\n");
+				return err;
+			}
+		}
+
+		if (counter->own_cpus) {
+			err = perf_event__synthesize_event_update_cpus(NULL, counter, process_synthesized_event);
+			if (err < 0) {
+				pr_err("Couldn't synthesize evsel scale.\n");
+				return err;
+			}
+		}
+
+		/*
+		 * Name is needed only for pipe output,
+		 * perf.data carries event names.
+		 */
+		if (is_pipe) {
+			err = perf_event__synthesize_event_update_name(NULL, counter, process_synthesized_event);
+			if (err < 0) {
+				pr_err("Couldn't synthesize evsel name.\n");
+				return err;
+			}
+		}
+	}
+
 	err = perf_event__synthesize_thread_map2(NULL, evsel_list->threads,
 						process_synthesized_event,
 						NULL);
-- 
2.1.0


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

* [PATCH 36/43] perf stat report: Add report command
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
                   ` (34 preceding siblings ...)
  2015-12-17 19:47 ` [PATCH 35/43] perf stat record: Synthesize event update events Arnaldo Carvalho de Melo
@ 2015-12-17 19:47 ` Arnaldo Carvalho de Melo
  2015-12-17 19:47 ` [PATCH 37/43] perf stat report: Process cpu/threads maps Arnaldo Carvalho de Melo
                   ` (7 subsequent siblings)
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:47 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

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

Reported-by: Kan Liang <kan.liang@intel.com>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1446734469-11352-12-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/Documentation/perf-stat.txt | 12 +++++++
 tools/perf/builtin-stat.c              | 61 +++++++++++++++++++++++++++++++---
 2 files changed, 69 insertions(+), 4 deletions(-)

diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 70eee1c2c444..95f492828657 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -11,6 +11,7 @@ SYNOPSIS
 'perf stat' [-e <EVENT> | --event=EVENT] [-a] <command>
 'perf stat' [-e <EVENT> | --event=EVENT] [-a] -- <command> [<options>]
 'perf stat' [-e <EVENT> | --event=EVENT] [-a] record [-o file] -- <command> [<options>]
+'perf stat' report [-i file]
 
 DESCRIPTION
 -----------
@@ -26,6 +27,9 @@ OPTIONS
 record::
 	See STAT RECORD.
 
+report::
+	See STAT REPORT.
+
 -e::
 --event=::
 	Select the PMU event. Selection can be:
@@ -170,6 +174,14 @@ Stores stat data into perf data file.
 --output file::
 Output file name.
 
+STAT REPORT
+-----------
+Reads and reports stat data from perf data file.
+
+-i file::
+--input file::
+Input file name.
+
 
 EXAMPLES
 --------
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 575e2535ea03..abba49b847d2 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -60,6 +60,8 @@
 #include "util/thread_map.h"
 #include "util/counts.h"
 #include "util/session.h"
+#include "util/tool.h"
+#include "asm/bug.h"
 
 #include <stdlib.h>
 #include <sys/prctl.h>
@@ -132,6 +134,7 @@ struct perf_stat {
 	struct perf_data_file	 file;
 	struct perf_session	*session;
 	u64			 bytes_written;
+	struct perf_tool	 tool;
 };
 
 static struct perf_stat		perf_stat;
@@ -1041,8 +1044,8 @@ static void print_header(int argc, const char **argv)
 		else if (target.cpu_list)
 			fprintf(output, "\'CPU(s) %s", target.cpu_list);
 		else if (!target__has_task(&target)) {
-			fprintf(output, "\'%s", argv[0]);
-			for (i = 1; i < argc; i++)
+			fprintf(output, "\'%s", argv ? argv[0] : "pipe");
+			for (i = 1; argv && (i < argc); i++)
 				fprintf(output, " %s", argv[i]);
 		} else if (target.pid)
 			fprintf(output, "process id \'%s", target.pid);
@@ -1527,6 +1530,55 @@ static int __cmd_record(int argc, const char **argv)
 	return argc;
 }
 
+static const char * const report_usage[] = {
+	"perf stat report [<options>]",
+	NULL,
+};
+
+static struct perf_stat perf_stat = {
+	.tool = {
+		.attr		= perf_event__process_attr,
+	},
+};
+
+static int __cmd_report(int argc, const char **argv)
+{
+	struct perf_session *session;
+	const struct option options[] = {
+	OPT_STRING('i', "input", &input_name, "file", "input file name"),
+	OPT_END()
+	};
+	struct stat st;
+	int ret;
+
+	argc = parse_options(argc, argv, options, report_usage, 0);
+
+	if (!input_name || !strlen(input_name)) {
+		if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode))
+			input_name = "-";
+		else
+			input_name = "perf.data";
+	}
+
+	perf_stat.file.path = input_name;
+	perf_stat.file.mode = PERF_DATA_MODE_READ;
+
+	session = perf_session__new(&perf_stat.file, false, &perf_stat.tool);
+	if (session == NULL)
+		return -1;
+
+	perf_stat.session  = session;
+	stat_config.output = stderr;
+	evsel_list         = session->evlist;
+
+	ret = perf_session__process_events(session);
+	if (ret)
+		return ret;
+
+	perf_session__delete(session);
+	return 0;
+}
+
 int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 {
 	const char * const stat_usage[] = {
@@ -1537,7 +1589,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 	const char *mode;
 	FILE *output = stderr;
 	unsigned int interval;
-	const char * const stat_subcommands[] = { "record" };
+	const char * const stat_subcommands[] = { "record", "report" };
 
 	setlocale(LC_ALL, "");
 
@@ -1553,7 +1605,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 		argc = __cmd_record(argc, argv);
 		if (argc < 0)
 			return -1;
-	}
+	} else if (argc && !strncmp(argv[0], "rep", 3))
+		return __cmd_report(argc, argv);
 
 	interval = stat_config.interval;
 
-- 
2.1.0


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

* [PATCH 37/43] perf stat report: Process cpu/threads maps
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
                   ` (35 preceding siblings ...)
  2015-12-17 19:47 ` [PATCH 36/43] perf stat report: Add report command Arnaldo Carvalho de Melo
@ 2015-12-17 19:47 ` Arnaldo Carvalho de Melo
  2015-12-17 19:47 ` [PATCH 38/43] perf stat report: Process stat config event Arnaldo Carvalho de Melo
                   ` (6 subsequent siblings)
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:47 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

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

Reported-by: Kan Liang <kan.liang@intel.com>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1446734469-11352-13-git-send-email-jolsa@kernel.org
[ s/stat/st/g, s/time/tm/g parameters to fix 'already defined' build error with older distros (e.g. RHEL6.7) ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 66 +++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 64 insertions(+), 2 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index abba49b847d2..0a1cfdd70df0 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -135,6 +135,9 @@ struct perf_stat {
 	struct perf_session	*session;
 	u64			 bytes_written;
 	struct perf_tool	 tool;
+	bool			 maps_allocated;
+	struct cpu_map		*cpus;
+	struct thread_map	*threads;
 };
 
 static struct perf_stat		perf_stat;
@@ -234,9 +237,9 @@ static int process_synthesized_event(struct perf_tool *tool __maybe_unused,
 	return 0;
 }
 
-static int write_stat_round_event(u64 time, u64 type)
+static int write_stat_round_event(u64 tm, u64 type)
 {
-	return perf_event__synthesize_stat_round(NULL, time, type,
+	return perf_event__synthesize_stat_round(NULL, tm, type,
 						 process_synthesized_event,
 						 NULL);
 }
@@ -1530,6 +1533,63 @@ static int __cmd_record(int argc, const char **argv)
 	return argc;
 }
 
+static int set_maps(struct perf_stat *st)
+{
+	if (!st->cpus || !st->threads)
+		return 0;
+
+	if (WARN_ONCE(st->maps_allocated, "stats double allocation\n"))
+		return -EINVAL;
+
+	perf_evlist__set_maps(evsel_list, st->cpus, st->threads);
+
+	if (perf_evlist__alloc_stats(evsel_list, true))
+		return -ENOMEM;
+
+	st->maps_allocated = true;
+	return 0;
+}
+
+static
+int process_thread_map_event(struct perf_tool *tool __maybe_unused,
+			     union perf_event *event,
+			     struct perf_session *session __maybe_unused)
+{
+	struct perf_stat *st = container_of(tool, struct perf_stat, tool);
+
+	if (st->threads) {
+		pr_warning("Extra thread map event, ignoring.\n");
+		return 0;
+	}
+
+	st->threads = thread_map__new_event(&event->thread_map);
+	if (!st->threads)
+		return -ENOMEM;
+
+	return set_maps(st);
+}
+
+static
+int process_cpu_map_event(struct perf_tool *tool __maybe_unused,
+			  union perf_event *event,
+			  struct perf_session *session __maybe_unused)
+{
+	struct perf_stat *st = container_of(tool, struct perf_stat, tool);
+	struct cpu_map *cpus;
+
+	if (st->cpus) {
+		pr_warning("Extra cpu map event, ignoring.\n");
+		return 0;
+	}
+
+	cpus = cpu_map__new_data(&event->cpu_map.data);
+	if (!cpus)
+		return -ENOMEM;
+
+	st->cpus = cpus;
+	return set_maps(st);
+}
+
 static const char * const report_usage[] = {
 	"perf stat report [<options>]",
 	NULL,
@@ -1538,6 +1598,8 @@ static const char * const report_usage[] = {
 static struct perf_stat perf_stat = {
 	.tool = {
 		.attr		= perf_event__process_attr,
+		.thread_map	= process_thread_map_event,
+		.cpu_map	= process_cpu_map_event,
 	},
 };
 
-- 
2.1.0


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

* [PATCH 38/43] perf stat report: Process stat config event
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
                   ` (36 preceding siblings ...)
  2015-12-17 19:47 ` [PATCH 37/43] perf stat report: Process cpu/threads maps Arnaldo Carvalho de Melo
@ 2015-12-17 19:47 ` Arnaldo Carvalho de Melo
  2015-12-17 19:47 ` [PATCH 39/43] perf stat report: Add support to initialize aggr_map from file Arnaldo Carvalho de Melo
                   ` (5 subsequent siblings)
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:47 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

Adding processing of stat config event and initialize stat_config
object.

Reported-by: Kan Liang <kan.liang@intel.com>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1446734469-11352-14-git-send-email-jolsa@kernel.org
[ Renamed 'stat' parameter to 'st' to fix 'already defined' build error with older distros (e.g. RHEL6.7) ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 0a1cfdd70df0..1e5db50dab9e 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1533,6 +1533,15 @@ static int __cmd_record(int argc, const char **argv)
 	return argc;
 }
 
+static
+int process_stat_config_event(struct perf_tool *tool __maybe_unused,
+			      union perf_event *event,
+			      struct perf_session *session __maybe_unused)
+{
+	perf_event__read_stat_config(&stat_config, &event->stat_config);
+	return 0;
+}
+
 static int set_maps(struct perf_stat *st)
 {
 	if (!st->cpus || !st->threads)
@@ -1600,6 +1609,7 @@ static struct perf_stat perf_stat = {
 		.attr		= perf_event__process_attr,
 		.thread_map	= process_thread_map_event,
 		.cpu_map	= process_cpu_map_event,
+		.stat_config	= process_stat_config_event,
 	},
 };
 
-- 
2.1.0


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

* [PATCH 39/43] perf stat report: Add support to initialize aggr_map from file
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
                   ` (37 preceding siblings ...)
  2015-12-17 19:47 ` [PATCH 38/43] perf stat report: Process stat config event Arnaldo Carvalho de Melo
@ 2015-12-17 19:47 ` Arnaldo Carvalho de Melo
  2015-12-17 19:47 ` [PATCH 40/43] perf stat report: Move csv_sep initialization before report command Arnaldo Carvalho de Melo
                   ` (4 subsequent siblings)
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:47 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

Using perf.data's perf_env data to initialize aggregate config.

Reported-by: Kan Liang <kan.liang@intel.com>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1446734469-11352-15-git-send-email-jolsa@kernel.org
[ s/stat/st/g, s/socket/socket_id/g to fix 'already defined' build error with older distros (e.g. RHEL6.7) ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 103 insertions(+)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 1e5db50dab9e..c78052580023 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1326,6 +1326,101 @@ static void perf_stat__exit_aggr_mode(void)
 	cpus_aggr_map = NULL;
 }
 
+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 core = -1, cpu = perf_env__get_cpu(env, map, idx);
+
+	if (cpu != -1) {
+		int socket_id = env->cpu[cpu].socket_id;
+
+		/*
+		 * Encode socket in upper 16 bits
+		 * core_id is relative to socket, and
+		 * we need a global id. So we combine
+		 * socket + core id.
+		 */
+		core = (socket_id << 16) | (env->cpu[cpu].core_id & 0xffff);
+	}
+
+	return core;
+}
+
+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 *st)
+{
+	struct perf_env *env = &st->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:
@@ -1538,7 +1633,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 *st = 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(st);
+
 	return 0;
 }
 
-- 
2.1.0


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

* [PATCH 40/43] perf stat report: Move csv_sep initialization before report command
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
                   ` (38 preceding siblings ...)
  2015-12-17 19:47 ` [PATCH 39/43] perf stat report: Add support to initialize aggr_map from file Arnaldo Carvalho de Melo
@ 2015-12-17 19:47 ` Arnaldo Carvalho de Melo
  2015-12-17 19:47 ` [PATCH 41/43] perf stat report: Process stat and stat round events Arnaldo Carvalho de Melo
                   ` (3 subsequent siblings)
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:47 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

So we have csv_sep properly initialized before report command leg.

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

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


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

* [PATCH 41/43] perf stat report: Process stat and stat round events
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
                   ` (39 preceding siblings ...)
  2015-12-17 19:47 ` [PATCH 40/43] perf stat report: Move csv_sep initialization before report command Arnaldo Carvalho de Melo
@ 2015-12-17 19:47 ` Arnaldo Carvalho de Melo
  2015-12-17 19:47 ` [PATCH 42/43] perf stat report: Process event update events Arnaldo Carvalho de Melo
                   ` (2 subsequent siblings)
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:47 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

Adding processing of stat and stat round events.

The stat data com in stat events, using generic function
process_stat_round_event to store data under perf_evsel object.

The stat-round events comes each interval or as last event in non
interval mode. The function process_stat_round_event process stored data
for each perf_evsel object and print it out.

Committer note:

After this patch:

  $ perf stat record usleep 1

   Performance counter stats for 'usleep 1':

        0.498381  task-clock (msec)       #    0.571 CPUs utilized
               2  context-switches        #    0.004 M/sec
               0  cpu-migrations          #    0.000 K/sec
             149  page-faults             #    0.299 M/sec
       1,271,635  cycles                  #    2.552 GHz
         928,712  stalled-cycles-frontend #   73.03% frontend cycles idle
         663,286  stalled-cycles-backend  #   52.16% backend  cycles idle
         792,614  instructions            #    0.62  insns per cycle
                                          #    1.17  stalled cycles per insn
         136,850  branches                #  274.589 M/sec
   <not counted>  branch-misses            (0.00%)

     0.000873419 seconds time elapsed

  $
  $ perf stat report

   Performance counter stats for '/home/acme/bin/perf stat record usleep 1':

        0.498381  task-clock (msec)       #    0.571 CPUs utilized
               2  context-switches        #    0.004 M/sec
               0  cpu-migrations          #    0.000 K/sec
             149  page-faults             #    0.299 M/sec
       1,271,635  cycles                  #    2.552 GHz
         928,712  stalled-cycles-frontend #   73.03% frontend cycles idle
         663,286  stalled-cycles-backend  #   52.16% backend  cycles idle
         792,614  instructions            #    0.62  insns per cycle
                                          #    1.17  stalled cycles per insn
         136,850  branches                #  274.589 M/sec
   <not counted>  branch-misses            (0.00%)

     0.000873419 seconds time elapsed

  $

Reported-by: Kan Liang <kan.liang@intel.com>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1446734469-11352-16-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index f9d4e0963ac7..d27d1b921efa 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1628,6 +1628,32 @@ static int __cmd_record(int argc, const char **argv)
 	return argc;
 }
 
+static int process_stat_round_event(struct perf_tool *tool __maybe_unused,
+				    union perf_event *event,
+				    struct perf_session *session)
+{
+	struct stat_round_event *round = &event->stat_round;
+	struct perf_evsel *counter;
+	struct timespec tsh, *ts = NULL;
+	const char **argv = session->header.env.cmdline_argv;
+	int argc = session->header.env.nr_cmdline;
+
+	evlist__for_each(evsel_list, counter)
+		perf_stat_process_counter(&stat_config, counter);
+
+	if (round->type == PERF_STAT_ROUND_TYPE__FINAL)
+		update_stats(&walltime_nsecs_stats, round->time);
+
+	if (stat_config.interval && round->time) {
+		tsh.tv_sec  = round->time / NSECS_PER_SEC;
+		tsh.tv_nsec = round->time % NSECS_PER_SEC;
+		ts = &tsh;
+	}
+
+	print_counters(ts, argc, argv);
+	return 0;
+}
+
 static
 int process_stat_config_event(struct perf_tool *tool __maybe_unused,
 			      union perf_event *event,
@@ -1713,6 +1739,8 @@ static struct perf_stat perf_stat = {
 		.thread_map	= process_thread_map_event,
 		.cpu_map	= process_cpu_map_event,
 		.stat_config	= process_stat_config_event,
+		.stat		= perf_event__process_stat_event,
+		.stat_round	= process_stat_round_event,
 	},
 };
 
-- 
2.1.0


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

* [PATCH 42/43] perf stat report: Process event update events
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
                   ` (40 preceding siblings ...)
  2015-12-17 19:47 ` [PATCH 41/43] perf stat report: Process stat and stat round events Arnaldo Carvalho de Melo
@ 2015-12-17 19:47 ` Arnaldo Carvalho de Melo
  2015-12-17 19:47 ` [PATCH 43/43] perf stat report: Allow to override aggr_mode Arnaldo Carvalho de Melo
  2015-12-18  8:48 ` [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Ingo Molnar
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:47 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

Adding processing of event update events, so perf stat report can store
additional info for events - unit,scale,name.

Committer note:

Before:

  # perf stat record -e power/energy-cores/ -a
  ^C
  Performance counter stats for 'system wide':

             77.41 Joules power/energy-cores/

       1.597176695 seconds time elapsed

  # perf stat report

  Performance counter stats for '/home/acme/bin/perf stat record -e power/energy-cores/ -a':

   332,488,114,176      power/energy-cores/

       1.597176695 seconds time elapsed

  #

After, using the same perf.data file generated in the "Before" case
above:

  # perf stat report

  Performance counter stats for '/home/acme/bin/perf stat record -e power/energy-cores/ -a':

             77.41 Joules power/energy-cores/

       1.597176695 seconds time elapsed

  #

Reported-by: Kan Liang <kan.liang@intel.com>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1446734469-11352-17-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index d27d1b921efa..3ccf5a9dab33 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1736,6 +1736,7 @@ static const char * const report_usage[] = {
 static struct perf_stat perf_stat = {
 	.tool = {
 		.attr		= perf_event__process_attr,
+		.event_update	= perf_event__process_event_update,
 		.thread_map	= process_thread_map_event,
 		.cpu_map	= process_cpu_map_event,
 		.stat_config	= process_stat_config_event,
-- 
2.1.0


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

* [PATCH 43/43] perf stat report: Allow to override aggr_mode
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
                   ` (41 preceding siblings ...)
  2015-12-17 19:47 ` [PATCH 42/43] perf stat report: Process event update events Arnaldo Carvalho de Melo
@ 2015-12-17 19:47 ` Arnaldo Carvalho de Melo
  2015-12-18  8:48 ` [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Ingo Molnar
  43 siblings, 0 replies; 47+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 19:47 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Jiri Olsa, David Ahern, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Jiri Olsa <jolsa@kernel.org>

Allowing to override record aggr_mode. It's possible to use perf stat
like:

   $ perf stat report -A
   $ perf stat report --per-core
   $ perf stat report --per-socket

To customize the recorded aggregate mode regardless what was used during
the stat record command.

Reported-by: Kan Liang <kan.liang@intel.com>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1446734469-11352-19-git-send-email-jolsa@kernel.org
[ Renamed 'stat' parameter to 'st' to fix 'already defined' build error with older distros (e.g. RHEL6.7) ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/Documentation/perf-stat.txt | 10 ++++++++++
 tools/perf/builtin-stat.c              | 17 +++++++++++++++++
 2 files changed, 27 insertions(+)

diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 95f492828657..52ef7a9d50aa 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -182,6 +182,16 @@ Reads and reports stat data from perf data file.
 --input file::
 Input file name.
 
+--per-socket::
+Aggregate counts per processor socket for system-wide mode measurements.
+
+--per-core::
+Aggregate counts per physical processor for system-wide mode measurements.
+
+-A::
+--no-aggr::
+Do not aggregate counts across all monitored CPUs.
+
 
 EXAMPLES
 --------
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 3ccf5a9dab33..9805e03ab163 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -138,6 +138,7 @@ struct perf_stat {
 	bool			 maps_allocated;
 	struct cpu_map		*cpus;
 	struct thread_map	*threads;
+	enum aggr_mode		 aggr_mode;
 };
 
 static struct perf_stat		perf_stat;
@@ -1663,6 +1664,15 @@ int process_stat_config_event(struct perf_tool *tool __maybe_unused,
 
 	perf_event__read_stat_config(&stat_config, &event->stat_config);
 
+	if (cpu_map__empty(st->cpus)) {
+		if (st->aggr_mode != AGGR_UNSET)
+			pr_warning("warning: processing task data, aggregation mode not set\n");
+		return 0;
+	}
+
+	if (st->aggr_mode != AGGR_UNSET)
+		stat_config.aggr_mode = st->aggr_mode;
+
 	if (perf_stat.file.is_pipe)
 		perf_stat_init_aggr_mode();
 	else
@@ -1743,6 +1753,7 @@ static struct perf_stat perf_stat = {
 		.stat		= perf_event__process_stat_event,
 		.stat_round	= process_stat_round_event,
 	},
+	.aggr_mode = AGGR_UNSET,
 };
 
 static int __cmd_report(int argc, const char **argv)
@@ -1750,6 +1761,12 @@ static int __cmd_report(int argc, const char **argv)
 	struct perf_session *session;
 	const struct option options[] = {
 	OPT_STRING('i', "input", &input_name, "file", "input file name"),
+	OPT_SET_UINT(0, "per-socket", &perf_stat.aggr_mode,
+		     "aggregate counts per processor socket", AGGR_SOCKET),
+	OPT_SET_UINT(0, "per-core", &perf_stat.aggr_mode,
+		     "aggregate counts per physical processor core", AGGR_CORE),
+	OPT_SET_UINT('A', "no-aggr", &perf_stat.aggr_mode,
+		     "disable CPU count aggregation", AGGR_NONE),
 	OPT_END()
 	};
 	struct stat st;
-- 
2.1.0


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

* Re: [GIT PULL 00/43] perf/core new feature: 'perf stat record/report'
  2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
                   ` (42 preceding siblings ...)
  2015-12-17 19:47 ` [PATCH 43/43] perf stat report: Allow to override aggr_mode Arnaldo Carvalho de Melo
@ 2015-12-18  8:48 ` Ingo Molnar
  2015-12-18  8:55   ` Ingo Molnar
  43 siblings, 1 reply; 47+ messages in thread
From: Ingo Molnar @ 2015-12-18  8:48 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: linux-kernel, Arnaldo Carvalho de Melo, David Ahern, Jiri Olsa,
	Kan Liang, Namhyung Kim, Peter Zijlstra, Wang Nan


* Arnaldo Carvalho de Melo <acme@kernel.org> wrote:

> From: Arnaldo Carvalho de Melo <acme@redhat.com>
> 
> Hi Ingo,
> 
> 	Please consider pulling, cool new feature! This is on top of the
> perf-core-for-mingo-2.1 tag, with that RHEL6.7 bugfix, I had also to go
> over this one fixing stuff in many spots :-\
> 
> - Arnaldo
> 
> The following changes since commit 1843b4e057b7717db21a3ad96fa16d6b4ee8f6c4:
> 
>   tools subcmd: Rename subcmd header include guards (2015-12-17 14:27:14 -0300)
> 
> are available in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-core-for-mingo-3
> 
> for you to fetch changes up to 89af4e05c21d68f22e07fe66940ea675615a49ed:
> 
>   perf stat report: Allow to override aggr_mode (2015-12-17 16:30:30 -0300)
> 
> ----------------------------------------------------------------
> perf/core improvement.
> 
> User visible:
> 
> - Generate perf.data files from 'perf stat', to tap into the scripting
>   capabilities perf has instead of defining a 'perf stat' specific scripting
>   support to calculate event ratios, etc. Simple example:
> 
>   $ perf stat record -e cycles usleep 1
> 
>    Performance counter stats for 'usleep 1':
> 
>          1,134,996      cycles
> 
>        0.000670644 seconds time elapsed
> 
>   $ perf stat report
> 
>    Performance counter stats for '/home/acme/bin/perf stat record -e cycles usleep 1':
> 
>          1,134,996      cycles
> 
>        0.000670644 seconds time elapsed
> 
>   $
> 
>   It generates PERF_RECORD_ userspace records to store the details:
> 
>   $ perf report -D | grep PERF_RECORD
>   0xf0 [0x28]: PERF_RECORD_THREAD_MAP nr: 1 thread: 27637
>   0x118 [0x12]: PERF_RECORD_CPU_MAP nr: 1 cpu: 65535
>   0x12a [0x40]: PERF_RECORD_STAT_CONFIG
>   0x16a [0x30]: PERF_RECORD_STAT
>   -1 -1 0x19a [0x40]: PERF_RECORD_MMAP -1/0: [0xffffffff81000000(0x1f000000) @ 0xffffffff81000000]: x [kernel.kallsyms]_text
>   0x1da [0x18]: PERF_RECORD_STAT_ROUND
>   [acme@ssdandy linux]$
> 
>   An effort was made to make perf.data files generated like this to not
>   generate cryptic messages when processed by older tools.
> 
>   The 'perf script' bits need rebasing, will go up later.

Nice feature!

> 
> Jiri's cover letter for this series:
> 
> 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.
> 
> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
> 
> ----------------------------------------------------------------
> Jiri Olsa (43):
>       perf thread_map: Add thread_map user level event
>       perf thread_map: Add thread_map event sythesize function
>       perf thread_map: Add thread_map__new_event function
>       perf thread_map: Add perf_event__fprintf_thread_map function
>       perf cpu_map: Add cpu_map user level event
>       perf cpu_map: Add cpu_map event synthesize function
>       perf cpu_map: Add cpu_map__new_event function
>       perf cpu_map: Add perf_event__fprintf_cpu_map function
>       perf tools: Add stat config user level event
>       perf tools: Add stat config event synthesize function
>       perf tools: Add stat config event read function
>       perf tools: Add stat user level event
>       perf tools: Add stat event synthesize function
>       perf tools: Add stat event read function
>       perf tools: Add stat round user level event
>       perf tools: Add stat round event synthesize function
>       perf tools: Add stat events fprintf functions
>       perf tools: Add event_update user level event
>       perf tools: Add event_update event unit type
>       perf tools: Add event_update event scale type
>       perf tools: Add event_update event name type
>       perf tools: Add event_update event cpus type
>       perf tools: Add perf_event__fprintf_event_update function
>       perf report: Display newly added events in raw dump
>       perf tools: Introduce stat perf.data header feature
>       perf stat record: Add record command
>       perf stat record: Initialize record features
>       perf stat record: Synthesize stat record data
>       perf evlist: Export id_add_fd()
>       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 stat record: Synthesize event update events
>       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: Move csv_sep initialization before report command
>       perf stat report: Process stat and stat round events
>       perf stat report: Process event update events
>       perf stat report: Allow to override aggr_mode
> 
>  tools/perf/Documentation/perf-stat.txt |  34 ++
>  tools/perf/builtin-record.c            |   2 +
>  tools/perf/builtin-stat.c              | 614 ++++++++++++++++++++++++++++++++-
>  tools/perf/tests/Build                 |   3 +
>  tools/perf/tests/builtin-test.c        |  24 ++
>  tools/perf/tests/cpumap.c              |  88 +++++
>  tools/perf/tests/event_update.c        | 117 +++++++
>  tools/perf/tests/stat.c                | 111 ++++++
>  tools/perf/tests/tests.h               |   6 +
>  tools/perf/tests/thread-map.c          |  43 +++
>  tools/perf/util/cpumap.c               |  42 +++
>  tools/perf/util/cpumap.h               |   1 +
>  tools/perf/util/event.c                | 308 +++++++++++++++++
>  tools/perf/util/event.h                | 150 +++++++-
>  tools/perf/util/evlist.c               |   6 +-
>  tools/perf/util/evlist.h               |   3 +
>  tools/perf/util/header.c               | 205 +++++++++++
>  tools/perf/util/header.h               |  17 +
>  tools/perf/util/session.c              | 189 ++++++++++
>  tools/perf/util/stat.c                 |  62 ++++
>  tools/perf/util/stat.h                 |  10 +
>  tools/perf/util/thread_map.c           |  27 ++
>  tools/perf/util/thread_map.h           |   3 +
>  tools/perf/util/tool.h                 |   8 +-
>  24 files changed, 2054 insertions(+), 19 deletions(-)
>  create mode 100644 tools/perf/tests/cpumap.c
>  create mode 100644 tools/perf/tests/event_update.c
>  create mode 100644 tools/perf/tests/stat.c

Pulled, thanks a lot Arnaldo!

	Ingo

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

* Re: [GIT PULL 00/43] perf/core new feature: 'perf stat record/report'
  2015-12-18  8:48 ` [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Ingo Molnar
@ 2015-12-18  8:55   ` Ingo Molnar
  2015-12-18 10:11     ` Jiri Olsa
  0 siblings, 1 reply; 47+ messages in thread
From: Ingo Molnar @ 2015-12-18  8:55 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: linux-kernel, Arnaldo Carvalho de Melo, David Ahern, Jiri Olsa,
	Kan Liang, Namhyung Kim, Peter Zijlstra, Wang Nan


* Ingo Molnar <mingo@kernel.org> wrote:

> 
> * Arnaldo Carvalho de Melo <acme@kernel.org> wrote:
> 
> > From: Arnaldo Carvalho de Melo <acme@redhat.com>
> > 
> > Hi Ingo,
> > 
> > 	Please consider pulling, cool new feature! This is on top of the
> > perf-core-for-mingo-2.1 tag, with that RHEL6.7 bugfix, I had also to go
> > over this one fixing stuff in many spots :-\
> > 
> > - Arnaldo
> > 
> > The following changes since commit 1843b4e057b7717db21a3ad96fa16d6b4ee8f6c4:
> > 
> >   tools subcmd: Rename subcmd header include guards (2015-12-17 14:27:14 -0300)
> > 
> > are available in the git repository at:
> > 
> >   git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-core-for-mingo-3
> > 
> > for you to fetch changes up to 89af4e05c21d68f22e07fe66940ea675615a49ed:
> > 
> >   perf stat report: Allow to override aggr_mode (2015-12-17 16:30:30 -0300)
> > 
> > ----------------------------------------------------------------
> > perf/core improvement.
> > 
> > User visible:
> > 
> > - Generate perf.data files from 'perf stat', to tap into the scripting
> >   capabilities perf has instead of defining a 'perf stat' specific scripting
> >   support to calculate event ratios, etc. Simple example:
> > 
> >   $ perf stat record -e cycles usleep 1
> > 
> >    Performance counter stats for 'usleep 1':
> > 
> >          1,134,996      cycles
> > 
> >        0.000670644 seconds time elapsed
> > 
> >   $ perf stat report
> > 
> >    Performance counter stats for '/home/acme/bin/perf stat record -e cycles usleep 1':
> > 
> >          1,134,996      cycles
> > 
> >        0.000670644 seconds time elapsed
> > 
> >   $
> > 
> >   It generates PERF_RECORD_ userspace records to store the details:
> > 
> >   $ perf report -D | grep PERF_RECORD
> >   0xf0 [0x28]: PERF_RECORD_THREAD_MAP nr: 1 thread: 27637
> >   0x118 [0x12]: PERF_RECORD_CPU_MAP nr: 1 cpu: 65535
> >   0x12a [0x40]: PERF_RECORD_STAT_CONFIG
> >   0x16a [0x30]: PERF_RECORD_STAT
> >   -1 -1 0x19a [0x40]: PERF_RECORD_MMAP -1/0: [0xffffffff81000000(0x1f000000) @ 0xffffffff81000000]: x [kernel.kallsyms]_text
> >   0x1da [0x18]: PERF_RECORD_STAT_ROUND
> >   [acme@ssdandy linux]$
> > 
> >   An effort was made to make perf.data files generated like this to not
> >   generate cryptic messages when processed by older tools.
> > 
> >   The 'perf script' bits need rebasing, will go up later.
> 
> Nice feature!

I tried it out, and it works as expected, cool stuff!

Btw., a very small usability observation: maybe 'perf report' should be enhanced 
to recognize 'stat record' generated perf.data files, and display a matching 
message?

Right now if I do 'perf report' on such a perf.data then I'll get a "no samples" 
TUI message, which is technically correct but somewhat misleading.

It's no big deal - and maybe you guys can think of a better solution than 
displaying an error message: maybe 'perf report' should automatically switch to 
'perf stat report'?

It would be a bit shorter to type as well and would continue to strengthen the 
very nice level of integration that the various subcommands already have today.

But maybe it would be confusing - don't know.

Thanks,

	Ingo

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

* Re: [GIT PULL 00/43] perf/core new feature: 'perf stat record/report'
  2015-12-18  8:55   ` Ingo Molnar
@ 2015-12-18 10:11     ` Jiri Olsa
  0 siblings, 0 replies; 47+ messages in thread
From: Jiri Olsa @ 2015-12-18 10:11 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Arnaldo Carvalho de Melo, linux-kernel, Arnaldo Carvalho de Melo,
	David Ahern, Jiri Olsa, Kan Liang, Namhyung Kim, Peter Zijlstra,
	Wang Nan

On Fri, Dec 18, 2015 at 09:55:38AM +0100, Ingo Molnar wrote:

SNIP

> 
> Right now if I do 'perf report' on such a perf.data then I'll get a "no samples" 
> TUI message, which is technically correct but somewhat misleading.
> 
> It's no big deal - and maybe you guys can think of a better solution than 
> displaying an error message: maybe 'perf report' should automatically switch to 
> 'perf stat report'?
> 
> It would be a bit shorter to type as well and would continue to strengthen the 
> very nice level of integration that the various subcommands already have today.
> 
> But maybe it would be confusing - don't know.

let's see ;-) I'll try to send out rfc soon

thanks,
jirka

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

end of thread, other threads:[~2015-12-18 10:11 UTC | newest]

Thread overview: 47+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-12-17 19:46 [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Arnaldo Carvalho de Melo
2015-12-17 19:46 ` [PATCH 01/43] perf thread_map: Add thread_map user level event Arnaldo Carvalho de Melo
2015-12-17 19:46 ` [PATCH 02/43] perf thread_map: Add thread_map event sythesize function Arnaldo Carvalho de Melo
2015-12-17 19:46 ` [PATCH 03/43] perf thread_map: Add thread_map__new_event function Arnaldo Carvalho de Melo
2015-12-17 19:46 ` [PATCH 04/43] perf thread_map: Add perf_event__fprintf_thread_map function Arnaldo Carvalho de Melo
2015-12-17 19:46 ` [PATCH 05/43] perf cpu_map: Add cpu_map user level event Arnaldo Carvalho de Melo
2015-12-17 19:46 ` [PATCH 06/43] perf cpu_map: Add cpu_map event synthesize function Arnaldo Carvalho de Melo
2015-12-17 19:46 ` [PATCH 07/43] perf cpu_map: Add cpu_map__new_event function Arnaldo Carvalho de Melo
2015-12-17 19:46 ` [PATCH 08/43] perf cpu_map: Add perf_event__fprintf_cpu_map function Arnaldo Carvalho de Melo
2015-12-17 19:46 ` [PATCH 09/43] perf tools: Add stat config user level event Arnaldo Carvalho de Melo
2015-12-17 19:46 ` [PATCH 10/43] perf tools: Add stat config event synthesize function Arnaldo Carvalho de Melo
2015-12-17 19:46 ` [PATCH 11/43] perf tools: Add stat config event read function Arnaldo Carvalho de Melo
2015-12-17 19:46 ` [PATCH 12/43] perf tools: Add stat user level event Arnaldo Carvalho de Melo
2015-12-17 19:46 ` [PATCH 13/43] perf tools: Add stat event synthesize function Arnaldo Carvalho de Melo
2015-12-17 19:46 ` [PATCH 14/43] perf tools: Add stat event read function Arnaldo Carvalho de Melo
2015-12-17 19:46 ` [PATCH 15/43] perf tools: Add stat round user level event Arnaldo Carvalho de Melo
2015-12-17 19:46 ` [PATCH 16/43] perf tools: Add stat round event synthesize function Arnaldo Carvalho de Melo
2015-12-17 19:46 ` [PATCH 17/43] perf tools: Add stat events fprintf functions Arnaldo Carvalho de Melo
2015-12-17 19:46 ` [PATCH 18/43] perf tools: Add event_update user level event Arnaldo Carvalho de Melo
2015-12-17 19:47 ` [PATCH 19/43] perf tools: Add event_update event unit type Arnaldo Carvalho de Melo
2015-12-17 19:47 ` [PATCH 20/43] perf tools: Add event_update event scale type Arnaldo Carvalho de Melo
2015-12-17 19:47 ` [PATCH 21/43] perf tools: Add event_update event name type Arnaldo Carvalho de Melo
2015-12-17 19:47 ` [PATCH 22/43] perf tools: Add event_update event cpus type Arnaldo Carvalho de Melo
2015-12-17 19:47 ` [PATCH 23/43] perf tools: Add perf_event__fprintf_event_update function Arnaldo Carvalho de Melo
2015-12-17 19:47 ` [PATCH 24/43] perf report: Display newly added events in raw dump Arnaldo Carvalho de Melo
2015-12-17 19:47 ` [PATCH 25/43] perf tools: Introduce stat perf.data header feature Arnaldo Carvalho de Melo
2015-12-17 19:47 ` [PATCH 26/43] perf stat record: Add record command Arnaldo Carvalho de Melo
2015-12-17 19:47 ` [PATCH 27/43] perf stat record: Initialize record features Arnaldo Carvalho de Melo
2015-12-17 19:47 ` [PATCH 28/43] perf stat record: Synthesize stat record data Arnaldo Carvalho de Melo
2015-12-17 19:47 ` [PATCH 29/43] perf evlist: Export id_add_fd() Arnaldo Carvalho de Melo
2015-12-17 19:47 ` [PATCH 30/43] perf stat record: Store events IDs in perf data file Arnaldo Carvalho de Melo
2015-12-17 19:47 ` [PATCH 31/43] perf stat record: Add pipe support for record command Arnaldo Carvalho de Melo
2015-12-17 19:47 ` [PATCH 32/43] perf stat record: Write stat events on record Arnaldo Carvalho de Melo
2015-12-17 19:47 ` [PATCH 33/43] perf stat record: Write stat round " Arnaldo Carvalho de Melo
2015-12-17 19:47 ` [PATCH 34/43] perf stat record: Do not allow record with multiple runs mode Arnaldo Carvalho de Melo
2015-12-17 19:47 ` [PATCH 35/43] perf stat record: Synthesize event update events Arnaldo Carvalho de Melo
2015-12-17 19:47 ` [PATCH 36/43] perf stat report: Add report command Arnaldo Carvalho de Melo
2015-12-17 19:47 ` [PATCH 37/43] perf stat report: Process cpu/threads maps Arnaldo Carvalho de Melo
2015-12-17 19:47 ` [PATCH 38/43] perf stat report: Process stat config event Arnaldo Carvalho de Melo
2015-12-17 19:47 ` [PATCH 39/43] perf stat report: Add support to initialize aggr_map from file Arnaldo Carvalho de Melo
2015-12-17 19:47 ` [PATCH 40/43] perf stat report: Move csv_sep initialization before report command Arnaldo Carvalho de Melo
2015-12-17 19:47 ` [PATCH 41/43] perf stat report: Process stat and stat round events Arnaldo Carvalho de Melo
2015-12-17 19:47 ` [PATCH 42/43] perf stat report: Process event update events Arnaldo Carvalho de Melo
2015-12-17 19:47 ` [PATCH 43/43] perf stat report: Allow to override aggr_mode Arnaldo Carvalho de Melo
2015-12-18  8:48 ` [GIT PULL 00/43] perf/core new feature: 'perf stat record/report' Ingo Molnar
2015-12-18  8:55   ` Ingo Molnar
2015-12-18 10:11     ` Jiri Olsa

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