linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [GIT PULL 00/25] perf/core fixes and improvements
@ 2011-11-28 23:14 Arnaldo Carvalho de Melo
  2011-11-28 23:14 ` [PATCH 01/25] perf tools: Eliminate duplicate code and use PATH_MAX consistently Arnaldo Carvalho de Melo
                   ` (24 more replies)
  0 siblings, 25 replies; 28+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-11-28 23:14 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Arnaldo Carvalho de Melo, David Ahern,
	Frederic Weisbecker, Mike Galbraith, Paul Mackerras,
	Peter Zijlstra, Stephane Eranian, arnaldo.melo

Hi Ingo,

        Please consider pulling from:

git://github.com/acmel/linux.git perf/core

	Mostly infrastructure improvements/refactorings to ease the development
of tracepoint based tools and to avoid having to create a perf.data file or
using pipes when wanting to produce and consume events directly like in a
strace reimplementation using these libraries.

	More is needed to make all tools use what has changed but what is
present in this patchset should illustrate the goals I'm pursuing.

Regards,

- Arnaldo

Arnaldo Carvalho de Melo (23):
  perf tools: Eliminate duplicate code and use PATH_MAX consistently
  perf tools: Simplify debugfs mountpoint handling code
  perf evlist: Introduce perf_evlist__add_attrs
  perf evlist: Introduce add_tracepoints method
  perf evsel: Introduce config attr method
  perf evlist: Introduce {prepare,start}_workload refactored from 'perf record'
  perf evlist: Handle default value for 'pages' on mmap method
  perf record: Move mmap_pages to perf_record_opts
  perf session: Move threads to struct machine
  perf record: Move 'group' to perf_event_ops
  perf ui progress: Fix divide by zero
  perf symbols: Add nr_events to symbol_conf
  perf evlist: Introduce id_hdr_size method out of perf_session
  perf event: perf_event_ops->attr() manipulates only an evlist
  perf session: Remove superfluous callchain_cursor member
  perf tools: Use evsel->attr.sample_type instead of session->sample_type
  perf report: Group options in a struct
  perf annotate: Group options in a struct
  perf tools: Pass tool context in the the perf_event_ops functions
  perf tools: Resolve machine earlier and pass it to perf_event_ops
  perf tools: Rename perf_event_ops to perf_tool
  perf top: Stop using globals for tool state
  perf tools: Save some loops using perf_evlist__id2evsel

David Ahern (2):
  perf tools: make -C consistent across commands (for cpu list arg)
  perf script: Add comm filtering option

 tools/perf/Documentation/perf-annotate.txt         |    2 +-
 tools/perf/Documentation/perf-report.txt           |    4 +-
 tools/perf/Documentation/perf-script.txt           |    7 +-
 tools/perf/Makefile                                |    1 +
 tools/perf/builtin-annotate.c                      |  133 +++---
 tools/perf/builtin-diff.c                          |   21 +-
 tools/perf/builtin-inject.c                        |  118 +++--
 tools/perf/builtin-kmem.c                          |   14 +-
 tools/perf/builtin-lock.c                          |   10 +-
 tools/perf/builtin-probe.c                         |    1 -
 tools/perf/builtin-record.c                        |  579 ++++++++------------
 tools/perf/builtin-report.c                        |  225 ++++----
 tools/perf/builtin-sched.c                         |  198 ++++----
 tools/perf/builtin-script.c                        |   50 ++-
 tools/perf/builtin-stat.c                          |   40 +--
 tools/perf/builtin-test.c                          |    3 +-
 tools/perf/builtin-timechart.c                     |   34 +-
 tools/perf/builtin-top.c                           |  540 +++++++++---------
 tools/perf/perf.c                                  |   33 +-
 tools/perf/perf.h                                  |   23 +
 tools/perf/util/annotate.c                         |    6 +-
 tools/perf/util/annotate.h                         |    5 +-
 tools/perf/util/build-id.c                         |   26 +-
 tools/perf/util/build-id.h                         |    2 +-
 tools/perf/util/callchain.h                        |    3 +
 tools/perf/util/cgroup.c                           |   15 +-
 tools/perf/util/debugfs.c                          |   35 +-
 tools/perf/util/debugfs.h                          |   31 +-
 tools/perf/util/event.c                            |  189 +++----
 tools/perf/util/event.h                            |   59 ++-
 tools/perf/util/evlist.c                           |  289 ++++++++++-
 tools/perf/util/evlist.h                           |   41 ++-
 tools/perf/util/evsel.c                            |   70 +++
 tools/perf/util/evsel.h                            |    8 +
 tools/perf/util/header.c                           |   75 ++--
 tools/perf/util/header.h                           |   45 +-
 tools/perf/util/hist.h                             |    3 +-
 tools/perf/util/map.c                              |    4 +
 tools/perf/util/map.h                              |   19 +
 tools/perf/util/parse-events.c                     |   28 +-
 tools/perf/util/parse-events.h                     |    1 -
 tools/perf/util/probe-finder.h                     |    1 -
 .../perf/util/scripting-engines/trace-event-perl.c |    4 +-
 .../util/scripting-engines/trace-event-python.c    |    4 +-
 tools/perf/util/session.c                          |  326 +++++++-----
 tools/perf/util/session.h                          |   62 +--
 tools/perf/util/setup.py                           |    3 +-
 tools/perf/util/symbol.h                           |    1 +
 tools/perf/util/thread.c                           |    6 +-
 tools/perf/util/thread.h                           |   14 +-
 tools/perf/util/tool.h                             |   50 ++
 tools/perf/util/top.h                              |   20 +-
 tools/perf/util/trace-event-info.c                 |   28 +-
 tools/perf/util/trace-event-scripting.c            |    2 +-
 tools/perf/util/trace-event.h                      |    8 +-
 tools/perf/util/ui/browsers/annotate.c             |   16 +-
 tools/perf/util/ui/browsers/hists.c                |    2 +-
 tools/perf/util/ui/progress.c                      |    3 +
 58 files changed, 1995 insertions(+), 1545 deletions(-)
 create mode 100644 tools/perf/util/tool.h

-- 
1.7.8.rc0.35.gee6df


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

* [PATCH 01/25] perf tools: Eliminate duplicate code and use PATH_MAX consistently
  2011-11-28 23:14 [GIT PULL 00/25] perf/core fixes and improvements Arnaldo Carvalho de Melo
@ 2011-11-28 23:14 ` Arnaldo Carvalho de Melo
  2011-11-28 23:14 ` [PATCH 02/25] perf tools: Simplify debugfs mountpoint handling code Arnaldo Carvalho de Melo
                   ` (23 subsequent siblings)
  24 siblings, 0 replies; 28+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-11-28 23:14 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Arnaldo Carvalho de Melo, David Ahern,
	Frederic Weisbecker, Mike Galbraith, Paul Mackerras,
	Peter Zijlstra, Stephane Eranian

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

No need for multiple definitions for STR() and die(), also use SuSv2's
PATH_MAX instead of adding MAX_PATH.

Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-qpujjkw7u0bf0tr4wt55cr9y@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-probe.c         |    1 -
 tools/perf/util/cgroup.c           |   15 +++++++--------
 tools/perf/util/debugfs.c          |   12 ++++++------
 tools/perf/util/debugfs.h          |   29 +++++++++--------------------
 tools/perf/util/probe-finder.h     |    1 -
 tools/perf/util/trace-event-info.c |   28 ++--------------------------
 6 files changed, 24 insertions(+), 62 deletions(-)

diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 710ae3d..59d43ab 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -46,7 +46,6 @@
 
 #define DEFAULT_VAR_FILTER "!__k???tab_* & !__crc_*"
 #define DEFAULT_FUNC_FILTER "!_*"
-#define MAX_PATH_LEN 256
 
 /* Session management structure */
 static struct {
diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c
index 96bee5c..dbe2f16 100644
--- a/tools/perf/util/cgroup.c
+++ b/tools/perf/util/cgroup.c
@@ -3,7 +3,6 @@
 #include "parse-options.h"
 #include "evsel.h"
 #include "cgroup.h"
-#include "debugfs.h" /* MAX_PATH, STR() */
 #include "evlist.h"
 
 int nr_cgroups;
@@ -12,7 +11,7 @@ static int
 cgroupfs_find_mountpoint(char *buf, size_t maxlen)
 {
 	FILE *fp;
-	char mountpoint[MAX_PATH+1], tokens[MAX_PATH+1], type[MAX_PATH+1];
+	char mountpoint[PATH_MAX + 1], tokens[PATH_MAX + 1], type[PATH_MAX + 1];
 	char *token, *saved_ptr = NULL;
 	int found = 0;
 
@@ -25,8 +24,8 @@ cgroupfs_find_mountpoint(char *buf, size_t maxlen)
 	 * and inspect every cgroupfs mount point to find one that has
 	 * perf_event subsystem
 	 */
-	while (fscanf(fp, "%*s %"STR(MAX_PATH)"s %"STR(MAX_PATH)"s %"
-				STR(MAX_PATH)"s %*d %*d\n",
+	while (fscanf(fp, "%*s %"STR(PATH_MAX)"s %"STR(PATH_MAX)"s %"
+				STR(PATH_MAX)"s %*d %*d\n",
 				mountpoint, type, tokens) == 3) {
 
 		if (!strcmp(type, "cgroup")) {
@@ -57,15 +56,15 @@ cgroupfs_find_mountpoint(char *buf, size_t maxlen)
 
 static int open_cgroup(char *name)
 {
-	char path[MAX_PATH+1];
-	char mnt[MAX_PATH+1];
+	char path[PATH_MAX + 1];
+	char mnt[PATH_MAX + 1];
 	int fd;
 
 
-	if (cgroupfs_find_mountpoint(mnt, MAX_PATH+1))
+	if (cgroupfs_find_mountpoint(mnt, PATH_MAX + 1))
 		return -1;
 
-	snprintf(path, MAX_PATH, "%s/%s", mnt, name);
+	snprintf(path, PATH_MAX, "%s/%s", mnt, name);
 
 	fd = open(path, O_RDONLY);
 	if (fd == -1)
diff --git a/tools/perf/util/debugfs.c b/tools/perf/util/debugfs.c
index a88fefc..680be34 100644
--- a/tools/perf/util/debugfs.c
+++ b/tools/perf/util/debugfs.c
@@ -2,8 +2,10 @@
 #include "debugfs.h"
 #include "cache.h"
 
+#include <sys/mount.h>
+
 static int debugfs_premounted;
-static char debugfs_mountpoint[MAX_PATH+1];
+static char debugfs_mountpoint[PATH_MAX + 1];
 
 static const char *debugfs_known_mountpoints[] = {
 	"/sys/kernel/debug/",
@@ -64,9 +66,7 @@ const char *debugfs_find_mountpoint(void)
 	if (fp == NULL)
 		die("Can't open /proc/mounts for read");
 
-	while (fscanf(fp, "%*s %"
-		      STR(MAX_PATH)
-		      "s %99s %*s %*d %*d\n",
+	while (fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n",
 		      debugfs_mountpoint, type) == 2) {
 		if (strcmp(type, "debugfs") == 0)
 			break;
@@ -158,7 +158,7 @@ int debugfs_umount(void)
 
 int debugfs_write(const char *entry, const char *value)
 {
-	char path[MAX_PATH+1];
+	char path[PATH_MAX + 1];
 	int ret, count;
 	int fd;
 
@@ -203,7 +203,7 @@ int debugfs_write(const char *entry, const char *value)
  */
 int debugfs_read(const char *entry, char *buffer, size_t size)
 {
-	char path[MAX_PATH+1];
+	char path[PATH_MAX + 1];
 	int ret;
 	int fd;
 
diff --git a/tools/perf/util/debugfs.h b/tools/perf/util/debugfs.h
index 83a0287..8cd3fa0 100644
--- a/tools/perf/util/debugfs.h
+++ b/tools/perf/util/debugfs.h
@@ -1,25 +1,14 @@
 #ifndef __DEBUGFS_H__
 #define __DEBUGFS_H__
 
-#include <sys/mount.h>
-
-#ifndef MAX_PATH
-# define MAX_PATH 256
-#endif
-
-#ifndef STR
-# define _STR(x) #x
-# define STR(x) _STR(x)
-#endif
-
-extern const char *debugfs_find_mountpoint(void);
-extern int debugfs_valid_mountpoint(const char *debugfs);
-extern int debugfs_valid_entry(const char *path);
-extern char *debugfs_mount(const char *mountpoint);
-extern int debugfs_umount(void);
-extern int debugfs_write(const char *entry, const char *value);
-extern int debugfs_read(const char *entry, char *buffer, size_t size);
-extern void debugfs_force_cleanup(void);
-extern int debugfs_make_path(const char *element, char *buffer, int size);
+const char *debugfs_find_mountpoint(void);
+int debugfs_valid_mountpoint(const char *debugfs);
+int debugfs_valid_entry(const char *path);
+char *debugfs_mount(const char *mountpoint);
+int debugfs_umount(void);
+int debugfs_write(const char *entry, const char *value);
+int debugfs_read(const char *entry, char *buffer, size_t size);
+void debugfs_force_cleanup(void);
+int debugfs_make_path(const char *element, char *buffer, int size);
 
 #endif /* __DEBUGFS_H__ */
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index 1132c8f..17e94d0 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -5,7 +5,6 @@
 #include "util.h"
 #include "probe-event.h"
 
-#define MAX_PATH_LEN		 256
 #define MAX_PROBE_BUFFER	1024
 #define MAX_PROBES		 128
 
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c
index d2655f0..ac6830d 100644
--- a/tools/perf/util/trace-event-info.c
+++ b/tools/perf/util/trace-event-info.c
@@ -18,7 +18,8 @@
  *
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  */
-#define _GNU_SOURCE
+#include <ctype.h>
+#include "util.h"
 #include <dirent.h>
 #include <mntent.h>
 #include <stdio.h>
@@ -31,7 +32,6 @@
 #include <pthread.h>
 #include <fcntl.h>
 #include <unistd.h>
-#include <ctype.h>
 #include <errno.h>
 #include <stdbool.h>
 #include <linux/list.h>
@@ -44,10 +44,6 @@
 
 #define VERSION "0.5"
 
-#define _STR(x) #x
-#define STR(x) _STR(x)
-#define MAX_PATH 256
-
 #define TRACE_CTRL	"tracing_on"
 #define TRACE		"trace"
 #define AVAILABLE	"available_tracers"
@@ -73,26 +69,6 @@ struct events {
 };
 
 
-
-static void die(const char *fmt, ...)
-{
-	va_list ap;
-	int ret = errno;
-
-	if (errno)
-		perror("perf");
-	else
-		ret = -1;
-
-	va_start(ap, fmt);
-	fprintf(stderr, "  ");
-	vfprintf(stderr, fmt, ap);
-	va_end(ap);
-
-	fprintf(stderr, "\n");
-	exit(ret);
-}
-
 void *malloc_or_die(unsigned int size)
 {
 	void *data;
-- 
1.7.8.rc0.35.gee6df


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

* [PATCH 02/25] perf tools: Simplify debugfs mountpoint handling code
  2011-11-28 23:14 [GIT PULL 00/25] perf/core fixes and improvements Arnaldo Carvalho de Melo
  2011-11-28 23:14 ` [PATCH 01/25] perf tools: Eliminate duplicate code and use PATH_MAX consistently Arnaldo Carvalho de Melo
@ 2011-11-28 23:14 ` Arnaldo Carvalho de Melo
  2011-11-28 23:14 ` [PATCH 03/25] perf evlist: Introduce perf_evlist__add_attrs Arnaldo Carvalho de Melo
                   ` (22 subsequent siblings)
  24 siblings, 0 replies; 28+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-11-28 23:14 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Arnaldo Carvalho de Melo, David Ahern,
	Frederic Weisbecker, Mike Galbraith, Paul Mackerras,
	Peter Zijlstra, Stephane Eranian

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

We don't need to have two PATH_MAX char sized arrays holding it, just
one in util/debugfs.c will do.

Also rename debugfs_path to tracing_events_path, as it is not the path
to debugfs, that is debugfs_mountpoint. Both are now accessible.

This will allow accessing this code in the perf python binding without
having to drag in perf.c and util/parse-events.c.

The defaults for these variables are the canonical "/sys/kernel/debug"
and "/sys/kernel/debug/tracing/events/", removing the need for simple
tools to call debugfs_mount(NULL).

Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-ug9jvtjrsqbluuhqqxpvg30f@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-test.c      |    3 ++-
 tools/perf/perf.c              |   33 ++++-----------------------------
 tools/perf/util/debugfs.c      |   25 ++++++++++++++++++++-----
 tools/perf/util/debugfs.h      |    4 ++++
 tools/perf/util/parse-events.c |   28 +++++++++++++---------------
 tools/perf/util/parse-events.h |    1 -
 6 files changed, 43 insertions(+), 51 deletions(-)

diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c
index 831d1ba..77d68bf 100644
--- a/tools/perf/builtin-test.c
+++ b/tools/perf/builtin-test.c
@@ -7,6 +7,7 @@
 
 #include "util/cache.h"
 #include "util/debug.h"
+#include "util/debugfs.h"
 #include "util/evlist.h"
 #include "util/parse-options.h"
 #include "util/parse-events.h"
@@ -247,7 +248,7 @@ static int trace_event__id(const char *evname)
 
 	if (asprintf(&filename,
 		     "%s/syscalls/%s/id",
-		     debugfs_path, evname) < 0)
+		     tracing_events_path, evname) < 0)
 		return -1;
 
 	fd = open(filename, O_RDONLY);
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 73d0cac..2b2e225 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -29,8 +29,6 @@ struct pager_config {
 	int val;
 };
 
-static char debugfs_mntpt[MAXPATHLEN];
-
 static int pager_command_config(const char *var, const char *value, void *data)
 {
 	struct pager_config *c = data;
@@ -81,15 +79,6 @@ static void commit_pager_choice(void)
 	}
 }
 
-static void set_debugfs_path(void)
-{
-	char *path;
-
-	path = getenv(PERF_DEBUGFS_ENVIRONMENT);
-	snprintf(debugfs_path, MAXPATHLEN, "%s/%s", path ?: debugfs_mntpt,
-		 "tracing/events");
-}
-
 static int handle_options(const char ***argv, int *argc, int *envchanged)
 {
 	int handled = 0;
@@ -161,15 +150,14 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
 				fprintf(stderr, "No directory given for --debugfs-dir.\n");
 				usage(perf_usage_string);
 			}
-			strncpy(debugfs_mntpt, (*argv)[1], MAXPATHLEN);
-			debugfs_mntpt[MAXPATHLEN - 1] = '\0';
+			debugfs_set_path((*argv)[1]);
 			if (envchanged)
 				*envchanged = 1;
 			(*argv)++;
 			(*argc)--;
 		} else if (!prefixcmp(cmd, CMD_DEBUGFS_DIR)) {
-			strncpy(debugfs_mntpt, cmd + strlen(CMD_DEBUGFS_DIR), MAXPATHLEN);
-			debugfs_mntpt[MAXPATHLEN - 1] = '\0';
+			debugfs_set_path(cmd + strlen(CMD_DEBUGFS_DIR));
+			fprintf(stderr, "dir: %s\n", debugfs_mountpoint);
 			if (envchanged)
 				*envchanged = 1;
 		} else {
@@ -281,7 +269,6 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
 	if (use_pager == -1 && p->option & USE_PAGER)
 		use_pager = 1;
 	commit_pager_choice();
-	set_debugfs_path();
 
 	status = p->fn(argc, argv, prefix);
 	exit_browser(status);
@@ -416,17 +403,6 @@ static int run_argv(int *argcp, const char ***argv)
 	return done_alias;
 }
 
-/* mini /proc/mounts parser: searching for "^blah /mount/point debugfs" */
-static void get_debugfs_mntpt(void)
-{
-	const char *path = debugfs_mount(NULL);
-
-	if (path)
-		strncpy(debugfs_mntpt, path, sizeof(debugfs_mntpt));
-	else
-		debugfs_mntpt[0] = '\0';
-}
-
 static void pthread__block_sigwinch(void)
 {
 	sigset_t set;
@@ -453,7 +429,7 @@ int main(int argc, const char **argv)
 	if (!cmd)
 		cmd = "perf-help";
 	/* get debugfs mount point from /proc/mounts */
-	get_debugfs_mntpt();
+	debugfs_mount(NULL);
 	/*
 	 * "perf-xxxx" is the same as "perf xxxx", but we obviously:
 	 *
@@ -476,7 +452,6 @@ int main(int argc, const char **argv)
 	argc--;
 	handle_options(&argv, &argc, NULL);
 	commit_pager_choice();
-	set_debugfs_path();
 	set_buildid_dir();
 
 	if (argc > 0) {
diff --git a/tools/perf/util/debugfs.c b/tools/perf/util/debugfs.c
index 680be34..ffc35e7 100644
--- a/tools/perf/util/debugfs.c
+++ b/tools/perf/util/debugfs.c
@@ -2,10 +2,12 @@
 #include "debugfs.h"
 #include "cache.h"
 
+#include <linux/kernel.h>
 #include <sys/mount.h>
 
 static int debugfs_premounted;
-static char debugfs_mountpoint[PATH_MAX + 1];
+char debugfs_mountpoint[PATH_MAX + 1] = "/sys/kernel/debug";
+char tracing_events_path[PATH_MAX + 1] = "/sys/kernel/debug/tracing/events";
 
 static const char *debugfs_known_mountpoints[] = {
 	"/sys/kernel/debug/",
@@ -64,7 +66,7 @@ const char *debugfs_find_mountpoint(void)
 	/* give up and parse /proc/mounts */
 	fp = fopen("/proc/mounts", "r");
 	if (fp == NULL)
-		die("Can't open /proc/mounts for read");
+		return NULL;
 
 	while (fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n",
 		      debugfs_mountpoint, type) == 2) {
@@ -106,6 +108,12 @@ int debugfs_valid_entry(const char *path)
 	return 0;
 }
 
+static void debugfs_set_tracing_events_path(const char *mountpoint)
+{
+	snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s",
+		 mountpoint, "tracing/events");
+}
+
 /* mount the debugfs somewhere if it's not mounted */
 
 char *debugfs_mount(const char *mountpoint)
@@ -113,7 +121,7 @@ char *debugfs_mount(const char *mountpoint)
 	/* see if it's already mounted */
 	if (debugfs_find_mountpoint()) {
 		debugfs_premounted = 1;
-		return debugfs_mountpoint;
+		goto out;
 	}
 
 	/* if not mounted and no argument */
@@ -129,12 +137,19 @@ char *debugfs_mount(const char *mountpoint)
 		return NULL;
 
 	/* save the mountpoint */
-	strncpy(debugfs_mountpoint, mountpoint, sizeof(debugfs_mountpoint));
 	debugfs_found = 1;
-
+	strncpy(debugfs_mountpoint, mountpoint, sizeof(debugfs_mountpoint));
+out:
+	debugfs_set_tracing_events_path(debugfs_mountpoint);
 	return debugfs_mountpoint;
 }
 
+void debugfs_set_path(const char *mountpoint)
+{
+	snprintf(debugfs_mountpoint, sizeof(debugfs_mountpoint), "%s", mountpoint);
+	debugfs_set_tracing_events_path(mountpoint);
+}
+
 /* umount the debugfs */
 
 int debugfs_umount(void)
diff --git a/tools/perf/util/debugfs.h b/tools/perf/util/debugfs.h
index 8cd3fa0..4a878f7 100644
--- a/tools/perf/util/debugfs.h
+++ b/tools/perf/util/debugfs.h
@@ -6,9 +6,13 @@ int debugfs_valid_mountpoint(const char *debugfs);
 int debugfs_valid_entry(const char *path);
 char *debugfs_mount(const char *mountpoint);
 int debugfs_umount(void);
+void debugfs_set_path(const char *mountpoint);
 int debugfs_write(const char *entry, const char *value);
 int debugfs_read(const char *entry, char *buffer, size_t size);
 void debugfs_force_cleanup(void);
 int debugfs_make_path(const char *element, char *buffer, int size);
 
+extern char debugfs_mountpoint[];
+extern char tracing_events_path[];
+
 #endif /* __DEBUGFS_H__ */
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 928918b..586ab3f 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -25,8 +25,6 @@ enum event_result {
 	EVT_HANDLED_ALL
 };
 
-char debugfs_path[MAXPATHLEN];
-
 #define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x
 #define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x
 
@@ -140,7 +138,7 @@ static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir)
 	char evt_path[MAXPATHLEN];
 	int fd;
 
-	snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path,
+	snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", tracing_events_path,
 			sys_dir->d_name, evt_dir->d_name);
 	fd = open(evt_path, O_RDONLY);
 	if (fd < 0)
@@ -171,16 +169,16 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config)
 	char evt_path[MAXPATHLEN];
 	char dir_path[MAXPATHLEN];
 
-	if (debugfs_valid_mountpoint(debugfs_path))
+	if (debugfs_valid_mountpoint(tracing_events_path))
 		return NULL;
 
-	sys_dir = opendir(debugfs_path);
+	sys_dir = opendir(tracing_events_path);
 	if (!sys_dir)
 		return NULL;
 
 	for_each_subsystem(sys_dir, sys_dirent, sys_next) {
 
-		snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path,
+		snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
 			 sys_dirent.d_name);
 		evt_dir = opendir(dir_path);
 		if (!evt_dir)
@@ -447,7 +445,7 @@ parse_single_tracepoint_event(char *sys_name,
 	u64 id;
 	int fd;
 
-	snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path,
+	snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", tracing_events_path,
 		 sys_name, evt_name);
 
 	fd = open(evt_path, O_RDONLY);
@@ -485,7 +483,7 @@ parse_multiple_tracepoint_event(struct perf_evlist *evlist, char *sys_name,
 	struct dirent *evt_ent;
 	DIR *evt_dir;
 
-	snprintf(evt_path, MAXPATHLEN, "%s/%s", debugfs_path, sys_name);
+	snprintf(evt_path, MAXPATHLEN, "%s/%s", tracing_events_path, sys_name);
 	evt_dir = opendir(evt_path);
 
 	if (!evt_dir) {
@@ -528,7 +526,7 @@ parse_tracepoint_event(struct perf_evlist *evlist, const char **strp,
 	char sys_name[MAX_EVENT_LENGTH];
 	unsigned int sys_length, evt_length;
 
-	if (debugfs_valid_mountpoint(debugfs_path))
+	if (debugfs_valid_mountpoint(tracing_events_path))
 		return 0;
 
 	evt_name = strchr(*strp, ':');
@@ -920,10 +918,10 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob)
 	char evt_path[MAXPATHLEN];
 	char dir_path[MAXPATHLEN];
 
-	if (debugfs_valid_mountpoint(debugfs_path))
+	if (debugfs_valid_mountpoint(tracing_events_path))
 		return;
 
-	sys_dir = opendir(debugfs_path);
+	sys_dir = opendir(tracing_events_path);
 	if (!sys_dir)
 		return;
 
@@ -932,7 +930,7 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob)
 		    !strglobmatch(sys_dirent.d_name, subsys_glob))
 			continue;
 
-		snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path,
+		snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
 			 sys_dirent.d_name);
 		evt_dir = opendir(dir_path);
 		if (!evt_dir)
@@ -964,16 +962,16 @@ int is_valid_tracepoint(const char *event_string)
 	char evt_path[MAXPATHLEN];
 	char dir_path[MAXPATHLEN];
 
-	if (debugfs_valid_mountpoint(debugfs_path))
+	if (debugfs_valid_mountpoint(tracing_events_path))
 		return 0;
 
-	sys_dir = opendir(debugfs_path);
+	sys_dir = opendir(tracing_events_path);
 	if (!sys_dir)
 		return 0;
 
 	for_each_subsystem(sys_dir, sys_dirent, sys_next) {
 
-		snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path,
+		snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
 			 sys_dirent.d_name);
 		evt_dir = opendir(dir_path);
 		if (!evt_dir)
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 2f8e375..7e0cbe7 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -39,7 +39,6 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob);
 int print_hwcache_events(const char *event_glob);
 extern int is_valid_tracepoint(const char *event_string);
 
-extern char debugfs_path[];
 extern int valid_debugfs_mount(const char *debugfs);
 
 #endif /* __PERF_PARSE_EVENTS_H */
-- 
1.7.8.rc0.35.gee6df


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

* [PATCH 03/25] perf evlist: Introduce perf_evlist__add_attrs
  2011-11-28 23:14 [GIT PULL 00/25] perf/core fixes and improvements Arnaldo Carvalho de Melo
  2011-11-28 23:14 ` [PATCH 01/25] perf tools: Eliminate duplicate code and use PATH_MAX consistently Arnaldo Carvalho de Melo
  2011-11-28 23:14 ` [PATCH 02/25] perf tools: Simplify debugfs mountpoint handling code Arnaldo Carvalho de Melo
@ 2011-11-28 23:14 ` Arnaldo Carvalho de Melo
  2011-11-28 23:14 ` [PATCH 04/25] perf evlist: Introduce add_tracepoints method Arnaldo Carvalho de Melo
                   ` (21 subsequent siblings)
  24 siblings, 0 replies; 28+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-11-28 23:14 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Arnaldo Carvalho de Melo, David Ahern,
	Frederic Weisbecker, Mike Galbraith, Paul Mackerras,
	Peter Zijlstra, Stephane Eranian

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

Replacing the open coded equivalents in 'perf stat'.

Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-1btwadnf2tds2g07hsccsdse@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c |   40 +++++++---------------------------------
 tools/perf/util/evlist.c  |   34 ++++++++++++++++++++++++++++++++++
 tools/perf/util/evlist.h  |    7 +++++++
 3 files changed, 48 insertions(+), 33 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 7d98676..227befb 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1107,22 +1107,13 @@ static const struct option options[] = {
  */
 static int add_default_attributes(void)
 {
-	struct perf_evsel *pos;
-	size_t attr_nr = 0;
-	size_t c;
-
 	/* Set attrs if no event is selected and !null_run: */
 	if (null_run)
 		return 0;
 
 	if (!evsel_list->nr_entries) {
-		for (c = 0; c < ARRAY_SIZE(default_attrs); c++) {
-			pos = perf_evsel__new(default_attrs + c, c + attr_nr);
-			if (pos == NULL)
-				return -1;
-			perf_evlist__add(evsel_list, pos);
-		}
-		attr_nr += c;
+		if (perf_evlist__add_attrs_array(evsel_list, default_attrs) < 0)
+			return -1;
 	}
 
 	/* Detailed events get appended to the event list: */
@@ -1131,38 +1122,21 @@ static int add_default_attributes(void)
 		return 0;
 
 	/* Append detailed run extra attributes: */
-	for (c = 0; c < ARRAY_SIZE(detailed_attrs); c++) {
-		pos = perf_evsel__new(detailed_attrs + c, c + attr_nr);
-		if (pos == NULL)
-			return -1;
-		perf_evlist__add(evsel_list, pos);
-	}
-	attr_nr += c;
+	if (perf_evlist__add_attrs_array(evsel_list, detailed_attrs) < 0)
+		return -1;
 
 	if (detailed_run < 2)
 		return 0;
 
 	/* Append very detailed run extra attributes: */
-	for (c = 0; c < ARRAY_SIZE(very_detailed_attrs); c++) {
-		pos = perf_evsel__new(very_detailed_attrs + c, c + attr_nr);
-		if (pos == NULL)
-			return -1;
-		perf_evlist__add(evsel_list, pos);
-	}
+	if (perf_evlist__add_attrs_array(evsel_list, very_detailed_attrs) < 0)
+		return -1;
 
 	if (detailed_run < 3)
 		return 0;
 
 	/* Append very, very detailed run extra attributes: */
-	for (c = 0; c < ARRAY_SIZE(very_very_detailed_attrs); c++) {
-		pos = perf_evsel__new(very_very_detailed_attrs + c, c + attr_nr);
-		if (pos == NULL)
-			return -1;
-		perf_evlist__add(evsel_list, pos);
-	}
-
-
-	return 0;
+	return perf_evlist__add_attrs_array(evsel_list, very_very_detailed_attrs);
 }
 
 int cmd_stat(int argc, const char **argv, const char *prefix __used)
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index fbb4b4a..58aa1e0 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -13,6 +13,8 @@
 #include "evsel.h"
 #include "util.h"
 
+#include "parse-events.h"
+
 #include <sys/mman.h>
 
 #include <linux/bitops.h>
@@ -76,6 +78,14 @@ void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry)
 	++evlist->nr_entries;
 }
 
+static void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
+					  struct list_head *list,
+					  int nr_entries)
+{
+	list_splice_tail(list, &evlist->entries);
+	evlist->nr_entries += nr_entries;
+}
+
 int perf_evlist__add_default(struct perf_evlist *evlist)
 {
 	struct perf_event_attr attr = {
@@ -100,6 +110,30 @@ error:
 	return -ENOMEM;
 }
 
+int perf_evlist__add_attrs(struct perf_evlist *evlist,
+			   struct perf_event_attr *attrs, size_t nr_attrs)
+{
+	struct perf_evsel *evsel, *n;
+	LIST_HEAD(head);
+	size_t i;
+
+	for (i = 0; i < nr_attrs; i++) {
+		evsel = perf_evsel__new(attrs + i, evlist->nr_entries + i);
+		if (evsel == NULL)
+			goto out_delete_partial_list;
+		list_add_tail(&evsel->node, &head);
+	}
+
+	perf_evlist__splice_list_tail(evlist, &head, nr_attrs);
+
+	return 0;
+
+out_delete_partial_list:
+	list_for_each_entry_safe(evsel, n, &head, node)
+		perf_evsel__delete(evsel);
+	return -1;
+}
+
 void perf_evlist__disable(struct perf_evlist *evlist)
 {
 	int cpu, thread;
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 1779ffe..57d91ff 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -2,8 +2,10 @@
 #define __PERF_EVLIST_H 1
 
 #include <linux/list.h>
+#include <stdio.h>
 #include "../perf.h"
 #include "event.h"
+#include "util.h"
 
 struct pollfd;
 struct thread_map;
@@ -39,6 +41,11 @@ void perf_evlist__delete(struct perf_evlist *evlist);
 
 void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry);
 int perf_evlist__add_default(struct perf_evlist *evlist);
+int perf_evlist__add_attrs(struct perf_evlist *evlist,
+			   struct perf_event_attr *attrs, size_t nr_attrs);
+
+#define perf_evlist__add_attrs_array(evlist, array) \
+	perf_evlist__add_attrs(evlist, array, ARRAY_SIZE(array))
 
 void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel,
 			 int cpu, int thread, u64 id);
-- 
1.7.8.rc0.35.gee6df


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

* [PATCH 04/25] perf evlist: Introduce add_tracepoints method
  2011-11-28 23:14 [GIT PULL 00/25] perf/core fixes and improvements Arnaldo Carvalho de Melo
                   ` (2 preceding siblings ...)
  2011-11-28 23:14 ` [PATCH 03/25] perf evlist: Introduce perf_evlist__add_attrs Arnaldo Carvalho de Melo
@ 2011-11-28 23:14 ` Arnaldo Carvalho de Melo
  2011-11-28 23:14 ` [PATCH 05/25] perf evsel: Introduce config attr method Arnaldo Carvalho de Melo
                   ` (20 subsequent siblings)
  24 siblings, 0 replies; 28+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-11-28 23:14 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Arnaldo Carvalho de Melo, David Ahern,
	Frederic Weisbecker, Mike Galbraith, Paul Mackerras,
	Peter Zijlstra, Stephane Eranian

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

Convenient way of asking for tracepoint events to be added to an
existing evlist.

Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-0ylj4wrg54791u0baqb9swbb@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/evlist.c |   57 +++++++++++++++++++++++++++++++++++++++++++++-
 tools/perf/util/evlist.h |    5 ++++
 tools/perf/util/setup.py |    3 +-
 3 files changed, 63 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 58aa1e0..3bc5a28 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -6,12 +6,13 @@
  *
  * Released under the GPL v2. (and only v2, not any later version)
  */
+#include "util.h"
+#include "debugfs.h"
 #include <poll.h>
 #include "cpumap.h"
 #include "thread_map.h"
 #include "evlist.h"
 #include "evsel.h"
-#include "util.h"
 
 #include "parse-events.h"
 
@@ -134,6 +135,60 @@ out_delete_partial_list:
 	return -1;
 }
 
+static int trace_event__id(const char *evname)
+{
+	char *filename, *colon;
+	int err = -1, fd;
+
+	if (asprintf(&filename, "%s/%s/id", tracing_events_path, evname) < 0)
+		return -1;
+
+	colon = strrchr(filename, ':');
+	if (colon != NULL)
+		*colon = '/';
+
+	fd = open(filename, O_RDONLY);
+	if (fd >= 0) {
+		char id[16];
+		if (read(fd, id, sizeof(id)) > 0)
+			err = atoi(id);
+		close(fd);
+	}
+
+	free(filename);
+	return err;
+}
+
+int perf_evlist__add_tracepoints(struct perf_evlist *evlist,
+				 const char *tracepoints[],
+				 size_t nr_tracepoints)
+{
+	int err;
+	size_t i;
+	struct perf_event_attr *attrs = zalloc(nr_tracepoints * sizeof(*attrs));
+
+	if (attrs == NULL)
+		return -1;
+
+	for (i = 0; i < nr_tracepoints; i++) {
+		err = trace_event__id(tracepoints[i]);
+
+		if (err < 0)
+			goto out_free_attrs;
+
+		attrs[i].type	       = PERF_TYPE_TRACEPOINT;
+		attrs[i].config	       = err;
+	        attrs[i].sample_type   = (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME |
+					  PERF_SAMPLE_CPU);
+		attrs[i].sample_period = 1;
+	}
+
+	err = perf_evlist__add_attrs(evlist, attrs, nr_tracepoints);
+out_free_attrs:
+	free(attrs);
+	return err;
+}
+
 void perf_evlist__disable(struct perf_evlist *evlist)
 {
 	int cpu, thread;
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 57d91ff..ec71c82 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -43,10 +43,15 @@ void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry);
 int perf_evlist__add_default(struct perf_evlist *evlist);
 int perf_evlist__add_attrs(struct perf_evlist *evlist,
 			   struct perf_event_attr *attrs, size_t nr_attrs);
+int perf_evlist__add_tracepoints(struct perf_evlist *evlist,
+				 const char *tracepoints[], size_t nr_tracepoints);
 
 #define perf_evlist__add_attrs_array(evlist, array) \
 	perf_evlist__add_attrs(evlist, array, ARRAY_SIZE(array))
 
+#define perf_evlist__add_tracepoints_array(evlist, array) \
+	perf_evlist__add_tracepoints(evlist, array, ARRAY_SIZE(array))
+
 void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel,
 			 int cpu, int thread, u64 id);
 
diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py
index 95d3700..36d4c56 100644
--- a/tools/perf/util/setup.py
+++ b/tools/perf/util/setup.py
@@ -27,7 +27,8 @@ build_tmp = getenv('PYTHON_EXTBUILD_TMP')
 perf = Extension('perf',
 		  sources = ['util/python.c', 'util/ctype.c', 'util/evlist.c',
 			     'util/evsel.c', 'util/cpumap.c', 'util/thread_map.c',
-			     'util/util.c', 'util/xyarray.c', 'util/cgroup.c'],
+			     'util/util.c', 'util/xyarray.c', 'util/cgroup.c',
+			     'util/debugfs.c'],
 		  include_dirs = ['util/include'],
 		  extra_compile_args = cflags,
                  )
-- 
1.7.8.rc0.35.gee6df


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

* [PATCH 05/25] perf evsel: Introduce config attr method
  2011-11-28 23:14 [GIT PULL 00/25] perf/core fixes and improvements Arnaldo Carvalho de Melo
                   ` (3 preceding siblings ...)
  2011-11-28 23:14 ` [PATCH 04/25] perf evlist: Introduce add_tracepoints method Arnaldo Carvalho de Melo
@ 2011-11-28 23:14 ` Arnaldo Carvalho de Melo
  2011-11-28 23:14 ` [PATCH 06/25] perf evlist: Introduce {prepare,start}_workload refactored from 'perf record' Arnaldo Carvalho de Melo
                   ` (19 subsequent siblings)
  24 siblings, 0 replies; 28+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-11-28 23:14 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Arnaldo Carvalho de Melo, David Ahern,
	Frederic Weisbecker, Mike Galbraith, Paul Mackerras,
	Peter Zijlstra, Stephane Eranian

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

Out of the code in 'perf record', so that we can share option parsing,
etc. Eventually will be used by 'perf top', but first 'trace' will use
it.

Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-hzjqsgnte1esk90ytq0ap98v@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-record.c |  180 ++++++++++++-------------------------------
 tools/perf/perf.h           |   20 +++++
 tools/perf/util/evlist.c    |   16 ++++
 tools/perf/util/evlist.h    |    4 +
 tools/perf/util/evsel.c     |   70 +++++++++++++++++
 tools/perf/util/evsel.h     |    4 +
 6 files changed, 162 insertions(+), 132 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 6ab58cc..c3ac541 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -35,32 +35,24 @@ enum write_mode_t {
 	WRITE_APPEND
 };
 
-static u64			user_interval			= ULLONG_MAX;
-static u64			default_interval		=      0;
+static struct perf_record_opts record_opts = {
+	.target_pid	     = -1,
+	.target_tid	     = -1,
+	.user_freq	     = UINT_MAX,
+	.user_interval	     = ULLONG_MAX,
+	.freq		     = 1000,
+	.sample_id_all_avail = true,
+};
 
 static unsigned int		page_size;
 static unsigned int		mmap_pages			= UINT_MAX;
-static unsigned int		user_freq 			= UINT_MAX;
-static int			freq				=   1000;
 static int			output;
 static int			pipe_output			=      0;
 static const char		*output_name			= NULL;
 static bool			group				=  false;
 static int			realtime_prio			=      0;
-static bool			nodelay				=  false;
-static bool			raw_samples			=  false;
-static bool			sample_id_all_avail		=   true;
-static bool			system_wide			=  false;
-static pid_t			target_pid			=     -1;
-static pid_t			target_tid			=     -1;
 static pid_t			child_pid			=     -1;
-static bool			no_inherit			=  false;
 static enum write_mode_t	write_mode			= WRITE_FORCE;
-static bool			call_graph			=  false;
-static bool			inherit_stat			=  false;
-static bool			no_samples			=  false;
-static bool			sample_address			=  false;
-static bool			sample_time			=  false;
 static bool			no_buildid			=  false;
 static bool			no_buildid_cache		=  false;
 static struct perf_evlist	*evsel_list;
@@ -72,7 +64,6 @@ static int			file_new			=      1;
 static off_t			post_processing_offset;
 
 static struct perf_session	*session;
-static const char		*cpu_list;
 static const char               *progname;
 
 static void advance_output(size_t size)
@@ -169,78 +160,6 @@ static void sig_atexit(void)
 	kill(getpid(), signr);
 }
 
-static void config_attr(struct perf_evsel *evsel, struct perf_evlist *evlist)
-{
-	struct perf_event_attr *attr = &evsel->attr;
-	int track = !evsel->idx; /* only the first counter needs these */
-
-	attr->disabled		= 1;
-	attr->inherit		= !no_inherit;
-	attr->read_format	= PERF_FORMAT_TOTAL_TIME_ENABLED |
-				  PERF_FORMAT_TOTAL_TIME_RUNNING |
-				  PERF_FORMAT_ID;
-
-	attr->sample_type	|= PERF_SAMPLE_IP | PERF_SAMPLE_TID;
-
-	if (evlist->nr_entries > 1)
-		attr->sample_type |= PERF_SAMPLE_ID;
-
-	/*
-	 * We default some events to a 1 default interval. But keep
-	 * it a weak assumption overridable by the user.
-	 */
-	if (!attr->sample_period || (user_freq != UINT_MAX &&
-				     user_interval != ULLONG_MAX)) {
-		if (freq) {
-			attr->sample_type	|= PERF_SAMPLE_PERIOD;
-			attr->freq		= 1;
-			attr->sample_freq	= freq;
-		} else {
-			attr->sample_period = default_interval;
-		}
-	}
-
-	if (no_samples)
-		attr->sample_freq = 0;
-
-	if (inherit_stat)
-		attr->inherit_stat = 1;
-
-	if (sample_address) {
-		attr->sample_type	|= PERF_SAMPLE_ADDR;
-		attr->mmap_data = track;
-	}
-
-	if (call_graph)
-		attr->sample_type	|= PERF_SAMPLE_CALLCHAIN;
-
-	if (system_wide)
-		attr->sample_type	|= PERF_SAMPLE_CPU;
-
-	if (sample_id_all_avail &&
-	    (sample_time || system_wide || !no_inherit || cpu_list))
-		attr->sample_type	|= PERF_SAMPLE_TIME;
-
-	if (raw_samples) {
-		attr->sample_type	|= PERF_SAMPLE_TIME;
-		attr->sample_type	|= PERF_SAMPLE_RAW;
-		attr->sample_type	|= PERF_SAMPLE_CPU;
-	}
-
-	if (nodelay) {
-		attr->watermark = 0;
-		attr->wakeup_events = 1;
-	}
-
-	attr->mmap		= track;
-	attr->comm		= track;
-
-	if (target_pid == -1 && target_tid == -1 && !system_wide) {
-		attr->disabled = 1;
-		attr->enable_on_exec = 1;
-	}
-}
-
 static bool perf_evlist__equal(struct perf_evlist *evlist,
 			       struct perf_evlist *other)
 {
@@ -264,11 +183,10 @@ static void open_counters(struct perf_evlist *evlist)
 {
 	struct perf_evsel *pos, *first;
 
-	if (evlist->cpus->map[0] < 0)
-		no_inherit = true;
-
 	first = list_entry(evlist->entries.next, struct perf_evsel, node);
 
+	perf_evlist__config_attrs(evlist, &record_opts);
+
 	list_for_each_entry(pos, &evlist->entries, node) {
 		struct perf_event_attr *attr = &pos->attr;
 		struct xyarray *group_fd = NULL;
@@ -288,10 +206,8 @@ static void open_counters(struct perf_evlist *evlist)
 
 		if (group && pos != first)
 			group_fd = first->fd;
-
-		config_attr(pos, evlist);
 retry_sample_id:
-		attr->sample_id_all = sample_id_all_avail ? 1 : 0;
+		attr->sample_id_all = record_opts.sample_id_all_avail ? 1 : 0;
 try_again:
 		if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group,
 				     group_fd) < 0) {
@@ -300,15 +216,15 @@ try_again:
 			if (err == EPERM || err == EACCES) {
 				ui__error_paranoid();
 				exit(EXIT_FAILURE);
-			} else if (err ==  ENODEV && cpu_list) {
+			} else if (err ==  ENODEV && record_opts.cpu_list) {
 				die("No such device - did you specify"
 					" an out-of-range profile CPU?\n");
-			} else if (err == EINVAL && sample_id_all_avail) {
+			} else if (err == EINVAL && record_opts.sample_id_all_avail) {
 				/*
 				 * Old kernel, no attr->sample_id_type_all field
 				 */
-				sample_id_all_avail = false;
-				if (!sample_time && !raw_samples && !time_needed)
+				record_opts.sample_id_all_avail = false;
+				if (!record_opts.sample_time && !record_opts.raw_samples && !time_needed)
 					attr->sample_type &= ~PERF_SAMPLE_TIME;
 
 				goto retry_sample_id;
@@ -482,13 +398,13 @@ static int __cmd_record(int argc, const char **argv)
 
 	if (!output_name) {
 		if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
-			pipe_output = 1;
+			pipe_output = true;
 		else
 			output_name = "perf.data";
 	}
 	if (output_name) {
 		if (!strcmp(output_name, "-"))
-			pipe_output = 1;
+			pipe_output = true;
 		else if (!stat(output_name, &st) && st.st_size) {
 			if (write_mode == WRITE_FORCE) {
 				char oldname[PATH_MAX];
@@ -592,7 +508,7 @@ static int __cmd_record(int argc, const char **argv)
 			exit(-1);
 		}
 
-		if (!system_wide && target_tid == -1 && target_pid == -1)
+		if (!record_opts.system_wide && record_opts.target_tid == -1 && record_opts.target_pid == -1)
 			evsel_list->threads->map[0] = child_pid;
 
 		close(child_ready_pipe[1]);
@@ -689,7 +605,7 @@ static int __cmd_record(int argc, const char **argv)
 		perf_session__process_machines(session,
 					       perf_event__synthesize_guest_os);
 
-	if (!system_wide)
+	if (!record_opts.system_wide)
 		perf_event__synthesize_thread_map(evsel_list->threads,
 						  process_synthesized_event,
 						  session);
@@ -766,44 +682,44 @@ const struct option record_options[] = {
 		     parse_events_option),
 	OPT_CALLBACK(0, "filter", &evsel_list, "filter",
 		     "event filter", parse_filter),
-	OPT_INTEGER('p', "pid", &target_pid,
+	OPT_INTEGER('p', "pid", &record_opts.target_pid,
 		    "record events on existing process id"),
-	OPT_INTEGER('t', "tid", &target_tid,
+	OPT_INTEGER('t', "tid", &record_opts.target_tid,
 		    "record events on existing thread id"),
 	OPT_INTEGER('r', "realtime", &realtime_prio,
 		    "collect data with this RT SCHED_FIFO priority"),
-	OPT_BOOLEAN('D', "no-delay", &nodelay,
+	OPT_BOOLEAN('D', "no-delay", &record_opts.no_delay,
 		    "collect data without buffering"),
-	OPT_BOOLEAN('R', "raw-samples", &raw_samples,
+	OPT_BOOLEAN('R', "raw-samples", &record_opts.raw_samples,
 		    "collect raw sample records from all opened counters"),
-	OPT_BOOLEAN('a', "all-cpus", &system_wide,
+	OPT_BOOLEAN('a', "all-cpus", &record_opts.system_wide,
 			    "system-wide collection from all CPUs"),
 	OPT_BOOLEAN('A', "append", &append_file,
 			    "append to the output file to do incremental profiling"),
-	OPT_STRING('C', "cpu", &cpu_list, "cpu",
+	OPT_STRING('C', "cpu", &record_opts.cpu_list, "cpu",
 		    "list of cpus to monitor"),
 	OPT_BOOLEAN('f', "force", &force,
 			"overwrite existing data file (deprecated)"),
-	OPT_U64('c', "count", &user_interval, "event period to sample"),
+	OPT_U64('c', "count", &record_opts.user_interval, "event period to sample"),
 	OPT_STRING('o', "output", &output_name, "file",
 		    "output file name"),
-	OPT_BOOLEAN('i', "no-inherit", &no_inherit,
+	OPT_BOOLEAN('i', "no-inherit", &record_opts.no_inherit,
 		    "child tasks do not inherit counters"),
-	OPT_UINTEGER('F', "freq", &user_freq, "profile at this frequency"),
+	OPT_UINTEGER('F', "freq", &record_opts.user_freq, "profile at this frequency"),
 	OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"),
 	OPT_BOOLEAN(0, "group", &group,
 		    "put the counters into a counter group"),
-	OPT_BOOLEAN('g', "call-graph", &call_graph,
+	OPT_BOOLEAN('g', "call-graph", &record_opts.call_graph,
 		    "do call-graph (stack chain/backtrace) recording"),
 	OPT_INCR('v', "verbose", &verbose,
 		    "be more verbose (show counter open errors, etc)"),
 	OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
-	OPT_BOOLEAN('s', "stat", &inherit_stat,
+	OPT_BOOLEAN('s', "stat", &record_opts.inherit_stat,
 		    "per thread counts"),
-	OPT_BOOLEAN('d', "data", &sample_address,
+	OPT_BOOLEAN('d', "data", &record_opts.sample_address,
 		    "Sample addresses"),
-	OPT_BOOLEAN('T', "timestamp", &sample_time, "Sample timestamps"),
-	OPT_BOOLEAN('n', "no-samples", &no_samples,
+	OPT_BOOLEAN('T', "timestamp", &record_opts.sample_time, "Sample timestamps"),
+	OPT_BOOLEAN('n', "no-samples", &record_opts.no_samples,
 		    "don't sample"),
 	OPT_BOOLEAN('N', "no-buildid-cache", &no_buildid_cache,
 		    "do not update the buildid cache"),
@@ -828,8 +744,8 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
 
 	argc = parse_options(argc, argv, record_options, record_usage,
 			    PARSE_OPT_STOP_AT_NON_OPTION);
-	if (!argc && target_pid == -1 && target_tid == -1 &&
-		!system_wide && !cpu_list)
+	if (!argc && record_opts.target_pid == -1 && record_opts.target_tid == -1 &&
+		!record_opts.system_wide && !record_opts.cpu_list)
 		usage_with_options(record_usage, record_options);
 
 	if (force && append_file) {
@@ -842,7 +758,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
 		write_mode = WRITE_FORCE;
 	}
 
-	if (nr_cgroups && !system_wide) {
+	if (nr_cgroups && !record_opts.system_wide) {
 		fprintf(stderr, "cgroup monitoring only available in"
 			" system-wide mode\n");
 		usage_with_options(record_usage, record_options);
@@ -869,11 +785,11 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
 		goto out_symbol_exit;
 	}
 
-	if (target_pid != -1)
-		target_tid = target_pid;
+	if (record_opts.target_pid != -1)
+		record_opts.target_tid = record_opts.target_pid;
 
-	if (perf_evlist__create_maps(evsel_list, target_pid,
-				     target_tid, cpu_list) < 0)
+	if (perf_evlist__create_maps(evsel_list, record_opts.target_pid,
+				     record_opts.target_tid, record_opts.cpu_list) < 0)
 		usage_with_options(record_usage, record_options);
 
 	list_for_each_entry(pos, &evsel_list->entries, node) {
@@ -887,18 +803,18 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
 	if (perf_evlist__alloc_pollfd(evsel_list) < 0)
 		goto out_free_fd;
 
-	if (user_interval != ULLONG_MAX)
-		default_interval = user_interval;
-	if (user_freq != UINT_MAX)
-		freq = user_freq;
+	if (record_opts.user_interval != ULLONG_MAX)
+		record_opts.default_interval = record_opts.user_interval;
+	if (record_opts.user_freq != UINT_MAX)
+		record_opts.freq = record_opts.user_freq;
 
 	/*
 	 * User specified count overrides default frequency.
 	 */
-	if (default_interval)
-		freq = 0;
-	else if (freq) {
-		default_interval = freq;
+	if (record_opts.default_interval)
+		record_opts.freq = 0;
+	else if (record_opts.freq) {
+		record_opts.default_interval = record_opts.freq;
 	} else {
 		fprintf(stderr, "frequency and count are zero, aborting\n");
 		err = -EINVAL;
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 914c895..eb6a138 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -185,4 +185,24 @@ extern const char perf_version_string[];
 
 void pthread__unblock_sigwinch(void);
 
+struct perf_record_opts {
+	pid_t	     target_pid;
+	pid_t	     target_tid;
+	bool	     call_graph;
+	bool	     inherit_stat;
+	bool	     no_delay;
+	bool	     no_inherit;
+	bool	     no_samples;
+	bool	     raw_samples;
+	bool	     sample_address;
+	bool	     sample_time;
+	bool	     sample_id_all_avail;
+	bool	     system_wide;
+	unsigned int freq;
+	unsigned int user_freq;
+	u64	     default_interval;
+	u64	     user_interval;
+	const char   *cpu_list;
+};
+
 #endif
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 3bc5a28..b774341 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -46,6 +46,22 @@ struct perf_evlist *perf_evlist__new(struct cpu_map *cpus,
 	return evlist;
 }
 
+void perf_evlist__config_attrs(struct perf_evlist *evlist,
+			       struct perf_record_opts *opts)
+{
+	struct perf_evsel *evsel;
+
+	if (evlist->cpus->map[0] < 0)
+		opts->no_inherit = true;
+
+	list_for_each_entry(evsel, &evlist->entries, node) {
+		perf_evsel__config(evsel, opts);
+
+		if (evlist->nr_entries > 1)
+			evsel->attr.sample_type |= PERF_SAMPLE_ID;
+	}
+}
+
 static void perf_evlist__purge(struct perf_evlist *evlist)
 {
 	struct perf_evsel *pos, *n;
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index ec71c82..231c06f 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -10,6 +10,7 @@
 struct pollfd;
 struct thread_map;
 struct cpu_map;
+struct perf_record_opts;
 
 #define PERF_EVLIST__HLIST_BITS 8
 #define PERF_EVLIST__HLIST_SIZE (1 << PERF_EVLIST__HLIST_BITS)
@@ -64,6 +65,9 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *self, int idx);
 
 int perf_evlist__open(struct perf_evlist *evlist, bool group);
 
+void perf_evlist__config_attrs(struct perf_evlist *evlist,
+			       struct perf_record_opts *opts);
+
 int perf_evlist__alloc_mmap(struct perf_evlist *evlist);
 int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite);
 void perf_evlist__munmap(struct perf_evlist *evlist);
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index e426264..b38eaa3 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -53,6 +53,76 @@ struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx)
 	return evsel;
 }
 
+void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts)
+{
+	struct perf_event_attr *attr = &evsel->attr;
+	int track = !evsel->idx; /* only the first counter needs these */
+
+	attr->sample_id_all = opts->sample_id_all_avail ? 1 : 0;
+	attr->inherit	    = !opts->no_inherit;
+	attr->read_format   = PERF_FORMAT_TOTAL_TIME_ENABLED |
+			      PERF_FORMAT_TOTAL_TIME_RUNNING |
+			      PERF_FORMAT_ID;
+
+	attr->sample_type  |= PERF_SAMPLE_IP | PERF_SAMPLE_TID;
+
+	/*
+	 * We default some events to a 1 default interval. But keep
+	 * it a weak assumption overridable by the user.
+	 */
+	if (!attr->sample_period || (opts->user_freq != UINT_MAX &&
+				     opts->user_interval != ULLONG_MAX)) {
+		if (opts->freq) {
+			attr->sample_type	|= PERF_SAMPLE_PERIOD;
+			attr->freq		= 1;
+			attr->sample_freq	= opts->freq;
+		} else {
+			attr->sample_period = opts->default_interval;
+		}
+	}
+
+	if (opts->no_samples)
+		attr->sample_freq = 0;
+
+	if (opts->inherit_stat)
+		attr->inherit_stat = 1;
+
+	if (opts->sample_address) {
+		attr->sample_type	|= PERF_SAMPLE_ADDR;
+		attr->mmap_data = track;
+	}
+
+	if (opts->call_graph)
+		attr->sample_type	|= PERF_SAMPLE_CALLCHAIN;
+
+	if (opts->system_wide)
+		attr->sample_type	|= PERF_SAMPLE_CPU;
+
+	if (opts->sample_id_all_avail &&
+	    (opts->sample_time || opts->system_wide ||
+	     !opts->no_inherit || opts->cpu_list))
+		attr->sample_type	|= PERF_SAMPLE_TIME;
+
+	if (opts->raw_samples) {
+		attr->sample_type	|= PERF_SAMPLE_TIME;
+		attr->sample_type	|= PERF_SAMPLE_RAW;
+		attr->sample_type	|= PERF_SAMPLE_CPU;
+	}
+
+	if (opts->no_delay) {
+		attr->watermark = 0;
+		attr->wakeup_events = 1;
+	}
+
+	attr->mmap = track;
+	attr->comm = track;
+
+	if (opts->target_pid == -1 && opts->target_tid == -1 && !opts->system_wide) {
+		attr->disabled = 1;
+		attr->enable_on_exec = 1;
+	}
+}
+
 int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
 {
 	int cpu, thread;
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index b1d15e6..6421c07 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -67,6 +67,7 @@ struct perf_evsel {
 struct cpu_map;
 struct thread_map;
 struct perf_evlist;
+struct perf_record_opts;
 
 struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx);
 void perf_evsel__init(struct perf_evsel *evsel,
@@ -74,6 +75,9 @@ void perf_evsel__init(struct perf_evsel *evsel,
 void perf_evsel__exit(struct perf_evsel *evsel);
 void perf_evsel__delete(struct perf_evsel *evsel);
 
+void perf_evsel__config(struct perf_evsel *evsel,
+			struct perf_record_opts *opts);
+
 int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
 int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads);
 int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus);
-- 
1.7.8.rc0.35.gee6df


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

* [PATCH 06/25] perf evlist: Introduce {prepare,start}_workload refactored from 'perf record'
  2011-11-28 23:14 [GIT PULL 00/25] perf/core fixes and improvements Arnaldo Carvalho de Melo
                   ` (4 preceding siblings ...)
  2011-11-28 23:14 ` [PATCH 05/25] perf evsel: Introduce config attr method Arnaldo Carvalho de Melo
@ 2011-11-28 23:14 ` Arnaldo Carvalho de Melo
  2011-11-28 23:14 ` [PATCH 07/25] perf evlist: Handle default value for 'pages' on mmap method Arnaldo Carvalho de Melo
                   ` (18 subsequent siblings)
  24 siblings, 0 replies; 28+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-11-28 23:14 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Arnaldo Carvalho de Melo, David Ahern,
	Frederic Weisbecker, Mike Galbraith, Paul Mackerras,
	Peter Zijlstra, Stephane Eranian

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

So that we can easily start a workload in other tools.

Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-zdsksd4aphu0nltg2lpwsw3x@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-record.c |   81 ++++++------------------------------
 tools/perf/perf.h           |    1 +
 tools/perf/util/evlist.c    |   96 +++++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/evlist.h    |   10 ++++
 4 files changed, 120 insertions(+), 68 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index c3ac541..4799195 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -47,11 +47,9 @@ static struct perf_record_opts record_opts = {
 static unsigned int		page_size;
 static unsigned int		mmap_pages			= UINT_MAX;
 static int			output;
-static int			pipe_output			=      0;
 static const char		*output_name			= NULL;
 static bool			group				=  false;
 static int			realtime_prio			=      0;
-static pid_t			child_pid			=     -1;
 static enum write_mode_t	write_mode			= WRITE_FORCE;
 static bool			no_buildid			=  false;
 static bool			no_buildid_cache		=  false;
@@ -144,9 +142,9 @@ static void sig_atexit(void)
 {
 	int status;
 
-	if (child_pid > 0) {
+	if (evsel_list->workload.pid > 0) {
 		if (!child_finished)
-			kill(child_pid, SIGTERM);
+			kill(evsel_list->workload.pid, SIGTERM);
 
 		wait(&status);
 		if (WIFSIGNALED(status))
@@ -304,7 +302,7 @@ static int process_buildids(void)
 
 static void atexit_header(void)
 {
-	if (!pipe_output) {
+	if (!record_opts.pipe_output) {
 		session->header.data_size += bytes_written;
 
 		if (!no_buildid)
@@ -377,9 +375,7 @@ static int __cmd_record(int argc, const char **argv)
 	int flags;
 	int err;
 	unsigned long waking = 0;
-	int child_ready_pipe[2], go_pipe[2];
 	const bool forks = argc > 0;
-	char buf;
 	struct machine *machine;
 
 	progname = argv[0];
@@ -391,20 +387,15 @@ static int __cmd_record(int argc, const char **argv)
 	signal(SIGINT, sig_handler);
 	signal(SIGUSR1, sig_handler);
 
-	if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
-		perror("failed to create pipes");
-		exit(-1);
-	}
-
 	if (!output_name) {
 		if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
-			pipe_output = true;
+			record_opts.pipe_output = true;
 		else
 			output_name = "perf.data";
 	}
 	if (output_name) {
 		if (!strcmp(output_name, "-"))
-			pipe_output = true;
+			record_opts.pipe_output = true;
 		else if (!stat(output_name, &st) && st.st_size) {
 			if (write_mode == WRITE_FORCE) {
 				char oldname[PATH_MAX];
@@ -424,7 +415,7 @@ static int __cmd_record(int argc, const char **argv)
 	else
 		flags |= O_TRUNC;
 
-	if (pipe_output)
+	if (record_opts.pipe_output)
 		output = STDOUT_FILENO;
 	else
 		output = open(output_name, flags, S_IRUSR | S_IWUSR);
@@ -470,57 +461,11 @@ static int __cmd_record(int argc, const char **argv)
 		mmap_pages = (512 * 1024) / page_size;
 
 	if (forks) {
-		child_pid = fork();
-		if (child_pid < 0) {
-			perror("failed to fork");
-			exit(-1);
-		}
-
-		if (!child_pid) {
-			if (pipe_output)
-				dup2(2, 1);
-			close(child_ready_pipe[0]);
-			close(go_pipe[1]);
-			fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
-
-			/*
-			 * Do a dummy execvp to get the PLT entry resolved,
-			 * so we avoid the resolver overhead on the real
-			 * execvp call.
-			 */
-			execvp("", (char **)argv);
-
-			/*
-			 * Tell the parent we're ready to go
-			 */
-			close(child_ready_pipe[1]);
-
-			/*
-			 * Wait until the parent tells us to go.
-			 */
-			if (read(go_pipe[0], &buf, 1) == -1)
-				perror("unable to read pipe");
-
-			execvp(argv[0], (char **)argv);
-
-			perror(argv[0]);
-			kill(getppid(), SIGUSR1);
-			exit(-1);
-		}
-
-		if (!record_opts.system_wide && record_opts.target_tid == -1 && record_opts.target_pid == -1)
-			evsel_list->threads->map[0] = child_pid;
-
-		close(child_ready_pipe[1]);
-		close(go_pipe[0]);
-		/*
-		 * wait for child to settle
-		 */
-		if (read(child_ready_pipe[0], &buf, 1) == -1) {
-			perror("unable to read pipe");
-			exit(-1);
+		err = perf_evlist__prepare_workload(evsel_list, &record_opts, argv);
+		if (err < 0) {
+			pr_err("Couldn't run the workload!\n");
+			goto out_delete_session;
 		}
-		close(child_ready_pipe[0]);
 	}
 
 	open_counters(evsel_list);
@@ -530,7 +475,7 @@ static int __cmd_record(int argc, const char **argv)
 	 */
 	atexit(atexit_header);
 
-	if (pipe_output) {
+	if (record_opts.pipe_output) {
 		err = perf_header__write_pipe(output);
 		if (err < 0)
 			return err;
@@ -543,7 +488,7 @@ static int __cmd_record(int argc, const char **argv)
 
 	post_processing_offset = lseek(output, 0, SEEK_CUR);
 
-	if (pipe_output) {
+	if (record_opts.pipe_output) {
 		err = perf_session__synthesize_attrs(session,
 						     process_synthesized_event);
 		if (err < 0) {
@@ -629,7 +574,7 @@ static int __cmd_record(int argc, const char **argv)
 	 * Let the child rip
 	 */
 	if (forks)
-		close(go_pipe[1]);
+		perf_evlist__start_workload(evsel_list);
 
 	for (;;) {
 		int hits = samples;
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index eb6a138..32ee6ca 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -193,6 +193,7 @@ struct perf_record_opts {
 	bool	     no_delay;
 	bool	     no_inherit;
 	bool	     no_samples;
+	bool	     pipe_output;
 	bool	     raw_samples;
 	bool	     sample_address;
 	bool	     sample_time;
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index b774341..a472247 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -13,6 +13,7 @@
 #include "thread_map.h"
 #include "evlist.h"
 #include "evsel.h"
+#include <unistd.h>
 
 #include "parse-events.h"
 
@@ -33,6 +34,7 @@ void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus,
 		INIT_HLIST_HEAD(&evlist->heads[i]);
 	INIT_LIST_HEAD(&evlist->entries);
 	perf_evlist__set_maps(evlist, cpus, threads);
+	evlist->workload.pid = -1;
 }
 
 struct perf_evlist *perf_evlist__new(struct cpu_map *cpus,
@@ -674,3 +676,97 @@ out_err:
 
 	return err;
 }
+
+int perf_evlist__prepare_workload(struct perf_evlist *evlist,
+				  struct perf_record_opts *opts,
+				  const char *argv[])
+{
+	int child_ready_pipe[2], go_pipe[2];
+	char bf;
+
+	if (pipe(child_ready_pipe) < 0) {
+		perror("failed to create 'ready' pipe");
+		return -1;
+	}
+
+	if (pipe(go_pipe) < 0) {
+		perror("failed to create 'go' pipe");
+		goto out_close_ready_pipe;
+	}
+
+	evlist->workload.pid = fork();
+	if (evlist->workload.pid < 0) {
+		perror("failed to fork");
+		goto out_close_pipes;
+	}
+
+	if (!evlist->workload.pid) {
+		if (opts->pipe_output)
+			dup2(2, 1);
+
+		close(child_ready_pipe[0]);
+		close(go_pipe[1]);
+		fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
+
+		/*
+		 * Do a dummy execvp to get the PLT entry resolved,
+		 * so we avoid the resolver overhead on the real
+		 * execvp call.
+		 */
+		execvp("", (char **)argv);
+
+		/*
+		 * Tell the parent we're ready to go
+		 */
+		close(child_ready_pipe[1]);
+
+		/*
+		 * Wait until the parent tells us to go.
+		 */
+		if (read(go_pipe[0], &bf, 1) == -1)
+			perror("unable to read pipe");
+
+		execvp(argv[0], (char **)argv);
+
+		perror(argv[0]);
+		kill(getppid(), SIGUSR1);
+		exit(-1);
+	}
+
+	if (!opts->system_wide && opts->target_tid == -1 && opts->target_pid == -1)
+		evlist->threads->map[0] = evlist->workload.pid;
+
+	close(child_ready_pipe[1]);
+	close(go_pipe[0]);
+	/*
+	 * wait for child to settle
+	 */
+	if (read(child_ready_pipe[0], &bf, 1) == -1) {
+		perror("unable to read pipe");
+		goto out_close_pipes;
+	}
+
+	evlist->workload.cork_fd = go_pipe[1];
+	close(child_ready_pipe[0]);
+	return 0;
+
+out_close_pipes:
+	close(go_pipe[0]);
+	close(go_pipe[1]);
+out_close_ready_pipe:
+	close(child_ready_pipe[0]);
+	close(child_ready_pipe[1]);
+	return -1;
+}
+
+int perf_evlist__start_workload(struct perf_evlist *evlist)
+{
+	if (evlist->workload.cork_fd > 0) {
+		/*
+		 * Remove the cork, let it rip!
+		 */
+		return close(evlist->workload.cork_fd);
+	}
+
+	return 0;
+}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 231c06f..07d56b3 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -6,6 +6,7 @@
 #include "../perf.h"
 #include "event.h"
 #include "util.h"
+#include <unistd.h>
 
 struct pollfd;
 struct thread_map;
@@ -22,6 +23,10 @@ struct perf_evlist {
 	int		 nr_fds;
 	int		 nr_mmaps;
 	int		 mmap_len;
+	struct {
+		int	cork_fd;
+		pid_t	pid;
+	} workload;
 	bool		 overwrite;
 	union perf_event event_copy;
 	struct perf_mmap *mmap;
@@ -68,6 +73,11 @@ int perf_evlist__open(struct perf_evlist *evlist, bool group);
 void perf_evlist__config_attrs(struct perf_evlist *evlist,
 			       struct perf_record_opts *opts);
 
+int perf_evlist__prepare_workload(struct perf_evlist *evlist,
+				  struct perf_record_opts *opts,
+				  const char *argv[]);
+int perf_evlist__start_workload(struct perf_evlist *evlist);
+
 int perf_evlist__alloc_mmap(struct perf_evlist *evlist);
 int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite);
 void perf_evlist__munmap(struct perf_evlist *evlist);
-- 
1.7.8.rc0.35.gee6df


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

* [PATCH 07/25] perf evlist: Handle default value for 'pages' on mmap method
  2011-11-28 23:14 [GIT PULL 00/25] perf/core fixes and improvements Arnaldo Carvalho de Melo
                   ` (5 preceding siblings ...)
  2011-11-28 23:14 ` [PATCH 06/25] perf evlist: Introduce {prepare,start}_workload refactored from 'perf record' Arnaldo Carvalho de Melo
@ 2011-11-28 23:14 ` Arnaldo Carvalho de Melo
  2011-11-28 23:14 ` [PATCH 08/25] perf record: Move mmap_pages to perf_record_opts Arnaldo Carvalho de Melo
                   ` (17 subsequent siblings)
  24 siblings, 0 replies; 28+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-11-28 23:14 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Arnaldo Carvalho de Melo, David Ahern,
	Frederic Weisbecker, Mike Galbraith, Paul Mackerras,
	Peter Zijlstra, Stephane Eranian

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

Every tool that calls this and allows the user to override the value
needs this logic.

Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-lwscxpg57xfzahz5dmdfp9uz@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-record.c |    4 ----
 tools/perf/util/evlist.c    |   12 +++++++++---
 tools/perf/util/evlist.h    |    3 ++-
 3 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 4799195..749862d 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -456,10 +456,6 @@ static int __cmd_record(int argc, const char **argv)
 	perf_header__set_feat(&session->header, HEADER_NUMA_TOPOLOGY);
 	perf_header__set_feat(&session->header, HEADER_CPUID);
 
-	/* 512 kiB: default amount of unprivileged mlocked memory */
-	if (mmap_pages == UINT_MAX)
-		mmap_pages = (512 * 1024) / page_size;
-
 	if (forks) {
 		err = perf_evlist__prepare_workload(evsel_list, &record_opts, argv);
 		if (err < 0) {
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index a472247..81237dc 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -507,14 +507,20 @@ out_unmap:
  *
  * Using perf_evlist__read_on_cpu does this automatically.
  */
-int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite)
+int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
+		      bool overwrite)
 {
 	unsigned int page_size = sysconf(_SC_PAGE_SIZE);
-	int mask = pages * page_size - 1;
 	struct perf_evsel *evsel;
 	const struct cpu_map *cpus = evlist->cpus;
 	const struct thread_map *threads = evlist->threads;
-	int prot = PROT_READ | (overwrite ? 0 : PROT_WRITE);
+	int prot = PROT_READ | (overwrite ? 0 : PROT_WRITE), mask;
+
+        /* 512 kiB: default amount of unprivileged mlocked memory */
+        if (pages == UINT_MAX)
+                pages = (512 * 1024) / page_size;
+
+	mask = pages * page_size - 1;
 
 	if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0)
 		return -ENOMEM;
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 07d56b3..17e9c80 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -79,7 +79,8 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist,
 int perf_evlist__start_workload(struct perf_evlist *evlist);
 
 int perf_evlist__alloc_mmap(struct perf_evlist *evlist);
-int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite);
+int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
+		      bool overwrite);
 void perf_evlist__munmap(struct perf_evlist *evlist);
 
 void perf_evlist__disable(struct perf_evlist *evlist);
-- 
1.7.8.rc0.35.gee6df


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

* [PATCH 08/25] perf record: Move mmap_pages to perf_record_opts
  2011-11-28 23:14 [GIT PULL 00/25] perf/core fixes and improvements Arnaldo Carvalho de Melo
                   ` (6 preceding siblings ...)
  2011-11-28 23:14 ` [PATCH 07/25] perf evlist: Handle default value for 'pages' on mmap method Arnaldo Carvalho de Melo
@ 2011-11-28 23:14 ` Arnaldo Carvalho de Melo
  2011-11-28 23:14 ` [PATCH 09/25] perf session: Move threads to struct machine Arnaldo Carvalho de Melo
                   ` (16 subsequent siblings)
  24 siblings, 0 replies; 28+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-11-28 23:14 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Arnaldo Carvalho de Melo, David Ahern,
	Frederic Weisbecker, Mike Galbraith, Paul Mackerras,
	Peter Zijlstra, Stephane Eranian

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

Tools being developed will need this to allow the user to override this
value.

Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-zydc1yhxfm0z35fuy95bsn1l@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-record.c |    9 +++++----
 tools/perf/perf.h           |    1 +
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 749862d..ffb627d 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -35,9 +35,10 @@ enum write_mode_t {
 	WRITE_APPEND
 };
 
-static struct perf_record_opts record_opts = {
+struct perf_record_opts record_opts = {
 	.target_pid	     = -1,
 	.target_tid	     = -1,
+	.mmap_pages	     = UINT_MAX,
 	.user_freq	     = UINT_MAX,
 	.user_interval	     = ULLONG_MAX,
 	.freq		     = 1000,
@@ -45,7 +46,6 @@ static struct perf_record_opts record_opts = {
 };
 
 static unsigned int		page_size;
-static unsigned int		mmap_pages			= UINT_MAX;
 static int			output;
 static const char		*output_name			= NULL;
 static bool			group				=  false;
@@ -272,7 +272,7 @@ try_again:
 		exit(-1);
 	}
 
-	if (perf_evlist__mmap(evlist, mmap_pages, false) < 0)
+	if (perf_evlist__mmap(evlist, record_opts.mmap_pages, false) < 0)
 		die("failed to mmap with %d (%s)\n", errno, strerror(errno));
 
 	if (file_new)
@@ -647,7 +647,8 @@ const struct option record_options[] = {
 	OPT_BOOLEAN('i', "no-inherit", &record_opts.no_inherit,
 		    "child tasks do not inherit counters"),
 	OPT_UINTEGER('F', "freq", &record_opts.user_freq, "profile at this frequency"),
-	OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"),
+	OPT_UINTEGER('m', "mmap-pages", &record_opts.mmap_pages,
+		     "number of mmap data pages"),
 	OPT_BOOLEAN(0, "group", &group,
 		    "put the counters into a counter group"),
 	OPT_BOOLEAN('g', "call-graph", &record_opts.call_graph,
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 32ee6ca..13c42f3 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -200,6 +200,7 @@ struct perf_record_opts {
 	bool	     sample_id_all_avail;
 	bool	     system_wide;
 	unsigned int freq;
+	unsigned int mmap_pages;
 	unsigned int user_freq;
 	u64	     default_interval;
 	u64	     user_interval;
-- 
1.7.8.rc0.35.gee6df


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

* [PATCH 09/25] perf session: Move threads to struct machine
  2011-11-28 23:14 [GIT PULL 00/25] perf/core fixes and improvements Arnaldo Carvalho de Melo
                   ` (7 preceding siblings ...)
  2011-11-28 23:14 ` [PATCH 08/25] perf record: Move mmap_pages to perf_record_opts Arnaldo Carvalho de Melo
@ 2011-11-28 23:14 ` Arnaldo Carvalho de Melo
  2011-11-28 23:14 ` [PATCH 10/25] perf record: Move 'group' to perf_event_ops Arnaldo Carvalho de Melo
                   ` (15 subsequent siblings)
  24 siblings, 0 replies; 28+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-11-28 23:14 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Arnaldo Carvalho de Melo, David Ahern,
	Frederic Weisbecker, Mike Galbraith, Paul Mackerras,
	Peter Zijlstra, Stephane Eranian

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

The 'machine' abstraction was introduced with 'perf kvm' where we could
have samples for the host and multiple guests, but at the time we ended
up keeping the list of all machines threads all in
session->host_machine.

Move the threads rb_tree to struct machine to separate the namespaces.

Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-mdg7sm6j3va09vtgj49gbsrp@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/build-id.c |    4 +-
 tools/perf/util/map.c      |    4 +++
 tools/perf/util/map.h      |    9 ++++++++
 tools/perf/util/session.c  |   47 +++++++++++++++++++++++++++++++++++++------
 tools/perf/util/session.h  |    3 --
 tools/perf/util/thread.c   |    6 ++--
 6 files changed, 58 insertions(+), 15 deletions(-)

diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index a91cd99..f2fe6ec 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -48,8 +48,8 @@ static int perf_event__exit_del_thread(union perf_event *event,
 		    event->fork.ppid, event->fork.ptid);
 
 	if (thread) {
-		rb_erase(&thread->rb_node, &session->threads);
-		session->last_match = NULL;
+		rb_erase(&thread->rb_node, &session->host_machine.threads);
+		session->host_machine.last_match = NULL;
 		thread__delete(thread);
 	}
 
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 78284b1..316aa0a 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -562,6 +562,10 @@ int machine__init(struct machine *self, const char *root_dir, pid_t pid)
 	INIT_LIST_HEAD(&self->user_dsos);
 	INIT_LIST_HEAD(&self->kernel_dsos);
 
+	self->threads = RB_ROOT;
+	INIT_LIST_HEAD(&self->dead_threads);
+	self->last_match = NULL;
+
 	self->kmaps.machine = self;
 	self->pid	    = pid;
 	self->root_dir      = strdup(root_dir);
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 890d855..bde6835 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -62,6 +62,9 @@ struct machine {
 	struct rb_node	  rb_node;
 	pid_t		  pid;
 	char		  *root_dir;
+	struct rb_root	  threads;
+	struct list_head  dead_threads;
+	struct thread	  *last_match;
 	struct list_head  user_dsos;
 	struct list_head  kernel_dsos;
 	struct map_groups kmaps;
@@ -190,6 +193,12 @@ struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg,
 					       struct map **mapp,
 					       symbol_filter_t filter);
 
+
+struct thread *machine__findnew_thread(struct machine *machine, pid_t pid);
+void machine__remove_thread(struct machine *machine, struct thread *th);
+
+size_t machine__fprintf(struct machine *machine, FILE *fp);
+
 static inline
 struct symbol *machine__find_kernel_symbol(struct machine *self,
 					   enum map_type type, u64 addr,
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 85c1e6b7..a76666f 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -139,9 +139,6 @@ struct perf_session *perf_session__new(const char *filename, int mode,
 		goto out;
 
 	memcpy(self->filename, filename, len);
-	self->threads = RB_ROOT;
-	INIT_LIST_HEAD(&self->dead_threads);
-	self->last_match = NULL;
 	/*
 	 * On 64bit we can mmap the data file in one go. No need for tiny mmap
 	 * slices. On 32bit we use 32MB.
@@ -184,17 +181,22 @@ out_delete:
 	return NULL;
 }
 
-static void perf_session__delete_dead_threads(struct perf_session *self)
+static void machine__delete_dead_threads(struct machine *machine)
 {
 	struct thread *n, *t;
 
-	list_for_each_entry_safe(t, n, &self->dead_threads, node) {
+	list_for_each_entry_safe(t, n, &machine->dead_threads, node) {
 		list_del(&t->node);
 		thread__delete(t);
 	}
 }
 
-static void perf_session__delete_threads(struct perf_session *self)
+static void perf_session__delete_dead_threads(struct perf_session *session)
+{
+	machine__delete_dead_threads(&session->host_machine);
+}
+
+static void machine__delete_threads(struct machine *self)
 {
 	struct rb_node *nd = rb_first(&self->threads);
 
@@ -207,6 +209,11 @@ static void perf_session__delete_threads(struct perf_session *self)
 	}
 }
 
+static void perf_session__delete_threads(struct perf_session *session)
+{
+	machine__delete_threads(&session->host_machine);
+}
+
 void perf_session__delete(struct perf_session *self)
 {
 	perf_session__destroy_kernel_maps(self);
@@ -217,7 +224,7 @@ void perf_session__delete(struct perf_session *self)
 	free(self);
 }
 
-void perf_session__remove_thread(struct perf_session *self, struct thread *th)
+void machine__remove_thread(struct machine *self, struct thread *th)
 {
 	self->last_match = NULL;
 	rb_erase(&th->rb_node, &self->threads);
@@ -884,6 +891,11 @@ void perf_event_header__bswap(struct perf_event_header *self)
 	self->size = bswap_16(self->size);
 }
 
+struct thread *perf_session__findnew(struct perf_session *session, pid_t pid)
+{
+	return machine__findnew_thread(&session->host_machine, pid);
+}
+
 static struct thread *perf_session__register_idle_thread(struct perf_session *self)
 {
 	struct thread *thread = perf_session__findnew(self, 0);
@@ -1224,6 +1236,27 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
 	return ret;
 }
 
+size_t perf_session__fprintf(struct perf_session *session, FILE *fp)
+{
+	/*
+	 * FIXME: Here we have to actually print all the machines in this
+	 * session, not just the host...
+	 */
+	return machine__fprintf(&session->host_machine, fp);
+}
+
+void perf_session__remove_thread(struct perf_session *session,
+				 struct thread *th)
+{
+	/*
+	 * FIXME: This one makes no sense, we need to remove the thread from
+	 * the machine it belongs to, perf_session can have many machines, so
+	 * doing it always on ->host_machine is wrong.  Fix when auditing all
+	 * the 'perf kvm' code.
+	 */
+	machine__remove_thread(&session->host_machine, th);
+}
+
 struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
 					      unsigned int type)
 {
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 6e393c9..76d462d 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -30,9 +30,6 @@ struct perf_session {
 	struct perf_header	header;
 	unsigned long		size;
 	unsigned long		mmap_window;
-	struct rb_root		threads;
-	struct list_head	dead_threads;
-	struct thread		*last_match;
 	struct machine		host_machine;
 	struct rb_root		machines;
 	struct perf_evlist	*evlist;
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index d5d3b22..fb4b7ea 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -61,7 +61,7 @@ static size_t thread__fprintf(struct thread *self, FILE *fp)
 	       map_groups__fprintf(&self->mg, verbose, fp);
 }
 
-struct thread *perf_session__findnew(struct perf_session *self, pid_t pid)
+struct thread *machine__findnew_thread(struct machine *self, pid_t pid)
 {
 	struct rb_node **p = &self->threads.rb_node;
 	struct rb_node *parent = NULL;
@@ -125,12 +125,12 @@ int thread__fork(struct thread *self, struct thread *parent)
 	return 0;
 }
 
-size_t perf_session__fprintf(struct perf_session *self, FILE *fp)
+size_t machine__fprintf(struct machine *machine, FILE *fp)
 {
 	size_t ret = 0;
 	struct rb_node *nd;
 
-	for (nd = rb_first(&self->threads); nd; nd = rb_next(nd)) {
+	for (nd = rb_first(&machine->threads); nd; nd = rb_next(nd)) {
 		struct thread *pos = rb_entry(nd, struct thread, rb_node);
 
 		ret += thread__fprintf(pos, fp);
-- 
1.7.8.rc0.35.gee6df


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

* [PATCH 10/25] perf record: Move 'group' to perf_event_ops
  2011-11-28 23:14 [GIT PULL 00/25] perf/core fixes and improvements Arnaldo Carvalho de Melo
                   ` (8 preceding siblings ...)
  2011-11-28 23:14 ` [PATCH 09/25] perf session: Move threads to struct machine Arnaldo Carvalho de Melo
@ 2011-11-28 23:14 ` Arnaldo Carvalho de Melo
  2011-11-28 23:14 ` [PATCH 11/25] perf ui progress: Fix divide by zero Arnaldo Carvalho de Melo
                   ` (14 subsequent siblings)
  24 siblings, 0 replies; 28+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-11-28 23:14 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Arnaldo Carvalho de Melo, David Ahern,
	Frederic Weisbecker, Mike Galbraith, Paul Mackerras,
	Peter Zijlstra, Stephane Eranian

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

Will be used in other tools to share the command line parsing code.

Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-8x0yr77r6lrd2t699s499m8n@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-record.c |    9 ++++-----
 tools/perf/perf.h           |    1 +
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index ffb627d..ba6777a 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -48,7 +48,6 @@ struct perf_record_opts record_opts = {
 static unsigned int		page_size;
 static int			output;
 static const char		*output_name			= NULL;
-static bool			group				=  false;
 static int			realtime_prio			=      0;
 static enum write_mode_t	write_mode			= WRITE_FORCE;
 static bool			no_buildid			=  false;
@@ -202,13 +201,13 @@ static void open_counters(struct perf_evlist *evlist)
 		 */
 		bool time_needed = attr->sample_type & PERF_SAMPLE_TIME;
 
-		if (group && pos != first)
+		if (record_opts.group && pos != first)
 			group_fd = first->fd;
 retry_sample_id:
 		attr->sample_id_all = record_opts.sample_id_all_avail ? 1 : 0;
 try_again:
-		if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group,
-				     group_fd) < 0) {
+		if (perf_evsel__open(pos, evlist->cpus, evlist->threads,
+				     record_opts.group, group_fd) < 0) {
 			int err = errno;
 
 			if (err == EPERM || err == EACCES) {
@@ -649,7 +648,7 @@ const struct option record_options[] = {
 	OPT_UINTEGER('F', "freq", &record_opts.user_freq, "profile at this frequency"),
 	OPT_UINTEGER('m', "mmap-pages", &record_opts.mmap_pages,
 		     "number of mmap data pages"),
-	OPT_BOOLEAN(0, "group", &group,
+	OPT_BOOLEAN(0, "group", &record_opts.group,
 		    "put the counters into a counter group"),
 	OPT_BOOLEAN('g', "call-graph", &record_opts.call_graph,
 		    "do call-graph (stack chain/backtrace) recording"),
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 13c42f3..ea804f5 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -189,6 +189,7 @@ struct perf_record_opts {
 	pid_t	     target_pid;
 	pid_t	     target_tid;
 	bool	     call_graph;
+	bool	     group;
 	bool	     inherit_stat;
 	bool	     no_delay;
 	bool	     no_inherit;
-- 
1.7.8.rc0.35.gee6df


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

* [PATCH 11/25] perf ui progress: Fix divide by zero
  2011-11-28 23:14 [GIT PULL 00/25] perf/core fixes and improvements Arnaldo Carvalho de Melo
                   ` (9 preceding siblings ...)
  2011-11-28 23:14 ` [PATCH 10/25] perf record: Move 'group' to perf_event_ops Arnaldo Carvalho de Melo
@ 2011-11-28 23:14 ` Arnaldo Carvalho de Melo
  2011-11-28 23:14 ` [PATCH 12/25] perf symbols: Add nr_events to symbol_conf Arnaldo Carvalho de Melo
                   ` (13 subsequent siblings)
  24 siblings, 0 replies; 28+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-11-28 23:14 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Arnaldo Carvalho de Melo, David Ahern,
	Frederic Weisbecker, Mike Galbraith, Paul Mackerras,
	Peter Zijlstra, Stephane Eranian

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

Happens in a perf.data file where one of the events had no samples.

Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-j7st3oyiotvfxqde2nc41kxb@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/ui/progress.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/tools/perf/util/ui/progress.c b/tools/perf/util/ui/progress.c
index 295e366..13aa64e 100644
--- a/tools/perf/util/ui/progress.c
+++ b/tools/perf/util/ui/progress.c
@@ -14,6 +14,9 @@ void ui_progress__update(u64 curr, u64 total, const char *title)
 	if (use_browser <= 0)
 		return;
 
+	if (total == 0)
+		return;
+
 	ui__refresh_dimensions(true);
 	pthread_mutex_lock(&ui__lock);
 	y = SLtt_Screen_Rows / 2 - 2;
-- 
1.7.8.rc0.35.gee6df


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

* [PATCH 12/25] perf symbols: Add nr_events to symbol_conf
  2011-11-28 23:14 [GIT PULL 00/25] perf/core fixes and improvements Arnaldo Carvalho de Melo
                   ` (10 preceding siblings ...)
  2011-11-28 23:14 ` [PATCH 11/25] perf ui progress: Fix divide by zero Arnaldo Carvalho de Melo
@ 2011-11-28 23:14 ` Arnaldo Carvalho de Melo
  2011-11-29  4:44   ` David Ahern
  2011-11-28 23:14 ` [PATCH 13/25] perf evlist: Introduce id_hdr_size method out of perf_session Arnaldo Carvalho de Melo
                   ` (12 subsequent siblings)
  24 siblings, 1 reply; 28+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-11-28 23:14 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Arnaldo Carvalho de Melo, David Ahern,
	Frederic Weisbecker, Mike Galbraith, Paul Mackerras,
	Peter Zijlstra, Stephane Eranian

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

Since symbol__alloc_hists need it, to avoid passing it around in many
functions have it in the symbol_conf struct.

Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-cwv8ysvpywzjq4v3xtbd4zwv@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-annotate.c          |   22 ++++++++--------------
 tools/perf/builtin-report.c            |    3 +--
 tools/perf/builtin-top.c               |    7 ++++---
 tools/perf/util/annotate.c             |    6 +++---
 tools/perf/util/annotate.h             |    5 ++---
 tools/perf/util/header.c               |    2 ++
 tools/perf/util/hist.h                 |    3 +--
 tools/perf/util/symbol.h               |    1 +
 tools/perf/util/ui/browsers/annotate.c |   16 +++++++---------
 tools/perf/util/ui/browsers/hists.c    |    2 +-
 10 files changed, 30 insertions(+), 37 deletions(-)

diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 46b4c24..8b9091b 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -43,10 +43,9 @@ static const char *sym_hist_filter;
 static const char	*cpu_list;
 static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
 
-static int perf_evlist__add_sample(struct perf_evlist *evlist,
-				   struct perf_sample *sample,
-				   struct perf_evsel *evsel,
-				   struct addr_location *al)
+static int perf_evsel__add_sample(struct perf_evsel *evsel,
+				  struct perf_sample *sample,
+				  struct addr_location *al)
 {
 	struct hist_entry *he;
 	int ret;
@@ -69,8 +68,7 @@ static int perf_evlist__add_sample(struct perf_evlist *evlist,
 	ret = 0;
 	if (he->ms.sym != NULL) {
 		struct annotation *notes = symbol__annotation(he->ms.sym);
-		if (notes->src == NULL &&
-		    symbol__alloc_hist(he->ms.sym, evlist->nr_entries) < 0)
+		if (notes->src == NULL && symbol__alloc_hist(he->ms.sym) < 0)
 			return -ENOMEM;
 
 		ret = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
@@ -98,8 +96,7 @@ static int process_sample_event(union perf_event *event,
 	if (cpu_list && !test_bit(sample->cpu, cpu_bitmap))
 		return 0;
 
-	if (!al.filtered &&
-	    perf_evlist__add_sample(session->evlist, sample, evsel, &al)) {
+	if (!al.filtered && perf_evsel__add_sample(evsel, sample, &al)) {
 		pr_warning("problem incrementing symbol count, "
 			   "skipping event\n");
 		return -1;
@@ -114,8 +111,7 @@ static int hist_entry__tty_annotate(struct hist_entry *he, int evidx)
 				    print_line, full_paths, 0, 0);
 }
 
-static void hists__find_annotations(struct hists *self, int evidx,
-				    int nr_events)
+static void hists__find_annotations(struct hists *self, int evidx)
 {
 	struct rb_node *nd = rb_first(&self->entries), *next;
 	int key = K_RIGHT;
@@ -138,8 +134,7 @@ find_next:
 		}
 
 		if (use_browser > 0) {
-			key = hist_entry__tui_annotate(he, evidx, nr_events,
-						       NULL, NULL, 0);
+			key = hist_entry__tui_annotate(he, evidx, NULL, NULL, 0);
 			switch (key) {
 			case K_RIGHT:
 				next = rb_next(nd);
@@ -217,8 +212,7 @@ static int __cmd_annotate(void)
 			total_nr_samples += nr_samples;
 			hists__collapse_resort(hists);
 			hists__output_resort(hists);
-			hists__find_annotations(hists, pos->idx,
-						session->evlist->nr_entries);
+			hists__find_annotations(hists, pos->idx);
 		}
 	}
 
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 4d7c834..758a287 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -92,8 +92,7 @@ static int perf_session__add_hist_entry(struct perf_session *session,
 		assert(evsel != NULL);
 
 		err = -ENOMEM;
-		if (notes->src == NULL &&
-		    symbol__alloc_hist(he->ms.sym, session->evlist->nr_entries) < 0)
+		if (notes->src == NULL && symbol__alloc_hist(he->ms.sym) < 0)
 			goto out;
 
 		err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index c9cdedb..04288ee 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -170,7 +170,7 @@ static int parse_source(struct hist_entry *he)
 
 	pthread_mutex_lock(&notes->lock);
 
-	if (symbol__alloc_hist(sym, top.evlist->nr_entries) < 0) {
+	if (symbol__alloc_hist(sym) < 0) {
 		pthread_mutex_unlock(&notes->lock);
 		pr_err("Not enough memory for annotating '%s' symbol!\n",
 		       sym->name);
@@ -210,8 +210,7 @@ static void record_precise_ip(struct hist_entry *he, int counter, u64 ip)
 	if (pthread_mutex_trylock(&notes->lock))
 		return;
 
-	if (notes->src == NULL &&
-	    symbol__alloc_hist(sym, top.evlist->nr_entries) < 0) {
+	if (notes->src == NULL && symbol__alloc_hist(sym) < 0) {
 		pthread_mutex_unlock(&notes->lock);
 		pr_err("Not enough memory for annotating '%s' symbol!\n",
 		       sym->name);
@@ -1215,6 +1214,8 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
 		return -ENOMEM;
 	}
 
+	symbol_conf.nr_events = top.evlist->nr_entries;
+
 	if (top.delay_secs < 1)
 		top.delay_secs = 1;
 
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 119e996..376e643 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -25,17 +25,17 @@ int symbol__annotate_init(struct map *map __used, struct symbol *sym)
 	return 0;
 }
 
-int symbol__alloc_hist(struct symbol *sym, int nevents)
+int symbol__alloc_hist(struct symbol *sym)
 {
 	struct annotation *notes = symbol__annotation(sym);
 	size_t sizeof_sym_hist = (sizeof(struct sym_hist) +
 				  (sym->end - sym->start) * sizeof(u64));
 
-	notes->src = zalloc(sizeof(*notes->src) + nevents * sizeof_sym_hist);
+	notes->src = zalloc(sizeof(*notes->src) + symbol_conf.nr_events * sizeof_sym_hist);
 	if (notes->src == NULL)
 		return -1;
 	notes->src->sizeof_sym_hist = sizeof_sym_hist;
-	notes->src->nr_histograms   = nevents;
+	notes->src->nr_histograms   = symbol_conf.nr_events;
 	INIT_LIST_HEAD(&notes->src->source);
 	return 0;
 }
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index d907252..efa5dc8 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -72,7 +72,7 @@ static inline struct annotation *symbol__annotation(struct symbol *sym)
 
 int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
 			     int evidx, u64 addr);
-int symbol__alloc_hist(struct symbol *sym, int nevents);
+int symbol__alloc_hist(struct symbol *sym);
 void symbol__annotate_zero_histograms(struct symbol *sym);
 
 int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize);
@@ -99,8 +99,7 @@ static inline int symbol__tui_annotate(struct symbol *sym __used,
 }
 #else
 int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
-			 int nr_events, void(*timer)(void *arg), void *arg,
-			 int delay_secs);
+			 void(*timer)(void *arg), void *arg, int delay_secs);
 #endif
 
 extern const char	*disassembler_style;
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index bcd05d0..41424a1 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2041,6 +2041,8 @@ int perf_session__read_header(struct perf_session *session, int fd)
 		lseek(fd, tmp, SEEK_SET);
 	}
 
+	symbol_conf.nr_events = nr_attrs;
+
 	if (f_header.event_types.size) {
 		lseek(fd, f_header.event_types.offset, SEEK_SET);
 		events = malloc(f_header.event_types.size);
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index c86c1d2..6676d55 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -119,7 +119,6 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __used,
 
 static inline int hist_entry__tui_annotate(struct hist_entry *self __used,
 					   int evidx __used,
-					   int nr_events __used,
 					   void(*timer)(void *arg) __used,
 					   void *arg __used,
 					   int delay_secs __used)
@@ -130,7 +129,7 @@ static inline int hist_entry__tui_annotate(struct hist_entry *self __used,
 #define K_RIGHT -2
 #else
 #include "ui/keysyms.h"
-int hist_entry__tui_annotate(struct hist_entry *he, int evidx, int nr_events,
+int hist_entry__tui_annotate(struct hist_entry *he, int evidx,
 			     void(*timer)(void *arg), void *arg, int delay_secs);
 
 int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 29f8d74..123c2e1 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -68,6 +68,7 @@ struct strlist;
 
 struct symbol_conf {
 	unsigned short	priv_size;
+	unsigned short	nr_events;
 	bool		try_vmlinux_path,
 			use_modules,
 			sort_by_name,
diff --git a/tools/perf/util/ui/browsers/annotate.c b/tools/perf/util/ui/browsers/annotate.c
index 0575905..295a9c9 100644
--- a/tools/perf/util/ui/browsers/annotate.c
+++ b/tools/perf/util/ui/browsers/annotate.c
@@ -224,7 +224,7 @@ static bool annotate_browser__toggle_source(struct annotate_browser *browser)
 }
 
 static int annotate_browser__run(struct annotate_browser *self, int evidx,
-				 int nr_events, void(*timer)(void *arg),
+				 void(*timer)(void *arg),
 				 void *arg, int delay_secs)
 {
 	struct rb_node *nd = NULL;
@@ -328,8 +328,7 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx,
 				notes = symbol__annotation(target);
 				pthread_mutex_lock(&notes->lock);
 
-				if (notes->src == NULL &&
-				    symbol__alloc_hist(target, nr_events) < 0) {
+				if (notes->src == NULL && symbol__alloc_hist(target) < 0) {
 					pthread_mutex_unlock(&notes->lock);
 					ui__warning("Not enough memory for annotating '%s' symbol!\n",
 						    target->name);
@@ -337,7 +336,7 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx,
 				}
 
 				pthread_mutex_unlock(&notes->lock);
-				symbol__tui_annotate(target, ms->map, evidx, nr_events,
+				symbol__tui_annotate(target, ms->map, evidx,
 						     timer, arg, delay_secs);
 			}
 			continue;
@@ -358,15 +357,15 @@ out:
 	return key;
 }
 
-int hist_entry__tui_annotate(struct hist_entry *he, int evidx, int nr_events,
+int hist_entry__tui_annotate(struct hist_entry *he, int evidx,
 			     void(*timer)(void *arg), void *arg, int delay_secs)
 {
-	return symbol__tui_annotate(he->ms.sym, he->ms.map, evidx, nr_events,
+	return symbol__tui_annotate(he->ms.sym, he->ms.map, evidx,
 				    timer, arg, delay_secs);
 }
 
 int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
-			 int nr_events, void(*timer)(void *arg), void *arg,
+			 void(*timer)(void *arg), void *arg,
 			 int delay_secs)
 {
 	struct objdump_line *pos, *n;
@@ -419,8 +418,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
 	browser.b.nr_entries = browser.nr_entries;
 	browser.b.entries = &notes->src->source,
 	browser.b.width += 18; /* Percentage */
-	ret = annotate_browser__run(&browser, evidx, nr_events,
-				    timer, arg, delay_secs);
+	ret = annotate_browser__run(&browser, evidx, timer, arg, delay_secs);
 	list_for_each_entry_safe(pos, n, &notes->src->source, node) {
 		list_del(&pos->node);
 		objdump_line__free(pos);
diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c
index d0c94b4..1212a38 100644
--- a/tools/perf/util/ui/browsers/hists.c
+++ b/tools/perf/util/ui/browsers/hists.c
@@ -1020,7 +1020,7 @@ do_annotate:
 			 * Don't let this be freed, say, by hists__decay_entry.
 			 */
 			he->used = true;
-			err = hist_entry__tui_annotate(he, evsel->idx, nr_events,
+			err = hist_entry__tui_annotate(he, evsel->idx,
 						       timer, arg, delay_secs);
 			he->used = false;
 			ui_browser__update_nr_entries(&browser->b, browser->hists->nr_entries);
-- 
1.7.8.rc0.35.gee6df


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

* [PATCH 13/25] perf evlist: Introduce id_hdr_size method out of perf_session
  2011-11-28 23:14 [GIT PULL 00/25] perf/core fixes and improvements Arnaldo Carvalho de Melo
                   ` (11 preceding siblings ...)
  2011-11-28 23:14 ` [PATCH 12/25] perf symbols: Add nr_events to symbol_conf Arnaldo Carvalho de Melo
@ 2011-11-28 23:14 ` Arnaldo Carvalho de Melo
  2011-11-28 23:14 ` [PATCH 14/25] perf event: perf_event_ops->attr() manipulates only an evlist Arnaldo Carvalho de Melo
                   ` (11 subsequent siblings)
  24 siblings, 0 replies; 28+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-11-28 23:14 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Arnaldo Carvalho de Melo, David Ahern,
	Frederic Weisbecker, Mike Galbraith, Paul Mackerras,
	Peter Zijlstra, Stephane Eranian

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

We will need this when not using perf_session in cases like 'perf top'
and strace where no perf.data file is created nor consumed.

Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-za923wjc41q5xot5vrhuhj3j@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/evlist.c  |   32 ++++++++++++++++++++++++++++++++
 tools/perf/util/evlist.h  |    1 +
 tools/perf/util/session.c |   29 +----------------------------
 3 files changed, 34 insertions(+), 28 deletions(-)

diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 81237dc..d44e3df 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -625,6 +625,38 @@ u64 perf_evlist__sample_type(const struct perf_evlist *evlist)
 	return first->attr.sample_type;
 }
 
+u16 perf_evlist__id_hdr_size(const struct perf_evlist *evlist)
+{
+	struct perf_evsel *first;
+	struct perf_sample *data;
+	u64 sample_type;
+	u16 size = 0;
+
+	first = list_entry(evlist->entries.next, struct perf_evsel, node);
+
+	if (!first->attr.sample_id_all)
+		goto out;
+
+	sample_type = first->attr.sample_type;
+
+	if (sample_type & PERF_SAMPLE_TID)
+		size += sizeof(data->tid) * 2;
+
+       if (sample_type & PERF_SAMPLE_TIME)
+		size += sizeof(data->time);
+
+	if (sample_type & PERF_SAMPLE_ID)
+		size += sizeof(data->id);
+
+	if (sample_type & PERF_SAMPLE_STREAM_ID)
+		size += sizeof(data->stream_id);
+
+	if (sample_type & PERF_SAMPLE_CPU)
+		size += sizeof(data->cpu) * 2;
+out:
+	return size;
+}
+
 bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist)
 {
 	struct perf_evsel *pos, *first;
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 17e9c80..2202e7b 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -104,6 +104,7 @@ int perf_evlist__set_filters(struct perf_evlist *evlist);
 
 u64 perf_evlist__sample_type(const struct perf_evlist *evlist);
 bool perf_evlist__sample_id_all(const const struct perf_evlist *evlist);
+u16 perf_evlist__id_hdr_size(const struct perf_evlist *evlist);
 
 bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist);
 bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index a76666f..675e080 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -78,39 +78,12 @@ out_close:
 	return -1;
 }
 
-static void perf_session__id_header_size(struct perf_session *session)
-{
-       struct perf_sample *data;
-       u64 sample_type = session->sample_type;
-       u16 size = 0;
-
-	if (!session->sample_id_all)
-		goto out;
-
-       if (sample_type & PERF_SAMPLE_TID)
-               size += sizeof(data->tid) * 2;
-
-       if (sample_type & PERF_SAMPLE_TIME)
-               size += sizeof(data->time);
-
-       if (sample_type & PERF_SAMPLE_ID)
-               size += sizeof(data->id);
-
-       if (sample_type & PERF_SAMPLE_STREAM_ID)
-               size += sizeof(data->stream_id);
-
-       if (sample_type & PERF_SAMPLE_CPU)
-               size += sizeof(data->cpu) * 2;
-out:
-       session->id_hdr_size = size;
-}
-
 void perf_session__update_sample_type(struct perf_session *self)
 {
 	self->sample_type = perf_evlist__sample_type(self->evlist);
 	self->sample_size = __perf_evsel__sample_size(self->sample_type);
 	self->sample_id_all = perf_evlist__sample_id_all(self->evlist);
-	perf_session__id_header_size(self);
+	self->id_hdr_size = perf_evlist__id_hdr_size(self->evlist);
 }
 
 int perf_session__create_kernel_maps(struct perf_session *self)
-- 
1.7.8.rc0.35.gee6df


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

* [PATCH 14/25] perf event: perf_event_ops->attr() manipulates only an evlist
  2011-11-28 23:14 [GIT PULL 00/25] perf/core fixes and improvements Arnaldo Carvalho de Melo
                   ` (12 preceding siblings ...)
  2011-11-28 23:14 ` [PATCH 13/25] perf evlist: Introduce id_hdr_size method out of perf_session Arnaldo Carvalho de Melo
@ 2011-11-28 23:14 ` Arnaldo Carvalho de Melo
  2011-11-28 23:14 ` [PATCH 15/25] perf session: Remove superfluous callchain_cursor member Arnaldo Carvalho de Melo
                   ` (10 subsequent siblings)
  24 siblings, 0 replies; 28+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-11-28 23:14 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Arnaldo Carvalho de Melo, David Ahern,
	Frederic Weisbecker, Mike Galbraith, Paul Mackerras,
	Peter Zijlstra, Stephane Eranian

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

Removing another case where a perf_session is required when processing
events.

Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-ug1wtjbnva4bxwknflkkrlrh@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-inject.c |    8 +++++++-
 tools/perf/util/header.c    |   19 ++++++++-----------
 tools/perf/util/header.h    |    2 +-
 tools/perf/util/session.c   |   16 ++++++++++++++--
 tools/perf/util/session.h   |    6 ++++--
 5 files changed, 34 insertions(+), 17 deletions(-)

diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 8dfc12b..978751e 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -36,6 +36,12 @@ static int perf_event__repipe_synth(union perf_event *event,
 	return 0;
 }
 
+static int perf_event__repipe_attr(union perf_event *event,
+				   struct perf_evlist **pevlist __used)
+{
+	return perf_event__repipe_synth(event, NULL);
+}
+
 static int perf_event__repipe(union perf_event *event,
 			      struct perf_sample *sample __used,
 			      struct perf_session *session)
@@ -182,7 +188,7 @@ struct perf_event_ops inject_ops = {
 	.read		= perf_event__repipe,
 	.throttle	= perf_event__repipe,
 	.unthrottle	= perf_event__repipe,
-	.attr		= perf_event__repipe_synth,
+	.attr		= perf_event__repipe_attr,
 	.event_type 	= perf_event__repipe_synth,
 	.tracing_data 	= perf_event__repipe_synth,
 	.build_id 	= perf_event__repipe_synth,
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 41424a1..1fa97dd 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2120,23 +2120,23 @@ int perf_session__synthesize_attrs(struct perf_session *session,
 }
 
 int perf_event__process_attr(union perf_event *event,
-			     struct perf_session *session)
+			     struct perf_evlist **pevlist)
 {
 	unsigned int i, ids, n_ids;
 	struct perf_evsel *evsel;
+	struct perf_evlist *evlist = *pevlist;
 
-	if (session->evlist == NULL) {
-		session->evlist = perf_evlist__new(NULL, NULL);
-		if (session->evlist == NULL)
+	if (evlist == NULL) {
+		*pevlist = evlist = perf_evlist__new(NULL, NULL);
+		if (evlist == NULL)
 			return -ENOMEM;
 	}
 
-	evsel = perf_evsel__new(&event->attr.attr,
-				session->evlist->nr_entries);
+	evsel = perf_evsel__new(&event->attr.attr, evlist->nr_entries);
 	if (evsel == NULL)
 		return -ENOMEM;
 
-	perf_evlist__add(session->evlist, evsel);
+	perf_evlist__add(evlist, evsel);
 
 	ids = event->header.size;
 	ids -= (void *)&event->attr.id - (void *)event;
@@ -2150,12 +2150,9 @@ int perf_event__process_attr(union perf_event *event,
 		return -ENOMEM;
 
 	for (i = 0; i < n_ids; i++) {
-		perf_evlist__id_add(session->evlist, evsel, 0, i,
-				    event->attr.id[i]);
+		perf_evlist__id_add(evlist, evsel, 0, i, event->attr.id[i]);
 	}
 
-	perf_session__update_sample_type(session);
-
 	return 0;
 }
 
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 3d5a742..0a88982 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -101,7 +101,7 @@ int perf_event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id,
 				struct perf_session *session);
 int perf_session__synthesize_attrs(struct perf_session *session,
 				   perf_event__handler_t process);
-int perf_event__process_attr(union perf_event *event, struct perf_session *session);
+int perf_event__process_attr(union perf_event *event, struct perf_evlist **pevlist);
 
 int perf_event__synthesize_event_type(u64 event_id, char *name,
 				      perf_event__handler_t process,
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 675e080..6e7d5f5 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -277,6 +277,13 @@ static int process_event_synth_stub(union perf_event *event __used,
 	return 0;
 }
 
+static int process_event_synth_attr_stub(union perf_event *event __used,
+					 struct perf_evlist **pevlist __used)
+{
+	dump_printf(": unhandled!\n");
+	return 0;
+}
+
 static int process_event_sample_stub(union perf_event *event __used,
 				     struct perf_sample *sample __used,
 				     struct perf_evsel *evsel __used,
@@ -327,7 +334,7 @@ static void perf_event_ops__fill_defaults(struct perf_event_ops *handler)
 	if (handler->unthrottle == NULL)
 		handler->unthrottle = process_event_stub;
 	if (handler->attr == NULL)
-		handler->attr = process_event_synth_stub;
+		handler->attr = process_event_synth_attr_stub;
 	if (handler->event_type == NULL)
 		handler->event_type = process_event_synth_stub;
 	if (handler->tracing_data == NULL)
@@ -794,12 +801,17 @@ static int perf_session__preprocess_sample(struct perf_session *session,
 static int perf_session__process_user_event(struct perf_session *session, union perf_event *event,
 					    struct perf_event_ops *ops, u64 file_offset)
 {
+	int err;
+
 	dump_event(session, event, file_offset, NULL);
 
 	/* These events are processed right away */
 	switch (event->header.type) {
 	case PERF_RECORD_HEADER_ATTR:
-		return ops->attr(event, session);
+		err = ops->attr(event, &session->evlist);
+		if (err == 0)
+			perf_session__update_sample_type(session);
+		return err;
 	case PERF_RECORD_HEADER_EVENT_TYPE:
 		return ops->event_type(event, session);
 	case PERF_RECORD_HEADER_TRACING_DATA:
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 76d462d..13bd5e0 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -63,6 +63,8 @@ typedef int (*event_op)(union perf_event *self, struct perf_sample *sample,
 			struct perf_session *session);
 typedef int (*event_synth_op)(union perf_event *self,
 			      struct perf_session *session);
+typedef int (*event_attr_op)(union perf_event *event,
+			     struct perf_evlist **pevlist);
 typedef int (*event_op2)(union perf_event *self, struct perf_session *session,
 			 struct perf_event_ops *ops);
 
@@ -76,8 +78,8 @@ struct perf_event_ops {
 			read,
 			throttle,
 			unthrottle;
-	event_synth_op	attr,
-			event_type,
+	event_attr_op	attr;
+	event_synth_op	event_type,
 			tracing_data,
 			build_id;
 	event_op2	finished_round;
-- 
1.7.8.rc0.35.gee6df


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

* [PATCH 15/25] perf session: Remove superfluous callchain_cursor member
  2011-11-28 23:14 [GIT PULL 00/25] perf/core fixes and improvements Arnaldo Carvalho de Melo
                   ` (13 preceding siblings ...)
  2011-11-28 23:14 ` [PATCH 14/25] perf event: perf_event_ops->attr() manipulates only an evlist Arnaldo Carvalho de Melo
@ 2011-11-28 23:14 ` Arnaldo Carvalho de Melo
  2011-11-28 23:14 ` [PATCH 16/25] perf tools: Use evsel->attr.sample_type instead of session->sample_type Arnaldo Carvalho de Melo
                   ` (9 subsequent siblings)
  24 siblings, 0 replies; 28+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-11-28 23:14 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Arnaldo Carvalho de Melo, David Ahern,
	Frederic Weisbecker, Mike Galbraith, Paul Mackerras,
	Peter Zijlstra, Stephane Eranian

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

Since we have it in evsel->hists.callchain_cursor, remove it from
perf_session.

One more step in disentangling several places from requiring a
perf_session pointer.

Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-rxr5dj3di7ckyfmnz0naku1z@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-report.c |    5 +++--
 tools/perf/builtin-script.c |    2 +-
 tools/perf/builtin-top.c    |    4 ++--
 tools/perf/util/session.c   |   12 ++++++------
 tools/perf/util/session.h   |    5 ++---
 5 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 758a287..b7ab373 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -65,7 +65,7 @@ static int perf_session__add_hist_entry(struct perf_session *session,
 	struct hist_entry *he;
 
 	if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) {
-		err = perf_session__resolve_callchain(session, al->thread,
+		err = perf_session__resolve_callchain(session, evsel, al->thread,
 						      sample->callchain, &parent);
 		if (err)
 			return err;
@@ -76,7 +76,8 @@ static int perf_session__add_hist_entry(struct perf_session *session,
 		return -ENOMEM;
 
 	if (symbol_conf.use_callchain) {
-		err = callchain_append(he->callchain, &session->callchain_cursor,
+		err = callchain_append(he->callchain,
+				       &evsel->hists.callchain_cursor,
 				       sample->period);
 		if (err)
 			return err;
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 2f62a29..47545e9 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -384,7 +384,7 @@ static void process_event(union perf_event *event __unused,
 			printf(" ");
 		else
 			printf("\n");
-		perf_session__print_ip(event, sample, session,
+		perf_session__print_ip(event, evsel, sample, session,
 					      PRINT_FIELD(SYM), PRINT_FIELD(DSO));
 	}
 
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 04288ee..9b3bbb4 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -777,7 +777,7 @@ static void perf_event__process_sample(const union perf_event *event,
 
 		if ((sort__has_parent || symbol_conf.use_callchain) &&
 		    sample->callchain) {
-			err = perf_session__resolve_callchain(session, al.thread,
+			err = perf_session__resolve_callchain(session, evsel, al.thread,
 							      sample->callchain, &parent);
 			if (err)
 				return;
@@ -790,7 +790,7 @@ static void perf_event__process_sample(const union perf_event *event,
 		}
 
 		if (symbol_conf.use_callchain) {
-			err = callchain_append(he->callchain, &session->callchain_cursor,
+			err = callchain_append(he->callchain, &evsel->hists.callchain_cursor,
 					       sample->period);
 			if (err)
 				return;
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 6e7d5f5..734358b 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -216,7 +216,7 @@ static bool symbol__match_parent_regex(struct symbol *sym)
 	return 0;
 }
 
-int perf_session__resolve_callchain(struct perf_session *self,
+int perf_session__resolve_callchain(struct perf_session *self, struct perf_evsel *evsel,
 				    struct thread *thread,
 				    struct ip_callchain *chain,
 				    struct symbol **parent)
@@ -225,7 +225,7 @@ int perf_session__resolve_callchain(struct perf_session *self,
 	unsigned int i;
 	int err;
 
-	callchain_cursor_reset(&self->callchain_cursor);
+	callchain_cursor_reset(&evsel->hists.callchain_cursor);
 
 	for (i = 0; i < chain->nr; i++) {
 		u64 ip;
@@ -261,7 +261,7 @@ int perf_session__resolve_callchain(struct perf_session *self,
 				break;
 		}
 
-		err = callchain_cursor_append(&self->callchain_cursor,
+		err = callchain_cursor_append(&evsel->hists.callchain_cursor,
 					      ip, al.map, al.sym);
 		if (err)
 			return err;
@@ -1254,14 +1254,14 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
 	return NULL;
 }
 
-void perf_session__print_ip(union perf_event *event,
+void perf_session__print_ip(union perf_event *event, struct perf_evsel *evsel,
 			    struct perf_sample *sample,
 			    struct perf_session *session,
 			    int print_sym, int print_dso)
 {
 	struct addr_location al;
 	const char *symname, *dsoname;
-	struct callchain_cursor *cursor = &session->callchain_cursor;
+	struct callchain_cursor *cursor = &evsel->hists.callchain_cursor;
 	struct callchain_cursor_node *node;
 
 	if (perf_event__preprocess_sample(event, session, &al, sample,
@@ -1273,7 +1273,7 @@ void perf_session__print_ip(union perf_event *event,
 
 	if (symbol_conf.use_callchain && sample->callchain) {
 
-		if (perf_session__resolve_callchain(session, al.thread,
+		if (perf_session__resolve_callchain(session, evsel, al.thread,
 						sample->callchain, NULL) != 0) {
 			if (verbose)
 				error("Failed to resolve callchain. Skipping\n");
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 13bd5e0..d2f4303 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -50,7 +50,6 @@ struct perf_session {
 	int			cwdlen;
 	char			*cwd;
 	struct ordered_samples	ordered_samples;
-	struct callchain_cursor	callchain_cursor;
 	char			filename[0];
 };
 
@@ -100,7 +99,7 @@ int __perf_session__process_events(struct perf_session *self,
 int perf_session__process_events(struct perf_session *self,
 				 struct perf_event_ops *event_ops);
 
-int perf_session__resolve_callchain(struct perf_session *self,
+int perf_session__resolve_callchain(struct perf_session *self, struct perf_evsel *evsel,
 				    struct thread *thread,
 				    struct ip_callchain *chain,
 				    struct symbol **parent);
@@ -169,7 +168,7 @@ static inline int perf_session__parse_sample(struct perf_session *session,
 struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
 					    unsigned int type);
 
-void perf_session__print_ip(union perf_event *event,
+void perf_session__print_ip(union perf_event *event, struct perf_evsel *evsel,
 				 struct perf_sample *sample,
 				 struct perf_session *session,
 				 int print_sym, int print_dso);
-- 
1.7.8.rc0.35.gee6df


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

* [PATCH 16/25] perf tools: Use evsel->attr.sample_type instead of session->sample_type
  2011-11-28 23:14 [GIT PULL 00/25] perf/core fixes and improvements Arnaldo Carvalho de Melo
                   ` (14 preceding siblings ...)
  2011-11-28 23:14 ` [PATCH 15/25] perf session: Remove superfluous callchain_cursor member Arnaldo Carvalho de Melo
@ 2011-11-28 23:14 ` Arnaldo Carvalho de Melo
  2011-11-28 23:14 ` [PATCH 17/25] perf report: Group options in a struct Arnaldo Carvalho de Melo
                   ` (8 subsequent siblings)
  24 siblings, 0 replies; 28+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-11-28 23:14 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Arnaldo Carvalho de Melo, David Ahern,
	Frederic Weisbecker, Mike Galbraith, Paul Mackerras,
	Peter Zijlstra, Stephane Eranian

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

Eventually session->sample_type will go away as we want to support
multiple sample types per session, so use it from the evsel which is a
step in that direction.

Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-0vwdpjcwbjezw459lw5n3ew1@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-sched.c     |    5 +++--
 tools/perf/builtin-timechart.c |    9 +++++----
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 5177964..d51af0b 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -3,6 +3,7 @@
 
 #include "util/util.h"
 #include "util/cache.h"
+#include "util/evsel.h"
 #include "util/symbol.h"
 #include "util/thread.h"
 #include "util/header.h"
@@ -1603,12 +1604,12 @@ static void process_raw_event(union perf_event *raw_event __used,
 
 static int process_sample_event(union perf_event *event,
 				struct perf_sample *sample,
-				struct perf_evsel *evsel __used,
+				struct perf_evsel *evsel,
 				struct perf_session *session)
 {
 	struct thread *thread;
 
-	if (!(session->sample_type & PERF_SAMPLE_RAW))
+	if (!(evsel->attr.sample_type & PERF_SAMPLE_RAW))
 		return 0;
 
 	thread = perf_session__findnew(session, sample->pid);
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index aa26f4d..3fc52b1 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -19,6 +19,7 @@
 #include "util/color.h"
 #include <linux/list.h>
 #include "util/cache.h"
+#include "util/evsel.h"
 #include <linux/rbtree.h>
 #include "util/symbol.h"
 #include "util/callchain.h"
@@ -488,12 +489,12 @@ static void sched_switch(int cpu, u64 timestamp, struct trace_entry *te)
 
 static int process_sample_event(union perf_event *event __used,
 				struct perf_sample *sample,
-				struct perf_evsel *evsel __used,
-				struct perf_session *session)
+				struct perf_evsel *evsel,
+				struct perf_session *session __used)
 {
 	struct trace_entry *te;
 
-	if (session->sample_type & PERF_SAMPLE_TIME) {
+	if (evsel->attr.sample_type & PERF_SAMPLE_TIME) {
 		if (!first_time || first_time > sample->time)
 			first_time = sample->time;
 		if (last_time < sample->time)
@@ -501,7 +502,7 @@ static int process_sample_event(union perf_event *event __used,
 	}
 
 	te = (void *)sample->raw_data;
-	if (session->sample_type & PERF_SAMPLE_RAW && sample->raw_size > 0) {
+	if ((evsel->attr.sample_type & PERF_SAMPLE_RAW) && sample->raw_size > 0) {
 		char *event_str;
 #ifdef SUPPORT_OLD_POWER_EVENTS
 		struct power_entry_old *peo;
-- 
1.7.8.rc0.35.gee6df


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

* [PATCH 17/25] perf report: Group options in a struct
  2011-11-28 23:14 [GIT PULL 00/25] perf/core fixes and improvements Arnaldo Carvalho de Melo
                   ` (15 preceding siblings ...)
  2011-11-28 23:14 ` [PATCH 16/25] perf tools: Use evsel->attr.sample_type instead of session->sample_type Arnaldo Carvalho de Melo
@ 2011-11-28 23:14 ` Arnaldo Carvalho de Melo
  2011-11-28 23:14 ` [PATCH 18/25] perf annotate: " Arnaldo Carvalho de Melo
                   ` (7 subsequent siblings)
  24 siblings, 0 replies; 28+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-11-28 23:14 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Arnaldo Carvalho de Melo, David Ahern,
	Frederic Weisbecker, Mike Galbraith, Paul Mackerras,
	Peter Zijlstra, Stephane Eranian

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

Paving the way to remove these globals when we change the perf_event_ops
to receive as a first parameter a pointer to a perf_event_ops that will
then provide access to perf_report via container_of.

Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-2eh2vi2nb5z3tg1lvoxv09xu@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-report.c |  111 +++++++++++++++++++++++--------------------
 1 files changed, 59 insertions(+), 52 deletions(-)

diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index b7ab373..5d2e819 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -35,25 +35,25 @@
 
 #include <linux/bitmap.h>
 
-static char		const *input_name = "perf.data";
-
-static bool		force, use_tui, use_stdio;
-static bool		hide_unresolved;
-static bool		dont_use_callchains;
-static bool		show_full_info;
-
-static bool		show_threads;
-static struct perf_read_values	show_threads_values;
-
-static const char	default_pretty_printing_style[] = "normal";
-static const char	*pretty_printing_style = default_pretty_printing_style;
-
-static char		callchain_default_opt[] = "fractal,0.5,callee";
-static bool		inverted_callchain;
-static symbol_filter_t	annotate_init;
-
-static const char	*cpu_list;
-static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
+static struct perf_report {
+	char const		*input_name;
+	bool			force, use_tui, use_stdio;
+	bool			hide_unresolved;
+	bool			dont_use_callchains;
+	bool			show_full_info;
+	bool			show_threads;
+	bool			inverted_callchain;
+	struct perf_read_values	show_threads_values;
+	const char		*pretty_printing_style;
+	symbol_filter_t		annotate_init;
+	const char		*cpu_list;
+	DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
+} report = {
+	.input_name	       = "perf.data",
+	.pretty_printing_style = "normal",
+}, *rep = &report;
+
+static char callchain_default_opt[] = "fractal,0.5,callee";
 
 static int perf_session__add_hist_entry(struct perf_session *session,
 					struct addr_location *al,
@@ -114,16 +114,16 @@ static int process_sample_event(union perf_event *event,
 	struct addr_location al;
 
 	if (perf_event__preprocess_sample(event, session, &al, sample,
-					  annotate_init) < 0) {
+					  rep->annotate_init) < 0) {
 		fprintf(stderr, "problem processing %d event, skipping it.\n",
 			event->header.type);
 		return -1;
 	}
 
-	if (al.filtered || (hide_unresolved && al.sym == NULL))
+	if (al.filtered || (rep->hide_unresolved && al.sym == NULL))
 		return 0;
 
-	if (cpu_list && !test_bit(sample->cpu, cpu_bitmap))
+	if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap))
 		return 0;
 
 	if (al.map != NULL)
@@ -143,9 +143,9 @@ static int process_read_event(union perf_event *event,
 {
 	struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist,
 							 event->read.id);
-	if (show_threads) {
+	if (rep->show_threads) {
 		const char *name = evsel ? event_name(evsel) : "unknown";
-		perf_read_values_add_value(&show_threads_values,
+		perf_read_values_add_value(&rep->show_threads_values,
 					   event->read.pid, event->read.tid,
 					   event->read.id,
 					   name,
@@ -173,7 +173,8 @@ static int perf_session__setup_sample_type(struct perf_session *self)
 				    "you call 'perf record' without -g?\n");
 			return -1;
 		}
-	} else if (!dont_use_callchains && callchain_param.mode != CHAIN_NONE &&
+	} else if (!rep->dont_use_callchains &&
+		   callchain_param.mode != CHAIN_NONE &&
 		   !symbol_conf.use_callchain) {
 			symbol_conf.use_callchain = true;
 			if (callchain_register_param(&callchain_param) < 0) {
@@ -241,11 +242,11 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
 	    parent_pattern == default_parent_pattern) {
 		fprintf(stdout, "#\n# (%s)\n#\n", help);
 
-		if (show_threads) {
-			bool style = !strcmp(pretty_printing_style, "raw");
-			perf_read_values_display(stdout, &show_threads_values,
+		if (rep->show_threads) {
+			bool style = !strcmp(rep->pretty_printing_style, "raw");
+			perf_read_values_display(stdout, &rep->show_threads_values,
 						 style);
-			perf_read_values_destroy(&show_threads_values);
+			perf_read_values_destroy(&rep->show_threads_values);
 		}
 	}
 
@@ -264,21 +265,23 @@ static int __cmd_report(void)
 
 	signal(SIGINT, sig_handler);
 
-	session = perf_session__new(input_name, O_RDONLY, force, false, &event_ops);
+	session = perf_session__new(rep->input_name, O_RDONLY,
+				    rep->force, false, &event_ops);
 	if (session == NULL)
 		return -ENOMEM;
 
-	if (cpu_list) {
-		ret = perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap);
+	if (rep->cpu_list) {
+		ret = perf_session__cpu_bitmap(session, rep->cpu_list,
+					       rep->cpu_bitmap);
 		if (ret)
 			goto out_delete;
 	}
 
 	if (use_browser <= 0)
-		perf_session__fprintf_info(session, stdout, show_full_info);
+		perf_session__fprintf_info(session, stdout, rep->show_full_info);
 
-	if (show_threads)
-		perf_read_values_init(&show_threads_values);
+	if (rep->show_threads)
+		perf_read_values_init(&rep->show_threads_values);
 
 	ret = perf_session__setup_sample_type(session);
 	if (ret)
@@ -327,7 +330,8 @@ static int __cmd_report(void)
 	}
 
 	if (nr_samples == 0) {
-		ui__warning("The %s file has no samples!\n", input_name);
+		ui__warning("The %s file has no samples!\n",
+			    rep->input_name);
 		goto out_delete;
 	}
 
@@ -364,7 +368,7 @@ parse_callchain_opt(const struct option *opt __used, const char *arg,
 	 * --no-call-graph
 	 */
 	if (unset) {
-		dont_use_callchains = true;
+		rep->dont_use_callchains = true;
 		return 0;
 	}
 
@@ -439,7 +443,7 @@ static const char * const report_usage[] = {
 };
 
 static const struct option options[] = {
-	OPT_STRING('i', "input", &input_name, "file",
+	OPT_STRING('i', "input", &report.input_name, "file",
 		    "input file name"),
 	OPT_INCR('v', "verbose", &verbose,
 		    "be more verbose (show symbol address, etc)"),
@@ -449,17 +453,18 @@ static const struct option options[] = {
 		   "file", "vmlinux pathname"),
 	OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
 		   "file", "kallsyms pathname"),
-	OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
+	OPT_BOOLEAN('f', "force", &report.force, "don't complain, do it"),
 	OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
 		    "load module symbols - WARNING: use only with -k and LIVE kernel"),
 	OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
 		    "Show a column with the number of samples"),
-	OPT_BOOLEAN('T', "threads", &show_threads,
+	OPT_BOOLEAN('T', "threads", &report.show_threads,
 		    "Show per-thread event counters"),
-	OPT_STRING(0, "pretty", &pretty_printing_style, "key",
+	OPT_STRING(0, "pretty", &report.pretty_printing_style, "key",
 		   "pretty printing style key: normal raw"),
-	OPT_BOOLEAN(0, "tui", &use_tui, "Use the TUI interface"),
-	OPT_BOOLEAN(0, "stdio", &use_stdio, "Use the stdio interface"),
+	OPT_BOOLEAN(0, "tui", &report.use_tui, "Use the TUI interface"),
+	OPT_BOOLEAN(0, "stdio", &report.use_stdio,
+		    "Use the stdio interface"),
 	OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
 		   "sort by key(s): pid, comm, dso, symbol, parent"),
 	OPT_BOOLEAN(0, "showcpuutilization", &symbol_conf.show_cpu_utilization,
@@ -471,7 +476,8 @@ static const struct option options[] = {
 	OPT_CALLBACK_DEFAULT('g', "call-graph", NULL, "output_type,min_percent, call_order",
 		     "Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold and callchain order. "
 		     "Default: fractal,0.5,callee", &parse_callchain_opt, callchain_default_opt),
-	OPT_BOOLEAN('G', "inverted", &inverted_callchain, "alias for inverted call graph"),
+	OPT_BOOLEAN('G', "inverted", &report.inverted_callchain,
+		    "alias for inverted call graph"),
 	OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
 		   "only consider symbols in these dsos"),
 	OPT_STRING('C', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
@@ -484,12 +490,13 @@ static const struct option options[] = {
 	OPT_STRING('t', "field-separator", &symbol_conf.field_sep, "separator",
 		   "separator for columns, no spaces will be added between "
 		   "columns '.' is reserved."),
-	OPT_BOOLEAN('U', "hide-unresolved", &hide_unresolved,
+	OPT_BOOLEAN('U', "hide-unresolved", &report.hide_unresolved,
 		    "Only display entries resolved to a symbol"),
 	OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
 		    "Look for files with symbols relative to this directory"),
-	OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
-	OPT_BOOLEAN('I', "show-info", &show_full_info,
+	OPT_STRING('c', "cpu", &report.cpu_list, "cpu",
+		   "list of cpus to profile"),
+	OPT_BOOLEAN('I', "show-info", &report.show_full_info,
 		    "Display extended information about perf.data file"),
 	OPT_BOOLEAN(0, "source", &symbol_conf.annotate_src,
 		    "Interleave source code with assembly code (default)"),
@@ -506,15 +513,15 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
 {
 	argc = parse_options(argc, argv, options, report_usage, 0);
 
-	if (use_stdio)
+	if (report.use_stdio)
 		use_browser = 0;
-	else if (use_tui)
+	else if (report.use_tui)
 		use_browser = 1;
 
-	if (inverted_callchain)
+	if (report.inverted_callchain)
 		callchain_param.order = ORDER_CALLER;
 
-	if (strcmp(input_name, "-") != 0)
+	if (strcmp(report.input_name, "-") != 0)
 		setup_browser(true);
 	else
 		use_browser = 0;
@@ -525,7 +532,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
 	 */
 	if (use_browser > 0) {
 		symbol_conf.priv_size = sizeof(struct annotation);
-		annotate_init	      = symbol__annotate_init;
+		report.annotate_init  = symbol__annotate_init;
 		/*
  		 * For searching by name on the "Browse map details".
  		 * providing it only in verbose mode not to bloat too
-- 
1.7.8.rc0.35.gee6df


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

* [PATCH 18/25] perf annotate: Group options in a struct
  2011-11-28 23:14 [GIT PULL 00/25] perf/core fixes and improvements Arnaldo Carvalho de Melo
                   ` (16 preceding siblings ...)
  2011-11-28 23:14 ` [PATCH 17/25] perf report: Group options in a struct Arnaldo Carvalho de Melo
@ 2011-11-28 23:14 ` Arnaldo Carvalho de Melo
  2011-11-28 23:14 ` [PATCH 19/25] perf tools: Pass tool context in the the perf_event_ops functions Arnaldo Carvalho de Melo
                   ` (6 subsequent siblings)
  24 siblings, 0 replies; 28+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-11-28 23:14 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Arnaldo Carvalho de Melo, David Ahern,
	Frederic Weisbecker, Mike Galbraith, Paul Mackerras,
	Peter Zijlstra, Stephane Eranian

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

Paving the way to remove these globals when we change the perf_event_ops
to receive as a first parameter a pointer to a perf_event_ops that will
then provide access to perf_annotate via container_of.

Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-xduzibqrdg3h5cttmk6p5wwc@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-annotate.c |   64 +++++++++++++++++++++--------------------
 1 files changed, 33 insertions(+), 31 deletions(-)

diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 8b9091b..4f0c3d9 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -30,18 +30,17 @@
 
 #include <linux/bitmap.h>
 
-static char		const *input_name = "perf.data";
-
-static bool		force, use_tui, use_stdio;
-
-static bool		full_paths;
-
-static bool		print_line;
-
-static const char *sym_hist_filter;
-
-static const char	*cpu_list;
-static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
+static struct perf_annotate {
+	char const *input_name;
+	bool	   force, use_tui, use_stdio;
+	bool	   full_paths;
+	bool	   print_line;
+	const char *sym_hist_filter;
+	const char *cpu_list;
+	DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
+} annotate = {
+	.input_name = "perf.data",
+}, *ann = &annotate;
 
 static int perf_evsel__add_sample(struct perf_evsel *evsel,
 				  struct perf_sample *sample,
@@ -50,8 +49,9 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
 	struct hist_entry *he;
 	int ret;
 
-	if (sym_hist_filter != NULL &&
-	    (al->sym == NULL || strcmp(sym_hist_filter, al->sym->name) != 0)) {
+	if (ann->sym_hist_filter != NULL &&
+	    (al->sym == NULL ||
+	     strcmp(ann->sym_hist_filter, al->sym->name) != 0)) {
 		/* We're only interested in a symbol named sym_hist_filter */
 		if (al->sym != NULL) {
 			rb_erase(&al->sym->rb_node,
@@ -93,7 +93,7 @@ static int process_sample_event(union perf_event *event,
 		return -1;
 	}
 
-	if (cpu_list && !test_bit(sample->cpu, cpu_bitmap))
+	if (ann->cpu_list && !test_bit(sample->cpu, ann->cpu_bitmap))
 		return 0;
 
 	if (!al.filtered && perf_evsel__add_sample(evsel, sample, &al)) {
@@ -108,7 +108,7 @@ static int process_sample_event(union perf_event *event,
 static int hist_entry__tty_annotate(struct hist_entry *he, int evidx)
 {
 	return symbol__tty_annotate(he->ms.sym, he->ms.map, evidx,
-				    print_line, full_paths, 0, 0);
+				    ann->print_line, ann->full_paths, 0, 0);
 }
 
 static void hists__find_annotations(struct hists *self, int evidx)
@@ -178,12 +178,14 @@ static int __cmd_annotate(void)
 	struct perf_evsel *pos;
 	u64 total_nr_samples;
 
-	session = perf_session__new(input_name, O_RDONLY, force, false, &event_ops);
+	session = perf_session__new(ann->input_name, O_RDONLY,
+				    ann->force, false, &event_ops);
 	if (session == NULL)
 		return -ENOMEM;
 
-	if (cpu_list) {
-		ret = perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap);
+	if (ann->cpu_list) {
+		ret = perf_session__cpu_bitmap(session, ann->cpu_list,
+					       ann->cpu_bitmap);
 		if (ret)
 			goto out_delete;
 	}
@@ -217,7 +219,7 @@ static int __cmd_annotate(void)
 	}
 
 	if (total_nr_samples == 0) {
-		ui__warning("The %s file has no samples!\n", input_name);
+		ui__warning("The %s file has no samples!\n", ann->input_name);
 		goto out_delete;
 	}
 out_delete:
@@ -242,28 +244,28 @@ static const char * const annotate_usage[] = {
 };
 
 static const struct option options[] = {
-	OPT_STRING('i', "input", &input_name, "file",
+	OPT_STRING('i', "input", &annotate.input_name, "file",
 		    "input file name"),
 	OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
 		   "only consider symbols in these dsos"),
-	OPT_STRING('s', "symbol", &sym_hist_filter, "symbol",
+	OPT_STRING('s', "symbol", &annotate.sym_hist_filter, "symbol",
 		    "symbol to annotate"),
-	OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
+	OPT_BOOLEAN('f', "force", &annotate.force, "don't complain, do it"),
 	OPT_INCR('v', "verbose", &verbose,
 		    "be more verbose (show symbol address, etc)"),
 	OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
 		    "dump raw trace in ASCII"),
-	OPT_BOOLEAN(0, "tui", &use_tui, "Use the TUI interface"),
-	OPT_BOOLEAN(0, "stdio", &use_stdio, "Use the stdio interface"),
+	OPT_BOOLEAN(0, "tui", &annotate.use_tui, "Use the TUI interface"),
+	OPT_BOOLEAN(0, "stdio", &annotate.use_stdio, "Use the stdio interface"),
 	OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
 		   "file", "vmlinux pathname"),
 	OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
 		    "load module symbols - WARNING: use only with -k and LIVE kernel"),
-	OPT_BOOLEAN('l', "print-line", &print_line,
+	OPT_BOOLEAN('l', "print-line", &annotate.print_line,
 		    "print matching source lines (may be slow)"),
-	OPT_BOOLEAN('P', "full-paths", &full_paths,
+	OPT_BOOLEAN('P', "full-paths", &annotate.full_paths,
 		    "Don't shorten the displayed pathnames"),
-	OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
+	OPT_STRING('c', "cpu", &annotate.cpu_list, "cpu", "list of cpus to profile"),
 	OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
 		   "Look for files with symbols relative to this directory"),
 	OPT_BOOLEAN(0, "source", &symbol_conf.annotate_src,
@@ -279,9 +281,9 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __used)
 {
 	argc = parse_options(argc, argv, options, annotate_usage, 0);
 
-	if (use_stdio)
+	if (annotate.use_stdio)
 		use_browser = 0;
-	else if (use_tui)
+	else if (annotate.use_tui)
 		use_browser = 1;
 
 	setup_browser(true);
@@ -302,7 +304,7 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __used)
 		if (argc > 1)
 			usage_with_options(annotate_usage, options);
 
-		sym_hist_filter = argv[0];
+		annotate.sym_hist_filter = argv[0];
 	}
 
 	if (field_sep && *field_sep == '.') {
-- 
1.7.8.rc0.35.gee6df


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

* [PATCH 19/25] perf tools: Pass tool context in the the perf_event_ops functions
  2011-11-28 23:14 [GIT PULL 00/25] perf/core fixes and improvements Arnaldo Carvalho de Melo
                   ` (17 preceding siblings ...)
  2011-11-28 23:14 ` [PATCH 18/25] perf annotate: " Arnaldo Carvalho de Melo
@ 2011-11-28 23:14 ` Arnaldo Carvalho de Melo
  2011-11-28 23:14 ` [PATCH 20/25] perf tools: Resolve machine earlier and pass it to perf_event_ops Arnaldo Carvalho de Melo
                   ` (5 subsequent siblings)
  24 siblings, 0 replies; 28+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-11-28 23:14 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Arnaldo Carvalho de Melo, David Ahern,
	Frederic Weisbecker, Mike Galbraith, Paul Mackerras,
	Peter Zijlstra, Stephane Eranian

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

So that we don't need to have that many globals.

Next steps will remove the 'session' pointer, that in most cases is
not needed.

Then we can rename perf_event_ops to 'perf_tool' that better describes
this class hierarchy.

Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-wp4djox7x6w1i2bab1pt4xxp@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-annotate.c  |   62 ++++---
 tools/perf/builtin-diff.c      |    3 +-
 tools/perf/builtin-inject.c    |   55 ++++---
 tools/perf/builtin-kmem.c      |    3 +-
 tools/perf/builtin-lock.c      |    3 +-
 tools/perf/builtin-record.c    |  383 ++++++++++++++++++++++------------------
 tools/perf/builtin-report.c    |   97 ++++++-----
 tools/perf/builtin-sched.c     |    3 +-
 tools/perf/builtin-script.c    |    3 +-
 tools/perf/builtin-timechart.c |   12 +-
 tools/perf/builtin-top.c       |    6 +-
 tools/perf/util/build-id.c     |    7 +-
 tools/perf/util/callchain.h    |    3 +
 tools/perf/util/event.c        |   66 ++++---
 tools/perf/util/event.h        |   38 +++--
 tools/perf/util/header.c       |   36 +++--
 tools/perf/util/header.h       |   27 ++-
 tools/perf/util/session.c      |   60 ++++---
 tools/perf/util/session.h      |   23 ++-
 tools/perf/util/top.h          |    3 +-
 20 files changed, 520 insertions(+), 373 deletions(-)

diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 4f0c3d9..483cb94 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -30,7 +30,8 @@
 
 #include <linux/bitmap.h>
 
-static struct perf_annotate {
+struct perf_annotate {
+	struct perf_event_ops ops;
 	char const *input_name;
 	bool	   force, use_tui, use_stdio;
 	bool	   full_paths;
@@ -38,13 +39,12 @@ static struct perf_annotate {
 	const char *sym_hist_filter;
 	const char *cpu_list;
 	DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
-} annotate = {
-	.input_name = "perf.data",
-}, *ann = &annotate;
+};
 
 static int perf_evsel__add_sample(struct perf_evsel *evsel,
 				  struct perf_sample *sample,
-				  struct addr_location *al)
+				  struct addr_location *al,
+				  struct perf_annotate *ann)
 {
 	struct hist_entry *he;
 	int ret;
@@ -79,11 +79,13 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
 	return ret;
 }
 
-static int process_sample_event(union perf_event *event,
+static int process_sample_event(struct perf_event_ops *ops,
+				union perf_event *event,
 				struct perf_sample *sample,
 				struct perf_evsel *evsel,
 				struct perf_session *session)
 {
+	struct perf_annotate *ann = container_of(ops, struct perf_annotate, ops);
 	struct addr_location al;
 
 	if (perf_event__preprocess_sample(event, session, &al, sample,
@@ -96,7 +98,7 @@ static int process_sample_event(union perf_event *event,
 	if (ann->cpu_list && !test_bit(sample->cpu, ann->cpu_bitmap))
 		return 0;
 
-	if (!al.filtered && perf_evsel__add_sample(evsel, sample, &al)) {
+	if (!al.filtered && perf_evsel__add_sample(evsel, sample, &al, ann)) {
 		pr_warning("problem incrementing symbol count, "
 			   "skipping event\n");
 		return -1;
@@ -105,13 +107,15 @@ static int process_sample_event(union perf_event *event,
 	return 0;
 }
 
-static int hist_entry__tty_annotate(struct hist_entry *he, int evidx)
+static int hist_entry__tty_annotate(struct hist_entry *he, int evidx,
+				    struct perf_annotate *ann)
 {
 	return symbol__tty_annotate(he->ms.sym, he->ms.map, evidx,
 				    ann->print_line, ann->full_paths, 0, 0);
 }
 
-static void hists__find_annotations(struct hists *self, int evidx)
+static void hists__find_annotations(struct hists *self, int evidx,
+				    struct perf_annotate *ann)
 {
 	struct rb_node *nd = rb_first(&self->entries), *next;
 	int key = K_RIGHT;
@@ -149,7 +153,7 @@ find_next:
 			if (next != NULL)
 				nd = next;
 		} else {
-			hist_entry__tty_annotate(he, evidx);
+			hist_entry__tty_annotate(he, evidx, ann);
 			nd = rb_next(nd);
 			/*
 			 * Since we have a hist_entry per IP for the same
@@ -162,16 +166,7 @@ find_next:
 	}
 }
 
-static struct perf_event_ops event_ops = {
-	.sample	= process_sample_event,
-	.mmap	= perf_event__process_mmap,
-	.comm	= perf_event__process_comm,
-	.fork	= perf_event__process_task,
-	.ordered_samples = true,
-	.ordering_requires_timestamps = true,
-};
-
-static int __cmd_annotate(void)
+static int __cmd_annotate(struct perf_annotate *ann)
 {
 	int ret;
 	struct perf_session *session;
@@ -179,7 +174,7 @@ static int __cmd_annotate(void)
 	u64 total_nr_samples;
 
 	session = perf_session__new(ann->input_name, O_RDONLY,
-				    ann->force, false, &event_ops);
+				    ann->force, false, &ann->ops);
 	if (session == NULL)
 		return -ENOMEM;
 
@@ -190,7 +185,7 @@ static int __cmd_annotate(void)
 			goto out_delete;
 	}
 
-	ret = perf_session__process_events(session, &event_ops);
+	ret = perf_session__process_events(session, &ann->ops);
 	if (ret)
 		goto out_delete;
 
@@ -214,7 +209,7 @@ static int __cmd_annotate(void)
 			total_nr_samples += nr_samples;
 			hists__collapse_resort(hists);
 			hists__output_resort(hists);
-			hists__find_annotations(hists, pos->idx);
+			hists__find_annotations(hists, pos->idx, ann);
 		}
 	}
 
@@ -243,7 +238,20 @@ static const char * const annotate_usage[] = {
 	NULL
 };
 
-static const struct option options[] = {
+int cmd_annotate(int argc, const char **argv, const char *prefix __used)
+{
+	struct perf_annotate annotate = {
+		.ops = {
+			.sample	= process_sample_event,
+			.mmap	= perf_event__process_mmap,
+			.comm	= perf_event__process_comm,
+			.fork	= perf_event__process_task,
+			.ordered_samples = true,
+			.ordering_requires_timestamps = true,
+		},
+		.input_name = "perf.data",
+	};
+	const struct option options[] = {
 	OPT_STRING('i', "input", &annotate.input_name, "file",
 		    "input file name"),
 	OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
@@ -275,10 +283,8 @@ static const struct option options[] = {
 	OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style",
 		   "Specify disassembler style (e.g. -M intel for intel syntax)"),
 	OPT_END()
-};
+	};
 
-int cmd_annotate(int argc, const char **argv, const char *prefix __used)
-{
 	argc = parse_options(argc, argv, options, annotate_usage, 0);
 
 	if (annotate.use_stdio)
@@ -312,5 +318,5 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __used)
 		return -1;
 	}
 
-	return __cmd_annotate();
+	return __cmd_annotate(&annotate);
 }
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index b39f3a1..9a0872f 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -30,7 +30,8 @@ static int hists__add_entry(struct hists *self,
 	return -ENOMEM;
 }
 
-static int diff__process_sample_event(union perf_event *event,
+static int diff__process_sample_event(struct perf_event_ops *ops __used,
+				      union perf_event *event,
 				      struct perf_sample *sample,
 				      struct perf_evsel *evsel __used,
 				      struct perf_session *session)
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 978751e..6ce6d80 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -16,7 +16,8 @@
 static char		const *input_name = "-";
 static bool		inject_build_ids;
 
-static int perf_event__repipe_synth(union perf_event *event,
+static int perf_event__repipe_synth(struct perf_event_ops *ops __used,
+				    union perf_event *event,
 				    struct perf_session *session __used)
 {
 	uint32_t size;
@@ -36,47 +37,57 @@ static int perf_event__repipe_synth(union perf_event *event,
 	return 0;
 }
 
+static int perf_event__repipe_tracing_data_synth(union perf_event *event,
+						 struct perf_session *session)
+{
+	return perf_event__repipe_synth(NULL, event, session);
+}
+
 static int perf_event__repipe_attr(union perf_event *event,
 				   struct perf_evlist **pevlist __used)
 {
-	return perf_event__repipe_synth(event, NULL);
+	return perf_event__repipe_synth(NULL, event, NULL);
 }
 
-static int perf_event__repipe(union perf_event *event,
+static int perf_event__repipe(struct perf_event_ops *ops,
+			      union perf_event *event,
 			      struct perf_sample *sample __used,
 			      struct perf_session *session)
 {
-	return perf_event__repipe_synth(event, session);
+	return perf_event__repipe_synth(ops, event, session);
 }
 
-static int perf_event__repipe_sample(union perf_event *event,
+static int perf_event__repipe_sample(struct perf_event_ops *ops,
+				     union perf_event *event,
 			      struct perf_sample *sample __used,
 			      struct perf_evsel *evsel __used,
 			      struct perf_session *session)
 {
-	return perf_event__repipe_synth(event, session);
+	return perf_event__repipe_synth(ops, event, session);
 }
 
-static int perf_event__repipe_mmap(union perf_event *event,
+static int perf_event__repipe_mmap(struct perf_event_ops *ops,
+				   union perf_event *event,
 				   struct perf_sample *sample,
 				   struct perf_session *session)
 {
 	int err;
 
-	err = perf_event__process_mmap(event, sample, session);
-	perf_event__repipe(event, sample, session);
+	err = perf_event__process_mmap(ops, event, sample, session);
+	perf_event__repipe(ops, event, sample, session);
 
 	return err;
 }
 
-static int perf_event__repipe_task(union perf_event *event,
+static int perf_event__repipe_task(struct perf_event_ops *ops,
+				   union perf_event *event,
 				   struct perf_sample *sample,
 				   struct perf_session *session)
 {
 	int err;
 
-	err = perf_event__process_task(event, sample, session);
-	perf_event__repipe(event, sample, session);
+	err = perf_event__process_task(ops, event, sample, session);
+	perf_event__repipe(ops, event, sample, session);
 
 	return err;
 }
@@ -86,7 +97,7 @@ static int perf_event__repipe_tracing_data(union perf_event *event,
 {
 	int err;
 
-	perf_event__repipe_synth(event, session);
+	perf_event__repipe_synth(NULL, event, session);
 	err = perf_event__process_tracing_data(event, session);
 
 	return err;
@@ -106,7 +117,8 @@ static int dso__read_build_id(struct dso *self)
 	return -1;
 }
 
-static int dso__inject_build_id(struct dso *self, struct perf_session *session)
+static int dso__inject_build_id(struct dso *self, struct perf_event_ops *ops,
+				struct perf_session *session)
 {
 	u16 misc = PERF_RECORD_MISC_USER;
 	struct machine *machine;
@@ -126,7 +138,7 @@ static int dso__inject_build_id(struct dso *self, struct perf_session *session)
 	if (self->kernel)
 		misc = PERF_RECORD_MISC_KERNEL;
 
-	err = perf_event__synthesize_build_id(self, misc, perf_event__repipe,
+	err = perf_event__synthesize_build_id(ops, self, misc, perf_event__repipe,
 					      machine, session);
 	if (err) {
 		pr_err("Can't synthesize build_id event for %s\n", self->long_name);
@@ -136,7 +148,8 @@ static int dso__inject_build_id(struct dso *self, struct perf_session *session)
 	return 0;
 }
 
-static int perf_event__inject_buildid(union perf_event *event,
+static int perf_event__inject_buildid(struct perf_event_ops *ops,
+				      union perf_event *event,
 				      struct perf_sample *sample,
 				      struct perf_evsel *evsel __used,
 				      struct perf_session *session)
@@ -161,7 +174,7 @@ static int perf_event__inject_buildid(union perf_event *event,
 		if (!al.map->dso->hit) {
 			al.map->dso->hit = 1;
 			if (map__load(al.map, NULL) >= 0) {
-				dso__inject_build_id(al.map->dso, session);
+				dso__inject_build_id(al.map->dso, ops, session);
 				/*
 				 * If this fails, too bad, let the other side
 				 * account this as unresolved.
@@ -174,7 +187,7 @@ static int perf_event__inject_buildid(union perf_event *event,
 	}
 
 repipe:
-	perf_event__repipe(event, sample, session);
+	perf_event__repipe(ops, event, sample, session);
 	return 0;
 }
 
@@ -189,9 +202,9 @@ struct perf_event_ops inject_ops = {
 	.throttle	= perf_event__repipe,
 	.unthrottle	= perf_event__repipe,
 	.attr		= perf_event__repipe_attr,
-	.event_type 	= perf_event__repipe_synth,
-	.tracing_data 	= perf_event__repipe_synth,
-	.build_id 	= perf_event__repipe_synth,
+	.event_type	= perf_event__repipe_synth,
+	.tracing_data	= perf_event__repipe_tracing_data_synth,
+	.build_id	= perf_event__repipe_synth,
 };
 
 extern volatile int session_done;
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index 225e963..5d01218 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -303,7 +303,8 @@ static void process_raw_event(union perf_event *raw_event __used, void *data,
 	}
 }
 
-static int process_sample_event(union perf_event *event,
+static int process_sample_event(struct perf_event_ops *ops __used,
+				union perf_event *event,
 				struct perf_sample *sample,
 				struct perf_evsel *evsel __used,
 				struct perf_session *session)
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index 899080a..f06b0a4 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -845,7 +845,8 @@ static void dump_info(void)
 		die("Unknown type of information\n");
 }
 
-static int process_sample_event(union perf_event *event,
+static int process_sample_event(struct perf_event_ops *ops __used,
+				union perf_event *event,
 				struct perf_sample *sample,
 				struct perf_evsel *evsel __used,
 				struct perf_session *s)
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index ba6777a..4642d38 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -35,43 +35,36 @@ enum write_mode_t {
 	WRITE_APPEND
 };
 
-struct perf_record_opts record_opts = {
-	.target_pid	     = -1,
-	.target_tid	     = -1,
-	.mmap_pages	     = UINT_MAX,
-	.user_freq	     = UINT_MAX,
-	.user_interval	     = ULLONG_MAX,
-	.freq		     = 1000,
-	.sample_id_all_avail = true,
+struct perf_record {
+	struct perf_event_ops	ops;
+	struct perf_record_opts	opts;
+	u64			bytes_written;
+	const char		*output_name;
+	struct perf_evlist	*evlist;
+	struct perf_session	*session;
+	const char		*progname;
+	int			output;
+	unsigned int		page_size;
+	int			realtime_prio;
+	enum write_mode_t	write_mode;
+	bool			no_buildid;
+	bool			no_buildid_cache;
+	bool			force;
+	bool			file_new;
+	bool			append_file;
+	long			samples;
+	off_t			post_processing_offset;
 };
 
-static unsigned int		page_size;
-static int			output;
-static const char		*output_name			= NULL;
-static int			realtime_prio			=      0;
-static enum write_mode_t	write_mode			= WRITE_FORCE;
-static bool			no_buildid			=  false;
-static bool			no_buildid_cache		=  false;
-static struct perf_evlist	*evsel_list;
-
-static long			samples				=      0;
-static u64			bytes_written			=      0;
-
-static int			file_new			=      1;
-static off_t			post_processing_offset;
-
-static struct perf_session	*session;
-static const char               *progname;
-
-static void advance_output(size_t size)
+static void advance_output(struct perf_record *rec, size_t size)
 {
-	bytes_written += size;
+	rec->bytes_written += size;
 }
 
-static void write_output(void *buf, size_t size)
+static void write_output(struct perf_record *rec, void *buf, size_t size)
 {
 	while (size) {
-		int ret = write(output, buf, size);
+		int ret = write(rec->output, buf, size);
 
 		if (ret < 0)
 			die("failed to write");
@@ -79,30 +72,33 @@ static void write_output(void *buf, size_t size)
 		size -= ret;
 		buf += ret;
 
-		bytes_written += ret;
+		rec->bytes_written += ret;
 	}
 }
 
-static int process_synthesized_event(union perf_event *event,
+static int process_synthesized_event(struct perf_event_ops *ops,
+				     union perf_event *event,
 				     struct perf_sample *sample __used,
 				     struct perf_session *self __used)
 {
-	write_output(event, event->header.size);
+	struct perf_record *rec = container_of(ops, struct perf_record, ops);
+	write_output(rec, event, event->header.size);
 	return 0;
 }
 
-static void mmap_read(struct perf_mmap *md)
+static void perf_record__mmap_read(struct perf_record *rec,
+				   struct perf_mmap *md)
 {
 	unsigned int head = perf_mmap__read_head(md);
 	unsigned int old = md->prev;
-	unsigned char *data = md->base + page_size;
+	unsigned char *data = md->base + rec->page_size;
 	unsigned long size;
 	void *buf;
 
 	if (old == head)
 		return;
 
-	samples++;
+	rec->samples++;
 
 	size = head - old;
 
@@ -111,14 +107,14 @@ static void mmap_read(struct perf_mmap *md)
 		size = md->mask + 1 - (old & md->mask);
 		old += size;
 
-		write_output(buf, size);
+		write_output(rec, buf, size);
 	}
 
 	buf = &data[old & md->mask];
 	size = head - old;
 	old += size;
 
-	write_output(buf, size);
+	write_output(rec, buf, size);
 
 	md->prev = old;
 	perf_mmap__write_tail(md, old);
@@ -137,17 +133,18 @@ static void sig_handler(int sig)
 	signr = sig;
 }
 
-static void sig_atexit(void)
+static void perf_record__sig_exit(int exit_status __used, void *arg)
 {
+	struct perf_record *rec = arg;
 	int status;
 
-	if (evsel_list->workload.pid > 0) {
+	if (rec->evlist->workload.pid > 0) {
 		if (!child_finished)
-			kill(evsel_list->workload.pid, SIGTERM);
+			kill(rec->evlist->workload.pid, SIGTERM);
 
 		wait(&status);
 		if (WIFSIGNALED(status))
-			psignal(WTERMSIG(status), progname);
+			psignal(WTERMSIG(status), rec->progname);
 	}
 
 	if (signr == -1 || signr == SIGUSR1)
@@ -176,13 +173,16 @@ static bool perf_evlist__equal(struct perf_evlist *evlist,
 	return true;
 }
 
-static void open_counters(struct perf_evlist *evlist)
+static void perf_record__open(struct perf_record *rec)
 {
 	struct perf_evsel *pos, *first;
+	struct perf_evlist *evlist = rec->evlist;
+	struct perf_session *session = rec->session;
+	struct perf_record_opts *opts = &rec->opts;
 
 	first = list_entry(evlist->entries.next, struct perf_evsel, node);
 
-	perf_evlist__config_attrs(evlist, &record_opts);
+	perf_evlist__config_attrs(evlist, opts);
 
 	list_for_each_entry(pos, &evlist->entries, node) {
 		struct perf_event_attr *attr = &pos->attr;
@@ -201,27 +201,27 @@ static void open_counters(struct perf_evlist *evlist)
 		 */
 		bool time_needed = attr->sample_type & PERF_SAMPLE_TIME;
 
-		if (record_opts.group && pos != first)
+		if (opts->group && pos != first)
 			group_fd = first->fd;
 retry_sample_id:
-		attr->sample_id_all = record_opts.sample_id_all_avail ? 1 : 0;
+		attr->sample_id_all = opts->sample_id_all_avail ? 1 : 0;
 try_again:
 		if (perf_evsel__open(pos, evlist->cpus, evlist->threads,
-				     record_opts.group, group_fd) < 0) {
+				     opts->group, group_fd) < 0) {
 			int err = errno;
 
 			if (err == EPERM || err == EACCES) {
 				ui__error_paranoid();
 				exit(EXIT_FAILURE);
-			} else if (err ==  ENODEV && record_opts.cpu_list) {
+			} else if (err ==  ENODEV && opts->cpu_list) {
 				die("No such device - did you specify"
 					" an out-of-range profile CPU?\n");
-			} else if (err == EINVAL && record_opts.sample_id_all_avail) {
+			} else if (err == EINVAL && opts->sample_id_all_avail) {
 				/*
 				 * Old kernel, no attr->sample_id_type_all field
 				 */
-				record_opts.sample_id_all_avail = false;
-				if (!record_opts.sample_time && !record_opts.raw_samples && !time_needed)
+				opts->sample_id_all_avail = false;
+				if (!opts->sample_time && !opts->raw_samples && !time_needed)
 					attr->sample_type &= ~PERF_SAMPLE_TIME;
 
 				goto retry_sample_id;
@@ -271,10 +271,10 @@ try_again:
 		exit(-1);
 	}
 
-	if (perf_evlist__mmap(evlist, record_opts.mmap_pages, false) < 0)
+	if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0)
 		die("failed to mmap with %d (%s)\n", errno, strerror(errno));
 
-	if (file_new)
+	if (rec->file_new)
 		session->evlist = evlist;
 	else {
 		if (!perf_evlist__equal(session->evlist, evlist)) {
@@ -286,29 +286,32 @@ try_again:
 	perf_session__update_sample_type(session);
 }
 
-static int process_buildids(void)
+static int process_buildids(struct perf_record *rec)
 {
-	u64 size = lseek(output, 0, SEEK_CUR);
+	u64 size = lseek(rec->output, 0, SEEK_CUR);
 
 	if (size == 0)
 		return 0;
 
-	session->fd = output;
-	return __perf_session__process_events(session, post_processing_offset,
-					      size - post_processing_offset,
+	rec->session->fd = rec->output;
+	return __perf_session__process_events(rec->session, rec->post_processing_offset,
+					      size - rec->post_processing_offset,
 					      size, &build_id__mark_dso_hit_ops);
 }
 
-static void atexit_header(void)
+static void perf_record__exit(int status __used, void *arg)
 {
-	if (!record_opts.pipe_output) {
-		session->header.data_size += bytes_written;
-
-		if (!no_buildid)
-			process_buildids();
-		perf_session__write_header(session, evsel_list, output, true);
-		perf_session__delete(session);
-		perf_evlist__delete(evsel_list);
+	struct perf_record *rec = arg;
+
+	if (!rec->opts.pipe_output) {
+		rec->session->header.data_size += rec->bytes_written;
+
+		if (!rec->no_buildid)
+			process_buildids(rec);
+		perf_session__write_header(rec->session, rec->evlist,
+					   rec->output, true);
+		perf_session__delete(rec->session);
+		perf_evlist__delete(rec->evlist);
 		symbol__exit();
 	}
 }
@@ -316,7 +319,9 @@ static void atexit_header(void)
 static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
 {
 	int err;
-	struct perf_session *psession = data;
+	struct perf_event_ops *ops = data;
+	struct perf_record *rec = container_of(ops, struct perf_record, ops);
+	struct perf_session *psession = rec->session;
 
 	if (machine__is_host(machine))
 		return;
@@ -329,7 +334,7 @@ static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
 	 *method is used to avoid symbol missing when the first addr is
 	 *in module instead of in guest kernel.
 	 */
-	err = perf_event__synthesize_modules(process_synthesized_event,
+	err = perf_event__synthesize_modules(ops, process_synthesized_event,
 					     psession, machine);
 	if (err < 0)
 		pr_err("Couldn't record guest kernel [%d]'s reference"
@@ -339,10 +344,10 @@ static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
 	 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
 	 * have no _text sometimes.
 	 */
-	err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
+	err = perf_event__synthesize_kernel_mmap(ops, process_synthesized_event,
 						 psession, machine, "_text");
 	if (err < 0)
-		err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
+		err = perf_event__synthesize_kernel_mmap(ops, process_synthesized_event,
 							 psession, machine,
 							 "_stext");
 	if (err < 0)
@@ -355,66 +360,71 @@ static struct perf_event_header finished_round_event = {
 	.type = PERF_RECORD_FINISHED_ROUND,
 };
 
-static void mmap_read_all(void)
+static void perf_record__mmap_read_all(struct perf_record *rec)
 {
 	int i;
 
-	for (i = 0; i < evsel_list->nr_mmaps; i++) {
-		if (evsel_list->mmap[i].base)
-			mmap_read(&evsel_list->mmap[i]);
+	for (i = 0; i < rec->evlist->nr_mmaps; i++) {
+		if (rec->evlist->mmap[i].base)
+			perf_record__mmap_read(rec, &rec->evlist->mmap[i]);
 	}
 
-	if (perf_header__has_feat(&session->header, HEADER_TRACE_INFO))
-		write_output(&finished_round_event, sizeof(finished_round_event));
+	if (perf_header__has_feat(&rec->session->header, HEADER_TRACE_INFO))
+		write_output(rec, &finished_round_event, sizeof(finished_round_event));
 }
 
-static int __cmd_record(int argc, const char **argv)
+static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
 {
 	struct stat st;
 	int flags;
-	int err;
+	int err, output;
 	unsigned long waking = 0;
 	const bool forks = argc > 0;
 	struct machine *machine;
+	struct perf_event_ops *ops = &rec->ops;
+	struct perf_record_opts *opts = &rec->opts;
+	struct perf_evlist *evsel_list = rec->evlist;
+	const char *output_name = rec->output_name;
+	struct perf_session *session;
 
-	progname = argv[0];
+	rec->progname = argv[0];
 
-	page_size = sysconf(_SC_PAGE_SIZE);
+	rec->page_size = sysconf(_SC_PAGE_SIZE);
 
-	atexit(sig_atexit);
+	on_exit(perf_record__sig_exit, rec);
 	signal(SIGCHLD, sig_handler);
 	signal(SIGINT, sig_handler);
 	signal(SIGUSR1, sig_handler);
 
 	if (!output_name) {
 		if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
-			record_opts.pipe_output = true;
+			opts->pipe_output = true;
 		else
-			output_name = "perf.data";
+			rec->output_name = output_name = "perf.data";
 	}
 	if (output_name) {
 		if (!strcmp(output_name, "-"))
-			record_opts.pipe_output = true;
+			opts->pipe_output = true;
 		else if (!stat(output_name, &st) && st.st_size) {
-			if (write_mode == WRITE_FORCE) {
+			if (rec->write_mode == WRITE_FORCE) {
 				char oldname[PATH_MAX];
 				snprintf(oldname, sizeof(oldname), "%s.old",
 					 output_name);
 				unlink(oldname);
 				rename(output_name, oldname);
 			}
-		} else if (write_mode == WRITE_APPEND) {
-			write_mode = WRITE_FORCE;
+		} else if (rec->write_mode == WRITE_APPEND) {
+			rec->write_mode = WRITE_FORCE;
 		}
 	}
 
 	flags = O_CREAT|O_RDWR;
-	if (write_mode == WRITE_APPEND)
-		file_new = 0;
+	if (rec->write_mode == WRITE_APPEND)
+		rec->file_new = 0;
 	else
 		flags |= O_TRUNC;
 
-	if (record_opts.pipe_output)
+	if (opts->pipe_output)
 		output = STDOUT_FILENO;
 	else
 		output = open(output_name, flags, S_IRUSR | S_IWUSR);
@@ -423,17 +433,21 @@ static int __cmd_record(int argc, const char **argv)
 		exit(-1);
 	}
 
+	rec->output = output;
+
 	session = perf_session__new(output_name, O_WRONLY,
-				    write_mode == WRITE_FORCE, false, NULL);
+				    rec->write_mode == WRITE_FORCE, false, NULL);
 	if (session == NULL) {
 		pr_err("Not enough memory for reading perf file header\n");
 		return -1;
 	}
 
-	if (!no_buildid)
+	rec->session = session;
+
+	if (!rec->no_buildid)
 		perf_header__set_feat(&session->header, HEADER_BUILD_ID);
 
-	if (!file_new) {
+	if (!rec->file_new) {
 		err = perf_session__read_header(session, output);
 		if (err < 0)
 			goto out_delete_session;
@@ -456,42 +470,42 @@ static int __cmd_record(int argc, const char **argv)
 	perf_header__set_feat(&session->header, HEADER_CPUID);
 
 	if (forks) {
-		err = perf_evlist__prepare_workload(evsel_list, &record_opts, argv);
+		err = perf_evlist__prepare_workload(evsel_list, opts, argv);
 		if (err < 0) {
 			pr_err("Couldn't run the workload!\n");
 			goto out_delete_session;
 		}
 	}
 
-	open_counters(evsel_list);
+	perf_record__open(rec);
 
 	/*
-	 * perf_session__delete(session) will be called at atexit_header()
+	 * perf_session__delete(session) will be called at perf_record__exit()
 	 */
-	atexit(atexit_header);
+	on_exit(perf_record__exit, rec);
 
-	if (record_opts.pipe_output) {
+	if (opts->pipe_output) {
 		err = perf_header__write_pipe(output);
 		if (err < 0)
 			return err;
-	} else if (file_new) {
+	} else if (rec->file_new) {
 		err = perf_session__write_header(session, evsel_list,
 						 output, false);
 		if (err < 0)
 			return err;
 	}
 
-	post_processing_offset = lseek(output, 0, SEEK_CUR);
+	rec->post_processing_offset = lseek(output, 0, SEEK_CUR);
 
-	if (record_opts.pipe_output) {
-		err = perf_session__synthesize_attrs(session,
-						     process_synthesized_event);
+	if (opts->pipe_output) {
+		err = perf_event__synthesize_attrs(ops, session,
+						   process_synthesized_event);
 		if (err < 0) {
 			pr_err("Couldn't synthesize attrs.\n");
 			return err;
 		}
 
-		err = perf_event__synthesize_event_types(process_synthesized_event,
+		err = perf_event__synthesize_event_types(ops, process_synthesized_event,
 							 session);
 		if (err < 0) {
 			pr_err("Couldn't synthesize event_types.\n");
@@ -507,14 +521,14 @@ static int __cmd_record(int argc, const char **argv)
 			 * return this more properly and also
 			 * propagate errors that now are calling die()
 			 */
-			err = perf_event__synthesize_tracing_data(output, evsel_list,
+			err = perf_event__synthesize_tracing_data(ops, output, evsel_list,
 								  process_synthesized_event,
 								  session);
 			if (err <= 0) {
 				pr_err("Couldn't record tracing data.\n");
 				return err;
 			}
-			advance_output(err);
+			advance_output(rec, err);
 		}
 	}
 
@@ -524,17 +538,17 @@ static int __cmd_record(int argc, const char **argv)
 		return -1;
 	}
 
-	err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
+	err = perf_event__synthesize_kernel_mmap(ops, process_synthesized_event,
 						 session, machine, "_text");
 	if (err < 0)
-		err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
+		err = perf_event__synthesize_kernel_mmap(ops, process_synthesized_event,
 							 session, machine, "_stext");
 	if (err < 0)
 		pr_err("Couldn't record kernel reference relocation symbol\n"
 		       "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
 		       "Check /proc/kallsyms permission or run as root.\n");
 
-	err = perf_event__synthesize_modules(process_synthesized_event,
+	err = perf_event__synthesize_modules(ops, process_synthesized_event,
 					     session, machine);
 	if (err < 0)
 		pr_err("Couldn't record kernel module information.\n"
@@ -542,21 +556,21 @@ static int __cmd_record(int argc, const char **argv)
 		       "Check /proc/modules permission or run as root.\n");
 
 	if (perf_guest)
-		perf_session__process_machines(session,
+		perf_session__process_machines(session, ops,
 					       perf_event__synthesize_guest_os);
 
-	if (!record_opts.system_wide)
-		perf_event__synthesize_thread_map(evsel_list->threads,
+	if (!opts->system_wide)
+		perf_event__synthesize_thread_map(ops, evsel_list->threads,
 						  process_synthesized_event,
 						  session);
 	else
-		perf_event__synthesize_threads(process_synthesized_event,
+		perf_event__synthesize_threads(ops, process_synthesized_event,
 					       session);
 
-	if (realtime_prio) {
+	if (rec->realtime_prio) {
 		struct sched_param param;
 
-		param.sched_priority = realtime_prio;
+		param.sched_priority = rec->realtime_prio;
 		if (sched_setscheduler(0, SCHED_FIFO, &param)) {
 			pr_err("Could not set realtime priority.\n");
 			exit(-1);
@@ -572,11 +586,11 @@ static int __cmd_record(int argc, const char **argv)
 		perf_evlist__start_workload(evsel_list);
 
 	for (;;) {
-		int hits = samples;
+		int hits = rec->samples;
 
-		mmap_read_all();
+		perf_record__mmap_read_all(rec);
 
-		if (hits == samples) {
+		if (hits == rec->samples) {
 			if (done)
 				break;
 			err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1);
@@ -597,9 +611,9 @@ static int __cmd_record(int argc, const char **argv)
 	 */
 	fprintf(stderr,
 		"[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n",
-		(double)bytes_written / 1024.0 / 1024.0,
+		(double)rec->bytes_written / 1024.0 / 1024.0,
 		output_name,
-		bytes_written / 24);
+		rec->bytes_written / 24);
 
 	return 0;
 
@@ -614,59 +628,88 @@ static const char * const record_usage[] = {
 	NULL
 };
 
-static bool force, append_file;
+/*
+ * XXX Ideally would be local to cmd_record() and passed to a perf_record__new
+ * because we need to have access to it in perf_record__exit, that is called
+ * after cmd_record() exits, but since record_options need to be accessible to
+ * builtin-script, leave it here.
+ *
+ * At least we don't ouch it in all the other functions here directly.
+ *
+ * Just say no to tons of global variables, sigh.
+ */
+static struct perf_record record = {
+	.opts = {
+		.target_pid	     = -1,
+		.target_tid	     = -1,
+		.mmap_pages	     = UINT_MAX,
+		.user_freq	     = UINT_MAX,
+		.user_interval	     = ULLONG_MAX,
+		.freq		     = 1000,
+		.sample_id_all_avail = true,
+	},
+	.write_mode = WRITE_FORCE,
+	.file_new   = true,
+};
 
+/*
+ * XXX Will stay a global variable till we fix builtin-script.c to stop messing
+ * with it and switch to use the library functions in perf_evlist that came
+ * from builtin-record.c, i.e. use perf_record_opts,
+ * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
+ * using pipes, etc.
+ */
 const struct option record_options[] = {
-	OPT_CALLBACK('e', "event", &evsel_list, "event",
+	OPT_CALLBACK('e', "event", &record.evlist, "event",
 		     "event selector. use 'perf list' to list available events",
 		     parse_events_option),
-	OPT_CALLBACK(0, "filter", &evsel_list, "filter",
+	OPT_CALLBACK(0, "filter", &record.evlist, "filter",
 		     "event filter", parse_filter),
-	OPT_INTEGER('p', "pid", &record_opts.target_pid,
+	OPT_INTEGER('p', "pid", &record.opts.target_pid,
 		    "record events on existing process id"),
-	OPT_INTEGER('t', "tid", &record_opts.target_tid,
+	OPT_INTEGER('t', "tid", &record.opts.target_tid,
 		    "record events on existing thread id"),
-	OPT_INTEGER('r', "realtime", &realtime_prio,
+	OPT_INTEGER('r', "realtime", &record.realtime_prio,
 		    "collect data with this RT SCHED_FIFO priority"),
-	OPT_BOOLEAN('D', "no-delay", &record_opts.no_delay,
+	OPT_BOOLEAN('D', "no-delay", &record.opts.no_delay,
 		    "collect data without buffering"),
-	OPT_BOOLEAN('R', "raw-samples", &record_opts.raw_samples,
+	OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples,
 		    "collect raw sample records from all opened counters"),
-	OPT_BOOLEAN('a', "all-cpus", &record_opts.system_wide,
+	OPT_BOOLEAN('a', "all-cpus", &record.opts.system_wide,
 			    "system-wide collection from all CPUs"),
-	OPT_BOOLEAN('A', "append", &append_file,
+	OPT_BOOLEAN('A', "append", &record.append_file,
 			    "append to the output file to do incremental profiling"),
-	OPT_STRING('C', "cpu", &record_opts.cpu_list, "cpu",
+	OPT_STRING('C', "cpu", &record.opts.cpu_list, "cpu",
 		    "list of cpus to monitor"),
-	OPT_BOOLEAN('f', "force", &force,
+	OPT_BOOLEAN('f', "force", &record.force,
 			"overwrite existing data file (deprecated)"),
-	OPT_U64('c', "count", &record_opts.user_interval, "event period to sample"),
-	OPT_STRING('o', "output", &output_name, "file",
+	OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
+	OPT_STRING('o', "output", &record.output_name, "file",
 		    "output file name"),
-	OPT_BOOLEAN('i', "no-inherit", &record_opts.no_inherit,
+	OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit,
 		    "child tasks do not inherit counters"),
-	OPT_UINTEGER('F', "freq", &record_opts.user_freq, "profile at this frequency"),
-	OPT_UINTEGER('m', "mmap-pages", &record_opts.mmap_pages,
+	OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"),
+	OPT_UINTEGER('m', "mmap-pages", &record.opts.mmap_pages,
 		     "number of mmap data pages"),
-	OPT_BOOLEAN(0, "group", &record_opts.group,
+	OPT_BOOLEAN(0, "group", &record.opts.group,
 		    "put the counters into a counter group"),
-	OPT_BOOLEAN('g', "call-graph", &record_opts.call_graph,
+	OPT_BOOLEAN('g', "call-graph", &record.opts.call_graph,
 		    "do call-graph (stack chain/backtrace) recording"),
 	OPT_INCR('v', "verbose", &verbose,
 		    "be more verbose (show counter open errors, etc)"),
 	OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
-	OPT_BOOLEAN('s', "stat", &record_opts.inherit_stat,
+	OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
 		    "per thread counts"),
-	OPT_BOOLEAN('d', "data", &record_opts.sample_address,
+	OPT_BOOLEAN('d', "data", &record.opts.sample_address,
 		    "Sample addresses"),
-	OPT_BOOLEAN('T', "timestamp", &record_opts.sample_time, "Sample timestamps"),
-	OPT_BOOLEAN('n', "no-samples", &record_opts.no_samples,
+	OPT_BOOLEAN('T', "timestamp", &record.opts.sample_time, "Sample timestamps"),
+	OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples,
 		    "don't sample"),
-	OPT_BOOLEAN('N', "no-buildid-cache", &no_buildid_cache,
+	OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache,
 		    "do not update the buildid cache"),
-	OPT_BOOLEAN('B', "no-buildid", &no_buildid,
+	OPT_BOOLEAN('B', "no-buildid", &record.no_buildid,
 		    "do not collect buildids in perf.data"),
-	OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
+	OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
 		     "monitor event in cgroup name only",
 		     parse_cgroups),
 	OPT_END()
@@ -676,6 +719,8 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
 {
 	int err = -ENOMEM;
 	struct perf_evsel *pos;
+	struct perf_evlist *evsel_list;
+	struct perf_record *rec = &record;
 
 	perf_header__set_cmdline(argc, argv);
 
@@ -683,23 +728,25 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
 	if (evsel_list == NULL)
 		return -ENOMEM;
 
+	rec->evlist = evsel_list;
+
 	argc = parse_options(argc, argv, record_options, record_usage,
 			    PARSE_OPT_STOP_AT_NON_OPTION);
-	if (!argc && record_opts.target_pid == -1 && record_opts.target_tid == -1 &&
-		!record_opts.system_wide && !record_opts.cpu_list)
+	if (!argc && rec->opts.target_pid == -1 && rec->opts.target_tid == -1 &&
+		!rec->opts.system_wide && !rec->opts.cpu_list)
 		usage_with_options(record_usage, record_options);
 
-	if (force && append_file) {
+	if (rec->force && rec->append_file) {
 		fprintf(stderr, "Can't overwrite and append at the same time."
 				" You need to choose between -f and -A");
 		usage_with_options(record_usage, record_options);
-	} else if (append_file) {
-		write_mode = WRITE_APPEND;
+	} else if (rec->append_file) {
+		rec->write_mode = WRITE_APPEND;
 	} else {
-		write_mode = WRITE_FORCE;
+		rec->write_mode = WRITE_FORCE;
 	}
 
-	if (nr_cgroups && !record_opts.system_wide) {
+	if (nr_cgroups && !rec->opts.system_wide) {
 		fprintf(stderr, "cgroup monitoring only available in"
 			" system-wide mode\n");
 		usage_with_options(record_usage, record_options);
@@ -717,7 +764,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
 "If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
 "even with a suitable vmlinux or kallsyms file.\n\n");
 
-	if (no_buildid_cache || no_buildid)
+	if (rec->no_buildid_cache || rec->no_buildid)
 		disable_buildid_cache();
 
 	if (evsel_list->nr_entries == 0 &&
@@ -726,11 +773,11 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
 		goto out_symbol_exit;
 	}
 
-	if (record_opts.target_pid != -1)
-		record_opts.target_tid = record_opts.target_pid;
+	if (rec->opts.target_pid != -1)
+		rec->opts.target_tid = rec->opts.target_pid;
 
-	if (perf_evlist__create_maps(evsel_list, record_opts.target_pid,
-				     record_opts.target_tid, record_opts.cpu_list) < 0)
+	if (perf_evlist__create_maps(evsel_list, rec->opts.target_pid,
+				     rec->opts.target_tid, rec->opts.cpu_list) < 0)
 		usage_with_options(record_usage, record_options);
 
 	list_for_each_entry(pos, &evsel_list->entries, node) {
@@ -744,25 +791,25 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
 	if (perf_evlist__alloc_pollfd(evsel_list) < 0)
 		goto out_free_fd;
 
-	if (record_opts.user_interval != ULLONG_MAX)
-		record_opts.default_interval = record_opts.user_interval;
-	if (record_opts.user_freq != UINT_MAX)
-		record_opts.freq = record_opts.user_freq;
+	if (rec->opts.user_interval != ULLONG_MAX)
+		rec->opts.default_interval = rec->opts.user_interval;
+	if (rec->opts.user_freq != UINT_MAX)
+		rec->opts.freq = rec->opts.user_freq;
 
 	/*
 	 * User specified count overrides default frequency.
 	 */
-	if (record_opts.default_interval)
-		record_opts.freq = 0;
-	else if (record_opts.freq) {
-		record_opts.default_interval = record_opts.freq;
+	if (rec->opts.default_interval)
+		rec->opts.freq = 0;
+	else if (rec->opts.freq) {
+		rec->opts.default_interval = rec->opts.freq;
 	} else {
 		fprintf(stderr, "frequency and count are zero, aborting\n");
 		err = -EINVAL;
 		goto out_free_fd;
 	}
 
-	err = __cmd_record(argc, argv);
+	err = __cmd_record(&record, argc, argv);
 out_free_fd:
 	perf_evlist__delete_maps(evsel_list);
 out_symbol_exit:
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 5d2e819..8795520 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -35,7 +35,9 @@
 
 #include <linux/bitmap.h>
 
-static struct perf_report {
+struct perf_report {
+	struct perf_event_ops	ops;
+	struct perf_session	*session;
 	char const		*input_name;
 	bool			force, use_tui, use_stdio;
 	bool			hide_unresolved;
@@ -48,12 +50,7 @@ static struct perf_report {
 	symbol_filter_t		annotate_init;
 	const char		*cpu_list;
 	DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
-} report = {
-	.input_name	       = "perf.data",
-	.pretty_printing_style = "normal",
-}, *rep = &report;
-
-static char callchain_default_opt[] = "fractal,0.5,callee";
+};
 
 static int perf_session__add_hist_entry(struct perf_session *session,
 					struct addr_location *al,
@@ -106,11 +103,13 @@ out:
 }
 
 
-static int process_sample_event(union perf_event *event,
+static int process_sample_event(struct perf_event_ops *ops,
+				union perf_event *event,
 				struct perf_sample *sample,
 				struct perf_evsel *evsel,
 				struct perf_session *session)
 {
+	struct perf_report *rep = container_of(ops, struct perf_report, ops);
 	struct addr_location al;
 
 	if (perf_event__preprocess_sample(event, session, &al, sample,
@@ -137,10 +136,12 @@ static int process_sample_event(union perf_event *event,
 	return 0;
 }
 
-static int process_read_event(union perf_event *event,
+static int process_read_event(struct perf_event_ops *ops,
+			      union perf_event *event,
 			      struct perf_sample *sample __used,
 			      struct perf_session *session)
 {
+	struct perf_report *rep = container_of(ops, struct perf_report, ops);
 	struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist,
 							 event->read.id);
 	if (rep->show_threads) {
@@ -159,8 +160,10 @@ static int process_read_event(union perf_event *event,
 	return 0;
 }
 
-static int perf_session__setup_sample_type(struct perf_session *self)
+static int perf_report__setup_sample_type(struct perf_report *rep)
 {
+	struct perf_session *self = rep->session;
+
 	if (!(self->sample_type & PERF_SAMPLE_CALLCHAIN)) {
 		if (sort__has_parent) {
 			ui__warning("Selected --sort parent, but no "
@@ -187,22 +190,6 @@ static int perf_session__setup_sample_type(struct perf_session *self)
 	return 0;
 }
 
-static struct perf_event_ops event_ops = {
-	.sample		 = process_sample_event,
-	.mmap		 = perf_event__process_mmap,
-	.comm		 = perf_event__process_comm,
-	.exit		 = perf_event__process_task,
-	.fork		 = perf_event__process_task,
-	.lost		 = perf_event__process_lost,
-	.read		 = process_read_event,
-	.attr		 = perf_event__process_attr,
-	.event_type	 = perf_event__process_event_type,
-	.tracing_data	 = perf_event__process_tracing_data,
-	.build_id	 = perf_event__process_build_id,
-	.ordered_samples = true,
-	.ordering_requires_timestamps = true,
-};
-
 extern volatile int session_done;
 
 static void sig_handler(int sig __used)
@@ -225,6 +212,7 @@ static size_t hists__fprintf_nr_sample_events(struct hists *self,
 }
 
 static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
+					 struct perf_report *rep,
 					 const char *help)
 {
 	struct perf_evsel *pos;
@@ -253,7 +241,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
 	return 0;
 }
 
-static int __cmd_report(void)
+static int __cmd_report(struct perf_report *rep)
 {
 	int ret = -EINVAL;
 	u64 nr_samples;
@@ -266,10 +254,12 @@ static int __cmd_report(void)
 	signal(SIGINT, sig_handler);
 
 	session = perf_session__new(rep->input_name, O_RDONLY,
-				    rep->force, false, &event_ops);
+				    rep->force, false, &rep->ops);
 	if (session == NULL)
 		return -ENOMEM;
 
+	rep->session = session;
+
 	if (rep->cpu_list) {
 		ret = perf_session__cpu_bitmap(session, rep->cpu_list,
 					       rep->cpu_bitmap);
@@ -283,11 +273,11 @@ static int __cmd_report(void)
 	if (rep->show_threads)
 		perf_read_values_init(&rep->show_threads_values);
 
-	ret = perf_session__setup_sample_type(session);
+	ret = perf_report__setup_sample_type(rep);
 	if (ret)
 		goto out_delete;
 
-	ret = perf_session__process_events(session, &event_ops);
+	ret = perf_session__process_events(session, &rep->ops);
 	if (ret)
 		goto out_delete;
 
@@ -339,7 +329,7 @@ static int __cmd_report(void)
 		perf_evlist__tui_browse_hists(session->evlist, help,
 					      NULL, NULL, 0);
 	} else
-		perf_evlist__tty_browse_hists(session->evlist, help);
+		perf_evlist__tty_browse_hists(session->evlist, rep, help);
 
 out_delete:
 	/*
@@ -358,9 +348,9 @@ out_delete:
 }
 
 static int
-parse_callchain_opt(const struct option *opt __used, const char *arg,
-		    int unset)
+parse_callchain_opt(const struct option *opt, const char *arg, int unset)
 {
+	struct perf_report *rep = (struct perf_report *)opt->value;
 	char *tok, *tok2;
 	char *endptr;
 
@@ -437,12 +427,33 @@ setup:
 	return 0;
 }
 
-static const char * const report_usage[] = {
-	"perf report [<options>] <command>",
-	NULL
-};
-
-static const struct option options[] = {
+int cmd_report(int argc, const char **argv, const char *prefix __used)
+{
+	char callchain_default_opt[] = "fractal,0.5,callee";
+	const char * const report_usage[] = {
+		"perf report [<options>] <command>",
+		NULL
+	};
+	struct perf_report report = {
+		.ops = {
+			.sample		 = process_sample_event,
+			.mmap		 = perf_event__process_mmap,
+			.comm		 = perf_event__process_comm,
+			.exit		 = perf_event__process_task,
+			.fork		 = perf_event__process_task,
+			.lost		 = perf_event__process_lost,
+			.read		 = process_read_event,
+			.attr		 = perf_event__process_attr,
+			.event_type	 = perf_event__process_event_type,
+			.tracing_data	 = perf_event__process_tracing_data,
+			.build_id	 = perf_event__process_build_id,
+			.ordered_samples = true,
+			.ordering_requires_timestamps = true,
+		},
+		.input_name		 = "perf.data",
+		.pretty_printing_style	 = "normal",
+	};
+	const struct option options[] = {
 	OPT_STRING('i', "input", &report.input_name, "file",
 		    "input file name"),
 	OPT_INCR('v', "verbose", &verbose,
@@ -473,7 +484,7 @@ static const struct option options[] = {
 		   "regex filter to identify parent, see: '--sort parent'"),
 	OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other,
 		    "Only display entries with parent-match"),
-	OPT_CALLBACK_DEFAULT('g', "call-graph", NULL, "output_type,min_percent, call_order",
+	OPT_CALLBACK_DEFAULT('g', "call-graph", &report, "output_type,min_percent, call_order",
 		     "Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold and callchain order. "
 		     "Default: fractal,0.5,callee", &parse_callchain_opt, callchain_default_opt),
 	OPT_BOOLEAN('G', "inverted", &report.inverted_callchain,
@@ -507,10 +518,8 @@ static const struct option options[] = {
 	OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
 		    "Show a column with the sum of periods"),
 	OPT_END()
-};
+	};
 
-int cmd_report(int argc, const char **argv, const char *prefix __used)
-{
 	argc = parse_options(argc, argv, options, report_usage, 0);
 
 	if (report.use_stdio)
@@ -579,5 +588,5 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
 	sort_entry__setup_elide(&sort_comm, symbol_conf.comm_list, "comm", stdout);
 	sort_entry__setup_elide(&sort_sym, symbol_conf.sym_list, "symbol", stdout);
 
-	return __cmd_report();
+	return __cmd_report(&report);
 }
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index d51af0b..b11d628 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -1602,7 +1602,8 @@ static void process_raw_event(union perf_event *raw_event __used,
 		process_sched_migrate_task_event(data, session, event, cpu, timestamp, thread);
 }
 
-static int process_sample_event(union perf_event *event,
+static int process_sample_event(struct perf_event_ops *ops __used,
+				union perf_event *event,
 				struct perf_sample *sample,
 				struct perf_evsel *evsel,
 				struct perf_session *session)
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 47545e9..3b78206 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -434,7 +434,8 @@ static int cleanup_scripting(void)
 
 static char const		*input_name = "perf.data";
 
-static int process_sample_event(union perf_event *event,
+static int process_sample_event(struct perf_event_ops *ops __used,
+				union perf_event *event,
 				struct perf_sample *sample,
 				struct perf_evsel *evsel,
 				struct perf_session *session)
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 3fc52b1..62298a0 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -274,7 +274,8 @@ static int cpus_cstate_state[MAX_CPUS];
 static u64 cpus_pstate_start_times[MAX_CPUS];
 static u64 cpus_pstate_state[MAX_CPUS];
 
-static int process_comm_event(union perf_event *event,
+static int process_comm_event(struct perf_event_ops *ops __used,
+			      union perf_event *event,
 			      struct perf_sample *sample __used,
 			      struct perf_session *session __used)
 {
@@ -282,7 +283,8 @@ static int process_comm_event(union perf_event *event,
 	return 0;
 }
 
-static int process_fork_event(union perf_event *event,
+static int process_fork_event(struct perf_event_ops *ops __used,
+			      union perf_event *event,
 			      struct perf_sample *sample __used,
 			      struct perf_session *session __used)
 {
@@ -290,7 +292,8 @@ static int process_fork_event(union perf_event *event,
 	return 0;
 }
 
-static int process_exit_event(union perf_event *event,
+static int process_exit_event(struct perf_event_ops *ops __used,
+			      union perf_event *event,
 			      struct perf_sample *sample __used,
 			      struct perf_session *session __used)
 {
@@ -487,7 +490,8 @@ static void sched_switch(int cpu, u64 timestamp, struct trace_entry *te)
 }
 
 
-static int process_sample_event(union perf_event *event __used,
+static int process_sample_event(struct perf_event_ops *ops __used,
+				union perf_event *event __used,
 				struct perf_sample *sample,
 				struct perf_evsel *evsel,
 				struct perf_session *session __used)
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 9b3bbb4..e8e3320 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -824,7 +824,7 @@ static void perf_session__mmap_read_idx(struct perf_session *self, int idx)
 			perf_event__process_sample(event, evsel, &sample, self);
 		else if (event->header.type < PERF_RECORD_MAX) {
 			hists__inc_nr_events(&evsel->hists, event->header.type);
-			perf_event__process(event, &sample, self);
+			perf_event__process(&top.ops, event, &sample, self);
 		} else
 			++self->hists.stats.nr_unknown_events;
 	}
@@ -966,10 +966,10 @@ static int __cmd_top(void)
 		goto out_delete;
 
 	if (top.target_tid != -1)
-		perf_event__synthesize_thread_map(top.evlist->threads,
+		perf_event__synthesize_thread_map(&top.ops, top.evlist->threads,
 						  perf_event__process, top.session);
 	else
-		perf_event__synthesize_threads(perf_event__process, top.session);
+		perf_event__synthesize_threads(&top.ops, perf_event__process, top.session);
 
 	start_counters(top.evlist);
 	top.session->evlist = top.evlist;
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index f2fe6ec..0e4de18 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -13,8 +13,10 @@
 #include "symbol.h"
 #include <linux/kernel.h>
 #include "debug.h"
+#include "session.h"
 
-static int build_id__mark_dso_hit(union perf_event *event,
+static int build_id__mark_dso_hit(struct perf_event_ops *ops __used,
+				  union perf_event *event,
 				  struct perf_sample *sample __used,
 				  struct perf_evsel *evsel __used,
 				  struct perf_session *session)
@@ -38,7 +40,8 @@ static int build_id__mark_dso_hit(union perf_event *event,
 	return 0;
 }
 
-static int perf_event__exit_del_thread(union perf_event *event,
+static int perf_event__exit_del_thread(struct perf_event_ops *ops __used,
+				       union perf_event *event,
 				       struct perf_sample *sample __used,
 				       struct perf_session *session)
 {
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 9b4ff16..7f9c0f1 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -101,6 +101,9 @@ int callchain_append(struct callchain_root *root,
 int callchain_merge(struct callchain_cursor *cursor,
 		    struct callchain_root *dst, struct callchain_root *src);
 
+struct ip_callchain;
+union perf_event;
+
 bool ip_callchain__valid(struct ip_callchain *chain,
 			 const union perf_event *event);
 /*
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 437f8ca..4800f38 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -44,7 +44,8 @@ static struct perf_sample synth_sample = {
 	.period	   = 1,
 };
 
-static pid_t perf_event__synthesize_comm(union perf_event *event, pid_t pid,
+static pid_t perf_event__synthesize_comm(struct perf_event_ops *ops,
+					 union perf_event *event, pid_t pid,
 					 int full, perf_event__handler_t process,
 					 struct perf_session *session)
 {
@@ -99,7 +100,7 @@ out_race:
 	if (!full) {
 		event->comm.tid = pid;
 
-		process(event, &synth_sample, session);
+		process(ops, event, &synth_sample, session);
 		goto out;
 	}
 
@@ -117,7 +118,7 @@ out_race:
 
 		event->comm.tid = pid;
 
-		process(event, &synth_sample, session);
+		process(ops, event, &synth_sample, session);
 	}
 
 	closedir(tasks);
@@ -127,7 +128,8 @@ out:
 	return tgid;
 }
 
-static int perf_event__synthesize_mmap_events(union perf_event *event,
+static int perf_event__synthesize_mmap_events(struct perf_event_ops *ops,
+					      union perf_event *event,
 					      pid_t pid, pid_t tgid,
 					      perf_event__handler_t process,
 					      struct perf_session *session)
@@ -198,7 +200,7 @@ static int perf_event__synthesize_mmap_events(union perf_event *event,
 			event->mmap.pid = tgid;
 			event->mmap.tid = pid;
 
-			process(event, &synth_sample, session);
+			process(ops, event, &synth_sample, session);
 		}
 	}
 
@@ -206,7 +208,8 @@ static int perf_event__synthesize_mmap_events(union perf_event *event,
 	return 0;
 }
 
-int perf_event__synthesize_modules(perf_event__handler_t process,
+int perf_event__synthesize_modules(struct perf_event_ops *ops,
+				   perf_event__handler_t process,
 				   struct perf_session *session,
 				   struct machine *machine)
 {
@@ -251,7 +254,7 @@ int perf_event__synthesize_modules(perf_event__handler_t process,
 
 		memcpy(event->mmap.filename, pos->dso->long_name,
 		       pos->dso->long_name_len + 1);
-		process(event, &synth_sample, session);
+		process(ops, event, &synth_sample, session);
 	}
 
 	free(event);
@@ -261,17 +264,19 @@ int perf_event__synthesize_modules(perf_event__handler_t process,
 static int __event__synthesize_thread(union perf_event *comm_event,
 				      union perf_event *mmap_event,
 				      pid_t pid, perf_event__handler_t process,
+				      struct perf_event_ops *ops,
 				      struct perf_session *session)
 {
-	pid_t tgid = perf_event__synthesize_comm(comm_event, pid, 1, process,
+	pid_t tgid = perf_event__synthesize_comm(ops, comm_event, pid, 1, process,
 					    session);
 	if (tgid == -1)
 		return -1;
-	return perf_event__synthesize_mmap_events(mmap_event, pid, tgid,
+	return perf_event__synthesize_mmap_events(ops, mmap_event, pid, tgid,
 					     process, session);
 }
 
-int perf_event__synthesize_thread_map(struct thread_map *threads,
+int perf_event__synthesize_thread_map(struct perf_event_ops *ops,
+				      struct thread_map *threads,
 				      perf_event__handler_t process,
 				      struct perf_session *session)
 {
@@ -290,7 +295,7 @@ int perf_event__synthesize_thread_map(struct thread_map *threads,
 	for (thread = 0; thread < threads->nr; ++thread) {
 		if (__event__synthesize_thread(comm_event, mmap_event,
 					       threads->map[thread],
-					       process, session)) {
+					       process, ops, session)) {
 			err = -1;
 			break;
 		}
@@ -302,7 +307,8 @@ out:
 	return err;
 }
 
-int perf_event__synthesize_threads(perf_event__handler_t process,
+int perf_event__synthesize_threads(struct perf_event_ops *ops,
+				   perf_event__handler_t process,
 				   struct perf_session *session)
 {
 	DIR *proc;
@@ -330,7 +336,7 @@ int perf_event__synthesize_threads(perf_event__handler_t process,
 			continue;
 
 		__event__synthesize_thread(comm_event, mmap_event, pid,
-					   process, session);
+					   process, ops, session);
 	}
 
 	closedir(proc);
@@ -365,7 +371,8 @@ static int find_symbol_cb(void *arg, const char *name, char type,
 	return 1;
 }
 
-int perf_event__synthesize_kernel_mmap(perf_event__handler_t process,
+int perf_event__synthesize_kernel_mmap(struct perf_event_ops *ops,
+				       perf_event__handler_t process,
 				       struct perf_session *session,
 				       struct machine *machine,
 				       const char *symbol_name)
@@ -423,13 +430,14 @@ int perf_event__synthesize_kernel_mmap(perf_event__handler_t process,
 	event->mmap.len   = map->end - event->mmap.start;
 	event->mmap.pid   = machine->pid;
 
-	err = process(event, &synth_sample, session);
+	err = process(ops, event, &synth_sample, session);
 	free(event);
 
 	return err;
 }
 
-int perf_event__process_comm(union perf_event *event,
+int perf_event__process_comm(struct perf_event_ops *ops __used,
+			     union perf_event *event,
 			     struct perf_sample *sample __used,
 			     struct perf_session *session)
 {
@@ -445,7 +453,8 @@ int perf_event__process_comm(union perf_event *event,
 	return 0;
 }
 
-int perf_event__process_lost(union perf_event *event,
+int perf_event__process_lost(struct perf_event_ops *ops __used,
+			     union perf_event *event,
 			     struct perf_sample *sample __used,
 			     struct perf_session *session)
 {
@@ -468,7 +477,8 @@ static void perf_event__set_kernel_mmap_len(union perf_event *event,
 		maps[MAP__FUNCTION]->end = ~0ULL;
 }
 
-static int perf_event__process_kernel_mmap(union perf_event *event,
+static int perf_event__process_kernel_mmap(struct perf_event_ops *ops __used,
+					   union perf_event *event,
 					   struct perf_session *session)
 {
 	struct map *map;
@@ -567,7 +577,8 @@ out_problem:
 	return -1;
 }
 
-int perf_event__process_mmap(union perf_event *event,
+int perf_event__process_mmap(struct perf_event_ops *ops,
+			     union perf_event *event,
 			     struct perf_sample *sample __used,
 			     struct perf_session *session)
 {
@@ -583,7 +594,7 @@ int perf_event__process_mmap(union perf_event *event,
 
 	if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL ||
 	    cpumode == PERF_RECORD_MISC_KERNEL) {
-		ret = perf_event__process_kernel_mmap(event, session);
+		ret = perf_event__process_kernel_mmap(ops, event, session);
 		if (ret < 0)
 			goto out_problem;
 		return 0;
@@ -610,7 +621,8 @@ out_problem:
 	return 0;
 }
 
-int perf_event__process_task(union perf_event *event,
+int perf_event__process_task(struct perf_event_ops *ops __used,
+			     union perf_event *event,
 			     struct perf_sample *sample __used,
 			     struct perf_session *session)
 {
@@ -634,22 +646,22 @@ int perf_event__process_task(union perf_event *event,
 	return 0;
 }
 
-int perf_event__process(union perf_event *event, struct perf_sample *sample,
-			struct perf_session *session)
+int perf_event__process(struct perf_event_ops *ops, union perf_event *event,
+			struct perf_sample *sample, struct perf_session *session)
 {
 	switch (event->header.type) {
 	case PERF_RECORD_COMM:
-		perf_event__process_comm(event, sample, session);
+		perf_event__process_comm(ops, event, sample, session);
 		break;
 	case PERF_RECORD_MMAP:
-		perf_event__process_mmap(event, sample, session);
+		perf_event__process_mmap(ops, event, sample, session);
 		break;
 	case PERF_RECORD_FORK:
 	case PERF_RECORD_EXIT:
-		perf_event__process_task(event, sample, session);
+		perf_event__process_task(ops, event, sample, session);
 		break;
 	case PERF_RECORD_LOST:
-		perf_event__process_lost(event, sample, session);
+		perf_event__process_lost(ops, event, sample, session);
 	default:
 		break;
 	}
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 357a85b..669409d 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -141,38 +141,52 @@ union perf_event {
 
 void perf_event__print_totals(void);
 
+struct perf_event_ops;
 struct perf_session;
 struct thread_map;
 
-typedef int (*perf_event__handler_synth_t)(union perf_event *event, 
-					   struct perf_session *session);
-typedef int (*perf_event__handler_t)(union perf_event *event,
+typedef int (*perf_event__handler_t)(struct perf_event_ops *ops,
+				     union perf_event *event,
 				     struct perf_sample *sample,
 				      struct perf_session *session);
 
-int perf_event__synthesize_thread_map(struct thread_map *threads,
+int perf_event__synthesize_thread_map(struct perf_event_ops *ops,
+				      struct thread_map *threads,
 				      perf_event__handler_t process,
 				      struct perf_session *session);
-int perf_event__synthesize_threads(perf_event__handler_t process,
+int perf_event__synthesize_threads(struct perf_event_ops *ops,
+				   perf_event__handler_t process,
 				   struct perf_session *session);
-int perf_event__synthesize_kernel_mmap(perf_event__handler_t process,
+int perf_event__synthesize_kernel_mmap(struct perf_event_ops *ops,
+				       perf_event__handler_t process,
 				       struct perf_session *session,
 				       struct machine *machine,
 				       const char *symbol_name);
 
-int perf_event__synthesize_modules(perf_event__handler_t process,
+int perf_event__synthesize_modules(struct perf_event_ops *ops,
+				   perf_event__handler_t process,
 				   struct perf_session *session,
 				   struct machine *machine);
 
-int perf_event__process_comm(union perf_event *event, struct perf_sample *sample,
+int perf_event__process_comm(struct perf_event_ops *ops,
+			     union perf_event *event,
+			     struct perf_sample *sample,
 			     struct perf_session *session);
-int perf_event__process_lost(union perf_event *event, struct perf_sample *sample,
+int perf_event__process_lost(struct perf_event_ops *ops,
+			     union perf_event *event,
+			     struct perf_sample *sample,
 			     struct perf_session *session);
-int perf_event__process_mmap(union perf_event *event, struct perf_sample *sample,
+int perf_event__process_mmap(struct perf_event_ops *ops,
+			     union perf_event *event,
+			     struct perf_sample *sample,
 			     struct perf_session *session);
-int perf_event__process_task(union perf_event *event, struct perf_sample *sample,
+int perf_event__process_task(struct perf_event_ops *ops,
+			     union perf_event *event,
+			     struct perf_sample *sample,
 			     struct perf_session *session);
-int perf_event__process(union perf_event *event, struct perf_sample *sample,
+int perf_event__process(struct perf_event_ops *ops,
+			union perf_event *event,
+			struct perf_sample *sample,
 			struct perf_session *session);
 
 struct addr_location;
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 1fa97dd..ab3a2b0 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2070,7 +2070,8 @@ out_delete_evlist:
 	return -ENOMEM;
 }
 
-int perf_event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id,
+int perf_event__synthesize_attr(struct perf_event_ops *ops,
+				struct perf_event_attr *attr, u16 ids, u64 *id,
 				perf_event__handler_t process,
 				struct perf_session *session)
 {
@@ -2094,21 +2095,22 @@ int perf_event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id,
 	ev->attr.header.type = PERF_RECORD_HEADER_ATTR;
 	ev->attr.header.size = size;
 
-	err = process(ev, NULL, session);
+	err = process(ops, ev, NULL, session);
 
 	free(ev);
 
 	return err;
 }
 
-int perf_session__synthesize_attrs(struct perf_session *session,
+int perf_event__synthesize_attrs(struct perf_event_ops *ops,
+				   struct perf_session *session,
 				   perf_event__handler_t process)
 {
 	struct perf_evsel *attr;
 	int err = 0;
 
 	list_for_each_entry(attr, &session->evlist->entries, node) {
-		err = perf_event__synthesize_attr(&attr->attr, attr->ids,
+		err = perf_event__synthesize_attr(ops, &attr->attr, attr->ids,
 						  attr->id, process, session);
 		if (err) {
 			pr_debug("failed to create perf header attribute\n");
@@ -2156,7 +2158,8 @@ int perf_event__process_attr(union perf_event *event,
 	return 0;
 }
 
-int perf_event__synthesize_event_type(u64 event_id, char *name,
+int perf_event__synthesize_event_type(struct perf_event_ops *ops,
+				      u64 event_id, char *name,
 				      perf_event__handler_t process,
 				      struct perf_session *session)
 {
@@ -2176,12 +2179,13 @@ int perf_event__synthesize_event_type(u64 event_id, char *name,
 	ev.event_type.header.size = sizeof(ev.event_type) -
 		(sizeof(ev.event_type.event_type.name) - size);
 
-	err = process(&ev, NULL, session);
+	err = process(ops, &ev, NULL, session);
 
 	return err;
 }
 
-int perf_event__synthesize_event_types(perf_event__handler_t process,
+int perf_event__synthesize_event_types(struct perf_event_ops *ops,
+				       perf_event__handler_t process,
 				       struct perf_session *session)
 {
 	struct perf_trace_event_type *type;
@@ -2190,7 +2194,7 @@ int perf_event__synthesize_event_types(perf_event__handler_t process,
 	for (i = 0; i < event_count; i++) {
 		type = &events[i];
 
-		err = perf_event__synthesize_event_type(type->event_id,
+		err = perf_event__synthesize_event_type(ops, type->event_id,
 							type->name, process,
 							session);
 		if (err) {
@@ -2202,7 +2206,8 @@ int perf_event__synthesize_event_types(perf_event__handler_t process,
 	return err;
 }
 
-int perf_event__process_event_type(union perf_event *event,
+int perf_event__process_event_type(struct perf_event_ops *ops __unused,
+				   union perf_event *event,
 				   struct perf_session *session __unused)
 {
 	if (perf_header__push_event(event->event_type.event_type.event_id,
@@ -2212,7 +2217,8 @@ int perf_event__process_event_type(union perf_event *event,
 	return 0;
 }
 
-int perf_event__synthesize_tracing_data(int fd, struct perf_evlist *evlist,
+int perf_event__synthesize_tracing_data(struct perf_event_ops *ops, int fd,
+					struct perf_evlist *evlist,
 					 perf_event__handler_t process,
 				   struct perf_session *session __unused)
 {
@@ -2245,7 +2251,7 @@ int perf_event__synthesize_tracing_data(int fd, struct perf_evlist *evlist,
 	ev.tracing_data.header.size = sizeof(ev.tracing_data);
 	ev.tracing_data.size = aligned_size;
 
-	process(&ev, NULL, session);
+	process(ops, &ev, NULL, session);
 
 	/*
 	 * The put function will copy all the tracing data
@@ -2287,7 +2293,8 @@ int perf_event__process_tracing_data(union perf_event *event,
 	return size_read + padding;
 }
 
-int perf_event__synthesize_build_id(struct dso *pos, u16 misc,
+int perf_event__synthesize_build_id(struct perf_event_ops *ops,
+				    struct dso *pos, u16 misc,
 				    perf_event__handler_t process,
 				    struct machine *machine,
 				    struct perf_session *session)
@@ -2310,12 +2317,13 @@ int perf_event__synthesize_build_id(struct dso *pos, u16 misc,
 	ev.build_id.header.size = sizeof(ev.build_id) + len;
 	memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len);
 
-	err = process(&ev, NULL, session);
+	err = process(ops, &ev, NULL, session);
 
 	return err;
 }
 
-int perf_event__process_build_id(union perf_event *event,
+int perf_event__process_build_id(struct perf_event_ops *ops __used,
+				 union perf_event *event,
 				 struct perf_session *session)
 {
 	__event_process_build_id(&event->build_id,
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 0a88982..54dae5f 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -68,6 +68,7 @@ struct perf_header {
 };
 
 struct perf_evlist;
+struct perf_session;
 
 int perf_session__read_header(struct perf_session *session, int fd);
 int perf_session__write_header(struct perf_session *session,
@@ -96,32 +97,40 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
 			  const char *name, bool is_kallsyms);
 int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir);
 
-int perf_event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id,
+int perf_event__synthesize_attr(struct perf_event_ops *ops,
+				struct perf_event_attr *attr, u16 ids, u64 *id,
 				perf_event__handler_t process,
 				struct perf_session *session);
-int perf_session__synthesize_attrs(struct perf_session *session,
-				   perf_event__handler_t process);
+int perf_event__synthesize_attrs(struct perf_event_ops *ops,
+				 struct perf_session *session,
+				 perf_event__handler_t process);
 int perf_event__process_attr(union perf_event *event, struct perf_evlist **pevlist);
 
-int perf_event__synthesize_event_type(u64 event_id, char *name,
+int perf_event__synthesize_event_type(struct perf_event_ops *ops,
+				      u64 event_id, char *name,
 				      perf_event__handler_t process,
 				      struct perf_session *session);
-int perf_event__synthesize_event_types(perf_event__handler_t process,
+int perf_event__synthesize_event_types(struct perf_event_ops *ops,
+				       perf_event__handler_t process,
 				       struct perf_session *session);
-int perf_event__process_event_type(union perf_event *event,
+int perf_event__process_event_type(struct perf_event_ops *ops,
+				   union perf_event *event,
 				   struct perf_session *session);
 
-int perf_event__synthesize_tracing_data(int fd, struct perf_evlist *evlist,
+int perf_event__synthesize_tracing_data(struct perf_event_ops *ops,
+					int fd, struct perf_evlist *evlist,
 					perf_event__handler_t process,
 					struct perf_session *session);
 int perf_event__process_tracing_data(union perf_event *event,
 				     struct perf_session *session);
 
-int perf_event__synthesize_build_id(struct dso *pos, u16 misc,
+int perf_event__synthesize_build_id(struct perf_event_ops *ops,
+				    struct dso *pos, u16 misc,
 				    perf_event__handler_t process,
 				    struct machine *machine,
 				    struct perf_session *session);
-int perf_event__process_build_id(union perf_event *event,
+int perf_event__process_build_id(struct perf_event_ops *ops,
+				 union perf_event *event,
 				 struct perf_session *session);
 
 /*
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 734358b..a36023a 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -270,13 +270,21 @@ int perf_session__resolve_callchain(struct perf_session *self, struct perf_evsel
 	return 0;
 }
 
-static int process_event_synth_stub(union perf_event *event __used,
+static int process_event_synth_stub(struct perf_event_ops *ops __used,
+				    union perf_event *event __used,
 				    struct perf_session *session __used)
 {
 	dump_printf(": unhandled!\n");
 	return 0;
 }
 
+static int process_event_synth_tracing_data_stub(union perf_event *event __used,
+						 struct perf_session *session __used)
+{
+	dump_printf(": unhandled!\n");
+	return 0;
+}
+
 static int process_event_synth_attr_stub(union perf_event *event __used,
 					 struct perf_evlist **pevlist __used)
 {
@@ -284,7 +292,8 @@ static int process_event_synth_attr_stub(union perf_event *event __used,
 	return 0;
 }
 
-static int process_event_sample_stub(union perf_event *event __used,
+static int process_event_sample_stub(struct perf_event_ops *ops __used,
+				     union perf_event *event __used,
 				     struct perf_sample *sample __used,
 				     struct perf_evsel *evsel __used,
 				     struct perf_session *session __used)
@@ -293,7 +302,8 @@ static int process_event_sample_stub(union perf_event *event __used,
 	return 0;
 }
 
-static int process_event_stub(union perf_event *event __used,
+static int process_event_stub(struct perf_event_ops *ops __used,
+			      union perf_event *event __used,
 			      struct perf_sample *sample __used,
 			      struct perf_session *session __used)
 {
@@ -301,17 +311,17 @@ static int process_event_stub(union perf_event *event __used,
 	return 0;
 }
 
-static int process_finished_round_stub(union perf_event *event __used,
-				       struct perf_session *session __used,
-				       struct perf_event_ops *ops __used)
+static int process_finished_round_stub(struct perf_event_ops *ops __used,
+				       union perf_event *event __used,
+				       struct perf_session *session __used)
 {
 	dump_printf(": unhandled!\n");
 	return 0;
 }
 
-static int process_finished_round(union perf_event *event,
-				  struct perf_session *session,
-				  struct perf_event_ops *ops);
+static int process_finished_round(struct perf_event_ops *ops,
+				  union perf_event *event,
+				  struct perf_session *session);
 
 static void perf_event_ops__fill_defaults(struct perf_event_ops *handler)
 {
@@ -338,7 +348,7 @@ static void perf_event_ops__fill_defaults(struct perf_event_ops *handler)
 	if (handler->event_type == NULL)
 		handler->event_type = process_event_synth_stub;
 	if (handler->tracing_data == NULL)
-		handler->tracing_data = process_event_synth_stub;
+		handler->tracing_data = process_event_synth_tracing_data_stub;
 	if (handler->build_id == NULL)
 		handler->build_id = process_event_synth_stub;
 	if (handler->finished_round == NULL) {
@@ -565,9 +575,9 @@ static void flush_sample_queue(struct perf_session *s,
  *      Flush every events below timestamp 7
  *      etc...
  */
-static int process_finished_round(union perf_event *event __used,
-				  struct perf_session *session,
-				  struct perf_event_ops *ops)
+static int process_finished_round(struct perf_event_ops *ops,
+				  union perf_event *event __used,
+				  struct perf_session *session)
 {
 	flush_sample_queue(session, ops);
 	session->ordered_samples.next_flush = session->ordered_samples.max_timestamp;
@@ -759,23 +769,23 @@ static int perf_session_deliver_event(struct perf_session *session,
 			++session->hists.stats.nr_unknown_id;
 			return -1;
 		}
-		return ops->sample(event, sample, evsel, session);
+		return ops->sample(ops, event, sample, evsel, session);
 	case PERF_RECORD_MMAP:
-		return ops->mmap(event, sample, session);
+		return ops->mmap(ops, event, sample, session);
 	case PERF_RECORD_COMM:
-		return ops->comm(event, sample, session);
+		return ops->comm(ops, event, sample, session);
 	case PERF_RECORD_FORK:
-		return ops->fork(event, sample, session);
+		return ops->fork(ops, event, sample, session);
 	case PERF_RECORD_EXIT:
-		return ops->exit(event, sample, session);
+		return ops->exit(ops, event, sample, session);
 	case PERF_RECORD_LOST:
-		return ops->lost(event, sample, session);
+		return ops->lost(ops, event, sample, session);
 	case PERF_RECORD_READ:
-		return ops->read(event, sample, session);
+		return ops->read(ops, event, sample, session);
 	case PERF_RECORD_THROTTLE:
-		return ops->throttle(event, sample, session);
+		return ops->throttle(ops, event, sample, session);
 	case PERF_RECORD_UNTHROTTLE:
-		return ops->unthrottle(event, sample, session);
+		return ops->unthrottle(ops, event, sample, session);
 	default:
 		++session->hists.stats.nr_unknown_events;
 		return -1;
@@ -813,15 +823,15 @@ static int perf_session__process_user_event(struct perf_session *session, union
 			perf_session__update_sample_type(session);
 		return err;
 	case PERF_RECORD_HEADER_EVENT_TYPE:
-		return ops->event_type(event, session);
+		return ops->event_type(ops, event, session);
 	case PERF_RECORD_HEADER_TRACING_DATA:
 		/* setup for reading amidst mmap */
 		lseek(session->fd, file_offset, SEEK_SET);
 		return ops->tracing_data(event, session);
 	case PERF_RECORD_HEADER_BUILD_ID:
-		return ops->build_id(event, session);
+		return ops->build_id(ops, event, session);
 	case PERF_RECORD_FINISHED_ROUND:
-		return ops->finished_round(event, session, ops);
+		return ops->finished_round(ops, event, session);
 	default:
 		return -EINVAL;
 	}
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index d2f4303..6de3d13 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -56,16 +56,18 @@ struct perf_session {
 struct perf_evsel;
 struct perf_event_ops;
 
-typedef int (*event_sample)(union perf_event *event, struct perf_sample *sample,
+typedef int (*event_sample)(struct perf_event_ops *ops,
+			    union perf_event *event, struct perf_sample *sample,
 			    struct perf_evsel *evsel, struct perf_session *session);
-typedef int (*event_op)(union perf_event *self, struct perf_sample *sample,
+typedef int (*event_op)(struct perf_event_ops *ops, union perf_event *event,
+			struct perf_sample *sample,
 			struct perf_session *session);
 typedef int (*event_synth_op)(union perf_event *self,
 			      struct perf_session *session);
 typedef int (*event_attr_op)(union perf_event *event,
 			     struct perf_evlist **pevlist);
-typedef int (*event_op2)(union perf_event *self, struct perf_session *session,
-			 struct perf_event_ops *ops);
+typedef int (*event_op2)(struct perf_event_ops *ops, union perf_event *event,
+			 struct perf_session *session);
 
 struct perf_event_ops {
 	event_sample	sample;
@@ -78,10 +80,10 @@ struct perf_event_ops {
 			throttle,
 			unthrottle;
 	event_attr_op	attr;
-	event_synth_op	event_type,
-			tracing_data,
-			build_id;
-	event_op2	finished_round;
+	event_synth_op	tracing_data;
+	event_op2	event_type,
+			build_id,
+			finished_round;
 	bool		ordered_samples;
 	bool		ordering_requires_timestamps;
 };
@@ -142,10 +144,11 @@ struct machine *perf_session__findnew_machine(struct perf_session *self, pid_t p
 
 static inline
 void perf_session__process_machines(struct perf_session *self,
+				    struct perf_event_ops *ops,
 				    machine__process_t process)
 {
-	process(&self->host_machine, self);
-	return machines__process(&self->machines, process, self);
+	process(&self->host_machine, ops);
+	return machines__process(&self->machines, process, ops);
 }
 
 size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp);
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index 3996509..44eda6f 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -2,14 +2,15 @@
 #define __PERF_TOP_H 1
 
 #include "types.h"
+#include "session.h"
 #include "../perf.h"
 #include <stddef.h>
 
 struct perf_evlist;
 struct perf_evsel;
-struct perf_session;
 
 struct perf_top {
+	struct perf_event_ops ops;
 	struct perf_evlist *evlist;
 	/*
 	 * Symbols will be added here in perf_event__process_sample and will
-- 
1.7.8.rc0.35.gee6df


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

* [PATCH 20/25] perf tools: Resolve machine earlier and pass it to perf_event_ops
  2011-11-28 23:14 [GIT PULL 00/25] perf/core fixes and improvements Arnaldo Carvalho de Melo
                   ` (18 preceding siblings ...)
  2011-11-28 23:14 ` [PATCH 19/25] perf tools: Pass tool context in the the perf_event_ops functions Arnaldo Carvalho de Melo
@ 2011-11-28 23:14 ` Arnaldo Carvalho de Melo
  2011-11-28 23:14 ` [PATCH 21/25] perf tools: Rename perf_event_ops to perf_tool Arnaldo Carvalho de Melo
                   ` (4 subsequent siblings)
  24 siblings, 0 replies; 28+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-11-28 23:14 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Arnaldo Carvalho de Melo, David Ahern,
	Frederic Weisbecker, Mike Galbraith, Paul Mackerras,
	Peter Zijlstra, Stephane Eranian

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

Reducing the exposure of perf_session further, so that we can use the
classes in cases where no perf.data file is created.

Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-stua66dcscsezzrcdugvbmvd@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-annotate.c                      |    4 +-
 tools/perf/builtin-diff.c                          |    9 +-
 tools/perf/builtin-inject.c                        |   70 +++++----
 tools/perf/builtin-kmem.c                          |    4 +-
 tools/perf/builtin-lock.c                          |    4 +-
 tools/perf/builtin-record.c                        |   38 +++---
 tools/perf/builtin-report.c                        |   24 ++--
 tools/perf/builtin-sched.c                         |   70 +++++-----
 tools/perf/builtin-script.c                        |   26 ++--
 tools/perf/builtin-timechart.c                     |    8 +-
 tools/perf/builtin-top.c                           |   99 +++++++------
 tools/perf/util/build-id.c                         |   16 +-
 tools/perf/util/event.c                            |  151 ++++++++-----------
 tools/perf/util/event.h                            |   21 ++--
 tools/perf/util/header.c                           |   28 ++--
 tools/perf/util/header.h                           |   16 +--
 tools/perf/util/map.h                              |   10 ++
 .../perf/util/scripting-engines/trace-event-perl.c |    4 +-
 .../util/scripting-engines/trace-event-python.c    |    4 +-
 tools/perf/util/session.c                          |   91 +++++++-----
 tools/perf/util/session.h                          |   30 ++--
 tools/perf/util/thread.h                           |   14 +--
 tools/perf/util/trace-event-scripting.c            |    2 +-
 tools/perf/util/trace-event.h                      |    8 +-
 24 files changed, 376 insertions(+), 375 deletions(-)

diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 483cb94..dff081a 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -83,12 +83,12 @@ static int process_sample_event(struct perf_event_ops *ops,
 				union perf_event *event,
 				struct perf_sample *sample,
 				struct perf_evsel *evsel,
-				struct perf_session *session)
+				struct machine *machine)
 {
 	struct perf_annotate *ann = container_of(ops, struct perf_annotate, ops);
 	struct addr_location al;
 
-	if (perf_event__preprocess_sample(event, session, &al, sample,
+	if (perf_event__preprocess_sample(event, machine, &al, sample,
 					  symbol__annotate_init) < 0) {
 		pr_warning("problem processing %d event, skipping it.\n",
 			   event->header.type);
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 9a0872f..478b0ae 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -9,6 +9,7 @@
 #include "util/debug.h"
 #include "util/event.h"
 #include "util/hist.h"
+#include "util/evsel.h"
 #include "util/session.h"
 #include "util/sort.h"
 #include "util/symbol.h"
@@ -34,11 +35,11 @@ static int diff__process_sample_event(struct perf_event_ops *ops __used,
 				      union perf_event *event,
 				      struct perf_sample *sample,
 				      struct perf_evsel *evsel __used,
-				      struct perf_session *session)
+				      struct machine *machine)
 {
 	struct addr_location al;
 
-	if (perf_event__preprocess_sample(event, session, &al, sample, NULL) < 0) {
+	if (perf_event__preprocess_sample(event, machine, &al, sample, NULL) < 0) {
 		pr_warning("problem processing %d event, skipping it.\n",
 			   event->header.type);
 		return -1;
@@ -47,12 +48,12 @@ static int diff__process_sample_event(struct perf_event_ops *ops __used,
 	if (al.filtered || al.sym == NULL)
 		return 0;
 
-	if (hists__add_entry(&session->hists, &al, sample->period)) {
+	if (hists__add_entry(&evsel->hists, &al, sample->period)) {
 		pr_warning("problem incrementing symbol period, skipping event\n");
 		return -1;
 	}
 
-	session->hists.stats.total_period += sample->period;
+	evsel->hists.stats.total_period += sample->period;
 	return 0;
 }
 
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 6ce6d80..a5bcf81 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -18,7 +18,7 @@ static bool		inject_build_ids;
 
 static int perf_event__repipe_synth(struct perf_event_ops *ops __used,
 				    union perf_event *event,
-				    struct perf_session *session __used)
+				    struct machine *machine __used)
 {
 	uint32_t size;
 	void *buf = event;
@@ -37,10 +37,23 @@ static int perf_event__repipe_synth(struct perf_event_ops *ops __used,
 	return 0;
 }
 
+static int perf_event__repipe_op2_synth(struct perf_event_ops *ops,
+					union perf_event *event,
+					struct perf_session *session __used)
+{
+	return perf_event__repipe_synth(ops, event, NULL);
+}
+
+static int perf_event__repipe_event_type_synth(struct perf_event_ops *ops,
+					       union perf_event *event)
+{
+	return perf_event__repipe_synth(ops, event, NULL);
+}
+
 static int perf_event__repipe_tracing_data_synth(union perf_event *event,
-						 struct perf_session *session)
+						 struct perf_session *session __used)
 {
-	return perf_event__repipe_synth(NULL, event, session);
+	return perf_event__repipe_synth(NULL, event, NULL);
 }
 
 static int perf_event__repipe_attr(union perf_event *event,
@@ -52,29 +65,29 @@ static int perf_event__repipe_attr(union perf_event *event,
 static int perf_event__repipe(struct perf_event_ops *ops,
 			      union perf_event *event,
 			      struct perf_sample *sample __used,
-			      struct perf_session *session)
+			      struct machine *machine)
 {
-	return perf_event__repipe_synth(ops, event, session);
+	return perf_event__repipe_synth(ops, event, machine);
 }
 
 static int perf_event__repipe_sample(struct perf_event_ops *ops,
 				     union perf_event *event,
 			      struct perf_sample *sample __used,
 			      struct perf_evsel *evsel __used,
-			      struct perf_session *session)
+			      struct machine *machine)
 {
-	return perf_event__repipe_synth(ops, event, session);
+	return perf_event__repipe_synth(ops, event, machine);
 }
 
 static int perf_event__repipe_mmap(struct perf_event_ops *ops,
 				   union perf_event *event,
 				   struct perf_sample *sample,
-				   struct perf_session *session)
+				   struct machine *machine)
 {
 	int err;
 
-	err = perf_event__process_mmap(ops, event, sample, session);
-	perf_event__repipe(ops, event, sample, session);
+	err = perf_event__process_mmap(ops, event, sample, machine);
+	perf_event__repipe(ops, event, sample, machine);
 
 	return err;
 }
@@ -82,12 +95,12 @@ static int perf_event__repipe_mmap(struct perf_event_ops *ops,
 static int perf_event__repipe_task(struct perf_event_ops *ops,
 				   union perf_event *event,
 				   struct perf_sample *sample,
-				   struct perf_session *session)
+				   struct machine *machine)
 {
 	int err;
 
-	err = perf_event__process_task(ops, event, sample, session);
-	perf_event__repipe(ops, event, sample, session);
+	err = perf_event__process_task(ops, event, sample, machine);
+	perf_event__repipe(ops, event, sample, machine);
 
 	return err;
 }
@@ -97,7 +110,7 @@ static int perf_event__repipe_tracing_data(union perf_event *event,
 {
 	int err;
 
-	perf_event__repipe_synth(NULL, event, session);
+	perf_event__repipe_synth(NULL, event, NULL);
 	err = perf_event__process_tracing_data(event, session);
 
 	return err;
@@ -118,10 +131,9 @@ static int dso__read_build_id(struct dso *self)
 }
 
 static int dso__inject_build_id(struct dso *self, struct perf_event_ops *ops,
-				struct perf_session *session)
+				struct machine *machine)
 {
 	u16 misc = PERF_RECORD_MISC_USER;
-	struct machine *machine;
 	int err;
 
 	if (dso__read_build_id(self) < 0) {
@@ -129,17 +141,11 @@ static int dso__inject_build_id(struct dso *self, struct perf_event_ops *ops,
 		return -1;
 	}
 
-	machine = perf_session__find_host_machine(session);
-	if (machine == NULL) {
-		pr_err("Can't find machine for session\n");
-		return -1;
-	}
-
 	if (self->kernel)
 		misc = PERF_RECORD_MISC_KERNEL;
 
 	err = perf_event__synthesize_build_id(ops, self, misc, perf_event__repipe,
-					      machine, session);
+					      machine);
 	if (err) {
 		pr_err("Can't synthesize build_id event for %s\n", self->long_name);
 		return -1;
@@ -152,7 +158,7 @@ static int perf_event__inject_buildid(struct perf_event_ops *ops,
 				      union perf_event *event,
 				      struct perf_sample *sample,
 				      struct perf_evsel *evsel __used,
-				      struct perf_session *session)
+				      struct machine *machine)
 {
 	struct addr_location al;
 	struct thread *thread;
@@ -160,21 +166,21 @@ static int perf_event__inject_buildid(struct perf_event_ops *ops,
 
 	cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
 
-	thread = perf_session__findnew(session, event->ip.pid);
+	thread = machine__findnew_thread(machine, event->ip.pid);
 	if (thread == NULL) {
 		pr_err("problem processing %d event, skipping it.\n",
 		       event->header.type);
 		goto repipe;
 	}
 
-	thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION,
-			      event->ip.pid, event->ip.ip, &al);
+	thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION,
+			      event->ip.ip, &al);
 
 	if (al.map != NULL) {
 		if (!al.map->dso->hit) {
 			al.map->dso->hit = 1;
 			if (map__load(al.map, NULL) >= 0) {
-				dso__inject_build_id(al.map->dso, ops, session);
+				dso__inject_build_id(al.map->dso, ops, machine);
 				/*
 				 * If this fails, too bad, let the other side
 				 * account this as unresolved.
@@ -187,7 +193,7 @@ static int perf_event__inject_buildid(struct perf_event_ops *ops,
 	}
 
 repipe:
-	perf_event__repipe(ops, event, sample, session);
+	perf_event__repipe(ops, event, sample, machine);
 	return 0;
 }
 
@@ -198,13 +204,13 @@ struct perf_event_ops inject_ops = {
 	.fork		= perf_event__repipe,
 	.exit		= perf_event__repipe,
 	.lost		= perf_event__repipe,
-	.read		= perf_event__repipe,
+	.read		= perf_event__repipe_sample,
 	.throttle	= perf_event__repipe,
 	.unthrottle	= perf_event__repipe,
 	.attr		= perf_event__repipe_attr,
-	.event_type	= perf_event__repipe_synth,
+	.event_type	= perf_event__repipe_event_type_synth,
 	.tracing_data	= perf_event__repipe_tracing_data_synth,
-	.build_id	= perf_event__repipe_synth,
+	.build_id	= perf_event__repipe_op2_synth,
 };
 
 extern volatile int session_done;
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index 5d01218..27b2a15 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -307,9 +307,9 @@ static int process_sample_event(struct perf_event_ops *ops __used,
 				union perf_event *event,
 				struct perf_sample *sample,
 				struct perf_evsel *evsel __used,
-				struct perf_session *session)
+				struct machine *machine)
 {
-	struct thread *thread = perf_session__findnew(session, event->ip.pid);
+	struct thread *thread = machine__findnew_thread(machine, event->ip.pid);
 
 	if (thread == NULL) {
 		pr_debug("problem processing %d event, skipping it.\n",
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index f06b0a4..99b032a 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -849,9 +849,9 @@ static int process_sample_event(struct perf_event_ops *ops __used,
 				union perf_event *event,
 				struct perf_sample *sample,
 				struct perf_evsel *evsel __used,
-				struct perf_session *s)
+				struct machine *machine)
 {
-	struct thread *thread = perf_session__findnew(s, sample->tid);
+	struct thread *thread = machine__findnew_thread(machine, sample->tid);
 
 	if (thread == NULL) {
 		pr_debug("problem processing %d event, skipping it.\n",
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 4642d38..0af598a 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -79,7 +79,7 @@ static void write_output(struct perf_record *rec, void *buf, size_t size)
 static int process_synthesized_event(struct perf_event_ops *ops,
 				     union perf_event *event,
 				     struct perf_sample *sample __used,
-				     struct perf_session *self __used)
+				     struct machine *machine __used)
 {
 	struct perf_record *rec = container_of(ops, struct perf_record, ops);
 	write_output(rec, event, event->header.size);
@@ -320,8 +320,6 @@ static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
 {
 	int err;
 	struct perf_event_ops *ops = data;
-	struct perf_record *rec = container_of(ops, struct perf_record, ops);
-	struct perf_session *psession = rec->session;
 
 	if (machine__is_host(machine))
 		return;
@@ -335,7 +333,7 @@ static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
 	 *in module instead of in guest kernel.
 	 */
 	err = perf_event__synthesize_modules(ops, process_synthesized_event,
-					     psession, machine);
+					     machine);
 	if (err < 0)
 		pr_err("Couldn't record guest kernel [%d]'s reference"
 		       " relocation symbol.\n", machine->pid);
@@ -345,11 +343,10 @@ static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
 	 * have no _text sometimes.
 	 */
 	err = perf_event__synthesize_kernel_mmap(ops, process_synthesized_event,
-						 psession, machine, "_text");
+						 machine, "_text");
 	if (err < 0)
 		err = perf_event__synthesize_kernel_mmap(ops, process_synthesized_event,
-							 psession, machine,
-							 "_stext");
+							 machine, "_stext");
 	if (err < 0)
 		pr_err("Couldn't record guest kernel [%d]'s reference"
 		       " relocation symbol.\n", machine->pid);
@@ -497,6 +494,12 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
 
 	rec->post_processing_offset = lseek(output, 0, SEEK_CUR);
 
+	machine = perf_session__find_host_machine(session);
+	if (!machine) {
+		pr_err("Couldn't find native kernel information.\n");
+		return -1;
+	}
+
 	if (opts->pipe_output) {
 		err = perf_event__synthesize_attrs(ops, session,
 						   process_synthesized_event);
@@ -506,7 +509,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
 		}
 
 		err = perf_event__synthesize_event_types(ops, process_synthesized_event,
-							 session);
+							 machine);
 		if (err < 0) {
 			pr_err("Couldn't synthesize event_types.\n");
 			return err;
@@ -522,8 +525,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
 			 * propagate errors that now are calling die()
 			 */
 			err = perf_event__synthesize_tracing_data(ops, output, evsel_list,
-								  process_synthesized_event,
-								  session);
+								  process_synthesized_event);
 			if (err <= 0) {
 				pr_err("Couldn't record tracing data.\n");
 				return err;
@@ -532,24 +534,18 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
 		}
 	}
 
-	machine = perf_session__find_host_machine(session);
-	if (!machine) {
-		pr_err("Couldn't find native kernel information.\n");
-		return -1;
-	}
-
 	err = perf_event__synthesize_kernel_mmap(ops, process_synthesized_event,
-						 session, machine, "_text");
+						 machine, "_text");
 	if (err < 0)
 		err = perf_event__synthesize_kernel_mmap(ops, process_synthesized_event,
-							 session, machine, "_stext");
+							 machine, "_stext");
 	if (err < 0)
 		pr_err("Couldn't record kernel reference relocation symbol\n"
 		       "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
 		       "Check /proc/kallsyms permission or run as root.\n");
 
 	err = perf_event__synthesize_modules(ops, process_synthesized_event,
-					     session, machine);
+					     machine);
 	if (err < 0)
 		pr_err("Couldn't record kernel module information.\n"
 		       "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
@@ -562,10 +558,10 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
 	if (!opts->system_wide)
 		perf_event__synthesize_thread_map(ops, evsel_list->threads,
 						  process_synthesized_event,
-						  session);
+						  machine);
 	else
 		perf_event__synthesize_threads(ops, process_synthesized_event,
-					       session);
+					       machine);
 
 	if (rec->realtime_prio) {
 		struct sched_param param;
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 8795520..ea64fbb 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -52,18 +52,18 @@ struct perf_report {
 	DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
 };
 
-static int perf_session__add_hist_entry(struct perf_session *session,
-					struct addr_location *al,
-					struct perf_sample *sample,
-					struct perf_evsel *evsel)
+static int perf_evsel__add_hist_entry(struct perf_evsel *evsel,
+				      struct addr_location *al,
+				      struct perf_sample *sample,
+				      struct machine *machine)
 {
 	struct symbol *parent = NULL;
 	int err = 0;
 	struct hist_entry *he;
 
 	if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) {
-		err = perf_session__resolve_callchain(session, evsel, al->thread,
-						      sample->callchain, &parent);
+		err = machine__resolve_callchain(machine, evsel, al->thread,
+						 sample->callchain, &parent);
 		if (err)
 			return err;
 	}
@@ -107,12 +107,12 @@ static int process_sample_event(struct perf_event_ops *ops,
 				union perf_event *event,
 				struct perf_sample *sample,
 				struct perf_evsel *evsel,
-				struct perf_session *session)
+				struct machine *machine)
 {
 	struct perf_report *rep = container_of(ops, struct perf_report, ops);
 	struct addr_location al;
 
-	if (perf_event__preprocess_sample(event, session, &al, sample,
+	if (perf_event__preprocess_sample(event, machine, &al, sample,
 					  rep->annotate_init) < 0) {
 		fprintf(stderr, "problem processing %d event, skipping it.\n",
 			event->header.type);
@@ -128,7 +128,7 @@ static int process_sample_event(struct perf_event_ops *ops,
 	if (al.map != NULL)
 		al.map->dso->hit = 1;
 
-	if (perf_session__add_hist_entry(session, &al, sample, evsel)) {
+	if (perf_evsel__add_hist_entry(evsel, &al, sample, machine)) {
 		pr_debug("problem incrementing symbol period, skipping event\n");
 		return -1;
 	}
@@ -139,11 +139,11 @@ static int process_sample_event(struct perf_event_ops *ops,
 static int process_read_event(struct perf_event_ops *ops,
 			      union perf_event *event,
 			      struct perf_sample *sample __used,
-			      struct perf_session *session)
+			      struct perf_evsel *evsel,
+			      struct machine *machine __used)
 {
 	struct perf_report *rep = container_of(ops, struct perf_report, ops);
-	struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist,
-							 event->read.id);
+
 	if (rep->show_threads) {
 		const char *name = evsel ? event_name(evsel) : "unknown";
 		perf_read_values_add_value(&rep->show_threads_values,
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index b11d628..6a771f8 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -724,21 +724,21 @@ struct trace_migrate_task_event {
 
 struct trace_sched_handler {
 	void (*switch_event)(struct trace_switch_event *,
-			     struct perf_session *,
+			     struct machine *,
 			     struct event *,
 			     int cpu,
 			     u64 timestamp,
 			     struct thread *thread);
 
 	void (*runtime_event)(struct trace_runtime_event *,
-			      struct perf_session *,
+			      struct machine *,
 			      struct event *,
 			      int cpu,
 			      u64 timestamp,
 			      struct thread *thread);
 
 	void (*wakeup_event)(struct trace_wakeup_event *,
-			     struct perf_session *,
+			     struct machine *,
 			     struct event *,
 			     int cpu,
 			     u64 timestamp,
@@ -751,7 +751,7 @@ struct trace_sched_handler {
 			   struct thread *thread);
 
 	void (*migrate_task_event)(struct trace_migrate_task_event *,
-			   struct perf_session *session,
+			   struct machine *machine,
 			   struct event *,
 			   int cpu,
 			   u64 timestamp,
@@ -761,7 +761,7 @@ struct trace_sched_handler {
 
 static void
 replay_wakeup_event(struct trace_wakeup_event *wakeup_event,
-		    struct perf_session *session __used,
+		    struct machine *machine __used,
 		    struct event *event,
 		    int cpu __used,
 		    u64 timestamp __used,
@@ -788,7 +788,7 @@ static u64 cpu_last_switched[MAX_CPUS];
 
 static void
 replay_switch_event(struct trace_switch_event *switch_event,
-		    struct perf_session *session __used,
+		    struct machine *machine __used,
 		    struct event *event,
 		    int cpu,
 		    u64 timestamp,
@@ -1022,7 +1022,7 @@ add_sched_in_event(struct work_atoms *atoms, u64 timestamp)
 
 static void
 latency_switch_event(struct trace_switch_event *switch_event,
-		     struct perf_session *session,
+		     struct machine *machine,
 		     struct event *event __used,
 		     int cpu,
 		     u64 timestamp,
@@ -1046,8 +1046,8 @@ latency_switch_event(struct trace_switch_event *switch_event,
 		die("hm, delta: %" PRIu64 " < 0 ?\n", delta);
 
 
-	sched_out = perf_session__findnew(session, switch_event->prev_pid);
-	sched_in = perf_session__findnew(session, switch_event->next_pid);
+	sched_out = machine__findnew_thread(machine, switch_event->prev_pid);
+	sched_in = machine__findnew_thread(machine, switch_event->next_pid);
 
 	out_events = thread_atoms_search(&atom_root, sched_out, &cmp_pid);
 	if (!out_events) {
@@ -1075,13 +1075,13 @@ latency_switch_event(struct trace_switch_event *switch_event,
 
 static void
 latency_runtime_event(struct trace_runtime_event *runtime_event,
-		     struct perf_session *session,
+		     struct machine *machine,
 		     struct event *event __used,
 		     int cpu,
 		     u64 timestamp,
 		     struct thread *this_thread __used)
 {
-	struct thread *thread = perf_session__findnew(session, runtime_event->pid);
+	struct thread *thread = machine__findnew_thread(machine, runtime_event->pid);
 	struct work_atoms *atoms = thread_atoms_search(&atom_root, thread, &cmp_pid);
 
 	BUG_ON(cpu >= MAX_CPUS || cpu < 0);
@@ -1098,7 +1098,7 @@ latency_runtime_event(struct trace_runtime_event *runtime_event,
 
 static void
 latency_wakeup_event(struct trace_wakeup_event *wakeup_event,
-		     struct perf_session *session,
+		     struct machine *machine,
 		     struct event *__event __used,
 		     int cpu __used,
 		     u64 timestamp,
@@ -1112,7 +1112,7 @@ latency_wakeup_event(struct trace_wakeup_event *wakeup_event,
 	if (!wakeup_event->success)
 		return;
 
-	wakee = perf_session__findnew(session, wakeup_event->pid);
+	wakee = machine__findnew_thread(machine, wakeup_event->pid);
 	atoms = thread_atoms_search(&atom_root, wakee, &cmp_pid);
 	if (!atoms) {
 		thread_atoms_insert(wakee);
@@ -1146,7 +1146,7 @@ latency_wakeup_event(struct trace_wakeup_event *wakeup_event,
 
 static void
 latency_migrate_task_event(struct trace_migrate_task_event *migrate_task_event,
-		     struct perf_session *session,
+		     struct machine *machine,
 		     struct event *__event __used,
 		     int cpu __used,
 		     u64 timestamp,
@@ -1162,7 +1162,7 @@ latency_migrate_task_event(struct trace_migrate_task_event *migrate_task_event,
 	if (profile_cpu == -1)
 		return;
 
-	migrant = perf_session__findnew(session, migrate_task_event->pid);
+	migrant = machine__findnew_thread(machine, migrate_task_event->pid);
 	atoms = thread_atoms_search(&atom_root, migrant, &cmp_pid);
 	if (!atoms) {
 		thread_atoms_insert(migrant);
@@ -1357,7 +1357,7 @@ static void sort_lat(void)
 static struct trace_sched_handler *trace_handler;
 
 static void
-process_sched_wakeup_event(void *data, struct perf_session *session,
+process_sched_wakeup_event(void *data, struct machine *machine,
 			   struct event *event,
 			   int cpu __used,
 			   u64 timestamp __used,
@@ -1374,7 +1374,7 @@ process_sched_wakeup_event(void *data, struct perf_session *session,
 	FILL_FIELD(wakeup_event, cpu, event, data);
 
 	if (trace_handler->wakeup_event)
-		trace_handler->wakeup_event(&wakeup_event, session, event,
+		trace_handler->wakeup_event(&wakeup_event, machine, event,
 					    cpu, timestamp, thread);
 }
 
@@ -1393,7 +1393,7 @@ static char next_shortname2 = '0';
 
 static void
 map_switch_event(struct trace_switch_event *switch_event,
-		 struct perf_session *session,
+		 struct machine *machine,
 		 struct event *event __used,
 		 int this_cpu,
 		 u64 timestamp,
@@ -1421,8 +1421,8 @@ map_switch_event(struct trace_switch_event *switch_event,
 		die("hm, delta: %" PRIu64 " < 0 ?\n", delta);
 
 
-	sched_out = perf_session__findnew(session, switch_event->prev_pid);
-	sched_in = perf_session__findnew(session, switch_event->next_pid);
+	sched_out = machine__findnew_thread(machine, switch_event->prev_pid);
+	sched_in = machine__findnew_thread(machine, switch_event->next_pid);
 
 	curr_thread[this_cpu] = sched_in;
 
@@ -1472,7 +1472,7 @@ map_switch_event(struct trace_switch_event *switch_event,
 
 
 static void
-process_sched_switch_event(void *data, struct perf_session *session,
+process_sched_switch_event(void *data, struct machine *machine,
 			   struct event *event,
 			   int this_cpu,
 			   u64 timestamp __used,
@@ -1499,14 +1499,14 @@ process_sched_switch_event(void *data, struct perf_session *session,
 			nr_context_switch_bugs++;
 	}
 	if (trace_handler->switch_event)
-		trace_handler->switch_event(&switch_event, session, event,
+		trace_handler->switch_event(&switch_event, machine, event,
 					    this_cpu, timestamp, thread);
 
 	curr_pid[this_cpu] = switch_event.next_pid;
 }
 
 static void
-process_sched_runtime_event(void *data, struct perf_session *session,
+process_sched_runtime_event(void *data, struct machine *machine,
 			   struct event *event,
 			   int cpu __used,
 			   u64 timestamp __used,
@@ -1520,7 +1520,7 @@ process_sched_runtime_event(void *data, struct perf_session *session,
 	FILL_FIELD(runtime_event, vruntime, event, data);
 
 	if (trace_handler->runtime_event)
-		trace_handler->runtime_event(&runtime_event, session, event, cpu, timestamp, thread);
+		trace_handler->runtime_event(&runtime_event, machine, event, cpu, timestamp, thread);
 }
 
 static void
@@ -1555,7 +1555,7 @@ process_sched_exit_event(struct event *event,
 }
 
 static void
-process_sched_migrate_task_event(void *data, struct perf_session *session,
+process_sched_migrate_task_event(void *data, struct machine *machine,
 			   struct event *event,
 			   int cpu __used,
 			   u64 timestamp __used,
@@ -1571,12 +1571,12 @@ process_sched_migrate_task_event(void *data, struct perf_session *session,
 	FILL_FIELD(migrate_task_event, cpu, event, data);
 
 	if (trace_handler->migrate_task_event)
-		trace_handler->migrate_task_event(&migrate_task_event, session,
+		trace_handler->migrate_task_event(&migrate_task_event, machine,
 						 event, cpu, timestamp, thread);
 }
 
 static void process_raw_event(union perf_event *raw_event __used,
-			      struct perf_session *session, void *data, int cpu,
+			      struct machine *machine, void *data, int cpu,
 			      u64 timestamp, struct thread *thread)
 {
 	struct event *event;
@@ -1587,33 +1587,33 @@ static void process_raw_event(union perf_event *raw_event __used,
 	event = trace_find_event(type);
 
 	if (!strcmp(event->name, "sched_switch"))
-		process_sched_switch_event(data, session, event, cpu, timestamp, thread);
+		process_sched_switch_event(data, machine, event, cpu, timestamp, thread);
 	if (!strcmp(event->name, "sched_stat_runtime"))
-		process_sched_runtime_event(data, session, event, cpu, timestamp, thread);
+		process_sched_runtime_event(data, machine, event, cpu, timestamp, thread);
 	if (!strcmp(event->name, "sched_wakeup"))
-		process_sched_wakeup_event(data, session, event, cpu, timestamp, thread);
+		process_sched_wakeup_event(data, machine, event, cpu, timestamp, thread);
 	if (!strcmp(event->name, "sched_wakeup_new"))
-		process_sched_wakeup_event(data, session, event, cpu, timestamp, thread);
+		process_sched_wakeup_event(data, machine, event, cpu, timestamp, thread);
 	if (!strcmp(event->name, "sched_process_fork"))
 		process_sched_fork_event(data, event, cpu, timestamp, thread);
 	if (!strcmp(event->name, "sched_process_exit"))
 		process_sched_exit_event(event, cpu, timestamp, thread);
 	if (!strcmp(event->name, "sched_migrate_task"))
-		process_sched_migrate_task_event(data, session, event, cpu, timestamp, thread);
+		process_sched_migrate_task_event(data, machine, event, cpu, timestamp, thread);
 }
 
 static int process_sample_event(struct perf_event_ops *ops __used,
 				union perf_event *event,
 				struct perf_sample *sample,
 				struct perf_evsel *evsel,
-				struct perf_session *session)
+				struct machine *machine)
 {
 	struct thread *thread;
 
 	if (!(evsel->attr.sample_type & PERF_SAMPLE_RAW))
 		return 0;
 
-	thread = perf_session__findnew(session, sample->pid);
+	thread = machine__findnew_thread(machine, sample->pid);
 	if (thread == NULL) {
 		pr_debug("problem processing %d event, skipping it.\n",
 			 event->header.type);
@@ -1625,7 +1625,7 @@ static int process_sample_event(struct perf_event_ops *ops __used,
 	if (profile_cpu != -1 && profile_cpu != (int)sample->cpu)
 		return 0;
 
-	process_raw_event(event, session, sample->raw_data, sample->cpu,
+	process_raw_event(event, machine, sample->raw_data, sample->cpu,
 			  sample->time, thread);
 
 	return 0;
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 3b78206..31a8d14 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -315,7 +315,7 @@ static bool sample_addr_correlates_sym(struct perf_event_attr *attr)
 
 static void print_sample_addr(union perf_event *event,
 			  struct perf_sample *sample,
-			  struct perf_session *session,
+			  struct machine *machine,
 			  struct thread *thread,
 			  struct perf_event_attr *attr)
 {
@@ -328,11 +328,11 @@ static void print_sample_addr(union perf_event *event,
 	if (!sample_addr_correlates_sym(attr))
 		return;
 
-	thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION,
-			      event->ip.pid, sample->addr, &al);
+	thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION,
+			      sample->addr, &al);
 	if (!al.map)
-		thread__find_addr_map(thread, session, cpumode, MAP__VARIABLE,
-				      event->ip.pid, sample->addr, &al);
+		thread__find_addr_map(thread, machine, cpumode, MAP__VARIABLE,
+				      sample->addr, &al);
 
 	al.cpu = sample->cpu;
 	al.sym = NULL;
@@ -362,7 +362,7 @@ static void print_sample_addr(union perf_event *event,
 static void process_event(union perf_event *event __unused,
 			  struct perf_sample *sample,
 			  struct perf_evsel *evsel,
-			  struct perf_session *session,
+			  struct machine *machine,
 			  struct thread *thread)
 {
 	struct perf_event_attr *attr = &evsel->attr;
@@ -377,15 +377,15 @@ static void process_event(union perf_event *event __unused,
 				  sample->raw_size);
 
 	if (PRINT_FIELD(ADDR))
-		print_sample_addr(event, sample, session, thread, attr);
+		print_sample_addr(event, sample, machine, thread, attr);
 
 	if (PRINT_FIELD(IP)) {
 		if (!symbol_conf.use_callchain)
 			printf(" ");
 		else
 			printf("\n");
-		perf_session__print_ip(event, evsel, sample, session,
-					      PRINT_FIELD(SYM), PRINT_FIELD(DSO));
+		perf_event__print_ip(event, sample, machine, evsel,
+				     PRINT_FIELD(SYM), PRINT_FIELD(DSO));
 	}
 
 	printf("\n");
@@ -438,9 +438,9 @@ static int process_sample_event(struct perf_event_ops *ops __used,
 				union perf_event *event,
 				struct perf_sample *sample,
 				struct perf_evsel *evsel,
-				struct perf_session *session)
+				struct machine *machine)
 {
-	struct thread *thread = perf_session__findnew(session, event->ip.pid);
+	struct thread *thread = machine__findnew_thread(machine, event->ip.pid);
 
 	if (thread == NULL) {
 		pr_debug("problem processing %d event, skipping it.\n",
@@ -462,9 +462,9 @@ static int process_sample_event(struct perf_event_ops *ops __used,
 	if (cpu_list && !test_bit(sample->cpu, cpu_bitmap))
 		return 0;
 
-	scripting_ops->process_event(event, sample, evsel, session, thread);
+	scripting_ops->process_event(event, sample, evsel, machine, thread);
 
-	session->hists.stats.total_period += sample->period;
+	evsel->hists.stats.total_period += sample->period;
 	return 0;
 }
 
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 62298a0..8e65396 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -277,7 +277,7 @@ static u64 cpus_pstate_state[MAX_CPUS];
 static int process_comm_event(struct perf_event_ops *ops __used,
 			      union perf_event *event,
 			      struct perf_sample *sample __used,
-			      struct perf_session *session __used)
+			      struct machine *machine __used)
 {
 	pid_set_comm(event->comm.tid, event->comm.comm);
 	return 0;
@@ -286,7 +286,7 @@ static int process_comm_event(struct perf_event_ops *ops __used,
 static int process_fork_event(struct perf_event_ops *ops __used,
 			      union perf_event *event,
 			      struct perf_sample *sample __used,
-			      struct perf_session *session __used)
+			      struct machine *machine __used)
 {
 	pid_fork(event->fork.pid, event->fork.ppid, event->fork.time);
 	return 0;
@@ -295,7 +295,7 @@ static int process_fork_event(struct perf_event_ops *ops __used,
 static int process_exit_event(struct perf_event_ops *ops __used,
 			      union perf_event *event,
 			      struct perf_sample *sample __used,
-			      struct perf_session *session __used)
+			      struct machine *machine __used)
 {
 	pid_exit(event->fork.pid, event->fork.time);
 	return 0;
@@ -494,7 +494,7 @@ static int process_sample_event(struct perf_event_ops *ops __used,
 				union perf_event *event __used,
 				struct perf_sample *sample,
 				struct perf_evsel *evsel,
-				struct perf_session *session __used)
+				struct machine *machine __used)
 {
 	struct trace_entry *te;
 
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index e8e3320..31d4973 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -258,11 +258,9 @@ out_unlock:
 
 static const char		CONSOLE_CLEAR[] = "^[[H^[[2J";
 
-static struct hist_entry *
-	perf_session__add_hist_entry(struct perf_session *session,
-				     struct addr_location *al,
-				     struct perf_sample *sample,
-				     struct perf_evsel *evsel)
+static struct hist_entry *perf_evsel__add_hist_entry(struct perf_evsel *evsel,
+						     struct addr_location *al,
+						     struct perf_sample *sample)
 {
 	struct hist_entry *he;
 
@@ -270,7 +268,7 @@ static struct hist_entry *
 	if (he == NULL)
 		return NULL;
 
-	session->hists.stats.total_period += sample->period;
+	evsel->hists.stats.total_period += sample->period;
 	hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
 	return he;
 }
@@ -675,44 +673,12 @@ static int symbol_filter(struct map *map __used, struct symbol *sym)
 static void perf_event__process_sample(const union perf_event *event,
 				       struct perf_evsel *evsel,
 				       struct perf_sample *sample,
-				       struct perf_session *session)
+				       struct machine *machine)
 {
 	struct symbol *parent = NULL;
 	u64 ip = event->ip.ip;
 	struct addr_location al;
-	struct machine *machine;
 	int err;
-	u8 origin = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
-
-	++top.samples;
-
-	switch (origin) {
-	case PERF_RECORD_MISC_USER:
-		++top.us_samples;
-		if (top.hide_user_symbols)
-			return;
-		machine = perf_session__find_host_machine(session);
-		break;
-	case PERF_RECORD_MISC_KERNEL:
-		++top.kernel_samples;
-		if (top.hide_kernel_symbols)
-			return;
-		machine = perf_session__find_host_machine(session);
-		break;
-	case PERF_RECORD_MISC_GUEST_KERNEL:
-		++top.guest_kernel_samples;
-		machine = perf_session__find_machine(session, event->ip.pid);
-		break;
-	case PERF_RECORD_MISC_GUEST_USER:
-		++top.guest_us_samples;
-		/*
-		 * TODO: we don't process guest user from host side
-		 * except simple counting.
-		 */
-		return;
-	default:
-		return;
-	}
 
 	if (!machine && perf_guest) {
 		pr_err("Can't find guest [%d]'s kernel information\n",
@@ -723,7 +689,7 @@ static void perf_event__process_sample(const union perf_event *event,
 	if (event->header.misc & PERF_RECORD_MISC_EXACT_IP)
 		top.exact_samples++;
 
-	if (perf_event__preprocess_sample(event, session, &al, sample,
+	if (perf_event__preprocess_sample(event, machine, &al, sample,
 					  symbol_filter) < 0 ||
 	    al.filtered)
 		return;
@@ -777,13 +743,13 @@ static void perf_event__process_sample(const union perf_event *event,
 
 		if ((sort__has_parent || symbol_conf.use_callchain) &&
 		    sample->callchain) {
-			err = perf_session__resolve_callchain(session, evsel, al.thread,
-							      sample->callchain, &parent);
+			err = machine__resolve_callchain(machine, evsel, al.thread,
+							 sample->callchain, &parent);
 			if (err)
 				return;
 		}
 
-		he = perf_session__add_hist_entry(session, &al, sample, evsel);
+		he = perf_evsel__add_hist_entry(evsel, &al, sample);
 		if (he == NULL) {
 			pr_err("Problem incrementing symbol period, skipping event\n");
 			return;
@@ -808,6 +774,8 @@ static void perf_session__mmap_read_idx(struct perf_session *self, int idx)
 	struct perf_sample sample;
 	struct perf_evsel *evsel;
 	union perf_event *event;
+	struct machine *machine;
+	u8 origin;
 	int ret;
 
 	while ((event = perf_evlist__mmap_read(top.evlist, idx)) != NULL) {
@@ -820,11 +788,45 @@ static void perf_session__mmap_read_idx(struct perf_session *self, int idx)
 		evsel = perf_evlist__id2evsel(self->evlist, sample.id);
 		assert(evsel != NULL);
 
+		origin = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
+
 		if (event->header.type == PERF_RECORD_SAMPLE)
-			perf_event__process_sample(event, evsel, &sample, self);
+			++top.samples;
+
+		switch (origin) {
+		case PERF_RECORD_MISC_USER:
+			++top.us_samples;
+			if (top.hide_user_symbols)
+				continue;
+			machine = perf_session__find_host_machine(self);
+			break;
+		case PERF_RECORD_MISC_KERNEL:
+			++top.kernel_samples;
+			if (top.hide_kernel_symbols)
+				continue;
+			machine = perf_session__find_host_machine(self);
+			break;
+		case PERF_RECORD_MISC_GUEST_KERNEL:
+			++top.guest_kernel_samples;
+			machine = perf_session__find_machine(self, event->ip.pid);
+			break;
+		case PERF_RECORD_MISC_GUEST_USER:
+			++top.guest_us_samples;
+			/*
+			 * TODO: we don't process guest user from host side
+			 * except simple counting.
+			 */
+			/* Fall thru */
+		default:
+			continue;
+		}
+
+
+		if (event->header.type == PERF_RECORD_SAMPLE)
+			perf_event__process_sample(event, evsel, &sample, machine);
 		else if (event->header.type < PERF_RECORD_MAX) {
 			hists__inc_nr_events(&evsel->hists, event->header.type);
-			perf_event__process(&top.ops, event, &sample, self);
+			perf_event__process(&top.ops, event, &sample, machine);
 		} else
 			++self->hists.stats.nr_unknown_events;
 	}
@@ -967,10 +969,11 @@ static int __cmd_top(void)
 
 	if (top.target_tid != -1)
 		perf_event__synthesize_thread_map(&top.ops, top.evlist->threads,
-						  perf_event__process, top.session);
+						  perf_event__process,
+						  &top.session->host_machine);
 	else
-		perf_event__synthesize_threads(&top.ops, perf_event__process, top.session);
-
+		perf_event__synthesize_threads(&top.ops, perf_event__process,
+					       &top.session->host_machine);
 	start_counters(top.evlist);
 	top.session->evlist = top.evlist;
 	perf_session__update_sample_type(top.session);
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 0e4de18..2f84c48 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -19,11 +19,11 @@ static int build_id__mark_dso_hit(struct perf_event_ops *ops __used,
 				  union perf_event *event,
 				  struct perf_sample *sample __used,
 				  struct perf_evsel *evsel __used,
-				  struct perf_session *session)
+				  struct machine *machine)
 {
 	struct addr_location al;
 	u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
-	struct thread *thread = perf_session__findnew(session, event->ip.pid);
+	struct thread *thread = machine__findnew_thread(machine, event->ip.pid);
 
 	if (thread == NULL) {
 		pr_err("problem processing %d event, skipping it.\n",
@@ -31,8 +31,8 @@ static int build_id__mark_dso_hit(struct perf_event_ops *ops __used,
 		return -1;
 	}
 
-	thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION,
-			      event->ip.pid, event->ip.ip, &al);
+	thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION,
+			      event->ip.ip, &al);
 
 	if (al.map != NULL)
 		al.map->dso->hit = 1;
@@ -43,16 +43,16 @@ static int build_id__mark_dso_hit(struct perf_event_ops *ops __used,
 static int perf_event__exit_del_thread(struct perf_event_ops *ops __used,
 				       union perf_event *event,
 				       struct perf_sample *sample __used,
-				       struct perf_session *session)
+				       struct machine *machine)
 {
-	struct thread *thread = perf_session__findnew(session, event->fork.tid);
+	struct thread *thread = machine__findnew_thread(machine, event->fork.tid);
 
 	dump_printf("(%d:%d):(%d:%d)\n", event->fork.pid, event->fork.tid,
 		    event->fork.ppid, event->fork.ptid);
 
 	if (thread) {
-		rb_erase(&thread->rb_node, &session->host_machine.threads);
-		session->host_machine.last_match = NULL;
+		rb_erase(&thread->rb_node, &machine->threads);
+		machine->last_match = NULL;
 		thread__delete(thread);
 	}
 
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 4800f38..0cdc811 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -1,7 +1,6 @@
 #include <linux/types.h>
 #include "event.h"
 #include "debug.h"
-#include "session.h"
 #include "sort.h"
 #include "string.h"
 #include "strlist.h"
@@ -47,7 +46,7 @@ static struct perf_sample synth_sample = {
 static pid_t perf_event__synthesize_comm(struct perf_event_ops *ops,
 					 union perf_event *event, pid_t pid,
 					 int full, perf_event__handler_t process,
-					 struct perf_session *session)
+					 struct machine *machine)
 {
 	char filename[PATH_MAX];
 	char bf[BUFSIZ];
@@ -93,14 +92,14 @@ out_race:
 
 	event->comm.header.type = PERF_RECORD_COMM;
 	size = ALIGN(size, sizeof(u64));
-	memset(event->comm.comm + size, 0, session->id_hdr_size);
+	memset(event->comm.comm + size, 0, machine->id_hdr_size);
 	event->comm.header.size = (sizeof(event->comm) -
 				(sizeof(event->comm.comm) - size) +
-				session->id_hdr_size);
+				machine->id_hdr_size);
 	if (!full) {
 		event->comm.tid = pid;
 
-		process(ops, event, &synth_sample, session);
+		process(ops, event, &synth_sample, machine);
 		goto out;
 	}
 
@@ -118,7 +117,7 @@ out_race:
 
 		event->comm.tid = pid;
 
-		process(ops, event, &synth_sample, session);
+		process(ops, event, &synth_sample, machine);
 	}
 
 	closedir(tasks);
@@ -132,7 +131,7 @@ static int perf_event__synthesize_mmap_events(struct perf_event_ops *ops,
 					      union perf_event *event,
 					      pid_t pid, pid_t tgid,
 					      perf_event__handler_t process,
-					      struct perf_session *session)
+					      struct machine *machine)
 {
 	char filename[PATH_MAX];
 	FILE *fp;
@@ -195,12 +194,12 @@ static int perf_event__synthesize_mmap_events(struct perf_event_ops *ops,
 			event->mmap.len -= event->mmap.start;
 			event->mmap.header.size = (sizeof(event->mmap) -
 					        (sizeof(event->mmap.filename) - size));
-			memset(event->mmap.filename + size, 0, session->id_hdr_size);
-			event->mmap.header.size += session->id_hdr_size;
+			memset(event->mmap.filename + size, 0, machine->id_hdr_size);
+			event->mmap.header.size += machine->id_hdr_size;
 			event->mmap.pid = tgid;
 			event->mmap.tid = pid;
 
-			process(ops, event, &synth_sample, session);
+			process(ops, event, &synth_sample, machine);
 		}
 	}
 
@@ -210,13 +209,12 @@ static int perf_event__synthesize_mmap_events(struct perf_event_ops *ops,
 
 int perf_event__synthesize_modules(struct perf_event_ops *ops,
 				   perf_event__handler_t process,
-				   struct perf_session *session,
 				   struct machine *machine)
 {
 	struct rb_node *nd;
 	struct map_groups *kmaps = &machine->kmaps;
 	union perf_event *event = zalloc((sizeof(event->mmap) +
-					  session->id_hdr_size));
+					  machine->id_hdr_size));
 	if (event == NULL) {
 		pr_debug("Not enough memory synthesizing mmap event "
 			 "for kernel modules\n");
@@ -246,15 +244,15 @@ int perf_event__synthesize_modules(struct perf_event_ops *ops,
 		event->mmap.header.type = PERF_RECORD_MMAP;
 		event->mmap.header.size = (sizeof(event->mmap) -
 				        (sizeof(event->mmap.filename) - size));
-		memset(event->mmap.filename + size, 0, session->id_hdr_size);
-		event->mmap.header.size += session->id_hdr_size;
+		memset(event->mmap.filename + size, 0, machine->id_hdr_size);
+		event->mmap.header.size += machine->id_hdr_size;
 		event->mmap.start = pos->start;
 		event->mmap.len   = pos->end - pos->start;
 		event->mmap.pid   = machine->pid;
 
 		memcpy(event->mmap.filename, pos->dso->long_name,
 		       pos->dso->long_name_len + 1);
-		process(ops, event, &synth_sample, session);
+		process(ops, event, &synth_sample, machine);
 	}
 
 	free(event);
@@ -265,29 +263,29 @@ static int __event__synthesize_thread(union perf_event *comm_event,
 				      union perf_event *mmap_event,
 				      pid_t pid, perf_event__handler_t process,
 				      struct perf_event_ops *ops,
-				      struct perf_session *session)
+				      struct machine *machine)
 {
-	pid_t tgid = perf_event__synthesize_comm(ops, comm_event, pid, 1, process,
-					    session);
+	pid_t tgid = perf_event__synthesize_comm(ops, comm_event, pid, 1,
+						 process, machine);
 	if (tgid == -1)
 		return -1;
 	return perf_event__synthesize_mmap_events(ops, mmap_event, pid, tgid,
-					     process, session);
+						  process, machine);
 }
 
 int perf_event__synthesize_thread_map(struct perf_event_ops *ops,
 				      struct thread_map *threads,
 				      perf_event__handler_t process,
-				      struct perf_session *session)
+				      struct machine *machine)
 {
 	union perf_event *comm_event, *mmap_event;
 	int err = -1, thread;
 
-	comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size);
+	comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size);
 	if (comm_event == NULL)
 		goto out;
 
-	mmap_event = malloc(sizeof(mmap_event->mmap) + session->id_hdr_size);
+	mmap_event = malloc(sizeof(mmap_event->mmap) + machine->id_hdr_size);
 	if (mmap_event == NULL)
 		goto out_free_comm;
 
@@ -295,7 +293,7 @@ int perf_event__synthesize_thread_map(struct perf_event_ops *ops,
 	for (thread = 0; thread < threads->nr; ++thread) {
 		if (__event__synthesize_thread(comm_event, mmap_event,
 					       threads->map[thread],
-					       process, ops, session)) {
+					       process, ops, machine)) {
 			err = -1;
 			break;
 		}
@@ -309,18 +307,18 @@ out:
 
 int perf_event__synthesize_threads(struct perf_event_ops *ops,
 				   perf_event__handler_t process,
-				   struct perf_session *session)
+				   struct machine *machine)
 {
 	DIR *proc;
 	struct dirent dirent, *next;
 	union perf_event *comm_event, *mmap_event;
 	int err = -1;
 
-	comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size);
+	comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size);
 	if (comm_event == NULL)
 		goto out;
 
-	mmap_event = malloc(sizeof(mmap_event->mmap) + session->id_hdr_size);
+	mmap_event = malloc(sizeof(mmap_event->mmap) + machine->id_hdr_size);
 	if (mmap_event == NULL)
 		goto out_free_comm;
 
@@ -336,7 +334,7 @@ int perf_event__synthesize_threads(struct perf_event_ops *ops,
 			continue;
 
 		__event__synthesize_thread(comm_event, mmap_event, pid,
-					   process, ops, session);
+					   process, ops, machine);
 	}
 
 	closedir(proc);
@@ -373,7 +371,6 @@ static int find_symbol_cb(void *arg, const char *name, char type,
 
 int perf_event__synthesize_kernel_mmap(struct perf_event_ops *ops,
 				       perf_event__handler_t process,
-				       struct perf_session *session,
 				       struct machine *machine,
 				       const char *symbol_name)
 {
@@ -390,7 +387,7 @@ int perf_event__synthesize_kernel_mmap(struct perf_event_ops *ops,
 	 */
 	struct process_symbol_args args = { .name = symbol_name, };
 	union perf_event *event = zalloc((sizeof(event->mmap) +
-					  session->id_hdr_size));
+					  machine->id_hdr_size));
 	if (event == NULL) {
 		pr_debug("Not enough memory synthesizing mmap event "
 			 "for kernel modules\n");
@@ -424,13 +421,13 @@ int perf_event__synthesize_kernel_mmap(struct perf_event_ops *ops,
 	size = ALIGN(size, sizeof(u64));
 	event->mmap.header.type = PERF_RECORD_MMAP;
 	event->mmap.header.size = (sizeof(event->mmap) -
-			(sizeof(event->mmap.filename) - size) + session->id_hdr_size);
+			(sizeof(event->mmap.filename) - size) + machine->id_hdr_size);
 	event->mmap.pgoff = args.start;
 	event->mmap.start = map->start;
 	event->mmap.len   = map->end - event->mmap.start;
 	event->mmap.pid   = machine->pid;
 
-	err = process(ops, event, &synth_sample, session);
+	err = process(ops, event, &synth_sample, machine);
 	free(event);
 
 	return err;
@@ -439,9 +436,9 @@ int perf_event__synthesize_kernel_mmap(struct perf_event_ops *ops,
 int perf_event__process_comm(struct perf_event_ops *ops __used,
 			     union perf_event *event,
 			     struct perf_sample *sample __used,
-			     struct perf_session *session)
+			     struct machine *machine)
 {
-	struct thread *thread = perf_session__findnew(session, event->comm.tid);
+	struct thread *thread = machine__findnew_thread(machine, event->comm.tid);
 
 	dump_printf(": %s:%d\n", event->comm.comm, event->comm.tid);
 
@@ -456,11 +453,10 @@ int perf_event__process_comm(struct perf_event_ops *ops __used,
 int perf_event__process_lost(struct perf_event_ops *ops __used,
 			     union perf_event *event,
 			     struct perf_sample *sample __used,
-			     struct perf_session *session)
+			     struct machine *machine __used)
 {
 	dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n",
 		    event->lost.id, event->lost.lost);
-	session->hists.stats.total_lost += event->lost.lost;
 	return 0;
 }
 
@@ -479,20 +475,13 @@ static void perf_event__set_kernel_mmap_len(union perf_event *event,
 
 static int perf_event__process_kernel_mmap(struct perf_event_ops *ops __used,
 					   union perf_event *event,
-					   struct perf_session *session)
+					   struct machine *machine)
 {
 	struct map *map;
 	char kmmap_prefix[PATH_MAX];
-	struct machine *machine;
 	enum dso_kernel_type kernel_type;
 	bool is_kernel_mmap;
 
-	machine = perf_session__findnew_machine(session, event->mmap.pid);
-	if (!machine) {
-		pr_err("Can't find id %d's machine\n", event->mmap.pid);
-		goto out_problem;
-	}
-
 	machine__mmap_name(machine, kmmap_prefix, sizeof(kmmap_prefix));
 	if (machine__is_host(machine))
 		kernel_type = DSO_TYPE_KERNEL;
@@ -559,9 +548,9 @@ static int perf_event__process_kernel_mmap(struct perf_event_ops *ops __used,
 		 * time /proc/sys/kernel/kptr_restrict was non zero.
 		 */
 		if (event->mmap.pgoff != 0) {
-			perf_session__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps,
-								 symbol_name,
-								 event->mmap.pgoff);
+			maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps,
+							 symbol_name,
+							 event->mmap.pgoff);
 		}
 
 		if (machine__is_default_guest(machine)) {
@@ -580,9 +569,8 @@ out_problem:
 int perf_event__process_mmap(struct perf_event_ops *ops,
 			     union perf_event *event,
 			     struct perf_sample *sample __used,
-			     struct perf_session *session)
+			     struct machine *machine)
 {
-	struct machine *machine;
 	struct thread *thread;
 	struct map *map;
 	u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
@@ -594,16 +582,13 @@ int perf_event__process_mmap(struct perf_event_ops *ops,
 
 	if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL ||
 	    cpumode == PERF_RECORD_MISC_KERNEL) {
-		ret = perf_event__process_kernel_mmap(ops, event, session);
+		ret = perf_event__process_kernel_mmap(ops, event, machine);
 		if (ret < 0)
 			goto out_problem;
 		return 0;
 	}
 
-	machine = perf_session__find_host_machine(session);
-	if (machine == NULL)
-		goto out_problem;
-	thread = perf_session__findnew(session, event->mmap.pid);
+	thread = machine__findnew_thread(machine, event->mmap.pid);
 	if (thread == NULL)
 		goto out_problem;
 	map = map__new(&machine->user_dsos, event->mmap.start,
@@ -624,16 +609,16 @@ out_problem:
 int perf_event__process_task(struct perf_event_ops *ops __used,
 			     union perf_event *event,
 			     struct perf_sample *sample __used,
-			     struct perf_session *session)
+			      struct machine *machine)
 {
-	struct thread *thread = perf_session__findnew(session, event->fork.tid);
-	struct thread *parent = perf_session__findnew(session, event->fork.ptid);
+	struct thread *thread = machine__findnew_thread(machine, event->fork.tid);
+	struct thread *parent = machine__findnew_thread(machine, event->fork.ptid);
 
 	dump_printf("(%d:%d):(%d:%d)\n", event->fork.pid, event->fork.tid,
 		    event->fork.ppid, event->fork.ptid);
 
 	if (event->header.type == PERF_RECORD_EXIT) {
-		perf_session__remove_thread(session, thread);
+		machine__remove_thread(machine, thread);
 		return 0;
 	}
 
@@ -647,21 +632,21 @@ int perf_event__process_task(struct perf_event_ops *ops __used,
 }
 
 int perf_event__process(struct perf_event_ops *ops, union perf_event *event,
-			struct perf_sample *sample, struct perf_session *session)
+			struct perf_sample *sample, struct machine *machine)
 {
 	switch (event->header.type) {
 	case PERF_RECORD_COMM:
-		perf_event__process_comm(ops, event, sample, session);
+		perf_event__process_comm(ops, event, sample, machine);
 		break;
 	case PERF_RECORD_MMAP:
-		perf_event__process_mmap(ops, event, sample, session);
+		perf_event__process_mmap(ops, event, sample, machine);
 		break;
 	case PERF_RECORD_FORK:
 	case PERF_RECORD_EXIT:
-		perf_event__process_task(ops, event, sample, session);
+		perf_event__process_task(ops, event, sample, machine);
 		break;
 	case PERF_RECORD_LOST:
-		perf_event__process_lost(ops, event, sample, session);
+		perf_event__process_lost(ops, event, sample, machine);
 	default:
 		break;
 	}
@@ -670,36 +655,29 @@ int perf_event__process(struct perf_event_ops *ops, union perf_event *event,
 }
 
 void thread__find_addr_map(struct thread *self,
-			   struct perf_session *session, u8 cpumode,
-			   enum map_type type, pid_t pid, u64 addr,
+			   struct machine *machine, u8 cpumode,
+			   enum map_type type, u64 addr,
 			   struct addr_location *al)
 {
 	struct map_groups *mg = &self->mg;
-	struct machine *machine = NULL;
 
 	al->thread = self;
 	al->addr = addr;
 	al->cpumode = cpumode;
 	al->filtered = false;
 
+	if (machine == NULL) {
+		al->map = NULL;
+		return;
+	}
+
 	if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) {
 		al->level = 'k';
-		machine = perf_session__find_host_machine(session);
-		if (machine == NULL) {
-			al->map = NULL;
-			return;
-		}
 		mg = &machine->kmaps;
 	} else if (cpumode == PERF_RECORD_MISC_USER && perf_host) {
 		al->level = '.';
-		machine = perf_session__find_host_machine(session);
 	} else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) {
 		al->level = 'g';
-		machine = perf_session__find_machine(session, pid);
-		if (machine == NULL) {
-			al->map = NULL;
-			return;
-		}
 		mg = &machine->kmaps;
 	} else {
 		/*
@@ -745,13 +723,12 @@ try_again:
 		al->addr = al->map->map_ip(al->map, al->addr);
 }
 
-void thread__find_addr_location(struct thread *self,
-				struct perf_session *session, u8 cpumode,
-				enum map_type type, pid_t pid, u64 addr,
+void thread__find_addr_location(struct thread *thread, struct machine *machine,
+				u8 cpumode, enum map_type type, u64 addr,
 				struct addr_location *al,
 				symbol_filter_t filter)
 {
-	thread__find_addr_map(self, session, cpumode, type, pid, addr, al);
+	thread__find_addr_map(thread, machine, cpumode, type, addr, al);
 	if (al->map != NULL)
 		al->sym = map__find_symbol(al->map, al->addr, filter);
 	else
@@ -759,13 +736,13 @@ void thread__find_addr_location(struct thread *self,
 }
 
 int perf_event__preprocess_sample(const union perf_event *event,
-				  struct perf_session *session,
+				  struct machine *machine,
 				  struct addr_location *al,
 				  struct perf_sample *sample,
 				  symbol_filter_t filter)
 {
 	u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
-	struct thread *thread = perf_session__findnew(session, event->ip.pid);
+	struct thread *thread = machine__findnew_thread(machine, event->ip.pid);
 
 	if (thread == NULL)
 		return -1;
@@ -776,18 +753,18 @@ int perf_event__preprocess_sample(const union perf_event *event,
 
 	dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
 	/*
-	 * Have we already created the kernel maps for the host machine?
+	 * Have we already created the kernel maps for this machine?
 	 *
 	 * This should have happened earlier, when we processed the kernel MMAP
 	 * events, but for older perf.data files there was no such thing, so do
 	 * it now.
 	 */
 	if (cpumode == PERF_RECORD_MISC_KERNEL &&
-	    session->host_machine.vmlinux_maps[MAP__FUNCTION] == NULL)
-		machine__create_kernel_maps(&session->host_machine);
+	    machine->vmlinux_maps[MAP__FUNCTION] == NULL)
+		machine__create_kernel_maps(machine);
 
-	thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION,
-			      event->ip.pid, event->ip.ip, al);
+	thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION,
+			      event->ip.ip, al);
 	dump_printf(" ...... dso: %s\n",
 		    al->map ? al->map->dso->long_name :
 			al->level == 'H' ? "[hypervisor]" : "<not found>");
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 669409d..1564877 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -142,56 +142,53 @@ union perf_event {
 void perf_event__print_totals(void);
 
 struct perf_event_ops;
-struct perf_session;
 struct thread_map;
 
 typedef int (*perf_event__handler_t)(struct perf_event_ops *ops,
 				     union perf_event *event,
 				     struct perf_sample *sample,
-				      struct perf_session *session);
+				     struct machine *machine);
 
 int perf_event__synthesize_thread_map(struct perf_event_ops *ops,
 				      struct thread_map *threads,
 				      perf_event__handler_t process,
-				      struct perf_session *session);
+				      struct machine *machine);
 int perf_event__synthesize_threads(struct perf_event_ops *ops,
 				   perf_event__handler_t process,
-				   struct perf_session *session);
+				   struct machine *machine);
 int perf_event__synthesize_kernel_mmap(struct perf_event_ops *ops,
 				       perf_event__handler_t process,
-				       struct perf_session *session,
 				       struct machine *machine,
 				       const char *symbol_name);
 
 int perf_event__synthesize_modules(struct perf_event_ops *ops,
 				   perf_event__handler_t process,
-				   struct perf_session *session,
 				   struct machine *machine);
 
 int perf_event__process_comm(struct perf_event_ops *ops,
 			     union perf_event *event,
 			     struct perf_sample *sample,
-			     struct perf_session *session);
+			     struct machine *machine);
 int perf_event__process_lost(struct perf_event_ops *ops,
 			     union perf_event *event,
 			     struct perf_sample *sample,
-			     struct perf_session *session);
+			     struct machine *machine);
 int perf_event__process_mmap(struct perf_event_ops *ops,
 			     union perf_event *event,
 			     struct perf_sample *sample,
-			     struct perf_session *session);
+			     struct machine *machine);
 int perf_event__process_task(struct perf_event_ops *ops,
 			     union perf_event *event,
 			     struct perf_sample *sample,
-			     struct perf_session *session);
+			     struct machine *machine);
 int perf_event__process(struct perf_event_ops *ops,
 			union perf_event *event,
 			struct perf_sample *sample,
-			struct perf_session *session);
+			struct machine *machine);
 
 struct addr_location;
 int perf_event__preprocess_sample(const union perf_event *self,
-				  struct perf_session *session,
+				  struct machine *machine,
 				  struct addr_location *al,
 				  struct perf_sample *sample,
 				  symbol_filter_t filter);
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index ab3a2b0..db280d6 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2072,8 +2072,7 @@ out_delete_evlist:
 
 int perf_event__synthesize_attr(struct perf_event_ops *ops,
 				struct perf_event_attr *attr, u16 ids, u64 *id,
-				perf_event__handler_t process,
-				struct perf_session *session)
+				perf_event__handler_t process)
 {
 	union perf_event *ev;
 	size_t size;
@@ -2095,7 +2094,7 @@ int perf_event__synthesize_attr(struct perf_event_ops *ops,
 	ev->attr.header.type = PERF_RECORD_HEADER_ATTR;
 	ev->attr.header.size = size;
 
-	err = process(ops, ev, NULL, session);
+	err = process(ops, ev, NULL, NULL);
 
 	free(ev);
 
@@ -2111,7 +2110,7 @@ int perf_event__synthesize_attrs(struct perf_event_ops *ops,
 
 	list_for_each_entry(attr, &session->evlist->entries, node) {
 		err = perf_event__synthesize_attr(ops, &attr->attr, attr->ids,
-						  attr->id, process, session);
+						  attr->id, process);
 		if (err) {
 			pr_debug("failed to create perf header attribute\n");
 			return err;
@@ -2161,7 +2160,7 @@ int perf_event__process_attr(union perf_event *event,
 int perf_event__synthesize_event_type(struct perf_event_ops *ops,
 				      u64 event_id, char *name,
 				      perf_event__handler_t process,
-				      struct perf_session *session)
+				      struct machine *machine)
 {
 	union perf_event ev;
 	size_t size = 0;
@@ -2179,14 +2178,14 @@ int perf_event__synthesize_event_type(struct perf_event_ops *ops,
 	ev.event_type.header.size = sizeof(ev.event_type) -
 		(sizeof(ev.event_type.event_type.name) - size);
 
-	err = process(ops, &ev, NULL, session);
+	err = process(ops, &ev, NULL, machine);
 
 	return err;
 }
 
 int perf_event__synthesize_event_types(struct perf_event_ops *ops,
 				       perf_event__handler_t process,
-				       struct perf_session *session)
+				       struct machine *machine)
 {
 	struct perf_trace_event_type *type;
 	int i, err = 0;
@@ -2196,7 +2195,7 @@ int perf_event__synthesize_event_types(struct perf_event_ops *ops,
 
 		err = perf_event__synthesize_event_type(ops, type->event_id,
 							type->name, process,
-							session);
+							machine);
 		if (err) {
 			pr_debug("failed to create perf header event type\n");
 			return err;
@@ -2207,8 +2206,7 @@ int perf_event__synthesize_event_types(struct perf_event_ops *ops,
 }
 
 int perf_event__process_event_type(struct perf_event_ops *ops __unused,
-				   union perf_event *event,
-				   struct perf_session *session __unused)
+				   union perf_event *event)
 {
 	if (perf_header__push_event(event->event_type.event_type.event_id,
 				    event->event_type.event_type.name) < 0)
@@ -2219,8 +2217,7 @@ int perf_event__process_event_type(struct perf_event_ops *ops __unused,
 
 int perf_event__synthesize_tracing_data(struct perf_event_ops *ops, int fd,
 					struct perf_evlist *evlist,
-					 perf_event__handler_t process,
-				   struct perf_session *session __unused)
+					perf_event__handler_t process)
 {
 	union perf_event ev;
 	struct tracing_data *tdata;
@@ -2251,7 +2248,7 @@ int perf_event__synthesize_tracing_data(struct perf_event_ops *ops, int fd,
 	ev.tracing_data.header.size = sizeof(ev.tracing_data);
 	ev.tracing_data.size = aligned_size;
 
-	process(ops, &ev, NULL, session);
+	process(ops, &ev, NULL, NULL);
 
 	/*
 	 * The put function will copy all the tracing data
@@ -2296,8 +2293,7 @@ int perf_event__process_tracing_data(union perf_event *event,
 int perf_event__synthesize_build_id(struct perf_event_ops *ops,
 				    struct dso *pos, u16 misc,
 				    perf_event__handler_t process,
-				    struct machine *machine,
-				    struct perf_session *session)
+				    struct machine *machine)
 {
 	union perf_event ev;
 	size_t len;
@@ -2317,7 +2313,7 @@ int perf_event__synthesize_build_id(struct perf_event_ops *ops,
 	ev.build_id.header.size = sizeof(ev.build_id) + len;
 	memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len);
 
-	err = process(ops, &ev, NULL, session);
+	err = process(ops, &ev, NULL, machine);
 
 	return err;
 }
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 54dae5f..a604962 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -99,8 +99,7 @@ int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir);
 
 int perf_event__synthesize_attr(struct perf_event_ops *ops,
 				struct perf_event_attr *attr, u16 ids, u64 *id,
-				perf_event__handler_t process,
-				struct perf_session *session);
+				perf_event__handler_t process);
 int perf_event__synthesize_attrs(struct perf_event_ops *ops,
 				 struct perf_session *session,
 				 perf_event__handler_t process);
@@ -109,26 +108,23 @@ int perf_event__process_attr(union perf_event *event, struct perf_evlist **pevli
 int perf_event__synthesize_event_type(struct perf_event_ops *ops,
 				      u64 event_id, char *name,
 				      perf_event__handler_t process,
-				      struct perf_session *session);
+				      struct machine *machine);
 int perf_event__synthesize_event_types(struct perf_event_ops *ops,
 				       perf_event__handler_t process,
-				       struct perf_session *session);
+				       struct machine *machine);
 int perf_event__process_event_type(struct perf_event_ops *ops,
-				   union perf_event *event,
-				   struct perf_session *session);
+				   union perf_event *event);
 
 int perf_event__synthesize_tracing_data(struct perf_event_ops *ops,
 					int fd, struct perf_evlist *evlist,
-					perf_event__handler_t process,
-					struct perf_session *session);
+					perf_event__handler_t process);
 int perf_event__process_tracing_data(union perf_event *event,
 				     struct perf_session *session);
 
 int perf_event__synthesize_build_id(struct perf_event_ops *ops,
 				    struct dso *pos, u16 misc,
 				    perf_event__handler_t process,
-				    struct machine *machine,
-				    struct perf_session *session);
+				    struct machine *machine);
 int perf_event__process_build_id(struct perf_event_ops *ops,
 				 union perf_event *event,
 				 struct perf_session *session);
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index bde6835..2b8017f 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -18,9 +18,11 @@ enum map_type {
 extern const char *map_type__name[MAP__NR_TYPES];
 
 struct dso;
+struct ip_callchain;
 struct ref_reloc_sym;
 struct map_groups;
 struct machine;
+struct perf_evsel;
 
 struct map {
 	union {
@@ -61,6 +63,7 @@ struct map_groups {
 struct machine {
 	struct rb_node	  rb_node;
 	pid_t		  pid;
+	u16		  id_hdr_size;
 	char		  *root_dir;
 	struct rb_root	  threads;
 	struct list_head  dead_threads;
@@ -151,6 +154,13 @@ int machine__init(struct machine *self, const char *root_dir, pid_t pid);
 void machine__exit(struct machine *self);
 void machine__delete(struct machine *self);
 
+int machine__resolve_callchain(struct machine *machine,
+			       struct perf_evsel *evsel, struct thread *thread,
+			       struct ip_callchain *chain,
+			       struct symbol **parent);
+int maps__set_kallsyms_ref_reloc_sym(struct map **maps, const char *symbol_name,
+				     u64 addr);
+
 /*
  * Default guest kernel is defined by parameter --guestkallsyms
  * and --guestmodules
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index 74350ff..a82ce43 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -27,6 +27,8 @@
 
 #include "../../perf.h"
 #include "../util.h"
+#include "../thread.h"
+#include "../event.h"
 #include "../trace-event.h"
 
 #include <EXTERN.h>
@@ -248,7 +250,7 @@ static inline struct event *find_cache_event(int type)
 static void perl_process_event(union perf_event *pevent __unused,
 			       struct perf_sample *sample,
 			       struct perf_evsel *evsel,
-			       struct perf_session *session __unused,
+			       struct machine *machine __unused,
 			       struct thread *thread)
 {
 	struct format_field *field;
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 6ccf70e..0b2a487 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -29,6 +29,8 @@
 
 #include "../../perf.h"
 #include "../util.h"
+#include "../event.h"
+#include "../thread.h"
 #include "../trace-event.h"
 
 PyMODINIT_FUNC initperf_trace_context(void);
@@ -207,7 +209,7 @@ static inline struct event *find_cache_event(int type)
 static void python_process_event(union perf_event *pevent __unused,
 				 struct perf_sample *sample,
 				 struct perf_evsel *evsel __unused,
-				 struct perf_session *session __unused,
+				 struct machine *machine __unused,
 				 struct thread *thread)
 {
 	PyObject *handler, *retval, *context, *t, *obj, *dict = NULL;
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index a36023a..be33606 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -84,6 +84,7 @@ void perf_session__update_sample_type(struct perf_session *self)
 	self->sample_size = __perf_evsel__sample_size(self->sample_type);
 	self->sample_id_all = perf_evlist__sample_id_all(self->evlist);
 	self->id_hdr_size = perf_evlist__id_hdr_size(self->evlist);
+	self->host_machine.id_hdr_size = self->id_hdr_size;
 }
 
 int perf_session__create_kernel_maps(struct perf_session *self)
@@ -216,10 +217,10 @@ static bool symbol__match_parent_regex(struct symbol *sym)
 	return 0;
 }
 
-int perf_session__resolve_callchain(struct perf_session *self, struct perf_evsel *evsel,
-				    struct thread *thread,
-				    struct ip_callchain *chain,
-				    struct symbol **parent)
+int machine__resolve_callchain(struct machine *self, struct perf_evsel *evsel,
+			       struct thread *thread,
+			       struct ip_callchain *chain,
+			       struct symbol **parent)
 {
 	u8 cpumode = PERF_RECORD_MISC_USER;
 	unsigned int i;
@@ -252,7 +253,7 @@ int perf_session__resolve_callchain(struct perf_session *self, struct perf_evsel
 
 		al.filtered = false;
 		thread__find_addr_location(thread, self, cpumode,
-				MAP__FUNCTION, thread->pid, ip, &al, NULL);
+					   MAP__FUNCTION, ip, &al, NULL);
 		if (al.sym != NULL) {
 			if (sort__has_parent && !*parent &&
 			    symbol__match_parent_regex(al.sym))
@@ -270,14 +271,6 @@ int perf_session__resolve_callchain(struct perf_session *self, struct perf_evsel
 	return 0;
 }
 
-static int process_event_synth_stub(struct perf_event_ops *ops __used,
-				    union perf_event *event __used,
-				    struct perf_session *session __used)
-{
-	dump_printf(": unhandled!\n");
-	return 0;
-}
-
 static int process_event_synth_tracing_data_stub(union perf_event *event __used,
 						 struct perf_session *session __used)
 {
@@ -296,7 +289,7 @@ static int process_event_sample_stub(struct perf_event_ops *ops __used,
 				     union perf_event *event __used,
 				     struct perf_sample *sample __used,
 				     struct perf_evsel *evsel __used,
-				     struct perf_session *session __used)
+				     struct machine *machine __used)
 {
 	dump_printf(": unhandled!\n");
 	return 0;
@@ -305,7 +298,7 @@ static int process_event_sample_stub(struct perf_event_ops *ops __used,
 static int process_event_stub(struct perf_event_ops *ops __used,
 			      union perf_event *event __used,
 			      struct perf_sample *sample __used,
-			      struct perf_session *session __used)
+			      struct machine *machine __used)
 {
 	dump_printf(": unhandled!\n");
 	return 0;
@@ -313,7 +306,14 @@ static int process_event_stub(struct perf_event_ops *ops __used,
 
 static int process_finished_round_stub(struct perf_event_ops *ops __used,
 				       union perf_event *event __used,
-				       struct perf_session *session __used)
+				       struct perf_session *perf_session __used)
+{
+	dump_printf(": unhandled!\n");
+	return 0;
+}
+
+static int process_event_type_stub(struct perf_event_ops *ops __used,
+				   union perf_event *event __used)
 {
 	dump_printf(": unhandled!\n");
 	return 0;
@@ -338,7 +338,7 @@ static void perf_event_ops__fill_defaults(struct perf_event_ops *handler)
 	if (handler->lost == NULL)
 		handler->lost = perf_event__process_lost;
 	if (handler->read == NULL)
-		handler->read = process_event_stub;
+		handler->read = process_event_sample_stub;
 	if (handler->throttle == NULL)
 		handler->throttle = process_event_stub;
 	if (handler->unthrottle == NULL)
@@ -346,11 +346,11 @@ static void perf_event_ops__fill_defaults(struct perf_event_ops *handler)
 	if (handler->attr == NULL)
 		handler->attr = process_event_synth_attr_stub;
 	if (handler->event_type == NULL)
-		handler->event_type = process_event_synth_stub;
+		handler->event_type = process_event_type_stub;
 	if (handler->tracing_data == NULL)
 		handler->tracing_data = process_event_synth_tracing_data_stub;
 	if (handler->build_id == NULL)
-		handler->build_id = process_event_synth_stub;
+		handler->build_id = process_finished_round_stub;
 	if (handler->finished_round == NULL) {
 		if (handler->ordered_samples)
 			handler->finished_round = process_finished_round;
@@ -734,6 +734,18 @@ static void dump_sample(struct perf_session *session, union perf_event *event,
 		callchain__printf(sample);
 }
 
+static struct machine *
+	perf_session__find_machine_for_cpumode(struct perf_session *session,
+					       union perf_event *event)
+{
+	const u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
+
+	if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest)
+		return perf_session__find_machine(session, event->ip.pid);
+
+	return perf_session__find_host_machine(session);
+}
+
 static int perf_session_deliver_event(struct perf_session *session,
 				      union perf_event *event,
 				      struct perf_sample *sample,
@@ -741,6 +753,7 @@ static int perf_session_deliver_event(struct perf_session *session,
 				      u64 file_offset)
 {
 	struct perf_evsel *evsel;
+	struct machine *machine;
 
 	dump_event(session, event, file_offset, sample);
 
@@ -762,6 +775,8 @@ static int perf_session_deliver_event(struct perf_session *session,
 		hists__inc_nr_events(&evsel->hists, event->header.type);
 	}
 
+	machine = perf_session__find_machine_for_cpumode(session, event);
+
 	switch (event->header.type) {
 	case PERF_RECORD_SAMPLE:
 		dump_sample(session, event, sample);
@@ -769,23 +784,25 @@ static int perf_session_deliver_event(struct perf_session *session,
 			++session->hists.stats.nr_unknown_id;
 			return -1;
 		}
-		return ops->sample(ops, event, sample, evsel, session);
+		return ops->sample(ops, event, sample, evsel, machine);
 	case PERF_RECORD_MMAP:
-		return ops->mmap(ops, event, sample, session);
+		return ops->mmap(ops, event, sample, machine);
 	case PERF_RECORD_COMM:
-		return ops->comm(ops, event, sample, session);
+		return ops->comm(ops, event, sample, machine);
 	case PERF_RECORD_FORK:
-		return ops->fork(ops, event, sample, session);
+		return ops->fork(ops, event, sample, machine);
 	case PERF_RECORD_EXIT:
-		return ops->exit(ops, event, sample, session);
+		return ops->exit(ops, event, sample, machine);
 	case PERF_RECORD_LOST:
-		return ops->lost(ops, event, sample, session);
+		if (ops->lost == perf_event__process_lost)
+			session->hists.stats.total_lost += event->lost.lost;
+		return ops->lost(ops, event, sample, machine);
 	case PERF_RECORD_READ:
-		return ops->read(ops, event, sample, session);
+		return ops->read(ops, event, sample, evsel, machine);
 	case PERF_RECORD_THROTTLE:
-		return ops->throttle(ops, event, sample, session);
+		return ops->throttle(ops, event, sample, machine);
 	case PERF_RECORD_UNTHROTTLE:
-		return ops->unthrottle(ops, event, sample, session);
+		return ops->unthrottle(ops, event, sample, machine);
 	default:
 		++session->hists.stats.nr_unknown_events;
 		return -1;
@@ -823,7 +840,7 @@ static int perf_session__process_user_event(struct perf_session *session, union
 			perf_session__update_sample_type(session);
 		return err;
 	case PERF_RECORD_HEADER_EVENT_TYPE:
-		return ops->event_type(ops, event, session);
+		return ops->event_type(ops, event);
 	case PERF_RECORD_HEADER_TRACING_DATA:
 		/* setup for reading amidst mmap */
 		lseek(session->fd, file_offset, SEEK_SET);
@@ -1170,9 +1187,8 @@ bool perf_session__has_traces(struct perf_session *self, const char *msg)
 	return true;
 }
 
-int perf_session__set_kallsyms_ref_reloc_sym(struct map **maps,
-					     const char *symbol_name,
-					     u64 addr)
+int maps__set_kallsyms_ref_reloc_sym(struct map **maps,
+				     const char *symbol_name, u64 addr)
 {
 	char *bracket;
 	enum map_type i;
@@ -1264,17 +1280,16 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
 	return NULL;
 }
 
-void perf_session__print_ip(union perf_event *event, struct perf_evsel *evsel,
-			    struct perf_sample *sample,
-			    struct perf_session *session,
-			    int print_sym, int print_dso)
+void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
+			  struct machine *machine, struct perf_evsel *evsel,
+			  int print_sym, int print_dso)
 {
 	struct addr_location al;
 	const char *symname, *dsoname;
 	struct callchain_cursor *cursor = &evsel->hists.callchain_cursor;
 	struct callchain_cursor_node *node;
 
-	if (perf_event__preprocess_sample(event, session, &al, sample,
+	if (perf_event__preprocess_sample(event, machine, &al, sample,
 					  NULL) < 0) {
 		error("problem processing %d event, skipping it.\n",
 			event->header.type);
@@ -1283,7 +1298,7 @@ void perf_session__print_ip(union perf_event *event, struct perf_evsel *evsel,
 
 	if (symbol_conf.use_callchain && sample->callchain) {
 
-		if (perf_session__resolve_callchain(session, evsel, al.thread,
+		if (machine__resolve_callchain(machine, evsel, al.thread,
 						sample->callchain, NULL) != 0) {
 			if (verbose)
 				error("Failed to resolve callchain. Skipping\n");
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 6de3d13..1c5823c 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -58,32 +58,34 @@ struct perf_event_ops;
 
 typedef int (*event_sample)(struct perf_event_ops *ops,
 			    union perf_event *event, struct perf_sample *sample,
-			    struct perf_evsel *evsel, struct perf_session *session);
+			    struct perf_evsel *evsel, struct machine *machine);
 typedef int (*event_op)(struct perf_event_ops *ops, union perf_event *event,
 			struct perf_sample *sample,
-			struct perf_session *session);
+			struct machine *machine);
 typedef int (*event_synth_op)(union perf_event *self,
 			      struct perf_session *session);
 typedef int (*event_attr_op)(union perf_event *event,
 			     struct perf_evlist **pevlist);
+typedef int (*event_simple_op)(struct perf_event_ops *ops,
+			       union perf_event *event);
 typedef int (*event_op2)(struct perf_event_ops *ops, union perf_event *event,
 			 struct perf_session *session);
 
 struct perf_event_ops {
-	event_sample	sample;
+	event_sample	sample,
+			read;
 	event_op	mmap,
 			comm,
 			fork,
 			exit,
 			lost,
-			read,
 			throttle,
 			unthrottle;
 	event_attr_op	attr;
 	event_synth_op	tracing_data;
-	event_op2	event_type,
-			build_id,
-			finished_round;
+	event_simple_op	event_type;
+	event_op2	finished_round,
+			build_id;
 	bool		ordered_samples;
 	bool		ordering_requires_timestamps;
 };
@@ -108,10 +110,6 @@ int perf_session__resolve_callchain(struct perf_session *self, struct perf_evsel
 
 bool perf_session__has_traces(struct perf_session *self, const char *msg);
 
-int perf_session__set_kallsyms_ref_reloc_sym(struct map **maps,
-					     const char *symbol_name,
-					     u64 addr);
-
 void mem_bswap_64(void *src, int byte_size);
 void perf_event__attr_swap(struct perf_event_attr *attr);
 
@@ -151,6 +149,9 @@ void perf_session__process_machines(struct perf_session *self,
 	return machines__process(&self->machines, process, ops);
 }
 
+struct thread *perf_session__findnew(struct perf_session *self, pid_t pid);
+size_t perf_session__fprintf(struct perf_session *self, FILE *fp);
+
 size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp);
 
 size_t perf_session__fprintf_dsos_buildid(struct perf_session *self,
@@ -171,10 +172,9 @@ static inline int perf_session__parse_sample(struct perf_session *session,
 struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
 					    unsigned int type);
 
-void perf_session__print_ip(union perf_event *event, struct perf_evsel *evsel,
-				 struct perf_sample *sample,
-				 struct perf_session *session,
-				 int print_sym, int print_dso);
+void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
+			  struct machine *machine, struct perf_evsel *evsel,
+			  int print_sym, int print_dso);
 
 int perf_session__cpu_bitmap(struct perf_session *session,
 			     const char *cpu_list, unsigned long *cpu_bitmap);
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index e5f2401..70c2c13 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -18,16 +18,14 @@ struct thread {
 	int			comm_len;
 };
 
-struct perf_session;
+struct machine;
 
 void thread__delete(struct thread *self);
 
 int thread__set_comm(struct thread *self, const char *comm);
 int thread__comm_len(struct thread *self);
-struct thread *perf_session__findnew(struct perf_session *self, pid_t pid);
 void thread__insert_map(struct thread *self, struct map *map);
 int thread__fork(struct thread *self, struct thread *parent);
-size_t perf_session__fprintf(struct perf_session *self, FILE *fp);
 
 static inline struct map *thread__find_map(struct thread *self,
 					   enum map_type type, u64 addr)
@@ -35,14 +33,12 @@ static inline struct map *thread__find_map(struct thread *self,
 	return self ? map_groups__find(&self->mg, type, addr) : NULL;
 }
 
-void thread__find_addr_map(struct thread *self,
-			   struct perf_session *session, u8 cpumode,
-			   enum map_type type, pid_t pid, u64 addr,
+void thread__find_addr_map(struct thread *thread, struct machine *machine,
+			   u8 cpumode, enum map_type type, u64 addr,
 			   struct addr_location *al);
 
-void thread__find_addr_location(struct thread *self,
-				struct perf_session *session, u8 cpumode,
-				enum map_type type, pid_t pid, u64 addr,
+void thread__find_addr_location(struct thread *thread, struct machine *machine,
+				u8 cpumode, enum map_type type, u64 addr,
 				struct addr_location *al,
 				symbol_filter_t filter);
 #endif	/* __PERF_THREAD_H */
diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c
index c9dcbec..a3fdf55 100644
--- a/tools/perf/util/trace-event-scripting.c
+++ b/tools/perf/util/trace-event-scripting.c
@@ -39,7 +39,7 @@ static int stop_script_unsupported(void)
 static void process_event_unsupported(union perf_event *event __unused,
 				      struct perf_sample *sample __unused,
 				      struct perf_evsel *evsel __unused,
-				      struct perf_session *session __unused,
+				      struct machine *machine __unused,
 				      struct thread *thread __unused)
 {
 }
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index a841008..58ae14c 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -3,7 +3,11 @@
 
 #include <stdbool.h>
 #include "parse-events.h"
-#include "session.h"
+
+struct machine;
+struct perf_sample;
+union perf_event;
+struct thread;
 
 #define __unused __attribute__((unused))
 
@@ -292,7 +296,7 @@ struct scripting_ops {
 	void (*process_event) (union perf_event *event,
 			       struct perf_sample *sample,
 			       struct perf_evsel *evsel,
-			       struct perf_session *session,
+			       struct machine *machine,
 			       struct thread *thread);
 	int (*generate_script) (const char *outfile);
 };
-- 
1.7.8.rc0.35.gee6df


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

* [PATCH 21/25] perf tools: Rename perf_event_ops to perf_tool
  2011-11-28 23:14 [GIT PULL 00/25] perf/core fixes and improvements Arnaldo Carvalho de Melo
                   ` (19 preceding siblings ...)
  2011-11-28 23:14 ` [PATCH 20/25] perf tools: Resolve machine earlier and pass it to perf_event_ops Arnaldo Carvalho de Melo
@ 2011-11-28 23:14 ` Arnaldo Carvalho de Melo
  2011-11-28 23:14 ` [PATCH 22/25] perf top: Stop using globals for tool state Arnaldo Carvalho de Melo
                   ` (3 subsequent siblings)
  24 siblings, 0 replies; 28+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-11-28 23:14 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Arnaldo Carvalho de Melo, David Ahern,
	Frederic Weisbecker, Mike Galbraith, Paul Mackerras,
	Peter Zijlstra, Stephane Eranian

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

To better reflect that it became the base class for all tools, that must
be in each tool struct and where common stuff will be put.

Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-qgpc4msetqlwr8y2k7537cxe@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/Makefile            |    1 +
 tools/perf/builtin-annotate.c  |   13 ++--
 tools/perf/builtin-diff.c      |   11 ++-
 tools/perf/builtin-inject.c    |   55 +++++++-------
 tools/perf/builtin-kmem.c      |    9 +-
 tools/perf/builtin-lock.c      |    5 +-
 tools/perf/builtin-record.c    |   35 +++++----
 tools/perf/builtin-report.c    |   17 ++--
 tools/perf/builtin-sched.c     |    9 +-
 tools/perf/builtin-script.c    |    9 +-
 tools/perf/builtin-timechart.c |   15 ++--
 tools/perf/builtin-top.c       |    6 +-
 tools/perf/util/build-id.c     |    7 +-
 tools/perf/util/build-id.h     |    2 +-
 tools/perf/util/event.c        |   54 +++++++-------
 tools/perf/util/event.h        |   22 +++---
 tools/perf/util/header.c       |   28 ++++----
 tools/perf/util/header.h       |   16 ++--
 tools/perf/util/session.c      |  163 ++++++++++++++++++++--------------------
 tools/perf/util/session.h      |   49 ++----------
 tools/perf/util/tool.h         |   45 +++++++++++
 tools/perf/util/top.h          |    7 +-
 22 files changed, 301 insertions(+), 277 deletions(-)
 create mode 100644 tools/perf/util/tool.h

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index b98e307..ac86d67 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -278,6 +278,7 @@ LIB_H += util/strbuf.h
 LIB_H += util/strlist.h
 LIB_H += util/strfilter.h
 LIB_H += util/svghelper.h
+LIB_H += util/tool.h
 LIB_H += util/run-command.h
 LIB_H += util/sigchain.h
 LIB_H += util/symbol.h
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index dff081a..c01139f 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -27,11 +27,12 @@
 #include "util/sort.h"
 #include "util/hist.h"
 #include "util/session.h"
+#include "util/tool.h"
 
 #include <linux/bitmap.h>
 
 struct perf_annotate {
-	struct perf_event_ops ops;
+	struct perf_tool tool;
 	char const *input_name;
 	bool	   force, use_tui, use_stdio;
 	bool	   full_paths;
@@ -79,13 +80,13 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
 	return ret;
 }
 
-static int process_sample_event(struct perf_event_ops *ops,
+static int process_sample_event(struct perf_tool *tool,
 				union perf_event *event,
 				struct perf_sample *sample,
 				struct perf_evsel *evsel,
 				struct machine *machine)
 {
-	struct perf_annotate *ann = container_of(ops, struct perf_annotate, ops);
+	struct perf_annotate *ann = container_of(tool, struct perf_annotate, tool);
 	struct addr_location al;
 
 	if (perf_event__preprocess_sample(event, machine, &al, sample,
@@ -174,7 +175,7 @@ static int __cmd_annotate(struct perf_annotate *ann)
 	u64 total_nr_samples;
 
 	session = perf_session__new(ann->input_name, O_RDONLY,
-				    ann->force, false, &ann->ops);
+				    ann->force, false, &ann->tool);
 	if (session == NULL)
 		return -ENOMEM;
 
@@ -185,7 +186,7 @@ static int __cmd_annotate(struct perf_annotate *ann)
 			goto out_delete;
 	}
 
-	ret = perf_session__process_events(session, &ann->ops);
+	ret = perf_session__process_events(session, &ann->tool);
 	if (ret)
 		goto out_delete;
 
@@ -241,7 +242,7 @@ static const char * const annotate_usage[] = {
 int cmd_annotate(int argc, const char **argv, const char *prefix __used)
 {
 	struct perf_annotate annotate = {
-		.ops = {
+		.tool = {
 			.sample	= process_sample_event,
 			.mmap	= perf_event__process_mmap,
 			.comm	= perf_event__process_comm,
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 478b0ae..4f19513 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -11,6 +11,7 @@
 #include "util/hist.h"
 #include "util/evsel.h"
 #include "util/session.h"
+#include "util/tool.h"
 #include "util/sort.h"
 #include "util/symbol.h"
 #include "util/util.h"
@@ -31,7 +32,7 @@ static int hists__add_entry(struct hists *self,
 	return -ENOMEM;
 }
 
-static int diff__process_sample_event(struct perf_event_ops *ops __used,
+static int diff__process_sample_event(struct perf_tool *tool __used,
 				      union perf_event *event,
 				      struct perf_sample *sample,
 				      struct perf_evsel *evsel __used,
@@ -57,7 +58,7 @@ static int diff__process_sample_event(struct perf_event_ops *ops __used,
 	return 0;
 }
 
-static struct perf_event_ops event_ops = {
+static struct perf_tool perf_diff = {
 	.sample	= diff__process_sample_event,
 	.mmap	= perf_event__process_mmap,
 	.comm	= perf_event__process_comm,
@@ -147,13 +148,13 @@ static int __cmd_diff(void)
 	int ret, i;
 	struct perf_session *session[2];
 
-	session[0] = perf_session__new(input_old, O_RDONLY, force, false, &event_ops);
-	session[1] = perf_session__new(input_new, O_RDONLY, force, false, &event_ops);
+	session[0] = perf_session__new(input_old, O_RDONLY, force, false, &perf_diff);
+	session[1] = perf_session__new(input_new, O_RDONLY, force, false, &perf_diff);
 	if (session[0] == NULL || session[1] == NULL)
 		return -ENOMEM;
 
 	for (i = 0; i < 2; ++i) {
-		ret = perf_session__process_events(session[i], &event_ops);
+		ret = perf_session__process_events(session[i], &perf_diff);
 		if (ret)
 			goto out_delete;
 	}
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index a5bcf81..09c1061 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -9,6 +9,7 @@
 
 #include "perf.h"
 #include "util/session.h"
+#include "util/tool.h"
 #include "util/debug.h"
 
 #include "util/parse-options.h"
@@ -16,7 +17,7 @@
 static char		const *input_name = "-";
 static bool		inject_build_ids;
 
-static int perf_event__repipe_synth(struct perf_event_ops *ops __used,
+static int perf_event__repipe_synth(struct perf_tool *tool __used,
 				    union perf_event *event,
 				    struct machine *machine __used)
 {
@@ -37,17 +38,17 @@ static int perf_event__repipe_synth(struct perf_event_ops *ops __used,
 	return 0;
 }
 
-static int perf_event__repipe_op2_synth(struct perf_event_ops *ops,
+static int perf_event__repipe_op2_synth(struct perf_tool *tool,
 					union perf_event *event,
 					struct perf_session *session __used)
 {
-	return perf_event__repipe_synth(ops, event, NULL);
+	return perf_event__repipe_synth(tool, event, NULL);
 }
 
-static int perf_event__repipe_event_type_synth(struct perf_event_ops *ops,
+static int perf_event__repipe_event_type_synth(struct perf_tool *tool,
 					       union perf_event *event)
 {
-	return perf_event__repipe_synth(ops, event, NULL);
+	return perf_event__repipe_synth(tool, event, NULL);
 }
 
 static int perf_event__repipe_tracing_data_synth(union perf_event *event,
@@ -62,45 +63,45 @@ static int perf_event__repipe_attr(union perf_event *event,
 	return perf_event__repipe_synth(NULL, event, NULL);
 }
 
-static int perf_event__repipe(struct perf_event_ops *ops,
+static int perf_event__repipe(struct perf_tool *tool,
 			      union perf_event *event,
 			      struct perf_sample *sample __used,
 			      struct machine *machine)
 {
-	return perf_event__repipe_synth(ops, event, machine);
+	return perf_event__repipe_synth(tool, event, machine);
 }
 
-static int perf_event__repipe_sample(struct perf_event_ops *ops,
+static int perf_event__repipe_sample(struct perf_tool *tool,
 				     union perf_event *event,
 			      struct perf_sample *sample __used,
 			      struct perf_evsel *evsel __used,
 			      struct machine *machine)
 {
-	return perf_event__repipe_synth(ops, event, machine);
+	return perf_event__repipe_synth(tool, event, machine);
 }
 
-static int perf_event__repipe_mmap(struct perf_event_ops *ops,
+static int perf_event__repipe_mmap(struct perf_tool *tool,
 				   union perf_event *event,
 				   struct perf_sample *sample,
 				   struct machine *machine)
 {
 	int err;
 
-	err = perf_event__process_mmap(ops, event, sample, machine);
-	perf_event__repipe(ops, event, sample, machine);
+	err = perf_event__process_mmap(tool, event, sample, machine);
+	perf_event__repipe(tool, event, sample, machine);
 
 	return err;
 }
 
-static int perf_event__repipe_task(struct perf_event_ops *ops,
+static int perf_event__repipe_task(struct perf_tool *tool,
 				   union perf_event *event,
 				   struct perf_sample *sample,
 				   struct machine *machine)
 {
 	int err;
 
-	err = perf_event__process_task(ops, event, sample, machine);
-	perf_event__repipe(ops, event, sample, machine);
+	err = perf_event__process_task(tool, event, sample, machine);
+	perf_event__repipe(tool, event, sample, machine);
 
 	return err;
 }
@@ -130,7 +131,7 @@ static int dso__read_build_id(struct dso *self)
 	return -1;
 }
 
-static int dso__inject_build_id(struct dso *self, struct perf_event_ops *ops,
+static int dso__inject_build_id(struct dso *self, struct perf_tool *tool,
 				struct machine *machine)
 {
 	u16 misc = PERF_RECORD_MISC_USER;
@@ -144,7 +145,7 @@ static int dso__inject_build_id(struct dso *self, struct perf_event_ops *ops,
 	if (self->kernel)
 		misc = PERF_RECORD_MISC_KERNEL;
 
-	err = perf_event__synthesize_build_id(ops, self, misc, perf_event__repipe,
+	err = perf_event__synthesize_build_id(tool, self, misc, perf_event__repipe,
 					      machine);
 	if (err) {
 		pr_err("Can't synthesize build_id event for %s\n", self->long_name);
@@ -154,7 +155,7 @@ static int dso__inject_build_id(struct dso *self, struct perf_event_ops *ops,
 	return 0;
 }
 
-static int perf_event__inject_buildid(struct perf_event_ops *ops,
+static int perf_event__inject_buildid(struct perf_tool *tool,
 				      union perf_event *event,
 				      struct perf_sample *sample,
 				      struct perf_evsel *evsel __used,
@@ -180,7 +181,7 @@ static int perf_event__inject_buildid(struct perf_event_ops *ops,
 		if (!al.map->dso->hit) {
 			al.map->dso->hit = 1;
 			if (map__load(al.map, NULL) >= 0) {
-				dso__inject_build_id(al.map->dso, ops, machine);
+				dso__inject_build_id(al.map->dso, tool, machine);
 				/*
 				 * If this fails, too bad, let the other side
 				 * account this as unresolved.
@@ -193,11 +194,11 @@ static int perf_event__inject_buildid(struct perf_event_ops *ops,
 	}
 
 repipe:
-	perf_event__repipe(ops, event, sample, machine);
+	perf_event__repipe(tool, event, sample, machine);
 	return 0;
 }
 
-struct perf_event_ops inject_ops = {
+struct perf_tool perf_inject = {
 	.sample		= perf_event__repipe_sample,
 	.mmap		= perf_event__repipe,
 	.comm		= perf_event__repipe,
@@ -228,17 +229,17 @@ static int __cmd_inject(void)
 	signal(SIGINT, sig_handler);
 
 	if (inject_build_ids) {
-		inject_ops.sample	= perf_event__inject_buildid;
-		inject_ops.mmap		= perf_event__repipe_mmap;
-		inject_ops.fork		= perf_event__repipe_task;
-		inject_ops.tracing_data	= perf_event__repipe_tracing_data;
+		perf_inject.sample	 = perf_event__inject_buildid;
+		perf_inject.mmap	 = perf_event__repipe_mmap;
+		perf_inject.fork	 = perf_event__repipe_task;
+		perf_inject.tracing_data = perf_event__repipe_tracing_data;
 	}
 
-	session = perf_session__new(input_name, O_RDONLY, false, true, &inject_ops);
+	session = perf_session__new(input_name, O_RDONLY, false, true, &perf_inject);
 	if (session == NULL)
 		return -ENOMEM;
 
-	ret = perf_session__process_events(session, &inject_ops);
+	ret = perf_session__process_events(session, &perf_inject);
 
 	perf_session__delete(session);
 
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index 27b2a15..886174e 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -7,6 +7,7 @@
 #include "util/thread.h"
 #include "util/header.h"
 #include "util/session.h"
+#include "util/tool.h"
 
 #include "util/parse-options.h"
 #include "util/trace-event.h"
@@ -303,7 +304,7 @@ static void process_raw_event(union perf_event *raw_event __used, void *data,
 	}
 }
 
-static int process_sample_event(struct perf_event_ops *ops __used,
+static int process_sample_event(struct perf_tool *tool __used,
 				union perf_event *event,
 				struct perf_sample *sample,
 				struct perf_evsel *evsel __used,
@@ -325,7 +326,7 @@ static int process_sample_event(struct perf_event_ops *ops __used,
 	return 0;
 }
 
-static struct perf_event_ops event_ops = {
+static struct perf_tool perf_kmem = {
 	.sample			= process_sample_event,
 	.comm			= perf_event__process_comm,
 	.ordered_samples	= true,
@@ -484,7 +485,7 @@ static int __cmd_kmem(void)
 {
 	int err = -EINVAL;
 	struct perf_session *session = perf_session__new(input_name, O_RDONLY,
-							 0, false, &event_ops);
+							 0, false, &perf_kmem);
 	if (session == NULL)
 		return -ENOMEM;
 
@@ -495,7 +496,7 @@ static int __cmd_kmem(void)
 		goto out_delete;
 
 	setup_pager();
-	err = perf_session__process_events(session, &event_ops);
+	err = perf_session__process_events(session, &perf_kmem);
 	if (err != 0)
 		goto out_delete;
 	sort_result();
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index 99b032a..4db5e52 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -12,6 +12,7 @@
 
 #include "util/debug.h"
 #include "util/session.h"
+#include "util/tool.h"
 
 #include <sys/types.h>
 #include <sys/prctl.h>
@@ -845,7 +846,7 @@ static void dump_info(void)
 		die("Unknown type of information\n");
 }
 
-static int process_sample_event(struct perf_event_ops *ops __used,
+static int process_sample_event(struct perf_tool *tool __used,
 				union perf_event *event,
 				struct perf_sample *sample,
 				struct perf_evsel *evsel __used,
@@ -864,7 +865,7 @@ static int process_sample_event(struct perf_event_ops *ops __used,
 	return 0;
 }
 
-static struct perf_event_ops eops = {
+static struct perf_tool eops = {
 	.sample			= process_sample_event,
 	.comm			= perf_event__process_comm,
 	.ordered_samples	= true,
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 0af598a..7d4fdaa 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -22,6 +22,7 @@
 #include "util/evsel.h"
 #include "util/debug.h"
 #include "util/session.h"
+#include "util/tool.h"
 #include "util/symbol.h"
 #include "util/cpumap.h"
 #include "util/thread_map.h"
@@ -36,7 +37,7 @@ enum write_mode_t {
 };
 
 struct perf_record {
-	struct perf_event_ops	ops;
+	struct perf_tool	tool;
 	struct perf_record_opts	opts;
 	u64			bytes_written;
 	const char		*output_name;
@@ -76,12 +77,12 @@ static void write_output(struct perf_record *rec, void *buf, size_t size)
 	}
 }
 
-static int process_synthesized_event(struct perf_event_ops *ops,
+static int process_synthesized_event(struct perf_tool *tool,
 				     union perf_event *event,
 				     struct perf_sample *sample __used,
 				     struct machine *machine __used)
 {
-	struct perf_record *rec = container_of(ops, struct perf_record, ops);
+	struct perf_record *rec = container_of(tool, struct perf_record, tool);
 	write_output(rec, event, event->header.size);
 	return 0;
 }
@@ -319,7 +320,7 @@ static void perf_record__exit(int status __used, void *arg)
 static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
 {
 	int err;
-	struct perf_event_ops *ops = data;
+	struct perf_tool *tool = data;
 
 	if (machine__is_host(machine))
 		return;
@@ -332,7 +333,7 @@ static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
 	 *method is used to avoid symbol missing when the first addr is
 	 *in module instead of in guest kernel.
 	 */
-	err = perf_event__synthesize_modules(ops, process_synthesized_event,
+	err = perf_event__synthesize_modules(tool, process_synthesized_event,
 					     machine);
 	if (err < 0)
 		pr_err("Couldn't record guest kernel [%d]'s reference"
@@ -342,10 +343,10 @@ static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
 	 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
 	 * have no _text sometimes.
 	 */
-	err = perf_event__synthesize_kernel_mmap(ops, process_synthesized_event,
+	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
 						 machine, "_text");
 	if (err < 0)
-		err = perf_event__synthesize_kernel_mmap(ops, process_synthesized_event,
+		err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
 							 machine, "_stext");
 	if (err < 0)
 		pr_err("Couldn't record guest kernel [%d]'s reference"
@@ -378,7 +379,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
 	unsigned long waking = 0;
 	const bool forks = argc > 0;
 	struct machine *machine;
-	struct perf_event_ops *ops = &rec->ops;
+	struct perf_tool *tool = &rec->tool;
 	struct perf_record_opts *opts = &rec->opts;
 	struct perf_evlist *evsel_list = rec->evlist;
 	const char *output_name = rec->output_name;
@@ -501,14 +502,14 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
 	}
 
 	if (opts->pipe_output) {
-		err = perf_event__synthesize_attrs(ops, session,
+		err = perf_event__synthesize_attrs(tool, session,
 						   process_synthesized_event);
 		if (err < 0) {
 			pr_err("Couldn't synthesize attrs.\n");
 			return err;
 		}
 
-		err = perf_event__synthesize_event_types(ops, process_synthesized_event,
+		err = perf_event__synthesize_event_types(tool, process_synthesized_event,
 							 machine);
 		if (err < 0) {
 			pr_err("Couldn't synthesize event_types.\n");
@@ -524,7 +525,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
 			 * return this more properly and also
 			 * propagate errors that now are calling die()
 			 */
-			err = perf_event__synthesize_tracing_data(ops, output, evsel_list,
+			err = perf_event__synthesize_tracing_data(tool, output, evsel_list,
 								  process_synthesized_event);
 			if (err <= 0) {
 				pr_err("Couldn't record tracing data.\n");
@@ -534,17 +535,17 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
 		}
 	}
 
-	err = perf_event__synthesize_kernel_mmap(ops, process_synthesized_event,
+	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
 						 machine, "_text");
 	if (err < 0)
-		err = perf_event__synthesize_kernel_mmap(ops, process_synthesized_event,
+		err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
 							 machine, "_stext");
 	if (err < 0)
 		pr_err("Couldn't record kernel reference relocation symbol\n"
 		       "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
 		       "Check /proc/kallsyms permission or run as root.\n");
 
-	err = perf_event__synthesize_modules(ops, process_synthesized_event,
+	err = perf_event__synthesize_modules(tool, process_synthesized_event,
 					     machine);
 	if (err < 0)
 		pr_err("Couldn't record kernel module information.\n"
@@ -552,15 +553,15 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
 		       "Check /proc/modules permission or run as root.\n");
 
 	if (perf_guest)
-		perf_session__process_machines(session, ops,
+		perf_session__process_machines(session, tool,
 					       perf_event__synthesize_guest_os);
 
 	if (!opts->system_wide)
-		perf_event__synthesize_thread_map(ops, evsel_list->threads,
+		perf_event__synthesize_thread_map(tool, evsel_list->threads,
 						  process_synthesized_event,
 						  machine);
 	else
-		perf_event__synthesize_threads(ops, process_synthesized_event,
+		perf_event__synthesize_threads(tool, process_synthesized_event,
 					       machine);
 
 	if (rec->realtime_prio) {
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index ea64fbb..eef8e42 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -25,6 +25,7 @@
 #include "util/evsel.h"
 #include "util/header.h"
 #include "util/session.h"
+#include "util/tool.h"
 
 #include "util/parse-options.h"
 #include "util/parse-events.h"
@@ -36,7 +37,7 @@
 #include <linux/bitmap.h>
 
 struct perf_report {
-	struct perf_event_ops	ops;
+	struct perf_tool	tool;
 	struct perf_session	*session;
 	char const		*input_name;
 	bool			force, use_tui, use_stdio;
@@ -103,13 +104,13 @@ out:
 }
 
 
-static int process_sample_event(struct perf_event_ops *ops,
+static int process_sample_event(struct perf_tool *tool,
 				union perf_event *event,
 				struct perf_sample *sample,
 				struct perf_evsel *evsel,
 				struct machine *machine)
 {
-	struct perf_report *rep = container_of(ops, struct perf_report, ops);
+	struct perf_report *rep = container_of(tool, struct perf_report, tool);
 	struct addr_location al;
 
 	if (perf_event__preprocess_sample(event, machine, &al, sample,
@@ -136,13 +137,13 @@ static int process_sample_event(struct perf_event_ops *ops,
 	return 0;
 }
 
-static int process_read_event(struct perf_event_ops *ops,
+static int process_read_event(struct perf_tool *tool,
 			      union perf_event *event,
 			      struct perf_sample *sample __used,
 			      struct perf_evsel *evsel,
 			      struct machine *machine __used)
 {
-	struct perf_report *rep = container_of(ops, struct perf_report, ops);
+	struct perf_report *rep = container_of(tool, struct perf_report, tool);
 
 	if (rep->show_threads) {
 		const char *name = evsel ? event_name(evsel) : "unknown";
@@ -254,7 +255,7 @@ static int __cmd_report(struct perf_report *rep)
 	signal(SIGINT, sig_handler);
 
 	session = perf_session__new(rep->input_name, O_RDONLY,
-				    rep->force, false, &rep->ops);
+				    rep->force, false, &rep->tool);
 	if (session == NULL)
 		return -ENOMEM;
 
@@ -277,7 +278,7 @@ static int __cmd_report(struct perf_report *rep)
 	if (ret)
 		goto out_delete;
 
-	ret = perf_session__process_events(session, &rep->ops);
+	ret = perf_session__process_events(session, &rep->tool);
 	if (ret)
 		goto out_delete;
 
@@ -435,7 +436,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
 		NULL
 	};
 	struct perf_report report = {
-		.ops = {
+		.tool = {
 			.sample		 = process_sample_event,
 			.mmap		 = perf_event__process_mmap,
 			.comm		 = perf_event__process_comm,
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 6a771f8..0ee868e 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -8,6 +8,7 @@
 #include "util/thread.h"
 #include "util/header.h"
 #include "util/session.h"
+#include "util/tool.h"
 
 #include "util/parse-options.h"
 #include "util/trace-event.h"
@@ -1602,7 +1603,7 @@ static void process_raw_event(union perf_event *raw_event __used,
 		process_sched_migrate_task_event(data, machine, event, cpu, timestamp, thread);
 }
 
-static int process_sample_event(struct perf_event_ops *ops __used,
+static int process_sample_event(struct perf_tool *tool __used,
 				union perf_event *event,
 				struct perf_sample *sample,
 				struct perf_evsel *evsel,
@@ -1631,7 +1632,7 @@ static int process_sample_event(struct perf_event_ops *ops __used,
 	return 0;
 }
 
-static struct perf_event_ops event_ops = {
+static struct perf_tool perf_sched = {
 	.sample			= process_sample_event,
 	.comm			= perf_event__process_comm,
 	.lost			= perf_event__process_lost,
@@ -1643,12 +1644,12 @@ static void read_events(bool destroy, struct perf_session **psession)
 {
 	int err = -EINVAL;
 	struct perf_session *session = perf_session__new(input_name, O_RDONLY,
-							 0, false, &event_ops);
+							 0, false, &perf_sched);
 	if (session == NULL)
 		die("No Memory");
 
 	if (perf_session__has_traces(session, "record -R")) {
-		err = perf_session__process_events(session, &event_ops);
+		err = perf_session__process_events(session, &perf_sched);
 		if (err)
 			die("Failed to process events, error %d", err);
 
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 31a8d14..5f8afc6 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -7,6 +7,7 @@
 #include "util/header.h"
 #include "util/parse-options.h"
 #include "util/session.h"
+#include "util/tool.h"
 #include "util/symbol.h"
 #include "util/thread.h"
 #include "util/trace-event.h"
@@ -434,7 +435,7 @@ static int cleanup_scripting(void)
 
 static char const		*input_name = "perf.data";
 
-static int process_sample_event(struct perf_event_ops *ops __used,
+static int process_sample_event(struct perf_tool *tool __used,
 				union perf_event *event,
 				struct perf_sample *sample,
 				struct perf_evsel *evsel,
@@ -468,7 +469,7 @@ static int process_sample_event(struct perf_event_ops *ops __used,
 	return 0;
 }
 
-static struct perf_event_ops event_ops = {
+static struct perf_tool perf_script = {
 	.sample		 = process_sample_event,
 	.mmap		 = perf_event__process_mmap,
 	.comm		 = perf_event__process_comm,
@@ -495,7 +496,7 @@ static int __cmd_script(struct perf_session *session)
 
 	signal(SIGINT, sig_handler);
 
-	ret = perf_session__process_events(session, &event_ops);
+	ret = perf_session__process_events(session, &perf_script);
 
 	if (debug_mode)
 		pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered);
@@ -1262,7 +1263,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
 	if (!script_name)
 		setup_pager();
 
-	session = perf_session__new(input_name, O_RDONLY, 0, false, &event_ops);
+	session = perf_session__new(input_name, O_RDONLY, 0, false, &perf_script);
 	if (session == NULL)
 		return -ENOMEM;
 
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 8e65396..135376a 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -32,6 +32,7 @@
 #include "util/event.h"
 #include "util/session.h"
 #include "util/svghelper.h"
+#include "util/tool.h"
 
 #define SUPPORT_OLD_POWER_EVENTS 1
 #define PWR_EVENT_EXIT -1
@@ -274,7 +275,7 @@ static int cpus_cstate_state[MAX_CPUS];
 static u64 cpus_pstate_start_times[MAX_CPUS];
 static u64 cpus_pstate_state[MAX_CPUS];
 
-static int process_comm_event(struct perf_event_ops *ops __used,
+static int process_comm_event(struct perf_tool *tool __used,
 			      union perf_event *event,
 			      struct perf_sample *sample __used,
 			      struct machine *machine __used)
@@ -283,7 +284,7 @@ static int process_comm_event(struct perf_event_ops *ops __used,
 	return 0;
 }
 
-static int process_fork_event(struct perf_event_ops *ops __used,
+static int process_fork_event(struct perf_tool *tool __used,
 			      union perf_event *event,
 			      struct perf_sample *sample __used,
 			      struct machine *machine __used)
@@ -292,7 +293,7 @@ static int process_fork_event(struct perf_event_ops *ops __used,
 	return 0;
 }
 
-static int process_exit_event(struct perf_event_ops *ops __used,
+static int process_exit_event(struct perf_tool *tool __used,
 			      union perf_event *event,
 			      struct perf_sample *sample __used,
 			      struct machine *machine __used)
@@ -490,7 +491,7 @@ static void sched_switch(int cpu, u64 timestamp, struct trace_entry *te)
 }
 
 
-static int process_sample_event(struct perf_event_ops *ops __used,
+static int process_sample_event(struct perf_tool *tool __used,
 				union perf_event *event __used,
 				struct perf_sample *sample,
 				struct perf_evsel *evsel,
@@ -979,7 +980,7 @@ static void write_svg_file(const char *filename)
 	svg_close();
 }
 
-static struct perf_event_ops event_ops = {
+static struct perf_tool perf_timechart = {
 	.comm			= process_comm_event,
 	.fork			= process_fork_event,
 	.exit			= process_exit_event,
@@ -990,7 +991,7 @@ static struct perf_event_ops event_ops = {
 static int __cmd_timechart(void)
 {
 	struct perf_session *session = perf_session__new(input_name, O_RDONLY,
-							 0, false, &event_ops);
+							 0, false, &perf_timechart);
 	int ret = -EINVAL;
 
 	if (session == NULL)
@@ -999,7 +1000,7 @@ static int __cmd_timechart(void)
 	if (!perf_session__has_traces(session, "timechart record"))
 		goto out_delete;
 
-	ret = perf_session__process_events(session, &event_ops);
+	ret = perf_session__process_events(session, &perf_timechart);
 	if (ret)
 		goto out_delete;
 
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 31d4973..42a7d96 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -826,7 +826,7 @@ static void perf_session__mmap_read_idx(struct perf_session *self, int idx)
 			perf_event__process_sample(event, evsel, &sample, machine);
 		else if (event->header.type < PERF_RECORD_MAX) {
 			hists__inc_nr_events(&evsel->hists, event->header.type);
-			perf_event__process(&top.ops, event, &sample, machine);
+			perf_event__process(&top.tool, event, &sample, machine);
 		} else
 			++self->hists.stats.nr_unknown_events;
 	}
@@ -968,11 +968,11 @@ static int __cmd_top(void)
 		goto out_delete;
 
 	if (top.target_tid != -1)
-		perf_event__synthesize_thread_map(&top.ops, top.evlist->threads,
+		perf_event__synthesize_thread_map(&top.tool, top.evlist->threads,
 						  perf_event__process,
 						  &top.session->host_machine);
 	else
-		perf_event__synthesize_threads(&top.ops, perf_event__process,
+		perf_event__synthesize_threads(&top.tool, perf_event__process,
 					       &top.session->host_machine);
 	start_counters(top.evlist);
 	top.session->evlist = top.evlist;
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 2f84c48..dff9c7a 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -14,8 +14,9 @@
 #include <linux/kernel.h>
 #include "debug.h"
 #include "session.h"
+#include "tool.h"
 
-static int build_id__mark_dso_hit(struct perf_event_ops *ops __used,
+static int build_id__mark_dso_hit(struct perf_tool *tool __used,
 				  union perf_event *event,
 				  struct perf_sample *sample __used,
 				  struct perf_evsel *evsel __used,
@@ -40,7 +41,7 @@ static int build_id__mark_dso_hit(struct perf_event_ops *ops __used,
 	return 0;
 }
 
-static int perf_event__exit_del_thread(struct perf_event_ops *ops __used,
+static int perf_event__exit_del_thread(struct perf_tool *tool __used,
 				       union perf_event *event,
 				       struct perf_sample *sample __used,
 				       struct machine *machine)
@@ -59,7 +60,7 @@ static int perf_event__exit_del_thread(struct perf_event_ops *ops __used,
 	return 0;
 }
 
-struct perf_event_ops build_id__mark_dso_hit_ops = {
+struct perf_tool build_id__mark_dso_hit_ops = {
 	.sample	= build_id__mark_dso_hit,
 	.mmap	= perf_event__process_mmap,
 	.fork	= perf_event__process_task,
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index 5dafb00..a993ba8 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -3,7 +3,7 @@
 
 #include "session.h"
 
-extern struct perf_event_ops build_id__mark_dso_hit_ops;
+extern struct perf_tool build_id__mark_dso_hit_ops;
 
 char *dso__build_id_filename(struct dso *self, char *bf, size_t size);
 
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 0cdc811..0ebbe76 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -43,7 +43,7 @@ static struct perf_sample synth_sample = {
 	.period	   = 1,
 };
 
-static pid_t perf_event__synthesize_comm(struct perf_event_ops *ops,
+static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
 					 union perf_event *event, pid_t pid,
 					 int full, perf_event__handler_t process,
 					 struct machine *machine)
@@ -99,7 +99,7 @@ out_race:
 	if (!full) {
 		event->comm.tid = pid;
 
-		process(ops, event, &synth_sample, machine);
+		process(tool, event, &synth_sample, machine);
 		goto out;
 	}
 
@@ -117,7 +117,7 @@ out_race:
 
 		event->comm.tid = pid;
 
-		process(ops, event, &synth_sample, machine);
+		process(tool, event, &synth_sample, machine);
 	}
 
 	closedir(tasks);
@@ -127,7 +127,7 @@ out:
 	return tgid;
 }
 
-static int perf_event__synthesize_mmap_events(struct perf_event_ops *ops,
+static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
 					      union perf_event *event,
 					      pid_t pid, pid_t tgid,
 					      perf_event__handler_t process,
@@ -199,7 +199,7 @@ static int perf_event__synthesize_mmap_events(struct perf_event_ops *ops,
 			event->mmap.pid = tgid;
 			event->mmap.tid = pid;
 
-			process(ops, event, &synth_sample, machine);
+			process(tool, event, &synth_sample, machine);
 		}
 	}
 
@@ -207,7 +207,7 @@ static int perf_event__synthesize_mmap_events(struct perf_event_ops *ops,
 	return 0;
 }
 
-int perf_event__synthesize_modules(struct perf_event_ops *ops,
+int perf_event__synthesize_modules(struct perf_tool *tool,
 				   perf_event__handler_t process,
 				   struct machine *machine)
 {
@@ -252,7 +252,7 @@ int perf_event__synthesize_modules(struct perf_event_ops *ops,
 
 		memcpy(event->mmap.filename, pos->dso->long_name,
 		       pos->dso->long_name_len + 1);
-		process(ops, event, &synth_sample, machine);
+		process(tool, event, &synth_sample, machine);
 	}
 
 	free(event);
@@ -262,18 +262,18 @@ int perf_event__synthesize_modules(struct perf_event_ops *ops,
 static int __event__synthesize_thread(union perf_event *comm_event,
 				      union perf_event *mmap_event,
 				      pid_t pid, perf_event__handler_t process,
-				      struct perf_event_ops *ops,
+				      struct perf_tool *tool,
 				      struct machine *machine)
 {
-	pid_t tgid = perf_event__synthesize_comm(ops, comm_event, pid, 1,
+	pid_t tgid = perf_event__synthesize_comm(tool, comm_event, pid, 1,
 						 process, machine);
 	if (tgid == -1)
 		return -1;
-	return perf_event__synthesize_mmap_events(ops, mmap_event, pid, tgid,
+	return perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
 						  process, machine);
 }
 
-int perf_event__synthesize_thread_map(struct perf_event_ops *ops,
+int perf_event__synthesize_thread_map(struct perf_tool *tool,
 				      struct thread_map *threads,
 				      perf_event__handler_t process,
 				      struct machine *machine)
@@ -293,7 +293,7 @@ int perf_event__synthesize_thread_map(struct perf_event_ops *ops,
 	for (thread = 0; thread < threads->nr; ++thread) {
 		if (__event__synthesize_thread(comm_event, mmap_event,
 					       threads->map[thread],
-					       process, ops, machine)) {
+					       process, tool, machine)) {
 			err = -1;
 			break;
 		}
@@ -305,7 +305,7 @@ out:
 	return err;
 }
 
-int perf_event__synthesize_threads(struct perf_event_ops *ops,
+int perf_event__synthesize_threads(struct perf_tool *tool,
 				   perf_event__handler_t process,
 				   struct machine *machine)
 {
@@ -334,7 +334,7 @@ int perf_event__synthesize_threads(struct perf_event_ops *ops,
 			continue;
 
 		__event__synthesize_thread(comm_event, mmap_event, pid,
-					   process, ops, machine);
+					   process, tool, machine);
 	}
 
 	closedir(proc);
@@ -369,7 +369,7 @@ static int find_symbol_cb(void *arg, const char *name, char type,
 	return 1;
 }
 
-int perf_event__synthesize_kernel_mmap(struct perf_event_ops *ops,
+int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
 				       perf_event__handler_t process,
 				       struct machine *machine,
 				       const char *symbol_name)
@@ -427,13 +427,13 @@ int perf_event__synthesize_kernel_mmap(struct perf_event_ops *ops,
 	event->mmap.len   = map->end - event->mmap.start;
 	event->mmap.pid   = machine->pid;
 
-	err = process(ops, event, &synth_sample, machine);
+	err = process(tool, event, &synth_sample, machine);
 	free(event);
 
 	return err;
 }
 
-int perf_event__process_comm(struct perf_event_ops *ops __used,
+int perf_event__process_comm(struct perf_tool *tool __used,
 			     union perf_event *event,
 			     struct perf_sample *sample __used,
 			     struct machine *machine)
@@ -450,7 +450,7 @@ int perf_event__process_comm(struct perf_event_ops *ops __used,
 	return 0;
 }
 
-int perf_event__process_lost(struct perf_event_ops *ops __used,
+int perf_event__process_lost(struct perf_tool *tool __used,
 			     union perf_event *event,
 			     struct perf_sample *sample __used,
 			     struct machine *machine __used)
@@ -473,7 +473,7 @@ static void perf_event__set_kernel_mmap_len(union perf_event *event,
 		maps[MAP__FUNCTION]->end = ~0ULL;
 }
 
-static int perf_event__process_kernel_mmap(struct perf_event_ops *ops __used,
+static int perf_event__process_kernel_mmap(struct perf_tool *tool __used,
 					   union perf_event *event,
 					   struct machine *machine)
 {
@@ -566,7 +566,7 @@ out_problem:
 	return -1;
 }
 
-int perf_event__process_mmap(struct perf_event_ops *ops,
+int perf_event__process_mmap(struct perf_tool *tool,
 			     union perf_event *event,
 			     struct perf_sample *sample __used,
 			     struct machine *machine)
@@ -582,7 +582,7 @@ int perf_event__process_mmap(struct perf_event_ops *ops,
 
 	if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL ||
 	    cpumode == PERF_RECORD_MISC_KERNEL) {
-		ret = perf_event__process_kernel_mmap(ops, event, machine);
+		ret = perf_event__process_kernel_mmap(tool, event, machine);
 		if (ret < 0)
 			goto out_problem;
 		return 0;
@@ -606,7 +606,7 @@ out_problem:
 	return 0;
 }
 
-int perf_event__process_task(struct perf_event_ops *ops __used,
+int perf_event__process_task(struct perf_tool *tool __used,
 			     union perf_event *event,
 			     struct perf_sample *sample __used,
 			      struct machine *machine)
@@ -631,22 +631,22 @@ int perf_event__process_task(struct perf_event_ops *ops __used,
 	return 0;
 }
 
-int perf_event__process(struct perf_event_ops *ops, union perf_event *event,
+int perf_event__process(struct perf_tool *tool, union perf_event *event,
 			struct perf_sample *sample, struct machine *machine)
 {
 	switch (event->header.type) {
 	case PERF_RECORD_COMM:
-		perf_event__process_comm(ops, event, sample, machine);
+		perf_event__process_comm(tool, event, sample, machine);
 		break;
 	case PERF_RECORD_MMAP:
-		perf_event__process_mmap(ops, event, sample, machine);
+		perf_event__process_mmap(tool, event, sample, machine);
 		break;
 	case PERF_RECORD_FORK:
 	case PERF_RECORD_EXIT:
-		perf_event__process_task(ops, event, sample, machine);
+		perf_event__process_task(tool, event, sample, machine);
 		break;
 	case PERF_RECORD_LOST:
-		perf_event__process_lost(ops, event, sample, machine);
+		perf_event__process_lost(tool, event, sample, machine);
 	default:
 		break;
 	}
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 1564877..d8499e7 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -141,47 +141,47 @@ union perf_event {
 
 void perf_event__print_totals(void);
 
-struct perf_event_ops;
+struct perf_tool;
 struct thread_map;
 
-typedef int (*perf_event__handler_t)(struct perf_event_ops *ops,
+typedef int (*perf_event__handler_t)(struct perf_tool *tool,
 				     union perf_event *event,
 				     struct perf_sample *sample,
 				     struct machine *machine);
 
-int perf_event__synthesize_thread_map(struct perf_event_ops *ops,
+int perf_event__synthesize_thread_map(struct perf_tool *tool,
 				      struct thread_map *threads,
 				      perf_event__handler_t process,
 				      struct machine *machine);
-int perf_event__synthesize_threads(struct perf_event_ops *ops,
+int perf_event__synthesize_threads(struct perf_tool *tool,
 				   perf_event__handler_t process,
 				   struct machine *machine);
-int perf_event__synthesize_kernel_mmap(struct perf_event_ops *ops,
+int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
 				       perf_event__handler_t process,
 				       struct machine *machine,
 				       const char *symbol_name);
 
-int perf_event__synthesize_modules(struct perf_event_ops *ops,
+int perf_event__synthesize_modules(struct perf_tool *tool,
 				   perf_event__handler_t process,
 				   struct machine *machine);
 
-int perf_event__process_comm(struct perf_event_ops *ops,
+int perf_event__process_comm(struct perf_tool *tool,
 			     union perf_event *event,
 			     struct perf_sample *sample,
 			     struct machine *machine);
-int perf_event__process_lost(struct perf_event_ops *ops,
+int perf_event__process_lost(struct perf_tool *tool,
 			     union perf_event *event,
 			     struct perf_sample *sample,
 			     struct machine *machine);
-int perf_event__process_mmap(struct perf_event_ops *ops,
+int perf_event__process_mmap(struct perf_tool *tool,
 			     union perf_event *event,
 			     struct perf_sample *sample,
 			     struct machine *machine);
-int perf_event__process_task(struct perf_event_ops *ops,
+int perf_event__process_task(struct perf_tool *tool,
 			     union perf_event *event,
 			     struct perf_sample *sample,
 			     struct machine *machine);
-int perf_event__process(struct perf_event_ops *ops,
+int perf_event__process(struct perf_tool *tool,
 			union perf_event *event,
 			struct perf_sample *sample,
 			struct machine *machine);
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index db280d6..9272f3a 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2070,7 +2070,7 @@ out_delete_evlist:
 	return -ENOMEM;
 }
 
-int perf_event__synthesize_attr(struct perf_event_ops *ops,
+int perf_event__synthesize_attr(struct perf_tool *tool,
 				struct perf_event_attr *attr, u16 ids, u64 *id,
 				perf_event__handler_t process)
 {
@@ -2094,14 +2094,14 @@ int perf_event__synthesize_attr(struct perf_event_ops *ops,
 	ev->attr.header.type = PERF_RECORD_HEADER_ATTR;
 	ev->attr.header.size = size;
 
-	err = process(ops, ev, NULL, NULL);
+	err = process(tool, ev, NULL, NULL);
 
 	free(ev);
 
 	return err;
 }
 
-int perf_event__synthesize_attrs(struct perf_event_ops *ops,
+int perf_event__synthesize_attrs(struct perf_tool *tool,
 				   struct perf_session *session,
 				   perf_event__handler_t process)
 {
@@ -2109,7 +2109,7 @@ int perf_event__synthesize_attrs(struct perf_event_ops *ops,
 	int err = 0;
 
 	list_for_each_entry(attr, &session->evlist->entries, node) {
-		err = perf_event__synthesize_attr(ops, &attr->attr, attr->ids,
+		err = perf_event__synthesize_attr(tool, &attr->attr, attr->ids,
 						  attr->id, process);
 		if (err) {
 			pr_debug("failed to create perf header attribute\n");
@@ -2157,7 +2157,7 @@ int perf_event__process_attr(union perf_event *event,
 	return 0;
 }
 
-int perf_event__synthesize_event_type(struct perf_event_ops *ops,
+int perf_event__synthesize_event_type(struct perf_tool *tool,
 				      u64 event_id, char *name,
 				      perf_event__handler_t process,
 				      struct machine *machine)
@@ -2178,12 +2178,12 @@ int perf_event__synthesize_event_type(struct perf_event_ops *ops,
 	ev.event_type.header.size = sizeof(ev.event_type) -
 		(sizeof(ev.event_type.event_type.name) - size);
 
-	err = process(ops, &ev, NULL, machine);
+	err = process(tool, &ev, NULL, machine);
 
 	return err;
 }
 
-int perf_event__synthesize_event_types(struct perf_event_ops *ops,
+int perf_event__synthesize_event_types(struct perf_tool *tool,
 				       perf_event__handler_t process,
 				       struct machine *machine)
 {
@@ -2193,7 +2193,7 @@ int perf_event__synthesize_event_types(struct perf_event_ops *ops,
 	for (i = 0; i < event_count; i++) {
 		type = &events[i];
 
-		err = perf_event__synthesize_event_type(ops, type->event_id,
+		err = perf_event__synthesize_event_type(tool, type->event_id,
 							type->name, process,
 							machine);
 		if (err) {
@@ -2205,7 +2205,7 @@ int perf_event__synthesize_event_types(struct perf_event_ops *ops,
 	return err;
 }
 
-int perf_event__process_event_type(struct perf_event_ops *ops __unused,
+int perf_event__process_event_type(struct perf_tool *tool __unused,
 				   union perf_event *event)
 {
 	if (perf_header__push_event(event->event_type.event_type.event_id,
@@ -2215,7 +2215,7 @@ int perf_event__process_event_type(struct perf_event_ops *ops __unused,
 	return 0;
 }
 
-int perf_event__synthesize_tracing_data(struct perf_event_ops *ops, int fd,
+int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd,
 					struct perf_evlist *evlist,
 					perf_event__handler_t process)
 {
@@ -2248,7 +2248,7 @@ int perf_event__synthesize_tracing_data(struct perf_event_ops *ops, int fd,
 	ev.tracing_data.header.size = sizeof(ev.tracing_data);
 	ev.tracing_data.size = aligned_size;
 
-	process(ops, &ev, NULL, NULL);
+	process(tool, &ev, NULL, NULL);
 
 	/*
 	 * The put function will copy all the tracing data
@@ -2290,7 +2290,7 @@ int perf_event__process_tracing_data(union perf_event *event,
 	return size_read + padding;
 }
 
-int perf_event__synthesize_build_id(struct perf_event_ops *ops,
+int perf_event__synthesize_build_id(struct perf_tool *tool,
 				    struct dso *pos, u16 misc,
 				    perf_event__handler_t process,
 				    struct machine *machine)
@@ -2313,12 +2313,12 @@ int perf_event__synthesize_build_id(struct perf_event_ops *ops,
 	ev.build_id.header.size = sizeof(ev.build_id) + len;
 	memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len);
 
-	err = process(ops, &ev, NULL, machine);
+	err = process(tool, &ev, NULL, machine);
 
 	return err;
 }
 
-int perf_event__process_build_id(struct perf_event_ops *ops __used,
+int perf_event__process_build_id(struct perf_tool *tool __used,
 				 union perf_event *event,
 				 struct perf_session *session)
 {
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index a604962..09365b3 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -97,35 +97,35 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
 			  const char *name, bool is_kallsyms);
 int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir);
 
-int perf_event__synthesize_attr(struct perf_event_ops *ops,
+int perf_event__synthesize_attr(struct perf_tool *tool,
 				struct perf_event_attr *attr, u16 ids, u64 *id,
 				perf_event__handler_t process);
-int perf_event__synthesize_attrs(struct perf_event_ops *ops,
+int perf_event__synthesize_attrs(struct perf_tool *tool,
 				 struct perf_session *session,
 				 perf_event__handler_t process);
 int perf_event__process_attr(union perf_event *event, struct perf_evlist **pevlist);
 
-int perf_event__synthesize_event_type(struct perf_event_ops *ops,
+int perf_event__synthesize_event_type(struct perf_tool *tool,
 				      u64 event_id, char *name,
 				      perf_event__handler_t process,
 				      struct machine *machine);
-int perf_event__synthesize_event_types(struct perf_event_ops *ops,
+int perf_event__synthesize_event_types(struct perf_tool *tool,
 				       perf_event__handler_t process,
 				       struct machine *machine);
-int perf_event__process_event_type(struct perf_event_ops *ops,
+int perf_event__process_event_type(struct perf_tool *tool,
 				   union perf_event *event);
 
-int perf_event__synthesize_tracing_data(struct perf_event_ops *ops,
+int perf_event__synthesize_tracing_data(struct perf_tool *tool,
 					int fd, struct perf_evlist *evlist,
 					perf_event__handler_t process);
 int perf_event__process_tracing_data(union perf_event *event,
 				     struct perf_session *session);
 
-int perf_event__synthesize_build_id(struct perf_event_ops *ops,
+int perf_event__synthesize_build_id(struct perf_tool *tool,
 				    struct dso *pos, u16 misc,
 				    perf_event__handler_t process,
 				    struct machine *machine);
-int perf_event__process_build_id(struct perf_event_ops *ops,
+int perf_event__process_build_id(struct perf_tool *tool,
 				 union perf_event *event,
 				 struct perf_session *session);
 
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index be33606..7d15908 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -10,6 +10,7 @@
 #include "evlist.h"
 #include "evsel.h"
 #include "session.h"
+#include "tool.h"
 #include "sort.h"
 #include "util.h"
 #include "cpumap.h"
@@ -104,7 +105,7 @@ static void perf_session__destroy_kernel_maps(struct perf_session *self)
 
 struct perf_session *perf_session__new(const char *filename, int mode,
 				       bool force, bool repipe,
-				       struct perf_event_ops *ops)
+				       struct perf_tool *tool)
 {
 	size_t len = filename ? strlen(filename) + 1 : 0;
 	struct perf_session *self = zalloc(sizeof(*self) + len);
@@ -142,10 +143,10 @@ struct perf_session *perf_session__new(const char *filename, int mode,
 			goto out_delete;
 	}
 
-	if (ops && ops->ordering_requires_timestamps &&
-	    ops->ordered_samples && !self->sample_id_all) {
+	if (tool && tool->ordering_requires_timestamps &&
+	    tool->ordered_samples && !self->sample_id_all) {
 		dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n");
-		ops->ordered_samples = false;
+		tool->ordered_samples = false;
 	}
 
 out:
@@ -285,7 +286,7 @@ static int process_event_synth_attr_stub(union perf_event *event __used,
 	return 0;
 }
 
-static int process_event_sample_stub(struct perf_event_ops *ops __used,
+static int process_event_sample_stub(struct perf_tool *tool __used,
 				     union perf_event *event __used,
 				     struct perf_sample *sample __used,
 				     struct perf_evsel *evsel __used,
@@ -295,7 +296,7 @@ static int process_event_sample_stub(struct perf_event_ops *ops __used,
 	return 0;
 }
 
-static int process_event_stub(struct perf_event_ops *ops __used,
+static int process_event_stub(struct perf_tool *tool __used,
 			      union perf_event *event __used,
 			      struct perf_sample *sample __used,
 			      struct machine *machine __used)
@@ -304,7 +305,7 @@ static int process_event_stub(struct perf_event_ops *ops __used,
 	return 0;
 }
 
-static int process_finished_round_stub(struct perf_event_ops *ops __used,
+static int process_finished_round_stub(struct perf_tool *tool __used,
 				       union perf_event *event __used,
 				       struct perf_session *perf_session __used)
 {
@@ -312,50 +313,50 @@ static int process_finished_round_stub(struct perf_event_ops *ops __used,
 	return 0;
 }
 
-static int process_event_type_stub(struct perf_event_ops *ops __used,
+static int process_event_type_stub(struct perf_tool *tool __used,
 				   union perf_event *event __used)
 {
 	dump_printf(": unhandled!\n");
 	return 0;
 }
 
-static int process_finished_round(struct perf_event_ops *ops,
+static int process_finished_round(struct perf_tool *tool,
 				  union perf_event *event,
 				  struct perf_session *session);
 
-static void perf_event_ops__fill_defaults(struct perf_event_ops *handler)
+static void perf_tool__fill_defaults(struct perf_tool *tool)
 {
-	if (handler->sample == NULL)
-		handler->sample = process_event_sample_stub;
-	if (handler->mmap == NULL)
-		handler->mmap = process_event_stub;
-	if (handler->comm == NULL)
-		handler->comm = process_event_stub;
-	if (handler->fork == NULL)
-		handler->fork = process_event_stub;
-	if (handler->exit == NULL)
-		handler->exit = process_event_stub;
-	if (handler->lost == NULL)
-		handler->lost = perf_event__process_lost;
-	if (handler->read == NULL)
-		handler->read = process_event_sample_stub;
-	if (handler->throttle == NULL)
-		handler->throttle = process_event_stub;
-	if (handler->unthrottle == NULL)
-		handler->unthrottle = process_event_stub;
-	if (handler->attr == NULL)
-		handler->attr = process_event_synth_attr_stub;
-	if (handler->event_type == NULL)
-		handler->event_type = process_event_type_stub;
-	if (handler->tracing_data == NULL)
-		handler->tracing_data = process_event_synth_tracing_data_stub;
-	if (handler->build_id == NULL)
-		handler->build_id = process_finished_round_stub;
-	if (handler->finished_round == NULL) {
-		if (handler->ordered_samples)
-			handler->finished_round = process_finished_round;
+	if (tool->sample == NULL)
+		tool->sample = process_event_sample_stub;
+	if (tool->mmap == NULL)
+		tool->mmap = process_event_stub;
+	if (tool->comm == NULL)
+		tool->comm = process_event_stub;
+	if (tool->fork == NULL)
+		tool->fork = process_event_stub;
+	if (tool->exit == NULL)
+		tool->exit = process_event_stub;
+	if (tool->lost == NULL)
+		tool->lost = perf_event__process_lost;
+	if (tool->read == NULL)
+		tool->read = process_event_sample_stub;
+	if (tool->throttle == NULL)
+		tool->throttle = process_event_stub;
+	if (tool->unthrottle == NULL)
+		tool->unthrottle = process_event_stub;
+	if (tool->attr == NULL)
+		tool->attr = process_event_synth_attr_stub;
+	if (tool->event_type == NULL)
+		tool->event_type = process_event_type_stub;
+	if (tool->tracing_data == NULL)
+		tool->tracing_data = process_event_synth_tracing_data_stub;
+	if (tool->build_id == NULL)
+		tool->build_id = process_finished_round_stub;
+	if (tool->finished_round == NULL) {
+		if (tool->ordered_samples)
+			tool->finished_round = process_finished_round;
 		else
-			handler->finished_round = process_finished_round_stub;
+			tool->finished_round = process_finished_round_stub;
 	}
 }
 
@@ -487,11 +488,11 @@ static void perf_session_free_sample_buffers(struct perf_session *session)
 static int perf_session_deliver_event(struct perf_session *session,
 				      union perf_event *event,
 				      struct perf_sample *sample,
-				      struct perf_event_ops *ops,
+				      struct perf_tool *tool,
 				      u64 file_offset);
 
 static void flush_sample_queue(struct perf_session *s,
-			       struct perf_event_ops *ops)
+			       struct perf_tool *tool)
 {
 	struct ordered_samples *os = &s->ordered_samples;
 	struct list_head *head = &os->samples;
@@ -502,7 +503,7 @@ static void flush_sample_queue(struct perf_session *s,
 	unsigned idx = 0, progress_next = os->nr_samples / 16;
 	int ret;
 
-	if (!ops->ordered_samples || !limit)
+	if (!tool->ordered_samples || !limit)
 		return;
 
 	list_for_each_entry_safe(iter, tmp, head, list) {
@@ -513,7 +514,7 @@ static void flush_sample_queue(struct perf_session *s,
 		if (ret)
 			pr_err("Can't parse sample, err = %d\n", ret);
 		else
-			perf_session_deliver_event(s, iter->event, &sample, ops,
+			perf_session_deliver_event(s, iter->event, &sample, tool,
 						   iter->file_offset);
 
 		os->last_flush = iter->timestamp;
@@ -575,11 +576,11 @@ static void flush_sample_queue(struct perf_session *s,
  *      Flush every events below timestamp 7
  *      etc...
  */
-static int process_finished_round(struct perf_event_ops *ops,
+static int process_finished_round(struct perf_tool *tool,
 				  union perf_event *event __used,
 				  struct perf_session *session)
 {
-	flush_sample_queue(session, ops);
+	flush_sample_queue(session, tool);
 	session->ordered_samples.next_flush = session->ordered_samples.max_timestamp;
 
 	return 0;
@@ -749,7 +750,7 @@ static struct machine *
 static int perf_session_deliver_event(struct perf_session *session,
 				      union perf_event *event,
 				      struct perf_sample *sample,
-				      struct perf_event_ops *ops,
+				      struct perf_tool *tool,
 				      u64 file_offset)
 {
 	struct perf_evsel *evsel;
@@ -784,25 +785,25 @@ static int perf_session_deliver_event(struct perf_session *session,
 			++session->hists.stats.nr_unknown_id;
 			return -1;
 		}
-		return ops->sample(ops, event, sample, evsel, machine);
+		return tool->sample(tool, event, sample, evsel, machine);
 	case PERF_RECORD_MMAP:
-		return ops->mmap(ops, event, sample, machine);
+		return tool->mmap(tool, event, sample, machine);
 	case PERF_RECORD_COMM:
-		return ops->comm(ops, event, sample, machine);
+		return tool->comm(tool, event, sample, machine);
 	case PERF_RECORD_FORK:
-		return ops->fork(ops, event, sample, machine);
+		return tool->fork(tool, event, sample, machine);
 	case PERF_RECORD_EXIT:
-		return ops->exit(ops, event, sample, machine);
+		return tool->exit(tool, event, sample, machine);
 	case PERF_RECORD_LOST:
-		if (ops->lost == perf_event__process_lost)
+		if (tool->lost == perf_event__process_lost)
 			session->hists.stats.total_lost += event->lost.lost;
-		return ops->lost(ops, event, sample, machine);
+		return tool->lost(tool, event, sample, machine);
 	case PERF_RECORD_READ:
-		return ops->read(ops, event, sample, evsel, machine);
+		return tool->read(tool, event, sample, evsel, machine);
 	case PERF_RECORD_THROTTLE:
-		return ops->throttle(ops, event, sample, machine);
+		return tool->throttle(tool, event, sample, machine);
 	case PERF_RECORD_UNTHROTTLE:
-		return ops->unthrottle(ops, event, sample, machine);
+		return tool->unthrottle(tool, event, sample, machine);
 	default:
 		++session->hists.stats.nr_unknown_events;
 		return -1;
@@ -826,7 +827,7 @@ static int perf_session__preprocess_sample(struct perf_session *session,
 }
 
 static int perf_session__process_user_event(struct perf_session *session, union perf_event *event,
-					    struct perf_event_ops *ops, u64 file_offset)
+					    struct perf_tool *tool, u64 file_offset)
 {
 	int err;
 
@@ -835,20 +836,20 @@ static int perf_session__process_user_event(struct perf_session *session, union
 	/* These events are processed right away */
 	switch (event->header.type) {
 	case PERF_RECORD_HEADER_ATTR:
-		err = ops->attr(event, &session->evlist);
+		err = tool->attr(event, &session->evlist);
 		if (err == 0)
 			perf_session__update_sample_type(session);
 		return err;
 	case PERF_RECORD_HEADER_EVENT_TYPE:
-		return ops->event_type(ops, event);
+		return tool->event_type(tool, event);
 	case PERF_RECORD_HEADER_TRACING_DATA:
 		/* setup for reading amidst mmap */
 		lseek(session->fd, file_offset, SEEK_SET);
-		return ops->tracing_data(event, session);
+		return tool->tracing_data(event, session);
 	case PERF_RECORD_HEADER_BUILD_ID:
-		return ops->build_id(ops, event, session);
+		return tool->build_id(tool, event, session);
 	case PERF_RECORD_FINISHED_ROUND:
-		return ops->finished_round(ops, event, session);
+		return tool->finished_round(tool, event, session);
 	default:
 		return -EINVAL;
 	}
@@ -856,7 +857,7 @@ static int perf_session__process_user_event(struct perf_session *session, union
 
 static int perf_session__process_event(struct perf_session *session,
 				       union perf_event *event,
-				       struct perf_event_ops *ops,
+				       struct perf_tool *tool,
 				       u64 file_offset)
 {
 	struct perf_sample sample;
@@ -872,7 +873,7 @@ static int perf_session__process_event(struct perf_session *session,
 	hists__inc_nr_events(&session->hists, event->header.type);
 
 	if (event->header.type >= PERF_RECORD_USER_TYPE_START)
-		return perf_session__process_user_event(session, event, ops, file_offset);
+		return perf_session__process_user_event(session, event, tool, file_offset);
 
 	/*
 	 * For all kernel events we get the sample data
@@ -885,14 +886,14 @@ static int perf_session__process_event(struct perf_session *session,
 	if (perf_session__preprocess_sample(session, event, &sample))
 		return 0;
 
-	if (ops->ordered_samples) {
+	if (tool->ordered_samples) {
 		ret = perf_session_queue_event(session, event, &sample,
 					       file_offset);
 		if (ret != -ETIME)
 			return ret;
 	}
 
-	return perf_session_deliver_event(session, event, &sample, ops,
+	return perf_session_deliver_event(session, event, &sample, tool,
 					  file_offset);
 }
 
@@ -921,9 +922,9 @@ static struct thread *perf_session__register_idle_thread(struct perf_session *se
 }
 
 static void perf_session__warn_about_errors(const struct perf_session *session,
-					    const struct perf_event_ops *ops)
+					    const struct perf_tool *tool)
 {
-	if (ops->lost == perf_event__process_lost &&
+	if (tool->lost == perf_event__process_lost &&
 	    session->hists.stats.nr_events[PERF_RECORD_LOST] != 0) {
 		ui__warning("Processed %d events and lost %d chunks!\n\n"
 			    "Check IO/CPU overload!\n\n",
@@ -958,7 +959,7 @@ static void perf_session__warn_about_errors(const struct perf_session *session,
 volatile int session_done;
 
 static int __perf_session__process_pipe_events(struct perf_session *self,
-					       struct perf_event_ops *ops)
+					       struct perf_tool *tool)
 {
 	union perf_event event;
 	uint32_t size;
@@ -967,7 +968,7 @@ static int __perf_session__process_pipe_events(struct perf_session *self,
 	int err;
 	void *p;
 
-	perf_event_ops__fill_defaults(ops);
+	perf_tool__fill_defaults(tool);
 
 	head = 0;
 more:
@@ -1004,7 +1005,7 @@ more:
 	}
 
 	if (size == 0 ||
-	    (skip = perf_session__process_event(self, &event, ops, head)) < 0) {
+	    (skip = perf_session__process_event(self, &event, tool, head)) < 0) {
 		dump_printf("%#" PRIx64 " [%#x]: skipping unknown header type: %d\n",
 			    head, event.header.size, event.header.type);
 		/*
@@ -1027,7 +1028,7 @@ more:
 done:
 	err = 0;
 out_err:
-	perf_session__warn_about_errors(self, ops);
+	perf_session__warn_about_errors(self, tool);
 	perf_session_free_sample_buffers(self);
 	return err;
 }
@@ -1058,7 +1059,7 @@ fetch_mmaped_event(struct perf_session *session,
 
 int __perf_session__process_events(struct perf_session *session,
 				   u64 data_offset, u64 data_size,
-				   u64 file_size, struct perf_event_ops *ops)
+				   u64 file_size, struct perf_tool *tool)
 {
 	u64 head, page_offset, file_offset, file_pos, progress_next;
 	int err, mmap_prot, mmap_flags, map_idx = 0;
@@ -1067,7 +1068,7 @@ int __perf_session__process_events(struct perf_session *session,
 	union perf_event *event;
 	uint32_t size;
 
-	perf_event_ops__fill_defaults(ops);
+	perf_tool__fill_defaults(tool);
 
 	page_size = sysconf(_SC_PAGESIZE);
 
@@ -1122,7 +1123,7 @@ more:
 	size = event->header.size;
 
 	if (size == 0 ||
-	    perf_session__process_event(session, event, ops, file_pos) < 0) {
+	    perf_session__process_event(session, event, tool, file_pos) < 0) {
 		dump_printf("%#" PRIx64 " [%#x]: skipping unknown header type: %d\n",
 			    file_offset + head, event->header.size,
 			    event->header.type);
@@ -1151,15 +1152,15 @@ more:
 	err = 0;
 	/* do the final flush for ordered samples */
 	session->ordered_samples.next_flush = ULLONG_MAX;
-	flush_sample_queue(session, ops);
+	flush_sample_queue(session, tool);
 out_err:
-	perf_session__warn_about_errors(session, ops);
+	perf_session__warn_about_errors(session, tool);
 	perf_session_free_sample_buffers(session);
 	return err;
 }
 
 int perf_session__process_events(struct perf_session *self,
-				 struct perf_event_ops *ops)
+				 struct perf_tool *tool)
 {
 	int err;
 
@@ -1170,9 +1171,9 @@ int perf_session__process_events(struct perf_session *self,
 		err = __perf_session__process_events(self,
 						     self->header.data_offset,
 						     self->header.data_size,
-						     self->size, ops);
+						     self->size, tool);
 	else
-		err = __perf_session__process_pipe_events(self, ops);
+		err = __perf_session__process_pipe_events(self, tool);
 
 	return err;
 }
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 1c5823c..30e9c6b6 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -53,55 +53,20 @@ struct perf_session {
 	char			filename[0];
 };
 
-struct perf_evsel;
-struct perf_event_ops;
-
-typedef int (*event_sample)(struct perf_event_ops *ops,
-			    union perf_event *event, struct perf_sample *sample,
-			    struct perf_evsel *evsel, struct machine *machine);
-typedef int (*event_op)(struct perf_event_ops *ops, union perf_event *event,
-			struct perf_sample *sample,
-			struct machine *machine);
-typedef int (*event_synth_op)(union perf_event *self,
-			      struct perf_session *session);
-typedef int (*event_attr_op)(union perf_event *event,
-			     struct perf_evlist **pevlist);
-typedef int (*event_simple_op)(struct perf_event_ops *ops,
-			       union perf_event *event);
-typedef int (*event_op2)(struct perf_event_ops *ops, union perf_event *event,
-			 struct perf_session *session);
-
-struct perf_event_ops {
-	event_sample	sample,
-			read;
-	event_op	mmap,
-			comm,
-			fork,
-			exit,
-			lost,
-			throttle,
-			unthrottle;
-	event_attr_op	attr;
-	event_synth_op	tracing_data;
-	event_simple_op	event_type;
-	event_op2	finished_round,
-			build_id;
-	bool		ordered_samples;
-	bool		ordering_requires_timestamps;
-};
+struct perf_tool;
 
 struct perf_session *perf_session__new(const char *filename, int mode,
 				       bool force, bool repipe,
-				       struct perf_event_ops *ops);
+				       struct perf_tool *tool);
 void perf_session__delete(struct perf_session *self);
 
 void perf_event_header__bswap(struct perf_event_header *self);
 
 int __perf_session__process_events(struct perf_session *self,
 				   u64 data_offset, u64 data_size, u64 size,
-				   struct perf_event_ops *ops);
+				   struct perf_tool *tool);
 int perf_session__process_events(struct perf_session *self,
-				 struct perf_event_ops *event_ops);
+				 struct perf_tool *tool);
 
 int perf_session__resolve_callchain(struct perf_session *self, struct perf_evsel *evsel,
 				    struct thread *thread,
@@ -142,11 +107,11 @@ struct machine *perf_session__findnew_machine(struct perf_session *self, pid_t p
 
 static inline
 void perf_session__process_machines(struct perf_session *self,
-				    struct perf_event_ops *ops,
+				    struct perf_tool *tool,
 				    machine__process_t process)
 {
-	process(&self->host_machine, ops);
-	return machines__process(&self->machines, process, ops);
+	process(&self->host_machine, tool);
+	return machines__process(&self->machines, process, tool);
 }
 
 struct thread *perf_session__findnew(struct perf_session *self, pid_t pid);
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
new file mode 100644
index 0000000..89ff1b5
--- /dev/null
+++ b/tools/perf/util/tool.h
@@ -0,0 +1,45 @@
+#ifndef __PERF_TOOL_H
+#define __PERF_TOOL_H
+
+struct perf_session;
+struct perf_evsel;
+struct perf_tool;
+struct machine;
+
+typedef int (*event_sample)(struct perf_tool *tool, union perf_event *event,
+			    struct perf_sample *sample,
+			    struct perf_evsel *evsel, struct machine *machine);
+
+typedef int (*event_op)(struct perf_tool *tool, union perf_event *event,
+			struct perf_sample *sample, struct machine *machine);
+
+typedef int (*event_attr_op)(union perf_event *event,
+			     struct perf_evlist **pevlist);
+typedef int (*event_simple_op)(struct perf_tool *tool, union perf_event *event);
+
+typedef int (*event_synth_op)(union perf_event *event,
+			      struct perf_session *session);
+
+typedef int (*event_op2)(struct perf_tool *tool, union perf_event *event,
+			 struct perf_session *session);
+
+struct perf_tool {
+	event_sample	sample,
+			read;
+	event_op	mmap,
+			comm,
+			fork,
+			exit,
+			lost,
+			throttle,
+			unthrottle;
+	event_attr_op	attr;
+	event_synth_op	tracing_data;
+	event_simple_op	event_type;
+	event_op2	finished_round,
+			build_id;
+	bool		ordered_samples;
+	bool		ordering_requires_timestamps;
+};
+
+#endif /* __PERF_TOOL_H */
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index 44eda6f..40430ec 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -1,16 +1,17 @@
 #ifndef __PERF_TOP_H
 #define __PERF_TOP_H 1
 
+#include "tool.h"
 #include "types.h"
-#include "session.h"
-#include "../perf.h"
 #include <stddef.h>
+#include <stdbool.h>
 
 struct perf_evlist;
 struct perf_evsel;
+struct perf_session;
 
 struct perf_top {
-	struct perf_event_ops ops;
+	struct perf_tool   tool;
 	struct perf_evlist *evlist;
 	/*
 	 * Symbols will be added here in perf_event__process_sample and will
-- 
1.7.8.rc0.35.gee6df


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

* [PATCH 22/25] perf top: Stop using globals for tool state
  2011-11-28 23:14 [GIT PULL 00/25] perf/core fixes and improvements Arnaldo Carvalho de Melo
                   ` (20 preceding siblings ...)
  2011-11-28 23:14 ` [PATCH 21/25] perf tools: Rename perf_event_ops to perf_tool Arnaldo Carvalho de Melo
@ 2011-11-28 23:14 ` Arnaldo Carvalho de Melo
  2011-11-28 23:14 ` [PATCH 23/25] perf tools: make -C consistent across commands (for cpu list arg) Arnaldo Carvalho de Melo
                   ` (2 subsequent siblings)
  24 siblings, 0 replies; 28+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-11-28 23:14 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Arnaldo Carvalho de Melo, David Ahern,
	Frederic Weisbecker, Mike Galbraith, Paul Mackerras,
	Peter Zijlstra, Stephane Eranian

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

Use its 'perf_tool' base class instead.

Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-i33q40wwvk2zna8fd36ex6sm@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-top.c |  464 +++++++++++++++++++++++-----------------------
 tools/perf/util/top.h    |   16 ++
 2 files changed, 245 insertions(+), 235 deletions(-)

diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 42a7d96..50ff362 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -64,44 +64,6 @@
 #include <linux/unistd.h>
 #include <linux/types.h>
 
-static struct perf_top top = {
-	.count_filter		= 5,
-	.delay_secs		= 2,
-	.target_pid		= -1,
-	.target_tid		= -1,
-	.freq			= 1000, /* 1 KHz */
-};
-
-static bool			system_wide			=  false;
-
-static bool			use_tui, use_stdio;
-
-static bool			sort_has_symbols;
-
-static bool			dont_use_callchains;
-static char			callchain_default_opt[]		= "fractal,0.5,callee";
-
-
-static int			default_interval		=      0;
-
-static bool			kptr_restrict_warned;
-static bool			vmlinux_warned;
-static bool			inherit				=  false;
-static int			realtime_prio			=      0;
-static bool			group				=  false;
-static bool			sample_id_all_avail		=   true;
-static unsigned int		mmap_pages			=    128;
-
-static bool			dump_symtab                     =  false;
-
-static struct winsize		winsize;
-
-static const char		*sym_filter			=   NULL;
-static int			sym_pcnt_filter			=      5;
-
-/*
- * Source functions
- */
 
 void get_term_dimensions(struct winsize *ws)
 {
@@ -125,21 +87,23 @@ void get_term_dimensions(struct winsize *ws)
 	ws->ws_col = 80;
 }
 
-static void update_print_entries(struct winsize *ws)
+static void perf_top__update_print_entries(struct perf_top *top)
 {
-	top.print_entries = ws->ws_row;
+	top->print_entries = top->winsize.ws_row;
 
-	if (top.print_entries > 9)
-		top.print_entries -= 9;
+	if (top->print_entries > 9)
+		top->print_entries -= 9;
 }
 
-static void sig_winch_handler(int sig __used)
+static void perf_top__sig_winch(int sig __used, siginfo_t *info __used, void *arg)
 {
-	get_term_dimensions(&winsize);
-	update_print_entries(&winsize);
+	struct perf_top *top = arg;
+
+	get_term_dimensions(&top->winsize);
+	perf_top__update_print_entries(top);
 }
 
-static int parse_source(struct hist_entry *he)
+static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he)
 {
 	struct symbol *sym;
 	struct annotation *notes;
@@ -181,7 +145,7 @@ static int parse_source(struct hist_entry *he)
 	err = symbol__annotate(sym, map, 0);
 	if (err == 0) {
 out_assign:
-		top.sym_filter_entry = he;
+		top->sym_filter_entry = he;
 	}
 
 	pthread_mutex_unlock(&notes->lock);
@@ -194,14 +158,16 @@ static void __zero_source_counters(struct hist_entry *he)
 	symbol__annotate_zero_histograms(sym);
 }
 
-static void record_precise_ip(struct hist_entry *he, int counter, u64 ip)
+static void perf_top__record_precise_ip(struct perf_top *top,
+					struct hist_entry *he,
+					int counter, u64 ip)
 {
 	struct annotation *notes;
 	struct symbol *sym;
 
 	if (he == NULL || he->ms.sym == NULL ||
-	    ((top.sym_filter_entry == NULL ||
-	      top.sym_filter_entry->ms.sym != he->ms.sym) && use_browser != 1))
+	    ((top->sym_filter_entry == NULL ||
+	      top->sym_filter_entry->ms.sym != he->ms.sym) && use_browser != 1))
 		return;
 
 	sym = he->ms.sym;
@@ -224,8 +190,9 @@ static void record_precise_ip(struct hist_entry *he, int counter, u64 ip)
 	pthread_mutex_unlock(&notes->lock);
 }
 
-static void show_details(struct hist_entry *he)
+static void perf_top__show_details(struct perf_top *top)
 {
+	struct hist_entry *he = top->sym_filter_entry;
 	struct annotation *notes;
 	struct symbol *symbol;
 	int more;
@@ -241,15 +208,15 @@ static void show_details(struct hist_entry *he)
 	if (notes->src == NULL)
 		goto out_unlock;
 
-	printf("Showing %s for %s\n", event_name(top.sym_evsel), symbol->name);
-	printf("  Events  Pcnt (>=%d%%)\n", sym_pcnt_filter);
+	printf("Showing %s for %s\n", event_name(top->sym_evsel), symbol->name);
+	printf("  Events  Pcnt (>=%d%%)\n", top->sym_pcnt_filter);
 
-	more = symbol__annotate_printf(symbol, he->ms.map, top.sym_evsel->idx,
-				       0, sym_pcnt_filter, top.print_entries, 4);
-	if (top.zero)
-		symbol__annotate_zero_histogram(symbol, top.sym_evsel->idx);
+	more = symbol__annotate_printf(symbol, he->ms.map, top->sym_evsel->idx,
+				       0, top->sym_pcnt_filter, top->print_entries, 4);
+	if (top->zero)
+		symbol__annotate_zero_histogram(symbol, top->sym_evsel->idx);
 	else
-		symbol__annotate_decay_histogram(symbol, top.sym_evsel->idx);
+		symbol__annotate_decay_histogram(symbol, top->sym_evsel->idx);
 	if (more != 0)
 		printf("%d lines not displayed, maybe increase display entries [e]\n", more);
 out_unlock:
@@ -273,45 +240,46 @@ static struct hist_entry *perf_evsel__add_hist_entry(struct perf_evsel *evsel,
 	return he;
 }
 
-static void print_sym_table(void)
+static void perf_top__print_sym_table(struct perf_top *top)
 {
 	char bf[160];
 	int printed = 0;
-	const int win_width = winsize.ws_col - 1;
+	const int win_width = top->winsize.ws_col - 1;
 
 	puts(CONSOLE_CLEAR);
 
-	perf_top__header_snprintf(&top, bf, sizeof(bf));
+	perf_top__header_snprintf(top, bf, sizeof(bf));
 	printf("%s\n", bf);
 
-	perf_top__reset_sample_counters(&top);
+	perf_top__reset_sample_counters(top);
 
 	printf("%-*.*s\n", win_width, win_width, graph_dotted_line);
 
-	if (top.sym_evsel->hists.stats.nr_lost_warned !=
-	    top.sym_evsel->hists.stats.nr_events[PERF_RECORD_LOST]) {
-		top.sym_evsel->hists.stats.nr_lost_warned =
-			top.sym_evsel->hists.stats.nr_events[PERF_RECORD_LOST];
+	if (top->sym_evsel->hists.stats.nr_lost_warned !=
+	    top->sym_evsel->hists.stats.nr_events[PERF_RECORD_LOST]) {
+		top->sym_evsel->hists.stats.nr_lost_warned =
+			top->sym_evsel->hists.stats.nr_events[PERF_RECORD_LOST];
 		color_fprintf(stdout, PERF_COLOR_RED,
 			      "WARNING: LOST %d chunks, Check IO/CPU overload",
-			      top.sym_evsel->hists.stats.nr_lost_warned);
+			      top->sym_evsel->hists.stats.nr_lost_warned);
 		++printed;
 	}
 
-	if (top.sym_filter_entry) {
-		show_details(top.sym_filter_entry);
+	if (top->sym_filter_entry) {
+		perf_top__show_details(top);
 		return;
 	}
 
-	hists__collapse_resort_threaded(&top.sym_evsel->hists);
-	hists__output_resort_threaded(&top.sym_evsel->hists);
-	hists__decay_entries_threaded(&top.sym_evsel->hists,
-				      top.hide_user_symbols,
-				      top.hide_kernel_symbols);
-	hists__output_recalc_col_len(&top.sym_evsel->hists, winsize.ws_row - 3);
+	hists__collapse_resort_threaded(&top->sym_evsel->hists);
+	hists__output_resort_threaded(&top->sym_evsel->hists);
+	hists__decay_entries_threaded(&top->sym_evsel->hists,
+				      top->hide_user_symbols,
+				      top->hide_kernel_symbols);
+	hists__output_recalc_col_len(&top->sym_evsel->hists,
+				     top->winsize.ws_row - 3);
 	putchar('\n');
-	hists__fprintf(&top.sym_evsel->hists, NULL, false, false,
-		       winsize.ws_row - 4 - printed, win_width, stdout);
+	hists__fprintf(&top->sym_evsel->hists, NULL, false, false,
+		       top->winsize.ws_row - 4 - printed, win_width, stdout);
 }
 
 static void prompt_integer(int *target, const char *msg)
@@ -349,17 +317,17 @@ static void prompt_percent(int *target, const char *msg)
 		*target = tmp;
 }
 
-static void prompt_symbol(struct hist_entry **target, const char *msg)
+static void perf_top__prompt_symbol(struct perf_top *top, const char *msg)
 {
 	char *buf = malloc(0), *p;
-	struct hist_entry *syme = *target, *n, *found = NULL;
+	struct hist_entry *syme = top->sym_filter_entry, *n, *found = NULL;
 	struct rb_node *next;
 	size_t dummy = 0;
 
 	/* zero counters of active symbol */
 	if (syme) {
 		__zero_source_counters(syme);
-		*target = NULL;
+		top->sym_filter_entry = NULL;
 	}
 
 	fprintf(stdout, "\n%s: ", msg);
@@ -370,7 +338,7 @@ static void prompt_symbol(struct hist_entry **target, const char *msg)
 	if (p)
 		*p = 0;
 
-	next = rb_first(&top.sym_evsel->hists.entries);
+	next = rb_first(&top->sym_evsel->hists.entries);
 	while (next) {
 		n = rb_entry(next, struct hist_entry, rb_node);
 		if (n->ms.sym && !strcmp(buf, n->ms.sym->name)) {
@@ -385,45 +353,45 @@ static void prompt_symbol(struct hist_entry **target, const char *msg)
 		sleep(1);
 		return;
 	} else
-		parse_source(found);
+		perf_top__parse_source(top, found);
 
 out_free:
 	free(buf);
 }
 
-static void print_mapped_keys(void)
+static void perf_top__print_mapped_keys(struct perf_top *top)
 {
 	char *name = NULL;
 
-	if (top.sym_filter_entry) {
-		struct symbol *sym = top.sym_filter_entry->ms.sym;
+	if (top->sym_filter_entry) {
+		struct symbol *sym = top->sym_filter_entry->ms.sym;
 		name = sym->name;
 	}
 
 	fprintf(stdout, "\nMapped keys:\n");
-	fprintf(stdout, "\t[d]     display refresh delay.             \t(%d)\n", top.delay_secs);
-	fprintf(stdout, "\t[e]     display entries (lines).           \t(%d)\n", top.print_entries);
+	fprintf(stdout, "\t[d]     display refresh delay.             \t(%d)\n", top->delay_secs);
+	fprintf(stdout, "\t[e]     display entries (lines).           \t(%d)\n", top->print_entries);
 
-	if (top.evlist->nr_entries > 1)
-		fprintf(stdout, "\t[E]     active event counter.              \t(%s)\n", event_name(top.sym_evsel));
+	if (top->evlist->nr_entries > 1)
+		fprintf(stdout, "\t[E]     active event counter.              \t(%s)\n", event_name(top->sym_evsel));
 
-	fprintf(stdout, "\t[f]     profile display filter (count).    \t(%d)\n", top.count_filter);
+	fprintf(stdout, "\t[f]     profile display filter (count).    \t(%d)\n", top->count_filter);
 
-	fprintf(stdout, "\t[F]     annotate display filter (percent). \t(%d%%)\n", sym_pcnt_filter);
+	fprintf(stdout, "\t[F]     annotate display filter (percent). \t(%d%%)\n", top->sym_pcnt_filter);
 	fprintf(stdout, "\t[s]     annotate symbol.                   \t(%s)\n", name?: "NULL");
 	fprintf(stdout, "\t[S]     stop annotation.\n");
 
 	fprintf(stdout,
 		"\t[K]     hide kernel_symbols symbols.     \t(%s)\n",
-		top.hide_kernel_symbols ? "yes" : "no");
+		top->hide_kernel_symbols ? "yes" : "no");
 	fprintf(stdout,
 		"\t[U]     hide user symbols.               \t(%s)\n",
-		top.hide_user_symbols ? "yes" : "no");
-	fprintf(stdout, "\t[z]     toggle sample zeroing.             \t(%d)\n", top.zero ? 1 : 0);
+		top->hide_user_symbols ? "yes" : "no");
+	fprintf(stdout, "\t[z]     toggle sample zeroing.             \t(%d)\n", top->zero ? 1 : 0);
 	fprintf(stdout, "\t[qQ]    quit.\n");
 }
 
-static int key_mapped(int c)
+static int perf_top__key_mapped(struct perf_top *top, int c)
 {
 	switch (c) {
 		case 'd':
@@ -439,7 +407,7 @@ static int key_mapped(int c)
 		case 'S':
 			return 1;
 		case 'E':
-			return top.evlist->nr_entries > 1 ? 1 : 0;
+			return top->evlist->nr_entries > 1 ? 1 : 0;
 		default:
 			break;
 	}
@@ -447,13 +415,13 @@ static int key_mapped(int c)
 	return 0;
 }
 
-static void handle_keypress(int c)
+static void perf_top__handle_keypress(struct perf_top *top, int c)
 {
-	if (!key_mapped(c)) {
+	if (!perf_top__key_mapped(top, c)) {
 		struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
 		struct termios tc, save;
 
-		print_mapped_keys();
+		perf_top__print_mapped_keys(top);
 		fprintf(stdout, "\nEnter selection, or unmapped key to continue: ");
 		fflush(stdout);
 
@@ -468,81 +436,86 @@ static void handle_keypress(int c)
 		c = getc(stdin);
 
 		tcsetattr(0, TCSAFLUSH, &save);
-		if (!key_mapped(c))
+		if (!perf_top__key_mapped(top, c))
 			return;
 	}
 
 	switch (c) {
 		case 'd':
-			prompt_integer(&top.delay_secs, "Enter display delay");
-			if (top.delay_secs < 1)
-				top.delay_secs = 1;
+			prompt_integer(&top->delay_secs, "Enter display delay");
+			if (top->delay_secs < 1)
+				top->delay_secs = 1;
 			break;
 		case 'e':
-			prompt_integer(&top.print_entries, "Enter display entries (lines)");
-			if (top.print_entries == 0) {
-				sig_winch_handler(SIGWINCH);
-				signal(SIGWINCH, sig_winch_handler);
+			prompt_integer(&top->print_entries, "Enter display entries (lines)");
+			if (top->print_entries == 0) {
+				struct sigaction act = {
+					.sa_sigaction = perf_top__sig_winch,
+					.sa_flags     = SA_SIGINFO,
+				};
+				perf_top__sig_winch(SIGWINCH, NULL, top);
+				sigaction(SIGWINCH, &act, NULL);
 			} else
 				signal(SIGWINCH, SIG_DFL);
 			break;
 		case 'E':
-			if (top.evlist->nr_entries > 1) {
+			if (top->evlist->nr_entries > 1) {
 				/* Select 0 as the default event: */
 				int counter = 0;
 
 				fprintf(stderr, "\nAvailable events:");
 
-				list_for_each_entry(top.sym_evsel, &top.evlist->entries, node)
-					fprintf(stderr, "\n\t%d %s", top.sym_evsel->idx, event_name(top.sym_evsel));
+				list_for_each_entry(top->sym_evsel, &top->evlist->entries, node)
+					fprintf(stderr, "\n\t%d %s", top->sym_evsel->idx, event_name(top->sym_evsel));
 
 				prompt_integer(&counter, "Enter details event counter");
 
-				if (counter >= top.evlist->nr_entries) {
-					top.sym_evsel = list_entry(top.evlist->entries.next, struct perf_evsel, node);
-					fprintf(stderr, "Sorry, no such event, using %s.\n", event_name(top.sym_evsel));
+				if (counter >= top->evlist->nr_entries) {
+					top->sym_evsel = list_entry(top->evlist->entries.next, struct perf_evsel, node);
+					fprintf(stderr, "Sorry, no such event, using %s.\n", event_name(top->sym_evsel));
 					sleep(1);
 					break;
 				}
-				list_for_each_entry(top.sym_evsel, &top.evlist->entries, node)
-					if (top.sym_evsel->idx == counter)
+				list_for_each_entry(top->sym_evsel, &top->evlist->entries, node)
+					if (top->sym_evsel->idx == counter)
 						break;
 			} else
-				top.sym_evsel = list_entry(top.evlist->entries.next, struct perf_evsel, node);
+				top->sym_evsel = list_entry(top->evlist->entries.next, struct perf_evsel, node);
 			break;
 		case 'f':
-			prompt_integer(&top.count_filter, "Enter display event count filter");
+			prompt_integer(&top->count_filter, "Enter display event count filter");
 			break;
 		case 'F':
-			prompt_percent(&sym_pcnt_filter, "Enter details display event filter (percent)");
+			prompt_percent(&top->sym_pcnt_filter,
+				       "Enter details display event filter (percent)");
 			break;
 		case 'K':
-			top.hide_kernel_symbols = !top.hide_kernel_symbols;
+			top->hide_kernel_symbols = !top->hide_kernel_symbols;
 			break;
 		case 'q':
 		case 'Q':
 			printf("exiting.\n");
-			if (dump_symtab)
-				perf_session__fprintf_dsos(top.session, stderr);
+			if (top->dump_symtab)
+				perf_session__fprintf_dsos(top->session, stderr);
 			exit(0);
 		case 's':
-			prompt_symbol(&top.sym_filter_entry, "Enter details symbol");
+			perf_top__prompt_symbol(top, "Enter details symbol");
 			break;
 		case 'S':
-			if (!top.sym_filter_entry)
+			if (!top->sym_filter_entry)
 				break;
 			else {
-				struct hist_entry *syme = top.sym_filter_entry;
+				struct hist_entry *syme = top->sym_filter_entry;
 
-				top.sym_filter_entry = NULL;
+				top->sym_filter_entry = NULL;
 				__zero_source_counters(syme);
 			}
 			break;
 		case 'U':
-			top.hide_user_symbols = !top.hide_user_symbols;
+			top->hide_user_symbols = !top->hide_user_symbols;
 			break;
 		case 'z':
-			top.zero = !top.zero;
+			top->zero = !top->zero;
 			break;
 		default:
 			break;
@@ -560,28 +533,30 @@ static void perf_top__sort_new_samples(void *arg)
 	hists__collapse_resort_threaded(&t->sym_evsel->hists);
 	hists__output_resort_threaded(&t->sym_evsel->hists);
 	hists__decay_entries_threaded(&t->sym_evsel->hists,
-				      top.hide_user_symbols,
-				      top.hide_kernel_symbols);
+				      t->hide_user_symbols,
+				      t->hide_kernel_symbols);
 }
 
-static void *display_thread_tui(void *arg __used)
+static void *display_thread_tui(void *arg)
 {
+	struct perf_top *top = arg;
 	const char *help = "For a higher level overview, try: perf top --sort comm,dso";
 
-	perf_top__sort_new_samples(&top);
-	perf_evlist__tui_browse_hists(top.evlist, help,
+	perf_top__sort_new_samples(top);
+	perf_evlist__tui_browse_hists(top->evlist, help,
 				      perf_top__sort_new_samples,
-				      &top, top.delay_secs);
+				      top, top->delay_secs);
 
 	exit_browser(0);
 	exit(0);
 	return NULL;
 }
 
-static void *display_thread(void *arg __used)
+static void *display_thread(void *arg)
 {
 	struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
 	struct termios tc, save;
+	struct perf_top *top = arg;
 	int delay_msecs, c;
 
 	tcgetattr(0, &save);
@@ -592,13 +567,13 @@ static void *display_thread(void *arg __used)
 
 	pthread__unblock_sigwinch();
 repeat:
-	delay_msecs = top.delay_secs * 1000;
+	delay_msecs = top->delay_secs * 1000;
 	tcsetattr(0, TCSANOW, &tc);
 	/* trash return*/
 	getc(stdin);
 
 	while (1) {
-		print_sym_table();
+		perf_top__print_sym_table(top);
 		/*
 		 * Either timeout expired or we got an EINTR due to SIGWINCH,
 		 * refresh screen in both cases.
@@ -618,7 +593,7 @@ process_hotkey:
 	c = getc(stdin);
 	tcsetattr(0, TCSAFLUSH, &save);
 
-	handle_keypress(c);
+	perf_top__handle_keypress(top, c);
 	goto repeat;
 
 	return NULL;
@@ -670,11 +645,13 @@ static int symbol_filter(struct map *map __used, struct symbol *sym)
 	return 0;
 }
 
-static void perf_event__process_sample(const union perf_event *event,
+static void perf_event__process_sample(struct perf_tool *tool,
+				       const union perf_event *event,
 				       struct perf_evsel *evsel,
 				       struct perf_sample *sample,
 				       struct machine *machine)
 {
+	struct perf_top *top = container_of(tool, struct perf_top, tool);
 	struct symbol *parent = NULL;
 	u64 ip = event->ip.ip;
 	struct addr_location al;
@@ -687,14 +664,14 @@ static void perf_event__process_sample(const union perf_event *event,
 	}
 
 	if (event->header.misc & PERF_RECORD_MISC_EXACT_IP)
-		top.exact_samples++;
+		top->exact_samples++;
 
 	if (perf_event__preprocess_sample(event, machine, &al, sample,
 					  symbol_filter) < 0 ||
 	    al.filtered)
 		return;
 
-	if (!kptr_restrict_warned &&
+	if (!top->kptr_restrict_warned &&
 	    symbol_conf.kptr_restrict &&
 	    al.cpumode == PERF_RECORD_MISC_KERNEL) {
 		ui__warning(
@@ -705,7 +682,7 @@ static void perf_event__process_sample(const union perf_event *event,
 			  " modules" : "");
 		if (use_browser <= 0)
 			sleep(5);
-		kptr_restrict_warned = true;
+		top->kptr_restrict_warned = true;
 	}
 
 	if (al.sym == NULL) {
@@ -721,7 +698,7 @@ static void perf_event__process_sample(const union perf_event *event,
 		 * --hide-kernel-symbols, even if the user specifies an
 		 * invalid --vmlinux ;-)
 		 */
-		if (!kptr_restrict_warned && !vmlinux_warned &&
+		if (!top->kptr_restrict_warned && !top->vmlinux_warned &&
 		    al.map == machine->vmlinux_maps[MAP__FUNCTION] &&
 		    RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION])) {
 			if (symbol_conf.vmlinux_name) {
@@ -734,7 +711,7 @@ static void perf_event__process_sample(const union perf_event *event,
 
 			if (use_browser <= 0)
 				sleep(5);
-			vmlinux_warned = true;
+			top->vmlinux_warned = true;
 		}
 	}
 
@@ -762,56 +739,57 @@ static void perf_event__process_sample(const union perf_event *event,
 				return;
 		}
 
-		if (sort_has_symbols)
-			record_precise_ip(he, evsel->idx, ip);
+		if (top->sort_has_symbols)
+			perf_top__record_precise_ip(top, he, evsel->idx, ip);
 	}
 
 	return;
 }
 
-static void perf_session__mmap_read_idx(struct perf_session *self, int idx)
+static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
 {
 	struct perf_sample sample;
 	struct perf_evsel *evsel;
+	struct perf_session *session = top->session;
 	union perf_event *event;
 	struct machine *machine;
 	u8 origin;
 	int ret;
 
-	while ((event = perf_evlist__mmap_read(top.evlist, idx)) != NULL) {
-		ret = perf_session__parse_sample(self, event, &sample);
+	while ((event = perf_evlist__mmap_read(top->evlist, idx)) != NULL) {
+		ret = perf_session__parse_sample(session, event, &sample);
 		if (ret) {
 			pr_err("Can't parse sample, err = %d\n", ret);
 			continue;
 		}
 
-		evsel = perf_evlist__id2evsel(self->evlist, sample.id);
+		evsel = perf_evlist__id2evsel(session->evlist, sample.id);
 		assert(evsel != NULL);
 
 		origin = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
 
 		if (event->header.type == PERF_RECORD_SAMPLE)
-			++top.samples;
+			++top->samples;
 
 		switch (origin) {
 		case PERF_RECORD_MISC_USER:
-			++top.us_samples;
-			if (top.hide_user_symbols)
+			++top->us_samples;
+			if (top->hide_user_symbols)
 				continue;
-			machine = perf_session__find_host_machine(self);
+			machine = perf_session__find_host_machine(session);
 			break;
 		case PERF_RECORD_MISC_KERNEL:
-			++top.kernel_samples;
-			if (top.hide_kernel_symbols)
+			++top->kernel_samples;
+			if (top->hide_kernel_symbols)
 				continue;
-			machine = perf_session__find_host_machine(self);
+			machine = perf_session__find_host_machine(session);
 			break;
 		case PERF_RECORD_MISC_GUEST_KERNEL:
-			++top.guest_kernel_samples;
-			machine = perf_session__find_machine(self, event->ip.pid);
+			++top->guest_kernel_samples;
+			machine = perf_session__find_machine(session, event->ip.pid);
 			break;
 		case PERF_RECORD_MISC_GUEST_USER:
-			++top.guest_us_samples;
+			++top->guest_us_samples;
 			/*
 			 * TODO: we don't process guest user from host side
 			 * except simple counting.
@@ -822,27 +800,29 @@ static void perf_session__mmap_read_idx(struct perf_session *self, int idx)
 		}
 
 
-		if (event->header.type == PERF_RECORD_SAMPLE)
-			perf_event__process_sample(event, evsel, &sample, machine);
-		else if (event->header.type < PERF_RECORD_MAX) {
+		if (event->header.type == PERF_RECORD_SAMPLE) {
+			perf_event__process_sample(&top->tool, event, evsel,
+						   &sample, machine);
+		} else if (event->header.type < PERF_RECORD_MAX) {
 			hists__inc_nr_events(&evsel->hists, event->header.type);
-			perf_event__process(&top.tool, event, &sample, machine);
+			perf_event__process(&top->tool, event, &sample, machine);
 		} else
-			++self->hists.stats.nr_unknown_events;
+			++session->hists.stats.nr_unknown_events;
 	}
 }
 
-static void perf_session__mmap_read(struct perf_session *self)
+static void perf_top__mmap_read(struct perf_top *top)
 {
 	int i;
 
-	for (i = 0; i < top.evlist->nr_mmaps; i++)
-		perf_session__mmap_read_idx(self, i);
+	for (i = 0; i < top->evlist->nr_mmaps; i++)
+		perf_top__mmap_read_idx(top, i);
 }
 
-static void start_counters(struct perf_evlist *evlist)
+static void perf_top__start_counters(struct perf_top *top)
 {
 	struct perf_evsel *counter, *first;
+	struct perf_evlist *evlist = top->evlist;
 
 	first = list_entry(evlist->entries.next, struct perf_evsel, node);
 
@@ -850,15 +830,15 @@ static void start_counters(struct perf_evlist *evlist)
 		struct perf_event_attr *attr = &counter->attr;
 		struct xyarray *group_fd = NULL;
 
-		if (group && counter != first)
+		if (top->group && counter != first)
 			group_fd = first->fd;
 
 		attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
 
-		if (top.freq) {
+		if (top->freq) {
 			attr->sample_type |= PERF_SAMPLE_PERIOD;
 			attr->freq	  = 1;
-			attr->sample_freq = top.freq;
+			attr->sample_freq = top->freq;
 		}
 
 		if (evlist->nr_entries > 1) {
@@ -871,23 +851,23 @@ static void start_counters(struct perf_evlist *evlist)
 
 		attr->mmap = 1;
 		attr->comm = 1;
-		attr->inherit = inherit;
+		attr->inherit = top->inherit;
 retry_sample_id:
-		attr->sample_id_all = sample_id_all_avail ? 1 : 0;
+		attr->sample_id_all = top->sample_id_all_avail ? 1 : 0;
 try_again:
-		if (perf_evsel__open(counter, top.evlist->cpus,
-				     top.evlist->threads, group,
+		if (perf_evsel__open(counter, top->evlist->cpus,
+				     top->evlist->threads, top->group,
 				     group_fd) < 0) {
 			int err = errno;
 
 			if (err == EPERM || err == EACCES) {
 				ui__error_paranoid();
 				goto out_err;
-			} else if (err == EINVAL && sample_id_all_avail) {
+			} else if (err == EINVAL && top->sample_id_all_avail) {
 				/*
 				 * Old kernel, no attr->sample_id_type_all field
 				 */
-				sample_id_all_avail = false;
+				top->sample_id_all_avail = false;
 				goto retry_sample_id;
 			}
 			/*
@@ -921,7 +901,7 @@ try_again:
 		}
 	}
 
-	if (perf_evlist__mmap(evlist, mmap_pages, false) < 0) {
+	if (perf_evlist__mmap(evlist, top->mmap_pages, false) < 0) {
 		ui__warning("Failed to mmap with %d (%s)\n",
 			    errno, strerror(errno));
 		goto out_err;
@@ -934,14 +914,14 @@ out_err:
 	exit(0);
 }
 
-static int setup_sample_type(void)
+static int perf_top__setup_sample_type(struct perf_top *top)
 {
-	if (!sort_has_symbols) {
+	if (!top->sort_has_symbols) {
 		if (symbol_conf.use_callchain) {
 			ui__warning("Selected -g but \"sym\" not present in --sort/-s.");
 			return -EINVAL;
 		}
-	} else if (!dont_use_callchains && callchain_param.mode != CHAIN_NONE) {
+	} else if (!top->dont_use_callchains && callchain_param.mode != CHAIN_NONE) {
 		if (callchain_register_param(&callchain_param) < 0) {
 			ui__warning("Can't register callchain params.\n");
 			return -EINVAL;
@@ -951,7 +931,7 @@ static int setup_sample_type(void)
 	return 0;
 }
 
-static int __cmd_top(void)
+static int __cmd_top(struct perf_top *top)
 {
 	pthread_t thread;
 	int ret;
@@ -959,40 +939,40 @@ static int __cmd_top(void)
 	 * FIXME: perf_session__new should allow passing a O_MMAP, so that all this
 	 * mmap reading, etc is encapsulated in it. Use O_WRONLY for now.
 	 */
-	top.session = perf_session__new(NULL, O_WRONLY, false, false, NULL);
-	if (top.session == NULL)
+	top->session = perf_session__new(NULL, O_WRONLY, false, false, NULL);
+	if (top->session == NULL)
 		return -ENOMEM;
 
-	ret = setup_sample_type();
+	ret = perf_top__setup_sample_type(top);
 	if (ret)
 		goto out_delete;
 
-	if (top.target_tid != -1)
-		perf_event__synthesize_thread_map(&top.tool, top.evlist->threads,
+	if (top->target_tid != -1)
+		perf_event__synthesize_thread_map(&top->tool, top->evlist->threads,
 						  perf_event__process,
-						  &top.session->host_machine);
+						  &top->session->host_machine);
 	else
-		perf_event__synthesize_threads(&top.tool, perf_event__process,
-					       &top.session->host_machine);
-	start_counters(top.evlist);
-	top.session->evlist = top.evlist;
-	perf_session__update_sample_type(top.session);
+		perf_event__synthesize_threads(&top->tool, perf_event__process,
+					       &top->session->host_machine);
+	perf_top__start_counters(top);
+	top->session->evlist = top->evlist;
+	perf_session__update_sample_type(top->session);
 
 	/* Wait for a minimal set of events before starting the snapshot */
-	poll(top.evlist->pollfd, top.evlist->nr_fds, 100);
+	poll(top->evlist->pollfd, top->evlist->nr_fds, 100);
 
-	perf_session__mmap_read(top.session);
+	perf_top__mmap_read(top);
 
 	if (pthread_create(&thread, NULL, (use_browser > 0 ? display_thread_tui :
-							     display_thread), NULL)) {
+							    display_thread), top)) {
 		printf("Could not create display thread.\n");
 		exit(-1);
 	}
 
-	if (realtime_prio) {
+	if (top->realtime_prio) {
 		struct sched_param param;
 
-		param.sched_priority = realtime_prio;
+		param.sched_priority = top->realtime_prio;
 		if (sched_setscheduler(0, SCHED_FIFO, &param)) {
 			printf("Could not set realtime priority.\n");
 			exit(-1);
@@ -1000,25 +980,25 @@ static int __cmd_top(void)
 	}
 
 	while (1) {
-		u64 hits = top.samples;
+		u64 hits = top->samples;
 
-		perf_session__mmap_read(top.session);
+		perf_top__mmap_read(top);
 
-		if (hits == top.samples)
-			ret = poll(top.evlist->pollfd, top.evlist->nr_fds, 100);
+		if (hits == top->samples)
+			ret = poll(top->evlist->pollfd, top->evlist->nr_fds, 100);
 	}
 
 out_delete:
-	perf_session__delete(top.session);
-	top.session = NULL;
+	perf_session__delete(top->session);
+	top->session = NULL;
 
 	return 0;
 }
 
 static int
-parse_callchain_opt(const struct option *opt __used, const char *arg,
-		    int unset)
+parse_callchain_opt(const struct option *opt, const char *arg, int unset)
 {
+	struct perf_top *top = (struct perf_top *)opt->value;
 	char *tok, *tok2;
 	char *endptr;
 
@@ -1026,7 +1006,7 @@ parse_callchain_opt(const struct option *opt __used, const char *arg,
 	 * --no-call-graph
 	 */
 	if (unset) {
-		dont_use_callchains = true;
+		top->dont_use_callchains = true;
 		return 0;
 	}
 
@@ -1100,17 +1080,32 @@ static const char * const top_usage[] = {
 	NULL
 };
 
-static const struct option options[] = {
+int cmd_top(int argc, const char **argv, const char *prefix __used)
+{
+	struct perf_evsel *pos;
+	int status = -ENOMEM;
+	struct perf_top top = {
+		.count_filter	     = 5,
+		.delay_secs	     = 2,
+		.target_pid	     = -1,
+		.target_tid	     = -1,
+		.freq		     = 1000, /* 1 KHz */
+		.sample_id_all_avail = true,
+		.mmap_pages	     = 128,
+		.sym_pcnt_filter     = 5,
+	};
+	char callchain_default_opt[] = "fractal,0.5,callee";
+	const struct option options[] = {
 	OPT_CALLBACK('e', "event", &top.evlist, "event",
 		     "event selector. use 'perf list' to list available events",
 		     parse_events_option),
-	OPT_INTEGER('c', "count", &default_interval,
+	OPT_INTEGER('c', "count", &top.default_interval,
 		    "event period to sample"),
 	OPT_INTEGER('p', "pid", &top.target_pid,
 		    "profile events on existing process id"),
 	OPT_INTEGER('t', "tid", &top.target_tid,
 		    "profile events on existing thread id"),
-	OPT_BOOLEAN('a', "all-cpus", &system_wide,
+	OPT_BOOLEAN('a', "all-cpus", &top.system_wide,
 			    "system-wide collection from all CPUs"),
 	OPT_STRING('C', "cpu", &top.cpu_list, "cpu",
 		    "list of cpus to monitor"),
@@ -1118,20 +1113,20 @@ static const struct option options[] = {
 		   "file", "vmlinux pathname"),
 	OPT_BOOLEAN('K', "hide_kernel_symbols", &top.hide_kernel_symbols,
 		    "hide kernel symbols"),
-	OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"),
-	OPT_INTEGER('r', "realtime", &realtime_prio,
+	OPT_UINTEGER('m', "mmap-pages", &top.mmap_pages, "number of mmap data pages"),
+	OPT_INTEGER('r', "realtime", &top.realtime_prio,
 		    "collect data with this RT SCHED_FIFO priority"),
 	OPT_INTEGER('d', "delay", &top.delay_secs,
 		    "number of seconds to delay between refreshes"),
-	OPT_BOOLEAN('D', "dump-symtab", &dump_symtab,
+	OPT_BOOLEAN('D', "dump-symtab", &top.dump_symtab,
 			    "dump the symbol table used for profiling"),
 	OPT_INTEGER('f', "count-filter", &top.count_filter,
 		    "only display functions with more events than this"),
-	OPT_BOOLEAN('g', "group", &group,
+	OPT_BOOLEAN('g', "group", &top.group,
 			    "put the counters into a counter group"),
-	OPT_BOOLEAN('i', "inherit", &inherit,
+	OPT_BOOLEAN('i', "inherit", &top.inherit,
 		    "child tasks inherit counters"),
-	OPT_STRING(0, "sym-annotate", &sym_filter, "symbol name",
+	OPT_STRING(0, "sym-annotate", &top.sym_filter, "symbol name",
 		    "symbol to annotate"),
 	OPT_BOOLEAN('z', "zero", &top.zero,
 		    "zero history across updates"),
@@ -1141,15 +1136,15 @@ static const struct option options[] = {
 		    "display this many functions"),
 	OPT_BOOLEAN('U', "hide_user_symbols", &top.hide_user_symbols,
 		    "hide user symbols"),
-	OPT_BOOLEAN(0, "tui", &use_tui, "Use the TUI interface"),
-	OPT_BOOLEAN(0, "stdio", &use_stdio, "Use the stdio interface"),
+	OPT_BOOLEAN(0, "tui", &top.use_tui, "Use the TUI interface"),
+	OPT_BOOLEAN(0, "stdio", &top.use_stdio, "Use the stdio interface"),
 	OPT_INCR('v', "verbose", &verbose,
 		    "be more verbose (show counter open errors, etc)"),
 	OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
 		   "sort by key(s): pid, comm, dso, symbol, parent"),
 	OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
 		    "Show a column with the number of samples"),
-	OPT_CALLBACK_DEFAULT('G', "call-graph", NULL, "output_type,min_percent, call_order",
+	OPT_CALLBACK_DEFAULT('G', "call-graph", &top, "output_type,min_percent, call_order",
 		     "Display callchains using output_type (graph, flat, fractal, or none), min percent threshold and callchain order. "
 		     "Default: fractal,0.5,callee", &parse_callchain_opt,
 		     callchain_default_opt),
@@ -1168,12 +1163,7 @@ static const struct option options[] = {
 	OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style",
 		   "Specify disassembler style (e.g. -M intel for intel syntax)"),
 	OPT_END()
-};
-
-int cmd_top(int argc, const char **argv, const char *prefix __used)
-{
-	struct perf_evsel *pos;
-	int status = -ENOMEM;
+	};
 
 	top.evlist = perf_evlist__new(NULL, NULL);
 	if (top.evlist == NULL)
@@ -1190,9 +1180,9 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
 
 	setup_sorting(top_usage, options);
 
-	if (use_stdio)
+	if (top.use_stdio)
 		use_browser = 0;
-	else if (use_tui)
+	else if (top.use_tui)
 		use_browser = 1;
 
 	setup_browser(false);
@@ -1225,10 +1215,10 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
 	/*
 	 * User specified count overrides default frequency.
 	 */
-	if (default_interval)
+	if (top.default_interval)
 		top.freq = 0;
 	else if (top.freq) {
-		default_interval = top.freq;
+		top.default_interval = top.freq;
 	} else {
 		fprintf(stderr, "frequency and count are zero, aborting\n");
 		exit(EXIT_FAILURE);
@@ -1244,7 +1234,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
 		if (pos->attr.sample_period)
 			continue;
 
-		pos->attr.sample_period = default_interval;
+		pos->attr.sample_period = top.default_interval;
 	}
 
 	if (perf_evlist__alloc_pollfd(top.evlist) < 0 ||
@@ -1267,15 +1257,19 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
 	 * Avoid annotation data structures overhead when symbols aren't on the
 	 * sort list.
 	 */
-	sort_has_symbols = sort_sym.list.next != NULL;
+	top.sort_has_symbols = sort_sym.list.next != NULL;
 
-	get_term_dimensions(&winsize);
+	get_term_dimensions(&top.winsize);
 	if (top.print_entries == 0) {
-		update_print_entries(&winsize);
-		signal(SIGWINCH, sig_winch_handler);
+		struct sigaction act = {
+			.sa_sigaction = perf_top__sig_winch,
+			.sa_flags     = SA_SIGINFO,
+		};
+		perf_top__update_print_entries(&top);
+		sigaction(SIGWINCH, &act, NULL);
 	}
 
-	status = __cmd_top();
+	status = __cmd_top(&top);
 out_free_fd:
 	perf_evlist__delete(top.evlist);
 
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index 40430ec..a248f3c 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -25,10 +25,26 @@ struct perf_top {
 	int		   freq;
 	pid_t		   target_pid, target_tid;
 	bool		   hide_kernel_symbols, hide_user_symbols, zero;
+	bool		   system_wide;
+	bool		   use_tui, use_stdio;
+	bool		   sort_has_symbols;
+	bool		   dont_use_callchains;
+	bool		   kptr_restrict_warned;
+	bool		   vmlinux_warned;
+	bool		   inherit;
+	bool		   group;
+	bool		   sample_id_all_avail;
+	bool		   dump_symtab;
 	const char	   *cpu_list;
 	struct hist_entry  *sym_filter_entry;
 	struct perf_evsel  *sym_evsel;
 	struct perf_session *session;
+	struct winsize	   winsize;
+	unsigned int	   mmap_pages;
+	int		   default_interval;
+	int		   realtime_prio;
+	int		   sym_pcnt_filter;
+	const char	   *sym_filter;
 };
 
 size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size);
-- 
1.7.8.rc0.35.gee6df


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

* [PATCH 23/25] perf tools: make -C consistent across commands (for cpu list arg)
  2011-11-28 23:14 [GIT PULL 00/25] perf/core fixes and improvements Arnaldo Carvalho de Melo
                   ` (21 preceding siblings ...)
  2011-11-28 23:14 ` [PATCH 22/25] perf top: Stop using globals for tool state Arnaldo Carvalho de Melo
@ 2011-11-28 23:14 ` Arnaldo Carvalho de Melo
  2011-11-28 23:14 ` [PATCH 24/25] perf script: Add comm filtering option Arnaldo Carvalho de Melo
  2011-11-28 23:14 ` [PATCH 25/25] perf tools: Save some loops using perf_evlist__id2evsel Arnaldo Carvalho de Melo
  24 siblings, 0 replies; 28+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-11-28 23:14 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, David Ahern, Frederic Weisbecker, Peter Zijlstra,
	Arnaldo Carvalho de Melo

From: David Ahern <dsahern@gmail.com>

Currently the meaning of -C varies by perf command: for perf-top,
perf-stat, perf-record it means cpu list. For perf-report it means comm
list. Then perf-annotate, perf-report and perf-script use -c for cpu
list.

Fix annotate, report and script to use -C for cpu list to be consistent
with top, stat and record. This means report needs to use -c for comm
list which does introduce a backward compatibility change.

v1 -> v2
- update perf-script.txt too

Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1321209008-7004-1-git-send-email-dsahern@gmail.com
Signed-off-by: David Ahern <dsahern@gmail.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/Documentation/perf-annotate.txt |    2 +-
 tools/perf/Documentation/perf-report.txt   |    4 ++--
 tools/perf/Documentation/perf-script.txt   |    2 +-
 tools/perf/builtin-annotate.c              |    2 +-
 tools/perf/builtin-report.c                |    4 ++--
 tools/perf/builtin-script.c                |    2 +-
 6 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/tools/perf/Documentation/perf-annotate.txt b/tools/perf/Documentation/perf-annotate.txt
index fe6762e..476029d 100644
--- a/tools/perf/Documentation/perf-annotate.txt
+++ b/tools/perf/Documentation/perf-annotate.txt
@@ -66,7 +66,7 @@ OPTIONS
 	used. This interfaces starts by centering on the line with more
 	samples, TAB/UNTAB cycles through the lines with more samples.
 
--c::
+-C::
 --cpu:: Only report samples for the list of CPUs provided. Multiple CPUs can
 	be provided as a comma-separated list with no space: 0,1. Ranges of
 	CPUs are specified with -: 0-2. Default is to report samples on all
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 212f24d..dc85392 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -39,7 +39,7 @@ OPTIONS
 -T::
 --threads::
 	Show per-thread event counters
--C::
+-c::
 --comms=::
 	Only consider symbols in these comms. CSV that understands
 	file://filename entries.
@@ -128,7 +128,7 @@ OPTIONS
 --symfs=<directory>::
         Look for files with symbols relative to this directory.
 
--c::
+-C::
 --cpu:: Only report samples for the list of CPUs provided. Multiple CPUs can
 	be provided as a comma-separated list with no space: 0,1. Ranges of
 	CPUs are specified with -: 0-2. Default is to report samples on all
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index dec87ec..3613b0a 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -182,7 +182,7 @@ OPTIONS
 --hide-call-graph::
         When printing symbols do not display call chain.
 
--c::
+-C::
 --cpu:: Only report samples for the list of CPUs provided. Multiple CPUs can
 	be provided as a comma-separated list with no space: 0,1. Ranges of
 	CPUs are specified with -: 0-2. Default is to report samples on all
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index c01139f..d449645 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -274,7 +274,7 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __used)
 		    "print matching source lines (may be slow)"),
 	OPT_BOOLEAN('P', "full-paths", &annotate.full_paths,
 		    "Don't shorten the displayed pathnames"),
-	OPT_STRING('c', "cpu", &annotate.cpu_list, "cpu", "list of cpus to profile"),
+	OPT_STRING('C', "cpu", &annotate.cpu_list, "cpu", "list of cpus to profile"),
 	OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
 		   "Look for files with symbols relative to this directory"),
 	OPT_BOOLEAN(0, "source", &symbol_conf.annotate_src,
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index eef8e42..ece7c5d 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -492,7 +492,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
 		    "alias for inverted call graph"),
 	OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
 		   "only consider symbols in these dsos"),
-	OPT_STRING('C', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
+	OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
 		   "only consider symbols in these comms"),
 	OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
 		   "only consider these symbols"),
@@ -506,7 +506,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
 		    "Only display entries resolved to a symbol"),
 	OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
 		    "Look for files with symbols relative to this directory"),
-	OPT_STRING('c', "cpu", &report.cpu_list, "cpu",
+	OPT_STRING('C', "cpu", &report.cpu_list, "cpu",
 		   "list of cpus to profile"),
 	OPT_BOOLEAN('I', "show-info", &report.show_full_info,
 		    "Display extended information about perf.data file"),
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 5f8afc6..7731a09 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -1085,7 +1085,7 @@ static const struct option options[] = {
 	OPT_CALLBACK('f', "fields", NULL, "str",
 		     "comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace,raw. Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,addr",
 		     parse_output_fields),
-	OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
+	OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
 	OPT_BOOLEAN('I', "show-info", &show_full_info,
 		    "display extended information from perf.data file"),
 	OPT_END()
-- 
1.7.8.rc0.35.gee6df


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

* [PATCH 24/25] perf script: Add comm filtering option
  2011-11-28 23:14 [GIT PULL 00/25] perf/core fixes and improvements Arnaldo Carvalho de Melo
                   ` (22 preceding siblings ...)
  2011-11-28 23:14 ` [PATCH 23/25] perf tools: make -C consistent across commands (for cpu list arg) Arnaldo Carvalho de Melo
@ 2011-11-28 23:14 ` Arnaldo Carvalho de Melo
  2011-11-28 23:14 ` [PATCH 25/25] perf tools: Save some loops using perf_evlist__id2evsel Arnaldo Carvalho de Melo
  24 siblings, 0 replies; 28+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-11-28 23:14 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, David Ahern, Frederic Weisbecker, Peter Zijlstra,
	Arnaldo Carvalho de Melo

From: David Ahern <dsahern@gmail.com>

Allows collecting events system wide and then pulling out events for a
specific task name(s). e.g,

    perf script -c gnome-shell,gnome-terminal

Applies on top of:
    https://lkml.org/lkml/2011/11/13/74

v2->v3
- update Documentation

v1->v2
- use comm_list from symbol_conf

Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1321894972-24246-1-git-send-email-dsahern@gmail.com
Signed-off-by: David Ahern <dsahern@gmail.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/Documentation/perf-script.txt |    5 +++++
 tools/perf/builtin-script.c              |   12 ++++++++++++
 2 files changed, 17 insertions(+), 0 deletions(-)

diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 3613b0a..7f61eaa 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -188,6 +188,11 @@ OPTIONS
 	CPUs are specified with -: 0-2. Default is to report samples on all
 	CPUs.
 
+-c::
+--comms=::
+	Only display events for these comms. CSV that understands
+	file://filename entries.
+
 -I::
 --show-info::
 	Display extended information about the perf.data file. This adds
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 7731a09..619d6dc 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -441,6 +441,7 @@ static int process_sample_event(struct perf_tool *tool __used,
 				struct perf_evsel *evsel,
 				struct machine *machine)
 {
+	struct addr_location al;
 	struct thread *thread = machine__findnew_thread(machine, event->ip.pid);
 
 	if (thread == NULL) {
@@ -460,6 +461,15 @@ static int process_sample_event(struct perf_tool *tool __used,
 		return 0;
 	}
 
+	if (perf_event__preprocess_sample(event, machine, &al, sample, 0) < 0) {
+		pr_err("problem processing %d event, skipping it.\n",
+		       event->header.type);
+		return -1;
+	}
+
+	if (al.filtered)
+		return 0;
+
 	if (cpu_list && !test_bit(sample->cpu, cpu_bitmap))
 		return 0;
 
@@ -1086,6 +1096,8 @@ static const struct option options[] = {
 		     "comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace,raw. Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,addr",
 		     parse_output_fields),
 	OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
+	OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
+		   "only display events for these comms"),
 	OPT_BOOLEAN('I', "show-info", &show_full_info,
 		    "display extended information from perf.data file"),
 	OPT_END()
-- 
1.7.8.rc0.35.gee6df


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

* [PATCH 25/25] perf tools: Save some loops using perf_evlist__id2evsel
  2011-11-28 23:14 [GIT PULL 00/25] perf/core fixes and improvements Arnaldo Carvalho de Melo
                   ` (23 preceding siblings ...)
  2011-11-28 23:14 ` [PATCH 24/25] perf script: Add comm filtering option Arnaldo Carvalho de Melo
@ 2011-11-28 23:14 ` Arnaldo Carvalho de Melo
  24 siblings, 0 replies; 28+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-11-28 23:14 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Arnaldo Carvalho de Melo, David Ahern,
	Frederic Weisbecker, Mike Galbraith, Paul Mackerras,
	Peter Zijlstra, Stephane Eranian

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

Since we already ask for PERF_SAMPLE_ID and use it to quickly find the
associated evsel, add handler func + data to struct perf_evsel to avoid
using chains of if(strcmp(event_name)) and also to avoid all the linear
list searches via trace_event_find.

To demonstrate the technique convert 'perf sched' to it:

 # perf sched record sleep 5m

And then:

 Performance counter stats for '/tmp/oldperf sched lat':

        646.929438 task-clock                #    0.999 CPUs utilized
                 9 context-switches          #    0.000 M/sec
                 0 CPU-migrations            #    0.000 M/sec
            20,901 page-faults               #    0.032 M/sec
     1,290,144,450 cycles                    #    1.994 GHz
   <not supported> stalled-cycles-frontend
   <not supported> stalled-cycles-backend
     1,606,158,439 instructions              #    1.24  insns per cycle
       339,088,395 branches                  #  524.151 M/sec
         4,550,735 branch-misses             #    1.34% of all branches

       0.647524759 seconds time elapsed

Versus:

 Performance counter stats for 'perf sched lat':

        473.564691 task-clock                #    0.999 CPUs utilized
                 9 context-switches          #    0.000 M/sec
                 0 CPU-migrations            #    0.000 M/sec
            20,903 page-faults               #    0.044 M/sec
       944,367,984 cycles                    #    1.994 GHz
   <not supported> stalled-cycles-frontend
   <not supported> stalled-cycles-backend
     1,442,385,571 instructions              #    1.53  insns per cycle
       308,383,106 branches                  #  651.195 M/sec
         4,481,784 branch-misses             #    1.45% of all branches

       0.474215751 seconds time elapsed

[root@emilia ~]#

Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-1kbzpl74lwi6lavpqke2u2p3@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-sched.c |  149 ++++++++++++++++++++++----------------------
 tools/perf/util/evlist.c   |   42 ++++++++++++
 tools/perf/util/evlist.h   |   11 +++
 tools/perf/util/evsel.h    |    4 +
 tools/perf/util/tool.h     |    5 ++
 5 files changed, 136 insertions(+), 75 deletions(-)

diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 0ee868e..6284ed2 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -2,6 +2,7 @@
 #include "perf.h"
 
 #include "util/util.h"
+#include "util/evlist.h"
 #include "util/cache.h"
 #include "util/evsel.h"
 #include "util/symbol.h"
@@ -1358,12 +1359,13 @@ static void sort_lat(void)
 static struct trace_sched_handler *trace_handler;
 
 static void
-process_sched_wakeup_event(void *data, struct machine *machine,
+process_sched_wakeup_event(struct perf_tool *tool __used,
 			   struct event *event,
-			   int cpu __used,
-			   u64 timestamp __used,
-			   struct thread *thread __used)
+			   struct perf_sample *sample,
+			   struct machine *machine,
+			   struct thread *thread)
 {
+	void *data = sample->raw_data;
 	struct trace_wakeup_event wakeup_event;
 
 	FILL_COMMON_FIELDS(wakeup_event, event, data);
@@ -1376,7 +1378,7 @@ process_sched_wakeup_event(void *data, struct machine *machine,
 
 	if (trace_handler->wakeup_event)
 		trace_handler->wakeup_event(&wakeup_event, machine, event,
-					    cpu, timestamp, thread);
+					    sample->cpu, sample->time, thread);
 }
 
 /*
@@ -1471,14 +1473,15 @@ map_switch_event(struct trace_switch_event *switch_event,
 	}
 }
 
-
 static void
-process_sched_switch_event(void *data, struct machine *machine,
+process_sched_switch_event(struct perf_tool *tool __used,
 			   struct event *event,
-			   int this_cpu,
-			   u64 timestamp __used,
-			   struct thread *thread __used)
+			   struct perf_sample *sample,
+			   struct machine *machine,
+			   struct thread *thread)
 {
+	int this_cpu = sample->cpu;
+	void *data = sample->raw_data;
 	struct trace_switch_event switch_event;
 
 	FILL_COMMON_FIELDS(switch_event, event, data);
@@ -1501,18 +1504,19 @@ process_sched_switch_event(void *data, struct machine *machine,
 	}
 	if (trace_handler->switch_event)
 		trace_handler->switch_event(&switch_event, machine, event,
-					    this_cpu, timestamp, thread);
+					    this_cpu, sample->time, thread);
 
 	curr_pid[this_cpu] = switch_event.next_pid;
 }
 
 static void
-process_sched_runtime_event(void *data, struct machine *machine,
-			   struct event *event,
-			   int cpu __used,
-			   u64 timestamp __used,
-			   struct thread *thread __used)
+process_sched_runtime_event(struct perf_tool *tool __used,
+			    struct event *event,
+			    struct perf_sample *sample,
+			    struct machine *machine,
+			    struct thread *thread)
 {
+	void *data = sample->raw_data;
 	struct trace_runtime_event runtime_event;
 
 	FILL_ARRAY(runtime_event, comm, event, data);
@@ -1521,16 +1525,18 @@ process_sched_runtime_event(void *data, struct machine *machine,
 	FILL_FIELD(runtime_event, vruntime, event, data);
 
 	if (trace_handler->runtime_event)
-		trace_handler->runtime_event(&runtime_event, machine, event, cpu, timestamp, thread);
+		trace_handler->runtime_event(&runtime_event, machine, event,
+					     sample->cpu, sample->time, thread);
 }
 
 static void
-process_sched_fork_event(void *data,
+process_sched_fork_event(struct perf_tool *tool __used,
 			 struct event *event,
-			 int cpu __used,
-			 u64 timestamp __used,
-			 struct thread *thread __used)
+			 struct perf_sample *sample,
+			 struct machine *machine __used,
+			 struct thread *thread)
 {
+	void *data = sample->raw_data;
 	struct trace_fork_event fork_event;
 
 	FILL_COMMON_FIELDS(fork_event, event, data);
@@ -1542,13 +1548,14 @@ process_sched_fork_event(void *data,
 
 	if (trace_handler->fork_event)
 		trace_handler->fork_event(&fork_event, event,
-					  cpu, timestamp, thread);
+					  sample->cpu, sample->time, thread);
 }
 
 static void
-process_sched_exit_event(struct event *event,
-			 int cpu __used,
-			 u64 timestamp __used,
+process_sched_exit_event(struct perf_tool *tool __used,
+			 struct event *event,
+			 struct perf_sample *sample __used,
+			 struct machine *machine __used,
 			 struct thread *thread __used)
 {
 	if (verbose)
@@ -1556,12 +1563,13 @@ process_sched_exit_event(struct event *event,
 }
 
 static void
-process_sched_migrate_task_event(void *data, struct machine *machine,
-			   struct event *event,
-			   int cpu __used,
-			   u64 timestamp __used,
-			   struct thread *thread __used)
+process_sched_migrate_task_event(struct perf_tool *tool __used,
+				 struct event *event,
+				 struct perf_sample *sample,
+				 struct machine *machine,
+				 struct thread *thread)
 {
+	void *data = sample->raw_data;
 	struct trace_migrate_task_event migrate_task_event;
 
 	FILL_COMMON_FIELDS(migrate_task_event, event, data);
@@ -1573,67 +1581,46 @@ process_sched_migrate_task_event(void *data, struct machine *machine,
 
 	if (trace_handler->migrate_task_event)
 		trace_handler->migrate_task_event(&migrate_task_event, machine,
-						 event, cpu, timestamp, thread);
+						  event, sample->cpu,
+						  sample->time, thread);
 }
 
-static void process_raw_event(union perf_event *raw_event __used,
-			      struct machine *machine, void *data, int cpu,
-			      u64 timestamp, struct thread *thread)
-{
-	struct event *event;
-	int type;
-
-
-	type = trace_parse_common_type(data);
-	event = trace_find_event(type);
-
-	if (!strcmp(event->name, "sched_switch"))
-		process_sched_switch_event(data, machine, event, cpu, timestamp, thread);
-	if (!strcmp(event->name, "sched_stat_runtime"))
-		process_sched_runtime_event(data, machine, event, cpu, timestamp, thread);
-	if (!strcmp(event->name, "sched_wakeup"))
-		process_sched_wakeup_event(data, machine, event, cpu, timestamp, thread);
-	if (!strcmp(event->name, "sched_wakeup_new"))
-		process_sched_wakeup_event(data, machine, event, cpu, timestamp, thread);
-	if (!strcmp(event->name, "sched_process_fork"))
-		process_sched_fork_event(data, event, cpu, timestamp, thread);
-	if (!strcmp(event->name, "sched_process_exit"))
-		process_sched_exit_event(event, cpu, timestamp, thread);
-	if (!strcmp(event->name, "sched_migrate_task"))
-		process_sched_migrate_task_event(data, machine, event, cpu, timestamp, thread);
-}
+typedef void (*tracepoint_handler)(struct perf_tool *tool, struct event *event,
+				   struct perf_sample *sample,
+				   struct machine *machine,
+				   struct thread *thread);
 
-static int process_sample_event(struct perf_tool *tool __used,
-				union perf_event *event,
-				struct perf_sample *sample,
-				struct perf_evsel *evsel,
-				struct machine *machine)
+static int perf_sched__process_tracepoint_sample(struct perf_tool *tool,
+						 union perf_event *event __used,
+						 struct perf_sample *sample,
+						 struct perf_evsel *evsel,
+						 struct machine *machine)
 {
-	struct thread *thread;
-
-	if (!(evsel->attr.sample_type & PERF_SAMPLE_RAW))
-		return 0;
+	struct thread *thread = machine__findnew_thread(machine, sample->pid);
 
-	thread = machine__findnew_thread(machine, sample->pid);
 	if (thread == NULL) {
-		pr_debug("problem processing %d event, skipping it.\n",
-			 event->header.type);
+		pr_debug("problem processing %s event, skipping it.\n",
+			 evsel->name);
 		return -1;
 	}
 
-	dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
+	evsel->hists.stats.total_period += sample->period;
+	hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
 
-	if (profile_cpu != -1 && profile_cpu != (int)sample->cpu)
-		return 0;
+	if (evsel->handler.func != NULL) {
+		tracepoint_handler f = evsel->handler.func;
 
-	process_raw_event(event, machine, sample->raw_data, sample->cpu,
-			  sample->time, thread);
+		if (evsel->handler.data == NULL)
+			evsel->handler.data = trace_find_event(evsel->attr.config);
+
+		f(tool, evsel->handler.data, sample, machine, thread);
+	}
 
 	return 0;
 }
 
 static struct perf_tool perf_sched = {
-	.sample			= process_sample_event,
+	.sample			= perf_sched__process_tracepoint_sample,
 	.comm			= perf_event__process_comm,
 	.lost			= perf_event__process_lost,
 	.fork			= perf_event__process_task,
@@ -1643,11 +1630,23 @@ static struct perf_tool perf_sched = {
 static void read_events(bool destroy, struct perf_session **psession)
 {
 	int err = -EINVAL;
+	const struct perf_evsel_str_handler handlers[] = {
+		{ "sched:sched_switch",	      process_sched_switch_event, },
+		{ "sched:sched_stat_runtime", process_sched_runtime_event, },
+		{ "sched:sched_wakeup",	      process_sched_wakeup_event, },
+		{ "sched:sched_wakeup_new",   process_sched_wakeup_event, },
+		{ "sched:sched_process_fork", process_sched_fork_event, },
+		{ "sched:sched_process_exit", process_sched_exit_event, },
+		{ "sched:sched_migrate_task", process_sched_migrate_task_event, },
+	};
 	struct perf_session *session = perf_session__new(input_name, O_RDONLY,
 							 0, false, &perf_sched);
 	if (session == NULL)
 		die("No Memory");
 
+	err = perf_evlist__set_tracepoints_handlers_array(session->evlist, handlers);
+	assert(err == 0);
+
 	if (perf_session__has_traces(session, "record -R")) {
 		err = perf_session__process_events(session, &perf_sched);
 		if (err)
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index d44e3df..b36f26f 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -207,6 +207,48 @@ out_free_attrs:
 	return err;
 }
 
+static struct perf_evsel *
+	perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id)
+{
+	struct perf_evsel *evsel;
+
+	list_for_each_entry(evsel, &evlist->entries, node) {
+		if (evsel->attr.type   == PERF_TYPE_TRACEPOINT &&
+		    (int)evsel->attr.config == id)
+			return evsel;
+	}
+
+	return NULL;
+}
+
+int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist,
+					  const struct perf_evsel_str_handler *assocs,
+					  size_t nr_assocs)
+{
+	struct perf_evsel *evsel;
+	int err;
+	size_t i;
+
+	for (i = 0; i < nr_assocs; i++) {
+		err = trace_event__id(assocs[i].name);
+		if (err < 0)
+			goto out;
+
+		evsel = perf_evlist__find_tracepoint_by_id(evlist, err);
+		if (evsel == NULL)
+			continue;
+
+		err = -EEXIST;
+		if (evsel->handler.func != NULL)
+			goto out;
+		evsel->handler.func = assocs[i].handler;
+	}
+
+	err = 0;
+out:
+	return err;
+}
+
 void perf_evlist__disable(struct perf_evlist *evlist)
 {
 	int cpu, thread;
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 2202e7b..f94ed7e 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -36,6 +36,11 @@ struct perf_evlist {
 	struct perf_evsel *selected;
 };
 
+struct perf_evsel_str_handler {
+	const char *name;
+	void	   *handler;
+};
+
 struct perf_evsel;
 
 struct perf_evlist *perf_evlist__new(struct cpu_map *cpus,
@@ -51,6 +56,9 @@ int perf_evlist__add_attrs(struct perf_evlist *evlist,
 			   struct perf_event_attr *attrs, size_t nr_attrs);
 int perf_evlist__add_tracepoints(struct perf_evlist *evlist,
 				 const char *tracepoints[], size_t nr_tracepoints);
+int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist,
+					  const struct perf_evsel_str_handler *assocs,
+					  size_t nr_assocs);
 
 #define perf_evlist__add_attrs_array(evlist, array) \
 	perf_evlist__add_attrs(evlist, array, ARRAY_SIZE(array))
@@ -58,6 +66,9 @@ int perf_evlist__add_tracepoints(struct perf_evlist *evlist,
 #define perf_evlist__add_tracepoints_array(evlist, array) \
 	perf_evlist__add_tracepoints(evlist, array, ARRAY_SIZE(array))
 
+#define perf_evlist__set_tracepoints_handlers_array(evlist, array) \
+	perf_evlist__set_tracepoints_handlers(evlist, array, ARRAY_SIZE(array))
+
 void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel,
 			 int cpu, int thread, u64 id);
 
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 6421c07..326b8e4 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -61,6 +61,10 @@ struct perf_evsel {
 		off_t		id_offset;
 	};
 	struct cgroup_sel	*cgrp;
+	struct {
+		void		*func;
+		void		*data;
+	} handler;
 	bool 			supported;
 };
 
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index 89ff1b5..b0e1aad 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -1,8 +1,13 @@
 #ifndef __PERF_TOOL_H
 #define __PERF_TOOL_H
 
+#include <stdbool.h>
+
 struct perf_session;
+union perf_event;
+struct perf_evlist;
 struct perf_evsel;
+struct perf_sample;
 struct perf_tool;
 struct machine;
 
-- 
1.7.8.rc0.35.gee6df


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

* Re: [PATCH 12/25] perf symbols: Add nr_events to symbol_conf
  2011-11-28 23:14 ` [PATCH 12/25] perf symbols: Add nr_events to symbol_conf Arnaldo Carvalho de Melo
@ 2011-11-29  4:44   ` David Ahern
  2011-11-29 11:52     ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 28+ messages in thread
From: David Ahern @ 2011-11-29  4:44 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Ingo Molnar, linux-kernel, Arnaldo Carvalho de Melo,
	Frederic Weisbecker, Mike Galbraith, Paul Mackerras,
	Peter Zijlstra, Stephane Eranian


On 11/28/2011 04:14 PM, Arnaldo Carvalho de Melo wrote:
> From: Arnaldo Carvalho de Melo <acme@redhat.com>
> 
> Since symbol__alloc_hists need it, to avoid passing it around in many
> functions have it in the symbol_conf struct.

I get why you want to do this, but symbol_conf seems to be an odd
choice. This is number of events, not how to resolve or display symbols.

David


> 
> Cc: David Ahern <dsahern@gmail.com>
> Cc: Frederic Weisbecker <fweisbec@gmail.com>
> Cc: Mike Galbraith <efault@gmx.de>
> Cc: Paul Mackerras <paulus@samba.org>
> Cc: Peter Zijlstra <peterz@infradead.org>
> Cc: Stephane Eranian <eranian@google.com>
> Link: http://lkml.kernel.org/n/tip-cwv8ysvpywzjq4v3xtbd4zwv@git.kernel.org
> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
> ---
>  tools/perf/builtin-annotate.c          |   22 ++++++++--------------
>  tools/perf/builtin-report.c            |    3 +--
>  tools/perf/builtin-top.c               |    7 ++++---
>  tools/perf/util/annotate.c             |    6 +++---
>  tools/perf/util/annotate.h             |    5 ++---
>  tools/perf/util/header.c               |    2 ++
>  tools/perf/util/hist.h                 |    3 +--
>  tools/perf/util/symbol.h               |    1 +
>  tools/perf/util/ui/browsers/annotate.c |   16 +++++++---------
>  tools/perf/util/ui/browsers/hists.c    |    2 +-
>  10 files changed, 30 insertions(+), 37 deletions(-)
> 
> diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
> index 46b4c24..8b9091b 100644
> --- a/tools/perf/builtin-annotate.c
> +++ b/tools/perf/builtin-annotate.c
> @@ -43,10 +43,9 @@ static const char *sym_hist_filter;
>  static const char	*cpu_list;
>  static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
>  
> -static int perf_evlist__add_sample(struct perf_evlist *evlist,
> -				   struct perf_sample *sample,
> -				   struct perf_evsel *evsel,
> -				   struct addr_location *al)
> +static int perf_evsel__add_sample(struct perf_evsel *evsel,
> +				  struct perf_sample *sample,
> +				  struct addr_location *al)
>  {
>  	struct hist_entry *he;
>  	int ret;
> @@ -69,8 +68,7 @@ static int perf_evlist__add_sample(struct perf_evlist *evlist,
>  	ret = 0;
>  	if (he->ms.sym != NULL) {
>  		struct annotation *notes = symbol__annotation(he->ms.sym);
> -		if (notes->src == NULL &&
> -		    symbol__alloc_hist(he->ms.sym, evlist->nr_entries) < 0)
> +		if (notes->src == NULL && symbol__alloc_hist(he->ms.sym) < 0)
>  			return -ENOMEM;
>  
>  		ret = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
> @@ -98,8 +96,7 @@ static int process_sample_event(union perf_event *event,
>  	if (cpu_list && !test_bit(sample->cpu, cpu_bitmap))
>  		return 0;
>  
> -	if (!al.filtered &&
> -	    perf_evlist__add_sample(session->evlist, sample, evsel, &al)) {
> +	if (!al.filtered && perf_evsel__add_sample(evsel, sample, &al)) {
>  		pr_warning("problem incrementing symbol count, "
>  			   "skipping event\n");
>  		return -1;
> @@ -114,8 +111,7 @@ static int hist_entry__tty_annotate(struct hist_entry *he, int evidx)
>  				    print_line, full_paths, 0, 0);
>  }
>  
> -static void hists__find_annotations(struct hists *self, int evidx,
> -				    int nr_events)
> +static void hists__find_annotations(struct hists *self, int evidx)
>  {
>  	struct rb_node *nd = rb_first(&self->entries), *next;
>  	int key = K_RIGHT;
> @@ -138,8 +134,7 @@ find_next:
>  		}
>  
>  		if (use_browser > 0) {
> -			key = hist_entry__tui_annotate(he, evidx, nr_events,
> -						       NULL, NULL, 0);
> +			key = hist_entry__tui_annotate(he, evidx, NULL, NULL, 0);
>  			switch (key) {
>  			case K_RIGHT:
>  				next = rb_next(nd);
> @@ -217,8 +212,7 @@ static int __cmd_annotate(void)
>  			total_nr_samples += nr_samples;
>  			hists__collapse_resort(hists);
>  			hists__output_resort(hists);
> -			hists__find_annotations(hists, pos->idx,
> -						session->evlist->nr_entries);
> +			hists__find_annotations(hists, pos->idx);
>  		}
>  	}
>  
> diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
> index 4d7c834..758a287 100644
> --- a/tools/perf/builtin-report.c
> +++ b/tools/perf/builtin-report.c
> @@ -92,8 +92,7 @@ static int perf_session__add_hist_entry(struct perf_session *session,
>  		assert(evsel != NULL);
>  
>  		err = -ENOMEM;
> -		if (notes->src == NULL &&
> -		    symbol__alloc_hist(he->ms.sym, session->evlist->nr_entries) < 0)
> +		if (notes->src == NULL && symbol__alloc_hist(he->ms.sym) < 0)
>  			goto out;
>  
>  		err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
> diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
> index c9cdedb..04288ee 100644
> --- a/tools/perf/builtin-top.c
> +++ b/tools/perf/builtin-top.c
> @@ -170,7 +170,7 @@ static int parse_source(struct hist_entry *he)
>  
>  	pthread_mutex_lock(&notes->lock);
>  
> -	if (symbol__alloc_hist(sym, top.evlist->nr_entries) < 0) {
> +	if (symbol__alloc_hist(sym) < 0) {
>  		pthread_mutex_unlock(&notes->lock);
>  		pr_err("Not enough memory for annotating '%s' symbol!\n",
>  		       sym->name);
> @@ -210,8 +210,7 @@ static void record_precise_ip(struct hist_entry *he, int counter, u64 ip)
>  	if (pthread_mutex_trylock(&notes->lock))
>  		return;
>  
> -	if (notes->src == NULL &&
> -	    symbol__alloc_hist(sym, top.evlist->nr_entries) < 0) {
> +	if (notes->src == NULL && symbol__alloc_hist(sym) < 0) {
>  		pthread_mutex_unlock(&notes->lock);
>  		pr_err("Not enough memory for annotating '%s' symbol!\n",
>  		       sym->name);
> @@ -1215,6 +1214,8 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
>  		return -ENOMEM;
>  	}
>  
> +	symbol_conf.nr_events = top.evlist->nr_entries;
> +
>  	if (top.delay_secs < 1)
>  		top.delay_secs = 1;
>  
> diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
> index 119e996..376e643 100644
> --- a/tools/perf/util/annotate.c
> +++ b/tools/perf/util/annotate.c
> @@ -25,17 +25,17 @@ int symbol__annotate_init(struct map *map __used, struct symbol *sym)
>  	return 0;
>  }
>  
> -int symbol__alloc_hist(struct symbol *sym, int nevents)
> +int symbol__alloc_hist(struct symbol *sym)
>  {
>  	struct annotation *notes = symbol__annotation(sym);
>  	size_t sizeof_sym_hist = (sizeof(struct sym_hist) +
>  				  (sym->end - sym->start) * sizeof(u64));
>  
> -	notes->src = zalloc(sizeof(*notes->src) + nevents * sizeof_sym_hist);
> +	notes->src = zalloc(sizeof(*notes->src) + symbol_conf.nr_events * sizeof_sym_hist);
>  	if (notes->src == NULL)
>  		return -1;
>  	notes->src->sizeof_sym_hist = sizeof_sym_hist;
> -	notes->src->nr_histograms   = nevents;
> +	notes->src->nr_histograms   = symbol_conf.nr_events;
>  	INIT_LIST_HEAD(&notes->src->source);
>  	return 0;
>  }
> diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
> index d907252..efa5dc8 100644
> --- a/tools/perf/util/annotate.h
> +++ b/tools/perf/util/annotate.h
> @@ -72,7 +72,7 @@ static inline struct annotation *symbol__annotation(struct symbol *sym)
>  
>  int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
>  			     int evidx, u64 addr);
> -int symbol__alloc_hist(struct symbol *sym, int nevents);
> +int symbol__alloc_hist(struct symbol *sym);
>  void symbol__annotate_zero_histograms(struct symbol *sym);
>  
>  int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize);
> @@ -99,8 +99,7 @@ static inline int symbol__tui_annotate(struct symbol *sym __used,
>  }
>  #else
>  int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
> -			 int nr_events, void(*timer)(void *arg), void *arg,
> -			 int delay_secs);
> +			 void(*timer)(void *arg), void *arg, int delay_secs);
>  #endif
>  
>  extern const char	*disassembler_style;
> diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
> index bcd05d0..41424a1 100644
> --- a/tools/perf/util/header.c
> +++ b/tools/perf/util/header.c
> @@ -2041,6 +2041,8 @@ int perf_session__read_header(struct perf_session *session, int fd)
>  		lseek(fd, tmp, SEEK_SET);
>  	}
>  
> +	symbol_conf.nr_events = nr_attrs;
> +
>  	if (f_header.event_types.size) {
>  		lseek(fd, f_header.event_types.offset, SEEK_SET);
>  		events = malloc(f_header.event_types.size);
> diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
> index c86c1d2..6676d55 100644
> --- a/tools/perf/util/hist.h
> +++ b/tools/perf/util/hist.h
> @@ -119,7 +119,6 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __used,
>  
>  static inline int hist_entry__tui_annotate(struct hist_entry *self __used,
>  					   int evidx __used,
> -					   int nr_events __used,
>  					   void(*timer)(void *arg) __used,
>  					   void *arg __used,
>  					   int delay_secs __used)
> @@ -130,7 +129,7 @@ static inline int hist_entry__tui_annotate(struct hist_entry *self __used,
>  #define K_RIGHT -2
>  #else
>  #include "ui/keysyms.h"
> -int hist_entry__tui_annotate(struct hist_entry *he, int evidx, int nr_events,
> +int hist_entry__tui_annotate(struct hist_entry *he, int evidx,
>  			     void(*timer)(void *arg), void *arg, int delay_secs);
>  
>  int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
> diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
> index 29f8d74..123c2e1 100644
> --- a/tools/perf/util/symbol.h
> +++ b/tools/perf/util/symbol.h
> @@ -68,6 +68,7 @@ struct strlist;
>  
>  struct symbol_conf {
>  	unsigned short	priv_size;
> +	unsigned short	nr_events;
>  	bool		try_vmlinux_path,
>  			use_modules,
>  			sort_by_name,
> diff --git a/tools/perf/util/ui/browsers/annotate.c b/tools/perf/util/ui/browsers/annotate.c
> index 0575905..295a9c9 100644
> --- a/tools/perf/util/ui/browsers/annotate.c
> +++ b/tools/perf/util/ui/browsers/annotate.c
> @@ -224,7 +224,7 @@ static bool annotate_browser__toggle_source(struct annotate_browser *browser)
>  }
>  
>  static int annotate_browser__run(struct annotate_browser *self, int evidx,
> -				 int nr_events, void(*timer)(void *arg),
> +				 void(*timer)(void *arg),
>  				 void *arg, int delay_secs)
>  {
>  	struct rb_node *nd = NULL;
> @@ -328,8 +328,7 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx,
>  				notes = symbol__annotation(target);
>  				pthread_mutex_lock(&notes->lock);
>  
> -				if (notes->src == NULL &&
> -				    symbol__alloc_hist(target, nr_events) < 0) {
> +				if (notes->src == NULL && symbol__alloc_hist(target) < 0) {
>  					pthread_mutex_unlock(&notes->lock);
>  					ui__warning("Not enough memory for annotating '%s' symbol!\n",
>  						    target->name);
> @@ -337,7 +336,7 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx,
>  				}
>  
>  				pthread_mutex_unlock(&notes->lock);
> -				symbol__tui_annotate(target, ms->map, evidx, nr_events,
> +				symbol__tui_annotate(target, ms->map, evidx,
>  						     timer, arg, delay_secs);
>  			}
>  			continue;
> @@ -358,15 +357,15 @@ out:
>  	return key;
>  }
>  
> -int hist_entry__tui_annotate(struct hist_entry *he, int evidx, int nr_events,
> +int hist_entry__tui_annotate(struct hist_entry *he, int evidx,
>  			     void(*timer)(void *arg), void *arg, int delay_secs)
>  {
> -	return symbol__tui_annotate(he->ms.sym, he->ms.map, evidx, nr_events,
> +	return symbol__tui_annotate(he->ms.sym, he->ms.map, evidx,
>  				    timer, arg, delay_secs);
>  }
>  
>  int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
> -			 int nr_events, void(*timer)(void *arg), void *arg,
> +			 void(*timer)(void *arg), void *arg,
>  			 int delay_secs)
>  {
>  	struct objdump_line *pos, *n;
> @@ -419,8 +418,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
>  	browser.b.nr_entries = browser.nr_entries;
>  	browser.b.entries = &notes->src->source,
>  	browser.b.width += 18; /* Percentage */
> -	ret = annotate_browser__run(&browser, evidx, nr_events,
> -				    timer, arg, delay_secs);
> +	ret = annotate_browser__run(&browser, evidx, timer, arg, delay_secs);
>  	list_for_each_entry_safe(pos, n, &notes->src->source, node) {
>  		list_del(&pos->node);
>  		objdump_line__free(pos);
> diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c
> index d0c94b4..1212a38 100644
> --- a/tools/perf/util/ui/browsers/hists.c
> +++ b/tools/perf/util/ui/browsers/hists.c
> @@ -1020,7 +1020,7 @@ do_annotate:
>  			 * Don't let this be freed, say, by hists__decay_entry.
>  			 */
>  			he->used = true;
> -			err = hist_entry__tui_annotate(he, evsel->idx, nr_events,
> +			err = hist_entry__tui_annotate(he, evsel->idx,
>  						       timer, arg, delay_secs);
>  			he->used = false;
>  			ui_browser__update_nr_entries(&browser->b, browser->hists->nr_entries);

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

* Re: [PATCH 12/25] perf symbols: Add nr_events to symbol_conf
  2011-11-29  4:44   ` David Ahern
@ 2011-11-29 11:52     ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 28+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-11-29 11:52 UTC (permalink / raw)
  To: David Ahern
  Cc: Ingo Molnar, linux-kernel, Frederic Weisbecker, Mike Galbraith,
	Paul Mackerras, Peter Zijlstra, Stephane Eranian

Em Mon, Nov 28, 2011 at 09:44:38PM -0700, David Ahern escreveu:
> On 11/28/2011 04:14 PM, Arnaldo Carvalho de Melo wrote:
> > From: Arnaldo Carvalho de Melo <acme@redhat.com>
> > Since symbol__alloc_hists need it, to avoid passing it around in many
> > functions have it in the symbol_conf struct.
> 
> I get why you want to do this, but symbol_conf seems to be an odd
> choice. This is number of events, not how to resolve or display symbols.

Well, its related to something you do per-symbol, namely annotate how
many hits per ip per event it got in its addr range.

I plan at some point look again at the symbol system to check things
like this, the filter, the need to have a map to load things, but for
now I think we can leave it there.

- Arnaldo

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

end of thread, other threads:[~2011-11-29 11:52 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-11-28 23:14 [GIT PULL 00/25] perf/core fixes and improvements Arnaldo Carvalho de Melo
2011-11-28 23:14 ` [PATCH 01/25] perf tools: Eliminate duplicate code and use PATH_MAX consistently Arnaldo Carvalho de Melo
2011-11-28 23:14 ` [PATCH 02/25] perf tools: Simplify debugfs mountpoint handling code Arnaldo Carvalho de Melo
2011-11-28 23:14 ` [PATCH 03/25] perf evlist: Introduce perf_evlist__add_attrs Arnaldo Carvalho de Melo
2011-11-28 23:14 ` [PATCH 04/25] perf evlist: Introduce add_tracepoints method Arnaldo Carvalho de Melo
2011-11-28 23:14 ` [PATCH 05/25] perf evsel: Introduce config attr method Arnaldo Carvalho de Melo
2011-11-28 23:14 ` [PATCH 06/25] perf evlist: Introduce {prepare,start}_workload refactored from 'perf record' Arnaldo Carvalho de Melo
2011-11-28 23:14 ` [PATCH 07/25] perf evlist: Handle default value for 'pages' on mmap method Arnaldo Carvalho de Melo
2011-11-28 23:14 ` [PATCH 08/25] perf record: Move mmap_pages to perf_record_opts Arnaldo Carvalho de Melo
2011-11-28 23:14 ` [PATCH 09/25] perf session: Move threads to struct machine Arnaldo Carvalho de Melo
2011-11-28 23:14 ` [PATCH 10/25] perf record: Move 'group' to perf_event_ops Arnaldo Carvalho de Melo
2011-11-28 23:14 ` [PATCH 11/25] perf ui progress: Fix divide by zero Arnaldo Carvalho de Melo
2011-11-28 23:14 ` [PATCH 12/25] perf symbols: Add nr_events to symbol_conf Arnaldo Carvalho de Melo
2011-11-29  4:44   ` David Ahern
2011-11-29 11:52     ` Arnaldo Carvalho de Melo
2011-11-28 23:14 ` [PATCH 13/25] perf evlist: Introduce id_hdr_size method out of perf_session Arnaldo Carvalho de Melo
2011-11-28 23:14 ` [PATCH 14/25] perf event: perf_event_ops->attr() manipulates only an evlist Arnaldo Carvalho de Melo
2011-11-28 23:14 ` [PATCH 15/25] perf session: Remove superfluous callchain_cursor member Arnaldo Carvalho de Melo
2011-11-28 23:14 ` [PATCH 16/25] perf tools: Use evsel->attr.sample_type instead of session->sample_type Arnaldo Carvalho de Melo
2011-11-28 23:14 ` [PATCH 17/25] perf report: Group options in a struct Arnaldo Carvalho de Melo
2011-11-28 23:14 ` [PATCH 18/25] perf annotate: " Arnaldo Carvalho de Melo
2011-11-28 23:14 ` [PATCH 19/25] perf tools: Pass tool context in the the perf_event_ops functions Arnaldo Carvalho de Melo
2011-11-28 23:14 ` [PATCH 20/25] perf tools: Resolve machine earlier and pass it to perf_event_ops Arnaldo Carvalho de Melo
2011-11-28 23:14 ` [PATCH 21/25] perf tools: Rename perf_event_ops to perf_tool Arnaldo Carvalho de Melo
2011-11-28 23:14 ` [PATCH 22/25] perf top: Stop using globals for tool state Arnaldo Carvalho de Melo
2011-11-28 23:14 ` [PATCH 23/25] perf tools: make -C consistent across commands (for cpu list arg) Arnaldo Carvalho de Melo
2011-11-28 23:14 ` [PATCH 24/25] perf script: Add comm filtering option Arnaldo Carvalho de Melo
2011-11-28 23:14 ` [PATCH 25/25] perf tools: Save some loops using perf_evlist__id2evsel Arnaldo Carvalho de Melo

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