Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[PATCH 24/32] perf ui: Introduce generic ui_progress helper

18 views
Skip to first unread message

Arnaldo Carvalho de Melo

unread,
Nov 18, 2012, 9:40:02 AM11/18/12
to
From: Namhyung Kim <namhyu...@lge.com>

Make ui_progress functions generic so that UI frontend code will add its
callbacks.

Signed-off-by: Namhyung Kim <namh...@kernel.org>
Cc: Ingo Molnar <mi...@kernel.org>
Cc: Pekka Enberg <pen...@kernel.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Link: http://lkml.kernel.org/r/1352813436-14173-2-gi...@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/Makefile | 1 +
tools/perf/ui/gtk/util.c | 11 -----------
tools/perf/ui/progress.c | 20 ++++++++++++++++++++
tools/perf/ui/progress.h | 8 ++++++++
tools/perf/ui/tui/progress.c | 12 +++++++++++-
tools/perf/ui/tui/setup.c | 1 +
6 files changed, 41 insertions(+), 12 deletions(-)
create mode 100644 tools/perf/ui/progress.c

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 50e85c8..f8466b4 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -423,6 +423,7 @@ LIB_OBJS += $(OUTPUT)util/vdso.o
LIB_OBJS += $(OUTPUT)util/stat.o

LIB_OBJS += $(OUTPUT)ui/helpline.o
+LIB_OBJS += $(OUTPUT)ui/progress.o
LIB_OBJS += $(OUTPUT)ui/hist.o
LIB_OBJS += $(OUTPUT)ui/stdio/hist.o

diff --git a/tools/perf/ui/gtk/util.c b/tools/perf/ui/gtk/util.c
index ccb046a..c06942a 100644
--- a/tools/perf/ui/gtk/util.c
+++ b/tools/perf/ui/gtk/util.c
@@ -111,14 +111,3 @@ struct perf_error_ops perf_gtk_eops = {
.warning = perf_gtk__warning_statusbar,
#endif
};
-
-/*
- * FIXME: Functions below should be implemented properly.
- * For now, just add stubs for NO_NEWT=1 build.
- */
-#ifndef NEWT_SUPPORT
-void ui_progress__update(u64 curr __maybe_unused, u64 total __maybe_unused,
- const char *title __maybe_unused)
-{
-}
-#endif
diff --git a/tools/perf/ui/progress.c b/tools/perf/ui/progress.c
new file mode 100644
index 0000000..f5e4d1b
--- /dev/null
+++ b/tools/perf/ui/progress.c
@@ -0,0 +1,20 @@
+#include "../cache.h"
+#include "progress.h"
+
+static void nop_progress_update(u64 curr __maybe_unused,
+ u64 total __maybe_unused,
+ const char *title __maybe_unused)
+{
+}
+
+static struct ui_progress default_progress_fns =
+{
+ .update = nop_progress_update,
+};
+
+struct ui_progress *progress_fns = &default_progress_fns;
+
+void ui_progress__update(u64 curr, u64 total, const char *title)
+{
+ return progress_fns->update(curr, total, title);
+}
diff --git a/tools/perf/ui/progress.h b/tools/perf/ui/progress.h
index d9c205b..717814b 100644
--- a/tools/perf/ui/progress.h
+++ b/tools/perf/ui/progress.h
@@ -3,6 +3,14 @@

#include <../types.h>

+struct ui_progress {
+ void (*update)(u64, u64, const char *);
+};
+
+extern struct ui_progress *progress_fns;
+
+void ui_progress__init(void);
+
void ui_progress__update(u64 curr, u64 total, const char *title);

#endif
diff --git a/tools/perf/ui/tui/progress.c b/tools/perf/ui/tui/progress.c
index f8dc986..6c2184d 100644
--- a/tools/perf/ui/tui/progress.c
+++ b/tools/perf/ui/tui/progress.c
@@ -4,7 +4,7 @@
#include "../ui.h"
#include "../browser.h"

-void ui_progress__update(u64 curr, u64 total, const char *title)
+static void tui_progress__update(u64 curr, u64 total, const char *title)
{
int bar, y;
/*
@@ -30,3 +30,13 @@ void ui_progress__update(u64 curr, u64 total, const char *title)
SLsmg_refresh();
pthread_mutex_unlock(&ui__lock);
}
+
+static struct ui_progress tui_progress_fns =
+{
+ .update = tui_progress__update,
+};
+
+void ui_progress__init(void)
+{
+ progress_fns = &tui_progress_fns;
+}
diff --git a/tools/perf/ui/tui/setup.c b/tools/perf/ui/tui/setup.c
index 60debb8..81efa19 100644
--- a/tools/perf/ui/tui/setup.c
+++ b/tools/perf/ui/tui/setup.c
@@ -118,6 +118,7 @@ int ui__init(void)
newtSetSuspendCallback(newt_suspend, NULL);
ui_helpline__init();
ui_browser__init();
+ ui_progress__init();

signal(SIGSEGV, ui__signal);
signal(SIGFPE, ui__signal);
--
1.7.9.2.358.g22243

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

Arnaldo Carvalho de Melo

unread,
Nov 18, 2012, 9:40:02 AM11/18/12
to
From: Jiri Olsa <jo...@redhat.com>

Final function renames to match test__* style and include cleanup.

Signed-off-by: Jiri Olsa <jo...@redhat.com>
Cc: Corey Ashford <cjas...@linux.vnet.ibm.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Ingo Molnar <mi...@elte.hu>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Link: http://lkml.kernel.org/r/1352508412-16914-12-...@redhat.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/perf.h | 1 -
tools/perf/tests/attr.c | 3 ++-
tools/perf/tests/builtin-test.c | 34 +++++++---------------------------
tools/perf/tests/dso-data.c | 3 ++-
tools/perf/tests/parse-events.c | 3 ++-
tools/perf/tests/tests.h | 3 +++
tools/perf/util/parse-events.h | 1 -
tools/perf/util/symbol.h | 1 -
8 files changed, 16 insertions(+), 33 deletions(-)

diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 054182e..0047264 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -178,7 +178,6 @@ extern bool test_attr__enabled;
void test_attr__init(void);
void test_attr__open(struct perf_event_attr *attr, pid_t pid, int cpu,
int fd, int group_fd, unsigned long flags);
-int test_attr__run(void);

static inline int
sys_perf_event_open(struct perf_event_attr *attr,
diff --git a/tools/perf/tests/attr.c b/tools/perf/tests/attr.c
index 6e2feee..25638a9 100644
--- a/tools/perf/tests/attr.c
+++ b/tools/perf/tests/attr.c
@@ -27,6 +27,7 @@
#include "../perf.h"
#include "util.h"
#include "exec_cmd.h"
+#include "tests.h"

#define ENV "PERF_TEST_ATTR"

@@ -151,7 +152,7 @@ static int run_dir(const char *d, const char *perf)
return system(cmd);
}

-int test_attr__run(void)
+int test__attr(void)
{
struct stat st;
char path_perf[PATH_MAX];
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index d3b95e0..186f675 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -4,31 +4,11 @@
* Builtin regression testing command: ever growing number of sanity tests
*/
#include "builtin.h"
-
-#include "util/cache.h"
-#include "util/color.h"
-#include "util/debug.h"
-#include "util/debugfs.h"
-#include "util/evlist.h"
-#include "util/machine.h"
-#include "util/parse-options.h"
-#include "util/parse-events.h"
-#include "util/symbol.h"
-#include "util/thread_map.h"
-#include "util/pmu.h"
-#include "event-parse.h"
-#include "../../include/linux/hw_breakpoint.h"
-
-#include <sys/mman.h>
-
-#include "util/cpumap.h"
-#include "util/evsel.h"
-#include <sys/types.h>
-
#include "tests.h"
-
-#include <sched.h>
-
+#include "debug.h"
+#include "color.h"
+#include "parse-options.h"
+#include "symbol.h"

static struct test {
const char *desc;
@@ -52,7 +32,7 @@ static struct test {
},
{
.desc = "parse events tests",
- .func = parse_events__test,
+ .func = test__parse_events,
},
#if defined(__x86_64__) || defined(__i386__)
{
@@ -70,7 +50,7 @@ static struct test {
},
{
.desc = "Test dso data interface",
- .func = dso__test_data,
+ .func = test__dso_data,
},
{
.desc = "roundtrip evsel->name check",
@@ -86,7 +66,7 @@ static struct test {
},
{
.desc = "struct perf_event_attr setup",
- .func = test_attr__run,
+ .func = test__attr,
},
{
.func = NULL,
diff --git a/tools/perf/tests/dso-data.c b/tools/perf/tests/dso-data.c
index 0cd42fc..b5198f5 100644
--- a/tools/perf/tests/dso-data.c
+++ b/tools/perf/tests/dso-data.c
@@ -8,6 +8,7 @@

#include "machine.h"
#include "symbol.h"
+#include "tests.h"

#define TEST_ASSERT_VAL(text, cond) \
do { \
@@ -95,7 +96,7 @@ struct test_data_offset offsets[] = {
},
};

-int dso__test_data(void)
+int test__dso_data(void)
{
struct machine machine;
struct dso *dso;
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c
index b49c2ee..f2a82d0 100644
--- a/tools/perf/tests/parse-events.c
+++ b/tools/perf/tests/parse-events.c
@@ -4,6 +4,7 @@
#include "evlist.h"
#include "sysfs.h"
#include "../../../include/linux/hw_breakpoint.h"
+#include "tests.h"

#define TEST_ASSERT_VAL(text, cond) \
do { \
@@ -1086,7 +1087,7 @@ static int test_pmu_events(void)
return ret;
}

-int parse_events__test(void)
+int test__parse_events(void)
{
int ret1, ret2 = 0;

diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 88a55df..fc121ed 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -12,6 +12,9 @@ int test__perf_evsel__roundtrip_name_test(void);
int test__perf_evsel__tp_sched_test(void);
int test__syscall_open_tp_fields(void);
int test__pmu(void);
+int test__attr(void);
+int test__dso_data(void);
+int test__parse_events(void);

/* Util */
int trace_event__id(const char *evname);
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index ac9a6aa..f639937 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -99,7 +99,6 @@ void parse_events__set_leader(char *name, struct list_head *list);
void parse_events_update_lists(struct list_head *list_event,
struct list_head *list_all);
void parse_events_error(void *data, void *scanner, char const *msg);
-int parse_events__test(void);

void print_events(const char *event_glob, bool name_only);
void print_events_type(u8 type);
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 04ccf29..de68f98 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -224,7 +224,6 @@ size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp);
size_t symbol__fprintf(struct symbol *sym, FILE *fp);
bool symbol_type__is_a(char symbol_type, enum map_type map_type);

-int dso__test_data(void);
int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
struct symsrc *runtime_ss, symbol_filter_t filter,
int kmodule);

Arnaldo Carvalho de Melo

unread,
Nov 18, 2012, 9:40:02 AM11/18/12
to
From: David Howells <dhow...@redhat.com>

Honour the O= flag that was passed to a higher level Makefile and then passed
down as part of a tool build.

To make this work, the top-level Makefile passes the original O= flag and
subdir=tools to the tools/Makefile, and that in turn passes
subdir=$(O)/$(subdir)/foodir when building tool foo in directory
$(O)/$(subdir)/foodir (where the intervening slashes aren't added if an
element is missing).

For example, take perf. This is found in tools/perf/. Assume we're building
into directory ~/zebra/, so we pass O=~/zebra to make. Dependening on where
we run the build from, we see:

make run in dir $(OUTPUT) dir
======================= ==================
linux ~/zebra/tools/perf/
linux/tools ~/zebra/perf/
linux/tools/perf ~/zebra/

and if O= is not set, we get:

make run in dir $(OUTPUT) dir
======================= ==================
linux linux/tools/perf/
linux/tools linux/tools/perf/
linux/tools/perf linux/tools/perf/

The output directories are created by the descend function if they don't
already exist.

Signed-off-by: David Howells <dhow...@redhat.com>
Cc: Borislav Petkov <b...@amd64.org>
Cc: Ingo Molnar <mi...@kernel.org>
Cc: Linus Torvalds <torv...@linux-foundation.org>
Cc: Namhyung Kim <namh...@gmail.com>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Thomas Gleixner <tg...@linutronix.de>
Link: http://lkml.kernel.org/r/1378.13...@warthog.procyon.org.uk
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
Makefile | 6 ++++--
tools/scripts/Makefile.include | 17 +++++++++++++----
2 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/Makefile b/Makefile
index 14c93b3..08a31d8 100644
--- a/Makefile
+++ b/Makefile
@@ -1321,10 +1321,12 @@ kernelversion:

# Clear a bunch of variables before executing the submake
tools/: FORCE
- $(Q)$(MAKE) LDFLAGS= MAKEFLAGS= -C $(src)/tools/
+ $(Q)mkdir -p $(objtree)/tools
+ $(Q)$(MAKE) LDFLAGS= MAKEFLAGS= O=$(objtree) subdir=tools -C $(src)/tools/

tools/%: FORCE
- $(Q)$(MAKE) LDFLAGS= MAKEFLAGS= -C $(src)/tools/ $*
+ $(Q)mkdir -p $(objtree)/tools
+ $(Q)$(MAKE) LDFLAGS= MAKEFLAGS= O=$(objtree) subdir=tools -C $(src)/tools/ $*

# Single targets
# ---------------------------------------------------------------------------
diff --git a/tools/scripts/Makefile.include b/tools/scripts/Makefile.include
index 4a9e317..87467b1 100644
--- a/tools/scripts/Makefile.include
+++ b/tools/scripts/Makefile.include
@@ -1,8 +1,11 @@
-ifeq ("$(origin O)", "command line")
+ifeq ($(origin O), command line)
dummy := $(if $(shell test -d $(O) || echo $(O)),$(error O=$(O) does not exist),)
ABSOLUTE_O := $(shell cd $(O) ; pwd)
- OUTPUT := $(ABSOLUTE_O)/
+ OUTPUT := $(ABSOLUTE_O)/$(if $(subdir),$(subdir)/)
COMMAND_O := O=$(ABSOLUTE_O)
+ifeq ($(objtree),)
+ objtree := $(O)
+endif
endif

ifneq ($(OUTPUT),)
@@ -47,9 +50,10 @@ endif
# Call by doing: $(call descend,directory[,target])
#
descend = \
- $(QUIET_SUBDIR0)$(1) $(QUIET_SUBDIR1) $(2)
+ +mkdir -p $(OUTPUT)$(1) && \
+ $(MAKE) $(COMMAND_O) subdir=$(if $(subdir),$(subdir)/$(1),$(1)) $(PRINT_DIR) -C $(1)

-QUIET_SUBDIR0 = +$(MAKE) -C # space to separate -C and subdir
+QUIET_SUBDIR0 = +$(MAKE) $(COMMAND_O) -C # space to separate -C and subdir
QUIET_SUBDIR1 =

ifneq ($(findstring $(MAKEFLAGS),s),s)
@@ -64,5 +68,10 @@ ifndef V
$(MAKE) $(PRINT_DIR) -C $$subdir
QUIET_FLEX = @echo ' ' FLEX $@;
QUIET_BISON = @echo ' ' BISON $@;
+
+ descend = \
+ @echo ' ' DESCEND $(1); \
+ mkdir -p $(OUTPUT)$(1) && \
+ $(MAKE) $(COMMAND_O) subdir=$(if $(subdir),$(subdir)/$(1),$(1)) $(PRINT_DIR) -C $(1)
endif
endif

Arnaldo Carvalho de Melo

unread,
Nov 18, 2012, 9:40:02 AM11/18/12
to
From: Namhyung Kim <namhyu...@lge.com>

We now have proper fallback logic, so always build it regardless of TUI
or GTK setting.

Signed-off-by: Namhyung Kim <namh...@kernel.org>
Cc: Ingo Molnar <mi...@kernel.org>
Cc: Pekka Enberg <pen...@kernel.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Link: http://lkml.kernel.org/r/1352813436-14173-5-gi...@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/Makefile | 3 +--
tools/perf/ui/ui.h | 28 ++++++++++++++++++++++++++++
tools/perf/util/cache.h | 39 +--------------------------------------
3 files changed, 30 insertions(+), 40 deletions(-)

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 5a9075e..a7c6aa8 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -422,6 +422,7 @@ LIB_OBJS += $(OUTPUT)util/intlist.o
LIB_OBJS += $(OUTPUT)util/vdso.o
LIB_OBJS += $(OUTPUT)util/stat.o

+LIB_OBJS += $(OUTPUT)ui/setup.o
LIB_OBJS += $(OUTPUT)ui/helpline.o
LIB_OBJS += $(OUTPUT)ui/progress.o
LIB_OBJS += $(OUTPUT)ui/hist.o
@@ -612,7 +613,6 @@ ifndef NO_NEWT
BASIC_CFLAGS += -I/usr/include/slang
BASIC_CFLAGS += -DNEWT_SUPPORT
EXTLIBS += -lnewt -lslang
- LIB_OBJS += $(OUTPUT)ui/setup.o
LIB_OBJS += $(OUTPUT)ui/browser.o
LIB_OBJS += $(OUTPUT)ui/browsers/annotate.o
LIB_OBJS += $(OUTPUT)ui/browsers/hists.o
@@ -651,7 +651,6 @@ ifndef NO_GTK2
LIB_OBJS += $(OUTPUT)ui/gtk/progress.o
# Make sure that it'd be included only once.
ifeq ($(findstring -DNEWT_SUPPORT,$(BASIC_CFLAGS)),)
- LIB_OBJS += $(OUTPUT)ui/setup.o
LIB_OBJS += $(OUTPUT)ui/util.o
endif
endif
diff --git a/tools/perf/ui/ui.h b/tools/perf/ui/ui.h
index 7b67045..d86359c 100644
--- a/tools/perf/ui/ui.h
+++ b/tools/perf/ui/ui.h
@@ -3,9 +3,37 @@

#include <pthread.h>
#include <stdbool.h>
+#include <linux/compiler.h>

extern pthread_mutex_t ui__lock;

+extern int use_browser;
+
+void setup_browser(bool fallback_to_pager);
+void exit_browser(bool wait_for_ok);
+
+#ifdef NEWT_SUPPORT
+int ui__init(void);
+void ui__exit(bool wait_for_ok);
+#else
+static inline int ui__init(void)
+{
+ return -1;
+}
+static inline void ui__exit(bool wait_for_ok __maybe_unused) {}
+#endif
+
+#ifdef GTK2_SUPPORT
+int perf_gtk__init(void);
+void perf_gtk__exit(bool wait_for_ok);
+#else
+static inline int perf_gtk__init(void)
+{
+ return -1;
+}
+static inline void perf_gtk__exit(bool wait_for_ok __maybe_unused) {}
+#endif
+
void ui__refresh_dimensions(bool force);

#endif /* _PERF_UI_H_ */
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index 2bd5137..26e3672 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -5,6 +5,7 @@
#include "util.h"
#include "strbuf.h"
#include "../perf.h"
+#include "../ui/ui.h"

#define CMD_EXEC_PATH "--exec-path"
#define CMD_PERF_DIR "--perf-dir="
@@ -31,44 +32,6 @@ extern const char *pager_program;
extern int pager_in_use(void);
extern int pager_use_color;

-extern int use_browser;
-
-#if defined(NEWT_SUPPORT) || defined(GTK2_SUPPORT)
-void setup_browser(bool fallback_to_pager);
-void exit_browser(bool wait_for_ok);
-
-#ifdef NEWT_SUPPORT
-int ui__init(void);
-void ui__exit(bool wait_for_ok);
-#else
-static inline int ui__init(void)
-{
- return -1;
-}
-static inline void ui__exit(bool wait_for_ok __maybe_unused) {}
-#endif
-
-#ifdef GTK2_SUPPORT
-int perf_gtk__init(void);
-void perf_gtk__exit(bool wait_for_ok);
-#else
-static inline int perf_gtk__init(void)
-{
- return -1;
-}
-static inline void perf_gtk__exit(bool wait_for_ok __maybe_unused) {}
-#endif
-
-#else /* NEWT_SUPPORT || GTK2_SUPPORT */
-
-static inline void setup_browser(bool fallback_to_pager)
-{
- if (fallback_to_pager)
- setup_pager();
-}
-static inline void exit_browser(bool wait_for_ok __maybe_unused) {}
-#endif /* NEWT_SUPPORT || GTK2_SUPPORT */
-
char *alias_lookup(const char *alias);
int split_cmdline(char *cmdline, const char ***argv);

Arnaldo Carvalho de Melo

unread,
Nov 18, 2012, 9:40:02 AM11/18/12
to
From: Jiri Olsa <jo...@redhat.com>

Adding check for mkstemp return error value in dso-data test.

Reported-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
Signed-off-by: Jiri Olsa <jo...@redhat.com>
Cc: Corey Ashford <cjas...@linux.vnet.ibm.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Ingo Molnar <mi...@elte.hu>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Link: http://lkml.kernel.org/r/1352508412-16914-13-...@redhat.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/tests/dso-data.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/tools/perf/tests/dso-data.c b/tools/perf/tests/dso-data.c
index b5198f5..5eaffa2 100644
--- a/tools/perf/tests/dso-data.c
+++ b/tools/perf/tests/dso-data.c
@@ -26,6 +26,10 @@ static char *test_file(int size)
unsigned char *buf;

fd = mkstemp(templ);
+ if (fd < 0) {
+ perror("mkstemp failed");
+ return NULL;
+ }

buf = malloc(size);
if (!buf) {

Arnaldo Carvalho de Melo

unread,
Nov 18, 2012, 9:40:02 AM11/18/12
to
From: Namhyung Kim <namh...@kernel.org>

When reading those files to synthesize MMAP events. It makes the code
shorter and cleaner.

Signed-off-by: Namhyung Kim <namh...@kernel.org>
Cc: Ingo Molnar <mi...@kernel.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Stephane Eranian <era...@google.com>
Link: http://lkml.kernel.org/r/1352643651-13891-1-gi...@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/event.c | 74 ++++++++++++++++++++---------------------------
1 file changed, 31 insertions(+), 43 deletions(-)

diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index ca9ca28..3cf2c3e 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -193,55 +193,43 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
event->header.misc = PERF_RECORD_MISC_USER;

while (1) {
- char bf[BUFSIZ], *pbf = bf;
- int n;
+ char bf[BUFSIZ];
+ char prot[5];
+ char execname[PATH_MAX];
+ char anonstr[] = "//anon";
size_t size;
+
if (fgets(bf, sizeof(bf), fp) == NULL)
break;

+ /* ensure null termination since stack will be reused. */
+ strcpy(execname, "");
+
/* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */
- n = hex2u64(pbf, &event->mmap.start);
- if (n < 0)
- continue;
- pbf += n + 1;
- n = hex2u64(pbf, &event->mmap.len);
- if (n < 0)
+ sscanf(bf, "%"PRIx64"-%"PRIx64" %s %"PRIx64" %*x:%*x %*u %s\n",
+ &event->mmap.start, &event->mmap.len, prot,
+ &event->mmap.pgoff, execname);
+
+ if (prot[2] != 'x')
continue;
- pbf += n + 3;
- if (*pbf == 'x') { /* vm_exec */
- char anonstr[] = "//anon\n";
- char *execname = strchr(bf, '/');
-
- /* Catch VDSO */
- if (execname == NULL)
- execname = strstr(bf, "[vdso]");
-
- /* Catch anonymous mmaps */
- if ((execname == NULL) && !strstr(bf, "["))
- execname = anonstr;
-
- if (execname == NULL)
- continue;
-
- pbf += 3;
- n = hex2u64(pbf, &event->mmap.pgoff);
-
- size = strlen(execname);
- execname[size - 1] = '\0'; /* Remove \n */
- memcpy(event->mmap.filename, execname, size);
- size = PERF_ALIGN(size, sizeof(u64));
- event->mmap.len -= event->mmap.start;
- event->mmap.header.size = (sizeof(event->mmap) -
- (sizeof(event->mmap.filename) - 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;
-
- if (process(tool, event, &synth_sample, machine) != 0) {
- rc = -1;
- break;
- }
+
+ if (!strcmp(execname, ""))
+ strcpy(execname, anonstr);
+
+ size = strlen(execname) + 1;
+ memcpy(event->mmap.filename, execname, size);
+ size = PERF_ALIGN(size, sizeof(u64));
+ event->mmap.len -= event->mmap.start;
+ event->mmap.header.size = (sizeof(event->mmap) -
+ (sizeof(event->mmap.filename) - 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;
+
+ if (process(tool, event, &synth_sample, machine) != 0) {
+ rc = -1;
+ break;

Arnaldo Carvalho de Melo

unread,
Nov 18, 2012, 9:40:02 AM11/18/12
to
From: Namhyung Kim <namhyu...@lge.com>

Sometimes we need to know when the progress bar should disappear.

Checking curr >= total wasn't enough since there're cases not met that
condition for the last call.

So add a new ->finish callback to identify this explicitly. Currently
only GTK frontend needs it.

Signed-off-by: Namhyung Kim <namh...@kernel.org>
Cc: Ingo Molnar <mi...@kernel.org>
Cc: Pekka Enberg <pen...@kernel.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Link: http://lkml.kernel.org/r/1352813436-14173-4-gi...@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/ui/gtk/progress.c | 9 +++++++++
tools/perf/ui/progress.c | 6 ++++++
tools/perf/ui/progress.h | 2 ++
tools/perf/util/debug.h | 1 +
tools/perf/util/session.c | 1 +
5 files changed, 19 insertions(+)

diff --git a/tools/perf/ui/gtk/progress.c b/tools/perf/ui/gtk/progress.c
index 903426f..482bcf3 100644
--- a/tools/perf/ui/gtk/progress.c
+++ b/tools/perf/ui/gtk/progress.c
@@ -40,8 +40,17 @@ static void gtk_progress_update(u64 curr, u64 total, const char *title)
gtk_main_iteration();
}

+static void gtk_progress_finish(void)
+{
+ /* this will also destroy all of its children */
+ gtk_widget_destroy(dialog);
+
+ dialog = NULL;
+}
+
static struct ui_progress gtk_progress_fns = {
.update = gtk_progress_update,
+ .finish = gtk_progress_finish,
};

void perf_gtk__init_progress(void)
diff --git a/tools/perf/ui/progress.c b/tools/perf/ui/progress.c
index f5e4d1b..3ec69560 100644
--- a/tools/perf/ui/progress.c
+++ b/tools/perf/ui/progress.c
@@ -18,3 +18,9 @@ void ui_progress__update(u64 curr, u64 total, const char *title)
{
return progress_fns->update(curr, total, title);
}
+
+void ui_progress__finish(void)
+{
+ if (progress_fns->finish)
+ progress_fns->finish();
+}
diff --git a/tools/perf/ui/progress.h b/tools/perf/ui/progress.h
index 717814b..257cc22 100644
--- a/tools/perf/ui/progress.h
+++ b/tools/perf/ui/progress.h
@@ -5,6 +5,7 @@

struct ui_progress {
void (*update)(u64, u64, const char *);
+ void (*finish)(void);
};

extern struct ui_progress *progress_fns;
@@ -12,5 +13,6 @@ extern struct ui_progress *progress_fns;
void ui_progress__init(void);

void ui_progress__update(u64 curr, u64 total, const char *title);
+void ui_progress__finish(void);

#endif
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index dec9875..83e8d23 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -26,6 +26,7 @@ int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2)));
static inline void ui_progress__update(u64 curr __maybe_unused,
u64 total __maybe_unused,
const char *title __maybe_unused) {}
+static inline void ui_progress__finish(void) {}

#define ui__error(format, arg...) ui__warning(format, ##arg)

diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 15abe40..ce6f511 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1458,6 +1458,7 @@ more:
session->ordered_samples.next_flush = ULLONG_MAX;
err = flush_sample_queue(session, tool);
out_err:
+ ui_progress__finish();
perf_session__warn_about_errors(session, tool);
perf_session_free_sample_buffers(session);
return err;

Arnaldo Carvalho de Melo

unread,
Nov 18, 2012, 9:40:02 AM11/18/12
to
From: Jiri Olsa <jo...@redhat.com>

Separating perf_evsel__roundtrip_name_test test from the builtin-test
into evsel-roundtrip-name object.

Signed-off-by: Jiri Olsa <jo...@redhat.com>
Cc: Corey Ashford <cjas...@linux.vnet.ibm.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Ingo Molnar <mi...@elte.hu>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Link: http://lkml.kernel.org/r/1352508412-16914-8-...@redhat.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/Makefile | 1 +
tools/perf/tests/builtin-test.c | 112 +-----------------------------
tools/perf/tests/evsel-roundtrip-name.c | 114 +++++++++++++++++++++++++++++++
tools/perf/tests/tests.h | 1 +
4 files changed, 117 insertions(+), 111 deletions(-)
create mode 100644 tools/perf/tests/evsel-roundtrip-name.c

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 2e5197a..ad6fcb5 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -437,6 +437,7 @@ LIB_OBJS += $(OUTPUT)tests/open-syscall-all-cpus.o
LIB_OBJS += $(OUTPUT)tests/mmap-basic.o
LIB_OBJS += $(OUTPUT)tests/perf-record.o
LIB_OBJS += $(OUTPUT)tests/rdpmc.o
+LIB_OBJS += $(OUTPUT)tests/evsel-roundtrip-name.o
LIB_OBJS += $(OUTPUT)tests/util.o

BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 1e9a0ea..93f5e91 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -35,116 +35,6 @@ static int test__perf_pmu(void)
return perf_pmu__test();
}

-static int perf_evsel__roundtrip_cache_name_test(void)
-{
- char name[128];
- int type, op, err = 0, ret = 0, i, idx;
- struct perf_evsel *evsel;
- struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
-
- if (evlist == NULL)
- return -ENOMEM;
-
- for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
- for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
- /* skip invalid cache type */
- if (!perf_evsel__is_cache_op_valid(type, op))
- continue;
-
- for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
- __perf_evsel__hw_cache_type_op_res_name(type, op, i,
- name, sizeof(name));
- err = parse_events(evlist, name, 0);
- if (err)
- ret = err;
- }
- }
- }
-
- idx = 0;
- evsel = perf_evlist__first(evlist);
-
- for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
- for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
- /* skip invalid cache type */
- if (!perf_evsel__is_cache_op_valid(type, op))
- continue;
-
- for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
- __perf_evsel__hw_cache_type_op_res_name(type, op, i,
- name, sizeof(name));
- if (evsel->idx != idx)
- continue;
-
- ++idx;
-
- if (strcmp(perf_evsel__name(evsel), name)) {
- pr_debug("%s != %s\n", perf_evsel__name(evsel), name);
- ret = -1;
- }
-
- evsel = perf_evsel__next(evsel);
- }
- }
- }
-
- perf_evlist__delete(evlist);
- return ret;
-}
-
-static int __perf_evsel__name_array_test(const char *names[], int nr_names)
-{
- int i, err;
- struct perf_evsel *evsel;
- struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
-
- if (evlist == NULL)
- return -ENOMEM;
-
- for (i = 0; i < nr_names; ++i) {
- err = parse_events(evlist, names[i], 0);
- if (err) {
- pr_debug("failed to parse event '%s', err %d\n",
- names[i], err);
- goto out_delete_evlist;
- }
- }
-
- err = 0;
- list_for_each_entry(evsel, &evlist->entries, node) {
- if (strcmp(perf_evsel__name(evsel), names[evsel->idx])) {
- --err;
- pr_debug("%s != %s\n", perf_evsel__name(evsel), names[evsel->idx]);
- }
- }
-
-out_delete_evlist:
- perf_evlist__delete(evlist);
- return err;
-}
-
-#define perf_evsel__name_array_test(names) \
- __perf_evsel__name_array_test(names, ARRAY_SIZE(names))
-
-static int perf_evsel__roundtrip_name_test(void)
-{
- int err = 0, ret = 0;
-
- err = perf_evsel__name_array_test(perf_evsel__hw_names);
- if (err)
- ret = err;
-
- err = perf_evsel__name_array_test(perf_evsel__sw_names);
- if (err)
- ret = err;
-
- err = perf_evsel__roundtrip_cache_name_test();
- if (err)
- ret = err;
-
- return ret;
-}
-
static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name,
int size, bool should_be_signed)
{
@@ -382,7 +272,7 @@ static struct test {
},
{
.desc = "roundtrip evsel->name check",
- .func = perf_evsel__roundtrip_name_test,
+ .func = test__perf_evsel__roundtrip_name_test,
},
{
.desc = "Check parsing of sched tracepoints fields",
diff --git a/tools/perf/tests/evsel-roundtrip-name.c b/tools/perf/tests/evsel-roundtrip-name.c
new file mode 100644
index 0000000..e61fc82
--- /dev/null
+++ b/tools/perf/tests/evsel-roundtrip-name.c
@@ -0,0 +1,114 @@
+#include "evlist.h"
+#include "evsel.h"
+#include "parse-events.h"
+#include "tests.h"
+
+static int perf_evsel__roundtrip_cache_name_test(void)
+{
+ char name[128];
+ int type, op, err = 0, ret = 0, i, idx;
+ struct perf_evsel *evsel;
+ struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
+
+ if (evlist == NULL)
+ return -ENOMEM;
+
+ for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
+ for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
+ /* skip invalid cache type */
+ if (!perf_evsel__is_cache_op_valid(type, op))
+ continue;
+
+ for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
+ __perf_evsel__hw_cache_type_op_res_name(type, op, i,
+ name, sizeof(name));
+ err = parse_events(evlist, name, 0);
+ if (err)
+ ret = err;
+ }
+ }
+ }
+
+ idx = 0;
+ evsel = perf_evlist__first(evlist);
+
+ for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
+ for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
+ /* skip invalid cache type */
+ if (!perf_evsel__is_cache_op_valid(type, op))
+ continue;
+
+ for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
+ __perf_evsel__hw_cache_type_op_res_name(type, op, i,
+ name, sizeof(name));
+ if (evsel->idx != idx)
+ continue;
+
+ ++idx;
+
+ if (strcmp(perf_evsel__name(evsel), name)) {
+ pr_debug("%s != %s\n", perf_evsel__name(evsel), name);
+ ret = -1;
+ }
+
+ evsel = perf_evsel__next(evsel);
+ }
+ }
+ }
+
+ perf_evlist__delete(evlist);
+ return ret;
+}
+
+static int __perf_evsel__name_array_test(const char *names[], int nr_names)
+{
+ int i, err;
+ struct perf_evsel *evsel;
+ struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
+
+ if (evlist == NULL)
+ return -ENOMEM;
+
+ for (i = 0; i < nr_names; ++i) {
+ err = parse_events(evlist, names[i], 0);
+ if (err) {
+ pr_debug("failed to parse event '%s', err %d\n",
+ names[i], err);
+ goto out_delete_evlist;
+ }
+ }
+
+ err = 0;
+ list_for_each_entry(evsel, &evlist->entries, node) {
+ if (strcmp(perf_evsel__name(evsel), names[evsel->idx])) {
+ --err;
+ pr_debug("%s != %s\n", perf_evsel__name(evsel), names[evsel->idx]);
+ }
+ }
+
+out_delete_evlist:
+ perf_evlist__delete(evlist);
+ return err;
+}
+
+#define perf_evsel__name_array_test(names) \
+ __perf_evsel__name_array_test(names, ARRAY_SIZE(names))
+
+int test__perf_evsel__roundtrip_name_test(void)
+{
+ int err = 0, ret = 0;
+
+ err = perf_evsel__name_array_test(perf_evsel__hw_names);
+ if (err)
+ ret = err;
+
+ err = perf_evsel__name_array_test(perf_evsel__sw_names);
+ if (err)
+ ret = err;
+
+ err = perf_evsel__roundtrip_cache_name_test();
+ if (err)
+ ret = err;
+
+ return ret;
+}
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 03d428d..5897dd1 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -8,6 +8,7 @@ int test__open_syscall_event_on_all_cpus(void);
int test__basic_mmap(void);
int test__PERF_RECORD(void);
int test__rdpmc(void);
+int test__perf_evsel__roundtrip_name_test(void);

/* Util */
int trace_event__id(const char *evname);

Arnaldo Carvalho de Melo

unread,
Nov 18, 2012, 9:40:03 AM11/18/12
to
From: Jiri Olsa <jo...@redhat.com>

It's possible we issue the event disable ioctl multiple times until we
read the final portion of the mmap buffer.

Ensuring just single disable ioctl call for event, because there's no
need to do that more than once.

Signed-off-by: Jiri Olsa <jo...@redhat.com>
Acked-by: Namhyung Kim <namh...@kernel.org>
Cc: Corey Ashford <cjas...@linux.vnet.ibm.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Ingo Molnar <mi...@elte.hu>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Link: http://lkml.kernel.org/r/1352741644-16809-4-...@redhat.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-record.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 268b356..f3151d3 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -502,6 +502,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
struct perf_evlist *evsel_list = rec->evlist;
const char *output_name = rec->output_name;
struct perf_session *session;
+ bool disabled = false;

rec->progname = argv[0];

@@ -735,8 +736,10 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
* die with the process and we wait for that. Thus no need to
* disable events in this case.
*/
- if (done && !perf_target__none(&opts->target))
+ if (done && !disabled && !perf_target__none(&opts->target)) {
perf_evlist__disable(evsel_list);
+ disabled = true;
+ }
}

if (quiet || signr == SIGUSR1)

Arnaldo Carvalho de Melo

unread,
Nov 18, 2012, 9:40:03 AM11/18/12
to
From: Namhyung Kim <namhyu...@lge.com>

Current ui_progress functions are implemented for TUI only. So move the
file under the tui directory. This is needed for providing an UI-
agnostic wrapper.

Signed-off-by: Namhyung Kim <namh...@kernel.org>
Cc: Ingo Molnar <mi...@kernel.org>
Cc: Pekka Enberg <pen...@kernel.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Link: http://lkml.kernel.org/r/1352813436-14173-1-gi...@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/Makefile | 2 +-
tools/perf/ui/progress.c | 32 --------------------------------
tools/perf/ui/tui/progress.c | 32 ++++++++++++++++++++++++++++++++
3 files changed, 33 insertions(+), 33 deletions(-)
delete mode 100644 tools/perf/ui/progress.c
create mode 100644 tools/perf/ui/tui/progress.c

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 9af012f..50e85c8 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -617,11 +617,11 @@ ifndef NO_NEWT
LIB_OBJS += $(OUTPUT)ui/browsers/hists.o
LIB_OBJS += $(OUTPUT)ui/browsers/map.o
LIB_OBJS += $(OUTPUT)ui/browsers/scripts.o
- LIB_OBJS += $(OUTPUT)ui/progress.o
LIB_OBJS += $(OUTPUT)ui/util.o
LIB_OBJS += $(OUTPUT)ui/tui/setup.o
LIB_OBJS += $(OUTPUT)ui/tui/util.o
LIB_OBJS += $(OUTPUT)ui/tui/helpline.o
+ LIB_OBJS += $(OUTPUT)ui/tui/progress.o
LIB_H += ui/browser.h
LIB_H += ui/browsers/map.h
LIB_H += ui/keysyms.h
diff --git a/tools/perf/ui/progress.c b/tools/perf/ui/progress.c
deleted file mode 100644
index 13aa64e..0000000
--- a/tools/perf/ui/progress.c
+++ /dev/null
@@ -1,32 +0,0 @@
-#include "../cache.h"
-#include "progress.h"
-#include "libslang.h"
-#include "ui.h"
-#include "browser.h"
-
-void ui_progress__update(u64 curr, u64 total, const char *title)
-{
- int bar, y;
- /*
- * FIXME: We should have a per UI backend way of showing progress,
- * stdio will just show a percentage as NN%, etc.
- */
- if (use_browser <= 0)
- return;
-
- if (total == 0)
- return;
-
- ui__refresh_dimensions(true);
- pthread_mutex_lock(&ui__lock);
- y = SLtt_Screen_Rows / 2 - 2;
- SLsmg_set_color(0);
- SLsmg_draw_box(y, 0, 3, SLtt_Screen_Cols);
- SLsmg_gotorc(y++, 1);
- SLsmg_write_string((char *)title);
- SLsmg_set_color(HE_COLORSET_SELECTED);
- bar = ((SLtt_Screen_Cols - 2) * curr) / total;
- SLsmg_fill_region(y, 1, 1, bar, ' ');
- SLsmg_refresh();
- pthread_mutex_unlock(&ui__lock);
-}
diff --git a/tools/perf/ui/tui/progress.c b/tools/perf/ui/tui/progress.c
new file mode 100644
index 0000000..f8dc986
--- /dev/null
+++ b/tools/perf/ui/tui/progress.c
@@ -0,0 +1,32 @@
+#include "../cache.h"
+#include "../progress.h"
+#include "../libslang.h"
+#include "../ui.h"
+#include "../browser.h"
+
+void ui_progress__update(u64 curr, u64 total, const char *title)
+{
+ int bar, y;
+ /*
+ * FIXME: We should have a per UI backend way of showing progress,
+ * stdio will just show a percentage as NN%, etc.
+ */
+ if (use_browser <= 0)
+ return;
+
+ if (total == 0)
+ return;
+
+ ui__refresh_dimensions(true);
+ pthread_mutex_lock(&ui__lock);
+ y = SLtt_Screen_Rows / 2 - 2;
+ SLsmg_set_color(0);
+ SLsmg_draw_box(y, 0, 3, SLtt_Screen_Cols);
+ SLsmg_gotorc(y++, 1);
+ SLsmg_write_string((char *)title);
+ SLsmg_set_color(HE_COLORSET_SELECTED);
+ bar = ((SLtt_Screen_Cols - 2) * curr) / total;
+ SLsmg_fill_region(y, 1, 1, bar, ' ');
+ SLsmg_refresh();
+ pthread_mutex_unlock(&ui__lock);
+}

Arnaldo Carvalho de Melo

unread,
Nov 18, 2012, 9:40:03 AM11/18/12
to
From: Jiri Olsa <jo...@redhat.com>

Separating test__open_syscall_event test from the builtin-test into
open-syscall object.

Adding util object under tests directory to gather help functions common
to more tests.

Signed-off-by: Jiri Olsa <jo...@redhat.com>
Cc: Corey Ashford <cjas...@linux.vnet.ibm.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Ingo Molnar <mi...@elte.hu>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Link: http://lkml.kernel.org/r/1352508412-16914-3-...@redhat.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/Makefile | 2 +
tools/perf/tests/builtin-test.c | 84 ---------------------------------------
tools/perf/tests/open-syscall.c | 66 ++++++++++++++++++++++++++++++
tools/perf/tests/tests.h | 5 +++
tools/perf/tests/util.c | 30 ++++++++++++++
5 files changed, 103 insertions(+), 84 deletions(-)
create mode 100644 tools/perf/tests/open-syscall.c
create mode 100644 tools/perf/tests/util.c

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 7c7ba4d..69f582c 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -432,6 +432,8 @@ LIB_OBJS += $(OUTPUT)tests/parse-events.o
LIB_OBJS += $(OUTPUT)tests/dso-data.o
LIB_OBJS += $(OUTPUT)tests/attr.o
LIB_OBJS += $(OUTPUT)tests/vmlinux-kallsyms.o
+LIB_OBJS += $(OUTPUT)tests/open-syscall.o
+LIB_OBJS += $(OUTPUT)tests/util.o

BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 5bc9063..b6b1e46 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -27,90 +27,6 @@

#include "tests.h"

-static int trace_event__id(const char *evname)
-{
- char *filename;
- int err = -1, fd;
-
- if (asprintf(&filename,
- "%s/syscalls/%s/id",
- tracing_events_path, evname) < 0)
- return -1;
-
- 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;
-}
-
-static int test__open_syscall_event(void)
-{
- int err = -1, fd;
- struct thread_map *threads;
- struct perf_evsel *evsel;
- struct perf_event_attr attr;
- unsigned int nr_open_calls = 111, i;
- int id = trace_event__id("sys_enter_open");
-
- if (id < 0) {
- pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
- return -1;
- }
-
- threads = thread_map__new(-1, getpid(), UINT_MAX);
- if (threads == NULL) {
- pr_debug("thread_map__new\n");
- return -1;
- }
-
- memset(&attr, 0, sizeof(attr));
- attr.type = PERF_TYPE_TRACEPOINT;
- attr.config = id;
- evsel = perf_evsel__new(&attr, 0);
- if (evsel == NULL) {
- pr_debug("perf_evsel__new\n");
- goto out_thread_map_delete;
- }
-
- if (perf_evsel__open_per_thread(evsel, threads) < 0) {
- pr_debug("failed to open counter: %s, "
- "tweak /proc/sys/kernel/perf_event_paranoid?\n",
- strerror(errno));
- goto out_evsel_delete;
- }
-
- for (i = 0; i < nr_open_calls; ++i) {
- fd = open("/etc/passwd", O_RDONLY);
- close(fd);
- }
-
- if (perf_evsel__read_on_cpu(evsel, 0, 0) < 0) {
- pr_debug("perf_evsel__read_on_cpu\n");
- goto out_close_fd;
- }
-
- if (evsel->counts->cpu[0].val != nr_open_calls) {
- pr_debug("perf_evsel__read_on_cpu: expected to intercept %d calls, got %" PRIu64 "\n",
- nr_open_calls, evsel->counts->cpu[0].val);
- goto out_close_fd;
- }
-
- err = 0;
-out_close_fd:
- perf_evsel__close_fd(evsel, 1, threads->nr);
-out_evsel_delete:
- perf_evsel__delete(evsel);
-out_thread_map_delete:
- thread_map__delete(threads);
- return err;
-}
-
#include <sched.h>

static int test__open_syscall_event_on_all_cpus(void)
diff --git a/tools/perf/tests/open-syscall.c b/tools/perf/tests/open-syscall.c
new file mode 100644
index 0000000..98be8b5
--- /dev/null
+++ b/tools/perf/tests/open-syscall.c
@@ -0,0 +1,66 @@
+#include "thread_map.h"
+#include "evsel.h"
+#include "debug.h"
+#include "tests.h"
+
+int test__open_syscall_event(void)
+{
+ int err = -1, fd;
+ struct thread_map *threads;
+ struct perf_evsel *evsel;
+ struct perf_event_attr attr;
+ unsigned int nr_open_calls = 111, i;
+ int id = trace_event__id("sys_enter_open");
+
+ if (id < 0) {
+ pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
+ return -1;
+ }
+
+ threads = thread_map__new(-1, getpid(), UINT_MAX);
+ if (threads == NULL) {
+ pr_debug("thread_map__new\n");
+ return -1;
+ }
+
+ memset(&attr, 0, sizeof(attr));
+ attr.type = PERF_TYPE_TRACEPOINT;
+ attr.config = id;
+ evsel = perf_evsel__new(&attr, 0);
+ if (evsel == NULL) {
+ pr_debug("perf_evsel__new\n");
+ goto out_thread_map_delete;
+ }
+
+ if (perf_evsel__open_per_thread(evsel, threads) < 0) {
+ pr_debug("failed to open counter: %s, "
+ "tweak /proc/sys/kernel/perf_event_paranoid?\n",
+ strerror(errno));
+ goto out_evsel_delete;
+ }
+
+ for (i = 0; i < nr_open_calls; ++i) {
+ fd = open("/etc/passwd", O_RDONLY);
+ close(fd);
+ }
+
+ if (perf_evsel__read_on_cpu(evsel, 0, 0) < 0) {
+ pr_debug("perf_evsel__read_on_cpu\n");
+ goto out_close_fd;
+ }
+
+ if (evsel->counts->cpu[0].val != nr_open_calls) {
+ pr_debug("perf_evsel__read_on_cpu: expected to intercept %d calls, got %" PRIu64 "\n",
+ nr_open_calls, evsel->counts->cpu[0].val);
+ goto out_close_fd;
+ }
+
+ err = 0;
+out_close_fd:
+ perf_evsel__close_fd(evsel, 1, threads->nr);
+out_evsel_delete:
+ perf_evsel__delete(evsel);
+out_thread_map_delete:
+ thread_map__delete(threads);
+ return err;
+}
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 2223de5..bac133e 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -1,6 +1,11 @@
#ifndef TESTS_H
#define TESTS_H

+/* Tests */
int test__vmlinux_matches_kallsyms(void);
+int test__open_syscall_event(void);
+
+/* Util */
+int trace_event__id(const char *evname);

#endif /* TESTS_H */
diff --git a/tools/perf/tests/util.c b/tools/perf/tests/util.c
new file mode 100644
index 0000000..748f2e8
--- /dev/null
+++ b/tools/perf/tests/util.c
@@ -0,0 +1,30 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "tests.h"
+#include "debugfs.h"
+
+int trace_event__id(const char *evname)
+{
+ char *filename;
+ int err = -1, fd;
+
+ if (asprintf(&filename,
+ "%s/syscalls/%s/id",
+ tracing_events_path, evname) < 0)
+ return -1;
+
+ 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;

Arnaldo Carvalho de Melo

unread,
Nov 18, 2012, 9:40:03 AM11/18/12
to
From: Jiri Olsa <jo...@redhat.com>

Currently the record command sets all events initially as disabled.

There's non conditional perf_evlist__enable call, that enables all
events before we exec tracee program. That actually screws whole
enable_on_exec logic, because the event is enabled before the traced
program got executed.

What we actually want is:

1) For any type of traced program:
- all independent events and group leaders are disabled
- all group members are enabled

Group members are ruled by group leaders. They need to
be enabled, because the group scheduling relies on that.

2) For traced programs executed by perf:
- all independent events and group leaders have
enable_on_exec set
- we don't specifically enable or disable any event during
the record command

Independent events and group leaders are initially disabled
and get enabled by exec. Group members are ruled by group
leaders as stated in 1).

3) For traced programs attached by perf (pid/tid):
- we specifically enable or disable all events during
the record command

When attaching events to already running traced we
enable/disable events specifically, as there's no
initial traced exec call.

Fixing appropriate perf_event_attr test case to cover this change.

Signed-off-by: Jiri Olsa <jo...@redhat.com>
Acked-by: Namhyung Kim <namh...@kernel.org>
Cc: Corey Ashford <cjas...@linux.vnet.ibm.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Ingo Molnar <mi...@elte.hu>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Link: http://lkml.kernel.org/r/1352741644-16809-3-...@redhat.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-record.c | 15 +++++++++--
tools/perf/tests/attr/test-record-group | 1 +
tools/perf/tests/attr/test-record-group1 | 1 +
tools/perf/util/evsel.c | 42 +++++++++++++++++++++++++++++-
4 files changed, 56 insertions(+), 3 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 3717027..268b356 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -701,7 +701,13 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
}
}

- perf_evlist__enable(evsel_list);
+ /*
+ * When perf is starting the traced process, all the events
+ * (apart from group members) have enable_on_exec=1 set,
+ * so don't spoil it by prematurely enabling them.
+ */
+ if (!perf_target__none(&opts->target))
+ perf_evlist__enable(evsel_list);

/*
* Let the child rip
@@ -724,7 +730,12 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
waking++;
}

- if (done)
+ /*
+ * When perf is starting the traced process, at the end events
+ * die with the process and we wait for that. Thus no need to
+ * disable events in this case.
+ */
+ if (done && !perf_target__none(&opts->target))
perf_evlist__disable(evsel_list);
}

diff --git a/tools/perf/tests/attr/test-record-group b/tools/perf/tests/attr/test-record-group
index b945f77..a6599e9 100644
--- a/tools/perf/tests/attr/test-record-group
+++ b/tools/perf/tests/attr/test-record-group
@@ -15,3 +15,4 @@ sample_type=327
mmap=0
comm=0
enable_on_exec=0
+disabled=0
diff --git a/tools/perf/tests/attr/test-record-group1 b/tools/perf/tests/attr/test-record-group1
index 013572f..5a8359d 100644
--- a/tools/perf/tests/attr/test-record-group1
+++ b/tools/perf/tests/attr/test-record-group1
@@ -16,3 +16,4 @@ sample_type=327
mmap=0
comm=0
enable_on_exec=0
+disabled=0
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 6d4a5f6..fc4faaa 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -404,13 +404,40 @@ const char *perf_evsel__name(struct perf_evsel *evsel)
return evsel->name ?: "unknown";
}

+/*
+ * The enable_on_exec/disabled value strategy:
+ *
+ * 1) For any type of traced program:
+ * - all independent events and group leaders are disabled
+ * - all group members are enabled
+ *
+ * Group members are ruled by group leaders. They need to
+ * be enabled, because the group scheduling relies on that.
+ *
+ * 2) For traced programs executed by perf:
+ * - all independent events and group leaders have
+ * enable_on_exec set
+ * - we don't specifically enable or disable any event during
+ * the record command
+ *
+ * Independent events and group leaders are initially disabled
+ * and get enabled by exec. Group members are ruled by group
+ * leaders as stated in 1).
+ *
+ * 3) For traced programs attached by perf (pid/tid):
+ * - we specifically enable or disable all events during
+ * the record command
+ *
+ * When attaching events to already running traced we
+ * enable/disable events specifically, as there's no
+ * initial traced exec call.
+ */
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->disabled = 1;
attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1;
attr->inherit = !opts->no_inherit;
attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
@@ -486,6 +513,19 @@ void perf_evsel__config(struct perf_evsel *evsel,
attr->mmap = track;
attr->comm = track;

+ /*
+ * XXX see the function comment above
+ *
+ * Disabling only independent events or group leaders,
+ * keeping group members enabled.
+ */
+ if (!evsel->leader)
+ attr->disabled = 1;
+
+ /*
+ * Setting enable_on_exec for independent events and
+ * group leaders for traced executed by perf.
+ */
if (perf_target__none(&opts->target) && (!evsel->leader))
attr->enable_on_exec = 1;

Arnaldo Carvalho de Melo

unread,
Nov 18, 2012, 9:40:03 AM11/18/12
to
From: Namhyung Kim <namhyu...@lge.com>

CC builtin-annotate.o
In file included from util/evsel.h:10:0,
from util/evlist.h:8,
from builtin-annotate.c:20:
util/hist.h: In function ‘script_browse’:
util/hist.h:198:45: error: unused parameter ‘script_opt’ [-Werror=unused-parameter]
cc1: all warnings being treated as errors
make: *** [builtin-annotate.o] Error 1
make: *** Waiting for unfinished jobs....

Signed-off-by: Namhyung Kim <namh...@kernel.org>
Cc: Feng Tang <feng...@intel.com>
Cc: Ingo Molnar <mi...@kernel.org>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Link: http://lkml.kernel.org/r/1352697240-422-1-git...@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/hist.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 1278c2c..8b091a5 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -195,7 +195,7 @@ static inline int hist_entry__tui_annotate(struct hist_entry *self
return 0;
}

-static inline int script_browse(const char *script_opt)
+static inline int script_browse(const char *script_opt __maybe_unused)
{
return 0;

Arnaldo Carvalho de Melo

unread,
Nov 18, 2012, 9:40:02 AM11/18/12
to
Hi Ingo,

Please consider pulling,

- Arnaldo

The following changes since commit ffadcf090d468e9c4938b718649f38dd10cfdb02:

perf annotate: Handle XBEGIN like a jump (2012-10-31 12:18:26 -0200)

are available in the git repository at:

git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux perf/core

for you to fetch changes up to 07ac002f2fcc74c5be47b656d9201d5de84dc53d:

perf evsel: Introduce is_group_member method (2012-11-14 16:53:45 -0300)

----------------------------------------------------------------
perf/core improvements and fixes

. UAPI fixes, from David Howels

. Separate perf tests into multiple objects, one per test, from Jiri Olsa.

. Fixes to /proc/pid/maps parsing, preparatory to supporting data maps,
from Namhyung Kim

. Fix compile error for non-NEWT builds, from Namhyung Kim

. Implement ui_progress for GTK, from Namhyung Kim

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

----------------------------------------------------------------
Andi Kleen (1):
perf tools: Add arbitary aliases and support names with -

Arnaldo Carvalho de Melo (13):
perf diff: Start moving to support matching more than two hists
perf diff: Move hists__match to the hists lib
perf hists: Introduce hists__link
perf diff: Use hists__link when not pairing just with baseline
perf machine: Move more methods to machine.[ch]
tools lib traceevent: Add __maybe_unused to unused parameters
tools lib traceevent: Avoid comparisions between signed/unsigned
tools lib traceevent: No need to check for < 0 on an unsigned enum
tools lib traceevent: Handle INVALID_ARG_TYPE errno in pevent_strerror
tools lib traceevent: Use 'const' in variables pointing to const strings
perf tools: Stop using 'self' in pstack
perf hists: Initialize all of he->stat with zeroes
perf evsel: Introduce is_group_member method

Daniel Walter (1):
tracing: Replace strict_strto* with kstrto*

David Howells (3):
tools: Define a Makefile function to do subdir processing
tools: Honour the O= flag when tool build called from a higher Makefile
tools: Pass the target in descend

David Sharp (2):
tracing: Trivial cleanup
tracing: Reset ring buffer when changing trace_clocks

Feng Tang (1):
perf browser: Don't show scripts menu for 'perf top'

Hiraku Toyooka (1):
tracing: Change tracer's integer flags to bool

Ingo Molnar (2):
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/.../acme/linux into perf/core
Merge branch 'tip/perf/core-2' of git://git.kernel.org/.../rostedt/linux-trace into perf/core

Jiri Olsa (47):
perf tools: Remove BINDIR define from exec_cmd.o compilation
perf tests: Move test objects into 'tests' directory
perf tests: Add framework for automated perf_event_attr tests
perf tests: Add attr record basic test
perf tests: Add attr tests under builtin test command
perf tests: Add attr record group test
perf tests: Add attr record event syntax group test
perf tests: Add attr record freq test
perf tests: Add attr record count test
perf tests: Add attr record graph test
perf tests: Add attr record period test
perf tests: Add attr record no samples test
perf tests: Add attr record no-inherit test
perf tests: Add attr record data test
perf tests: Add attr record raw test
perf tests: Add attr record no delay test
perf tests: Add attr record branch any test
perf tests: Add attr record branch filter tests
perf tests: Add attr stat no-inherit test
perf tests: Add attr stat group test
perf tests: Add attr stat event syntax group test
perf tests: Add attr stat default test
perf tests: Add attr stat default test
perf tests: Add documentation for attr tests
perf tests: Add missing attr stat basic test
perf tests: Factor attr tests WRITE_ASS macro
perf tests: Fix attr watermark field name typo
perf tests: Removing 'optional' field
perf tests: Move attr.py temp dir cleanup into finally section
perf tools: Add LIBDW_DIR Makefile variable to for alternate libdw
perf tests: Move test__vmlinux_matches_kallsyms into separate object
perf tests: Move test__open_syscall_event into separate object
perf tests: Move test__open_syscall_event_on_all_cpus into separate object
perf tests: Move test__basic_mmap into separate object
perf tests: Move test__PERF_RECORD into separate object
perf tests: Move test__rdpmc into separate object
perf tests: Move perf_evsel__roundtrip_name_test into separate object
perf tests: Move perf_evsel__tp_sched_test into separate object
perf tests: Move test__syscall_open_tp_fields into separate object
perf tests: Move pmu tests into separate object
perf tests: Final cleanup for builtin-test move
perf tests: Check for mkstemp return value in dso-data test
perf tools: Fix attributes for '{}' defined event groups
perf tools: Fix 'disabled' attribute config for record command
perf tools: Ensure single disable call per event in record comand
perf tools: Omit group members from perf_evlist__disable/enable
perf tools: Add basic event modifier sanity check

Michal Hocko (1):
linux/kernel.h: Remove duplicate trace_printk declaration

Namhyung Kim (18):
perf tools: Use normalized arch name for searching objdump path
perf tools: Introduce struct hist_browser_timer
perf report: Postpone objdump check until annotation requested
perf machine: Set kernel data mapping length
perf tools: Fix detection of stack area
perf hists: Free branch_info when freeing hist_entry
perf tools: Don't try to lookup objdump for live mode
perf annotate: Whitespace fixups
perf annotate: Don't try to follow jump target on PLT symbols
perf annotate: Merge same lines in summary view
perf tools: Fix compile error on NO_NEWT=1 build
perf tools: Add gtk.<command> config option for launching GTK browser
perf tools: Use sscanf for parsing /proc/pid/maps
perf ui tui: Move progress.c under ui/tui directory
perf ui: Introduce generic ui_progress helper
perf ui gtk: Implement ui_progress functions
perf ui: Add ui_progress__finish()
perf ui: Always compile browser setup code

Slava Pestov (1):
ring-buffer: Add a 'dropped events' counter

Steven Rostedt (11):
tracing: Allow tracers to start at core initcall
tracing: Expand ring buffer when trace_printk() is used
tracing: Enable comm recording if trace_printk() is used
tracing: Have tracing_sched_wakeup_trace() use standard unlock_commit
tracing: Cache comms only after an event occurred
tracing: Separate open function from set_event and available_events
tracing: Remove unused function unregister_tracer()
tracing: Make tracing_enabled be equal to tracing_on
tracing: Remove deprecated tracing_enabled file
tracing: Use irq_work for wake ups and remove *_nowake_*() functions
tracing: Add trace_options kernel command line parameter

Sukadev Bhattiprolu (1):
perf powerpc: Use uapi/unistd.h to fix build error

Vaibhav Nagarnaik (1):
tracing: Cleanup unnecessary function declarations

Yoshihiro YUNOMAE (1):
ring-buffer: Change unsigned long type of ring_buffer_oldest_event_ts() to u64

Zheng Liu (1):
perf test: fix a build error on builtin-test

Documentation/kernel-parameters.txt | 16 +
Makefile | 6 +-
include/linux/ftrace_event.h | 14 +-
include/linux/kernel.h | 7 +-
include/linux/ring_buffer.h | 3 +-
include/trace/ftrace.h | 3 +-
include/trace/syscall.h | 23 -
kernel/trace/Kconfig | 1 +
kernel/trace/ftrace.c | 6 +-
kernel/trace/ring_buffer.c | 51 +-
kernel/trace/trace.c | 372 ++---
kernel/trace/trace.h | 14 +-
kernel/trace/trace_branch.c | 4 +-
kernel/trace/trace_events.c | 51 +-
kernel/trace/trace_events_filter.c | 4 +-
kernel/trace/trace_functions.c | 5 +-
kernel/trace/trace_functions_graph.c | 6 +-
kernel/trace/trace_irqsoff.c | 14 +-
kernel/trace/trace_kprobe.c | 10 +-
kernel/trace/trace_probe.c | 14 +-
kernel/trace/trace_sched_switch.c | 4 +-
kernel/trace/trace_sched_wakeup.c | 10 +-
kernel/trace/trace_selftest.c | 13 +-
kernel/trace/trace_syscalls.c | 61 +-
kernel/trace/trace_uprobe.c | 2 +-
tools/Makefile | 24 +-
tools/lib/traceevent/event-parse.c | 22 +-
tools/perf/Makefile | 50 +-
tools/perf/arch/common.c | 47 +-
tools/perf/builtin-annotate.c | 2 +-
tools/perf/builtin-diff.c | 48 +-
tools/perf/builtin-record.c | 26 +-
tools/perf/builtin-report.c | 11 +-
tools/perf/builtin-stat.c | 12 +-
tools/perf/builtin-test.c | 1559 --------------------
tools/perf/builtin-top.c | 10 +-
tools/perf/perf.c | 17 +-
tools/perf/perf.h | 18 +-
tools/perf/tests/attr.c | 175 +++
tools/perf/tests/attr.py | 322 ++++
tools/perf/tests/attr/README | 64 +
tools/perf/tests/attr/base-record | 39 +
tools/perf/tests/attr/base-stat | 39 +
tools/perf/tests/attr/test-record-basic | 5 +
tools/perf/tests/attr/test-record-branch-any | 8 +
.../perf/tests/attr/test-record-branch-filter-any | 8 +
.../tests/attr/test-record-branch-filter-any_call | 8 +
.../tests/attr/test-record-branch-filter-any_ret | 8 +
tools/perf/tests/attr/test-record-branch-filter-hv | 8 +
.../tests/attr/test-record-branch-filter-ind_call | 8 +
tools/perf/tests/attr/test-record-branch-filter-k | 8 +
tools/perf/tests/attr/test-record-branch-filter-u | 8 +
tools/perf/tests/attr/test-record-count | 8 +
tools/perf/tests/attr/test-record-data | 8 +
tools/perf/tests/attr/test-record-freq | 6 +
tools/perf/tests/attr/test-record-graph-default | 6 +
tools/perf/tests/attr/test-record-graph-dwarf | 10 +
tools/perf/tests/attr/test-record-graph-fp | 6 +
tools/perf/tests/attr/test-record-group | 18 +
tools/perf/tests/attr/test-record-group1 | 19 +
tools/perf/tests/attr/test-record-no-delay | 9 +
tools/perf/tests/attr/test-record-no-inherit | 7 +
tools/perf/tests/attr/test-record-no-samples | 6 +
tools/perf/tests/attr/test-record-period | 7 +
tools/perf/tests/attr/test-record-raw | 7 +
tools/perf/tests/attr/test-stat-basic | 6 +
tools/perf/tests/attr/test-stat-default | 64 +
tools/perf/tests/attr/test-stat-detailed-1 | 101 ++
tools/perf/tests/attr/test-stat-detailed-2 | 155 ++
tools/perf/tests/attr/test-stat-detailed-3 | 173 +++
tools/perf/tests/attr/test-stat-group | 15 +
tools/perf/tests/attr/test-stat-group1 | 15 +
tools/perf/tests/attr/test-stat-no-inherit | 7 +
tools/perf/tests/builtin-test.c | 173 +++
.../{util/dso-test-data.c => tests/dso-data.c} | 8 +-
tools/perf/tests/evsel-roundtrip-name.c | 114 ++
tools/perf/tests/evsel-tp-sched.c | 84 ++
tools/perf/tests/mmap-basic.c | 162 ++
tools/perf/tests/open-syscall-all-cpus.c | 120 ++
tools/perf/tests/open-syscall-tp-fields.c | 117 ++
tools/perf/tests/open-syscall.c | 66 +
.../parse-events-test.c => tests/parse-events.c} | 23 +-
tools/perf/tests/perf-record.c | 312 ++++
tools/perf/tests/pmu.c | 178 +++
tools/perf/tests/rdpmc.c | 175 +++
tools/perf/tests/tests.h | 22 +
tools/perf/tests/util.c | 30 +
tools/perf/tests/vmlinux-kallsyms.c | 230 +++
tools/perf/ui/browsers/annotate.c | 39 +-
tools/perf/ui/browsers/hists.c | 63 +-
tools/perf/ui/gtk/browser.c | 4 +-
tools/perf/ui/gtk/gtk.h | 1 +
tools/perf/ui/gtk/progress.c | 59 +
tools/perf/ui/gtk/setup.c | 2 +
tools/perf/ui/gtk/util.c | 11 -
tools/perf/ui/hist.c | 10 +-
tools/perf/ui/progress.c | 44 +-
tools/perf/ui/progress.h | 10 +
tools/perf/ui/tui/progress.c | 42 +
tools/perf/ui/tui/setup.c | 1 +
tools/perf/ui/ui.h | 28 +
tools/perf/util/annotate.c | 69 +-
tools/perf/util/annotate.h | 9 +-
tools/perf/util/cache.h | 39 +-
tools/perf/util/debug.h | 1 +
tools/perf/util/dso.c | 1 +
tools/perf/util/event.c | 74 +-
tools/perf/util/evlist.c | 10 +-
tools/perf/util/evsel.c | 52 +-
tools/perf/util/evsel.h | 9 +-
tools/perf/util/hist.c | 99 ++
tools/perf/util/hist.h | 36 +-
tools/perf/util/machine.c | 205 ++-
tools/perf/util/machine.h | 131 +-
tools/perf/util/map.c | 181 +--
tools/perf/util/map.h | 93 --
tools/perf/util/parse-events.c | 24 +
tools/perf/util/parse-events.h | 1 -
tools/perf/util/parse-events.l | 4 +-
tools/perf/util/pmu.c | 185 +--
tools/perf/util/pmu.h | 4 +
tools/perf/util/pstack.c | 46 +-
tools/perf/util/session.c | 1 +
tools/perf/util/session.h | 5 +-
tools/perf/util/sort.h | 27 +-
tools/perf/util/symbol.c | 1 +
tools/perf/util/symbol.h | 21 -
tools/scripts/Makefile.include | 23 +-
128 files changed, 4649 insertions(+), 2751 deletions(-)
delete mode 100644 tools/perf/builtin-test.c
create mode 100644 tools/perf/tests/attr.c
create mode 100644 tools/perf/tests/attr.py
create mode 100644 tools/perf/tests/attr/README
create mode 100644 tools/perf/tests/attr/base-record
create mode 100644 tools/perf/tests/attr/base-stat
create mode 100644 tools/perf/tests/attr/test-record-basic
create mode 100644 tools/perf/tests/attr/test-record-branch-any
create mode 100644 tools/perf/tests/attr/test-record-branch-filter-any
create mode 100644 tools/perf/tests/attr/test-record-branch-filter-any_call
create mode 100644 tools/perf/tests/attr/test-record-branch-filter-any_ret
create mode 100644 tools/perf/tests/attr/test-record-branch-filter-hv
create mode 100644 tools/perf/tests/attr/test-record-branch-filter-ind_call
create mode 100644 tools/perf/tests/attr/test-record-branch-filter-k
create mode 100644 tools/perf/tests/attr/test-record-branch-filter-u
create mode 100644 tools/perf/tests/attr/test-record-count
create mode 100644 tools/perf/tests/attr/test-record-data
create mode 100644 tools/perf/tests/attr/test-record-freq
create mode 100644 tools/perf/tests/attr/test-record-graph-default
create mode 100644 tools/perf/tests/attr/test-record-graph-dwarf
create mode 100644 tools/perf/tests/attr/test-record-graph-fp
create mode 100644 tools/perf/tests/attr/test-record-group
create mode 100644 tools/perf/tests/attr/test-record-group1
create mode 100644 tools/perf/tests/attr/test-record-no-delay
create mode 100644 tools/perf/tests/attr/test-record-no-inherit
create mode 100644 tools/perf/tests/attr/test-record-no-samples
create mode 100644 tools/perf/tests/attr/test-record-period
create mode 100644 tools/perf/tests/attr/test-record-raw
create mode 100644 tools/perf/tests/attr/test-stat-basic
create mode 100644 tools/perf/tests/attr/test-stat-default
create mode 100644 tools/perf/tests/attr/test-stat-detailed-1
create mode 100644 tools/perf/tests/attr/test-stat-detailed-2
create mode 100644 tools/perf/tests/attr/test-stat-detailed-3
create mode 100644 tools/perf/tests/attr/test-stat-group
create mode 100644 tools/perf/tests/attr/test-stat-group1
create mode 100644 tools/perf/tests/attr/test-stat-no-inherit
create mode 100644 tools/perf/tests/builtin-test.c
rename tools/perf/{util/dso-test-data.c => tests/dso-data.c} (95%)
create mode 100644 tools/perf/tests/evsel-roundtrip-name.c
create mode 100644 tools/perf/tests/evsel-tp-sched.c
create mode 100644 tools/perf/tests/mmap-basic.c
create mode 100644 tools/perf/tests/open-syscall-all-cpus.c
create mode 100644 tools/perf/tests/open-syscall-tp-fields.c
create mode 100644 tools/perf/tests/open-syscall.c
rename tools/perf/{util/parse-events-test.c => tests/parse-events.c} (97%)
create mode 100644 tools/perf/tests/perf-record.c
create mode 100644 tools/perf/tests/pmu.c
create mode 100644 tools/perf/tests/rdpmc.c
create mode 100644 tools/perf/tests/tests.h
create mode 100644 tools/perf/tests/util.c
create mode 100644 tools/perf/tests/vmlinux-kallsyms.c
create mode 100644 tools/perf/ui/gtk/progress.c
create mode 100644 tools/perf/ui/tui/progress.c

Arnaldo Carvalho de Melo

unread,
Nov 18, 2012, 9:40:03 AM11/18/12
to
From: Jiri Olsa <jo...@redhat.com>

Separating test__open_syscall_event_on_all_cpus test from the
builtin-test into open-syscall-all-cpus object.

Signed-off-by: Jiri Olsa <jo...@redhat.com>
Cc: Corey Ashford <cjas...@linux.vnet.ibm.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Ingo Molnar <mi...@elte.hu>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Link: http://lkml.kernel.org/r/1352508412-16914-4-...@redhat.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/Makefile | 1 +
tools/perf/tests/builtin-test.c | 114 ----------------------------
tools/perf/tests/open-syscall-all-cpus.c | 120 ++++++++++++++++++++++++++++++
tools/perf/tests/tests.h | 1 +
4 files changed, 122 insertions(+), 114 deletions(-)
create mode 100644 tools/perf/tests/open-syscall-all-cpus.c

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 69f582c..d413e89c 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -433,6 +433,7 @@ LIB_OBJS += $(OUTPUT)tests/dso-data.o
LIB_OBJS += $(OUTPUT)tests/attr.o
LIB_OBJS += $(OUTPUT)tests/vmlinux-kallsyms.o
LIB_OBJS += $(OUTPUT)tests/open-syscall.o
+LIB_OBJS += $(OUTPUT)tests/open-syscall-all-cpus.o
LIB_OBJS += $(OUTPUT)tests/util.o

BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index b6b1e46..98e883b 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -29,120 +29,6 @@

#include <sched.h>

-static int test__open_syscall_event_on_all_cpus(void)
-{
- int err = -1, fd, cpu;
- struct thread_map *threads;
- struct cpu_map *cpus;
- struct perf_evsel *evsel;
- struct perf_event_attr attr;
- unsigned int nr_open_calls = 111, i;
- cpu_set_t cpu_set;
- int id = trace_event__id("sys_enter_open");
-
- if (id < 0) {
- pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
- return -1;
- }
-
- threads = thread_map__new(-1, getpid(), UINT_MAX);
- if (threads == NULL) {
- pr_debug("thread_map__new\n");
- return -1;
- }
-
- cpus = cpu_map__new(NULL);
- if (cpus == NULL) {
- pr_debug("cpu_map__new\n");
- goto out_thread_map_delete;
- }
-
-
- CPU_ZERO(&cpu_set);
-
- memset(&attr, 0, sizeof(attr));
- attr.type = PERF_TYPE_TRACEPOINT;
- attr.config = id;
- evsel = perf_evsel__new(&attr, 0);
- if (evsel == NULL) {
- pr_debug("perf_evsel__new\n");
- goto out_thread_map_delete;
- }
-
- if (perf_evsel__open(evsel, cpus, threads) < 0) {
- pr_debug("failed to open counter: %s, "
- "tweak /proc/sys/kernel/perf_event_paranoid?\n",
- strerror(errno));
- goto out_evsel_delete;
- }
-
- for (cpu = 0; cpu < cpus->nr; ++cpu) {
- unsigned int ncalls = nr_open_calls + cpu;
- /*
- * XXX eventually lift this restriction in a way that
- * keeps perf building on older glibc installations
- * without CPU_ALLOC. 1024 cpus in 2010 still seems
- * a reasonable upper limit tho :-)
- */
- if (cpus->map[cpu] >= CPU_SETSIZE) {
- pr_debug("Ignoring CPU %d\n", cpus->map[cpu]);
- continue;
- }
-
- CPU_SET(cpus->map[cpu], &cpu_set);
- if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) {
- pr_debug("sched_setaffinity() failed on CPU %d: %s ",
- cpus->map[cpu],
- strerror(errno));
- goto out_close_fd;
- }
- for (i = 0; i < ncalls; ++i) {
- fd = open("/etc/passwd", O_RDONLY);
- close(fd);
- }
- CPU_CLR(cpus->map[cpu], &cpu_set);
- }
-
- /*
- * Here we need to explicitely preallocate the counts, as if
- * we use the auto allocation it will allocate just for 1 cpu,
- * as we start by cpu 0.
- */
- if (perf_evsel__alloc_counts(evsel, cpus->nr) < 0) {
- pr_debug("perf_evsel__alloc_counts(ncpus=%d)\n", cpus->nr);
- goto out_close_fd;
- }
-
- err = 0;
-
- for (cpu = 0; cpu < cpus->nr; ++cpu) {
- unsigned int expected;
-
- if (cpus->map[cpu] >= CPU_SETSIZE)
- continue;
-
- if (perf_evsel__read_on_cpu(evsel, cpu, 0) < 0) {
- pr_debug("perf_evsel__read_on_cpu\n");
- err = -1;
- break;
- }
-
- expected = nr_open_calls + cpu;
- if (evsel->counts->cpu[cpu].val != expected) {
- pr_debug("perf_evsel__read_on_cpu: expected to intercept %d calls on cpu %d, got %" PRIu64 "\n",
- expected, cpus->map[cpu], evsel->counts->cpu[cpu].val);
- err = -1;
- }
- }
-
-out_close_fd:
- perf_evsel__close_fd(evsel, 1, threads->nr);
-out_evsel_delete:
- perf_evsel__delete(evsel);
-out_thread_map_delete:
- thread_map__delete(threads);
- return err;
-}

/*
* This test will generate random numbers of calls to some getpid syscalls,
diff --git a/tools/perf/tests/open-syscall-all-cpus.c b/tools/perf/tests/open-syscall-all-cpus.c
new file mode 100644
index 0000000..31072ab
--- /dev/null
+++ b/tools/perf/tests/open-syscall-all-cpus.c
@@ -0,0 +1,120 @@
+#include "evsel.h"
+#include "tests.h"
+#include "thread_map.h"
+#include "cpumap.h"
+#include "debug.h"
+
+int test__open_syscall_event_on_all_cpus(void)
+{
+ int err = -1, fd, cpu;
+ struct thread_map *threads;
+ struct cpu_map *cpus;
+ struct perf_evsel *evsel;
+ struct perf_event_attr attr;
+ unsigned int nr_open_calls = 111, i;
+ cpu_set_t cpu_set;
+ int id = trace_event__id("sys_enter_open");
+
+ if (id < 0) {
+ pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
+ return -1;
+ }
+
+ threads = thread_map__new(-1, getpid(), UINT_MAX);
+ if (threads == NULL) {
+ pr_debug("thread_map__new\n");
+ return -1;
+ }
+
+ cpus = cpu_map__new(NULL);
+ if (cpus == NULL) {
+ pr_debug("cpu_map__new\n");
+ goto out_thread_map_delete;
+ }
+
+
+ CPU_ZERO(&cpu_set);
+
+ memset(&attr, 0, sizeof(attr));
+ attr.type = PERF_TYPE_TRACEPOINT;
+ attr.config = id;
+ evsel = perf_evsel__new(&attr, 0);
+ if (evsel == NULL) {
+ pr_debug("perf_evsel__new\n");
+ goto out_thread_map_delete;
+ }
+
+ if (perf_evsel__open(evsel, cpus, threads) < 0) {
+ pr_debug("failed to open counter: %s, "
+ "tweak /proc/sys/kernel/perf_event_paranoid?\n",
+ strerror(errno));
+ goto out_evsel_delete;
+ }
+
+ for (cpu = 0; cpu < cpus->nr; ++cpu) {
+ unsigned int ncalls = nr_open_calls + cpu;
+ /*
+ * XXX eventually lift this restriction in a way that
+ * keeps perf building on older glibc installations
+ * without CPU_ALLOC. 1024 cpus in 2010 still seems
+ * a reasonable upper limit tho :-)
+ */
+ if (cpus->map[cpu] >= CPU_SETSIZE) {
+ pr_debug("Ignoring CPU %d\n", cpus->map[cpu]);
+ continue;
+ }
+
+ CPU_SET(cpus->map[cpu], &cpu_set);
+ if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) {
+ pr_debug("sched_setaffinity() failed on CPU %d: %s ",
+ cpus->map[cpu],
+ strerror(errno));
+ goto out_close_fd;
+ }
+ for (i = 0; i < ncalls; ++i) {
+ fd = open("/etc/passwd", O_RDONLY);
+ close(fd);
+ }
+ CPU_CLR(cpus->map[cpu], &cpu_set);
+ }
+
+ /*
+ * Here we need to explicitely preallocate the counts, as if
+ * we use the auto allocation it will allocate just for 1 cpu,
+ * as we start by cpu 0.
+ */
+ if (perf_evsel__alloc_counts(evsel, cpus->nr) < 0) {
+ pr_debug("perf_evsel__alloc_counts(ncpus=%d)\n", cpus->nr);
+ goto out_close_fd;
+ }
+
+ err = 0;
+
+ for (cpu = 0; cpu < cpus->nr; ++cpu) {
+ unsigned int expected;
+
+ if (cpus->map[cpu] >= CPU_SETSIZE)
+ continue;
+
+ if (perf_evsel__read_on_cpu(evsel, cpu, 0) < 0) {
+ pr_debug("perf_evsel__read_on_cpu\n");
+ err = -1;
+ break;
+ }
+
+ expected = nr_open_calls + cpu;
+ if (evsel->counts->cpu[cpu].val != expected) {
+ pr_debug("perf_evsel__read_on_cpu: expected to intercept %d calls on cpu %d, got %" PRIu64 "\n",
+ expected, cpus->map[cpu], evsel->counts->cpu[cpu].val);
+ err = -1;
+ }
+ }
+
+out_close_fd:
+ perf_evsel__close_fd(evsel, 1, threads->nr);
+out_evsel_delete:
+ perf_evsel__delete(evsel);
+out_thread_map_delete:
+ thread_map__delete(threads);
+ return err;
+}
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index bac133e..c2887f2 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -4,6 +4,7 @@
/* Tests */
int test__vmlinux_matches_kallsyms(void);
int test__open_syscall_event(void);
+int test__open_syscall_event_on_all_cpus(void);

/* Util */
int trace_event__id(const char *evname);
--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Nov 18, 2012, 9:40:03 AM11/18/12
to
From: Jiri Olsa <jo...@redhat.com>

Separating test__basic_mmap test from the builtin-test into mmap-basic
object.

Signed-off-by: Jiri Olsa <jo...@redhat.com>
Cc: Corey Ashford <cjas...@linux.vnet.ibm.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Ingo Molnar <mi...@elte.hu>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Link: http://lkml.kernel.org/r/1352508412-16914-5-...@redhat.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/Makefile | 1 +
tools/perf/tests/builtin-test.c | 157 -------------------------------------
tools/perf/tests/mmap-basic.c | 162 +++++++++++++++++++++++++++++++++++++++
tools/perf/tests/tests.h | 1 +
4 files changed, 164 insertions(+), 157 deletions(-)
create mode 100644 tools/perf/tests/mmap-basic.c

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index d413e89c..337489e 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -434,6 +434,7 @@ LIB_OBJS += $(OUTPUT)tests/attr.o
LIB_OBJS += $(OUTPUT)tests/vmlinux-kallsyms.o
LIB_OBJS += $(OUTPUT)tests/open-syscall.o
LIB_OBJS += $(OUTPUT)tests/open-syscall-all-cpus.o
+LIB_OBJS += $(OUTPUT)tests/mmap-basic.o
LIB_OBJS += $(OUTPUT)tests/util.o

BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 98e883b..609f592 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -30,163 +30,6 @@
#include <sched.h>


-/*
- * This test will generate random numbers of calls to some getpid syscalls,
- * then establish an mmap for a group of events that are created to monitor
- * the syscalls.
- *
- * It will receive the events, using mmap, use its PERF_SAMPLE_ID generated
- * sample.id field to map back to its respective perf_evsel instance.
- *
- * Then it checks if the number of syscalls reported as perf events by
- * the kernel corresponds to the number of syscalls made.
- */
-static int test__basic_mmap(void)
-{
- int err = -1;
- union perf_event *event;
- struct thread_map *threads;
- struct cpu_map *cpus;
- struct perf_evlist *evlist;
- struct perf_event_attr attr = {
- .type = PERF_TYPE_TRACEPOINT,
- .read_format = PERF_FORMAT_ID,
- .sample_type = PERF_SAMPLE_ID,
- .watermark = 0,
- };
- cpu_set_t cpu_set;
- const char *syscall_names[] = { "getsid", "getppid", "getpgrp",
- "getpgid", };
- pid_t (*syscalls[])(void) = { (void *)getsid, getppid, getpgrp,
- (void*)getpgid };
-#define nsyscalls ARRAY_SIZE(syscall_names)
- int ids[nsyscalls];
- unsigned int nr_events[nsyscalls],
- expected_nr_events[nsyscalls], i, j;
- struct perf_evsel *evsels[nsyscalls], *evsel;
-
- for (i = 0; i < nsyscalls; ++i) {
- char name[64];
-
- snprintf(name, sizeof(name), "sys_enter_%s", syscall_names[i]);
- ids[i] = trace_event__id(name);
- if (ids[i] < 0) {
- pr_debug("Is debugfs mounted on /sys/kernel/debug?\n");
- return -1;
- }
- nr_events[i] = 0;
- expected_nr_events[i] = random() % 257;
- }
-
- threads = thread_map__new(-1, getpid(), UINT_MAX);
- if (threads == NULL) {
- pr_debug("thread_map__new\n");
- return -1;
- }
-
- cpus = cpu_map__new(NULL);
- if (cpus == NULL) {
- pr_debug("cpu_map__new\n");
- goto out_free_threads;
- }
-
- CPU_ZERO(&cpu_set);
- CPU_SET(cpus->map[0], &cpu_set);
- sched_setaffinity(0, sizeof(cpu_set), &cpu_set);
- if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) {
- pr_debug("sched_setaffinity() failed on CPU %d: %s ",
- cpus->map[0], strerror(errno));
- goto out_free_cpus;
- }
-
- evlist = perf_evlist__new(cpus, threads);
- if (evlist == NULL) {
- pr_debug("perf_evlist__new\n");
- goto out_free_cpus;
- }
-
- /* anonymous union fields, can't be initialized above */
- attr.wakeup_events = 1;
- attr.sample_period = 1;
-
- for (i = 0; i < nsyscalls; ++i) {
- attr.config = ids[i];
- evsels[i] = perf_evsel__new(&attr, i);
- if (evsels[i] == NULL) {
- pr_debug("perf_evsel__new\n");
- goto out_free_evlist;
- }
-
- perf_evlist__add(evlist, evsels[i]);
-
- if (perf_evsel__open(evsels[i], cpus, threads) < 0) {
- pr_debug("failed to open counter: %s, "
- "tweak /proc/sys/kernel/perf_event_paranoid?\n",
- strerror(errno));
- goto out_close_fd;
- }
- }
-
- if (perf_evlist__mmap(evlist, 128, true) < 0) {
- pr_debug("failed to mmap events: %d (%s)\n", errno,
- strerror(errno));
- goto out_close_fd;
- }
-
- for (i = 0; i < nsyscalls; ++i)
- for (j = 0; j < expected_nr_events[i]; ++j) {
- int foo = syscalls[i]();
- ++foo;
- }
-
- while ((event = perf_evlist__mmap_read(evlist, 0)) != NULL) {
- struct perf_sample sample;
-
- if (event->header.type != PERF_RECORD_SAMPLE) {
- pr_debug("unexpected %s event\n",
- perf_event__name(event->header.type));
- goto out_munmap;
- }
-
- err = perf_evlist__parse_sample(evlist, event, &sample);
- if (err) {
- pr_err("Can't parse sample, err = %d\n", err);
- goto out_munmap;
- }
-
- evsel = perf_evlist__id2evsel(evlist, sample.id);
- if (evsel == NULL) {
- pr_debug("event with id %" PRIu64
- " doesn't map to an evsel\n", sample.id);
- goto out_munmap;
- }
- nr_events[evsel->idx]++;
- }
-
- list_for_each_entry(evsel, &evlist->entries, node) {
- if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) {
- pr_debug("expected %d %s events, got %d\n",
- expected_nr_events[evsel->idx],
- perf_evsel__name(evsel), nr_events[evsel->idx]);
- goto out_munmap;
- }
- }
-
- err = 0;
-out_munmap:
- perf_evlist__munmap(evlist);
-out_close_fd:
- for (i = 0; i < nsyscalls; ++i)
- perf_evsel__close_fd(evsels[i], 1, threads->nr);
-out_free_evlist:
- perf_evlist__delete(evlist);
-out_free_cpus:
- cpu_map__delete(cpus);
-out_free_threads:
- thread_map__delete(threads);
- return err;
-#undef nsyscalls
-}

static int sched__get_first_possible_cpu(pid_t pid, cpu_set_t *maskp)
{
diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c
new file mode 100644
index 0000000..e174681
--- /dev/null
+++ b/tools/perf/tests/mmap-basic.c
@@ -0,0 +1,162 @@
+#include "evlist.h"
+#include "evsel.h"
+#include "thread_map.h"
+#include "cpumap.h"
+#include "tests.h"
+
+/*
+ * This test will generate random numbers of calls to some getpid syscalls,
+ * then establish an mmap for a group of events that are created to monitor
+ * the syscalls.
+ *
+ * It will receive the events, using mmap, use its PERF_SAMPLE_ID generated
+ * sample.id field to map back to its respective perf_evsel instance.
+ *
+ * Then it checks if the number of syscalls reported as perf events by
+ * the kernel corresponds to the number of syscalls made.
+ */
+int test__basic_mmap(void)
+{
+ int err = -1;
+ union perf_event *event;
+ struct thread_map *threads;
+ struct cpu_map *cpus;
+ struct perf_evlist *evlist;
+ struct perf_event_attr attr = {
+ .type = PERF_TYPE_TRACEPOINT,
+ .read_format = PERF_FORMAT_ID,
+ .sample_type = PERF_SAMPLE_ID,
+ .watermark = 0,
+ };
+ cpu_set_t cpu_set;
+ const char *syscall_names[] = { "getsid", "getppid", "getpgrp",
+ "getpgid", };
+ pid_t (*syscalls[])(void) = { (void *)getsid, getppid, getpgrp,
+ (void*)getpgid };
+#define nsyscalls ARRAY_SIZE(syscall_names)
+ int ids[nsyscalls];
+ unsigned int nr_events[nsyscalls],
+ expected_nr_events[nsyscalls], i, j;
+ struct perf_evsel *evsels[nsyscalls], *evsel;
+
+ for (i = 0; i < nsyscalls; ++i) {
+ char name[64];
+
+ snprintf(name, sizeof(name), "sys_enter_%s", syscall_names[i]);
+ ids[i] = trace_event__id(name);
+ if (ids[i] < 0) {
+ pr_debug("Is debugfs mounted on /sys/kernel/debug?\n");
+ return -1;
+ }
+ nr_events[i] = 0;
+ expected_nr_events[i] = random() % 257;
+ }
+
+ threads = thread_map__new(-1, getpid(), UINT_MAX);
+ if (threads == NULL) {
+ pr_debug("thread_map__new\n");
+ return -1;
+ }
+
+ cpus = cpu_map__new(NULL);
+ if (cpus == NULL) {
+ pr_debug("cpu_map__new\n");
+ goto out_free_threads;
+ }
+
+ CPU_ZERO(&cpu_set);
+ CPU_SET(cpus->map[0], &cpu_set);
+ sched_setaffinity(0, sizeof(cpu_set), &cpu_set);
+ if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) {
+ pr_debug("sched_setaffinity() failed on CPU %d: %s ",
+ cpus->map[0], strerror(errno));
+ goto out_free_cpus;
+ }
+
+ evlist = perf_evlist__new(cpus, threads);
+ if (evlist == NULL) {
+ pr_debug("perf_evlist__new\n");
+ goto out_free_cpus;
+ }
+
+ /* anonymous union fields, can't be initialized above */
+ attr.wakeup_events = 1;
+ attr.sample_period = 1;
+
+ for (i = 0; i < nsyscalls; ++i) {
+ attr.config = ids[i];
+ evsels[i] = perf_evsel__new(&attr, i);
+ if (evsels[i] == NULL) {
+ pr_debug("perf_evsel__new\n");
+ goto out_free_evlist;
+ }
+
+ perf_evlist__add(evlist, evsels[i]);
+
+ if (perf_evsel__open(evsels[i], cpus, threads) < 0) {
+ pr_debug("failed to open counter: %s, "
+ "tweak /proc/sys/kernel/perf_event_paranoid?\n",
+ strerror(errno));
+ goto out_close_fd;
+ }
+ }
+
+ if (perf_evlist__mmap(evlist, 128, true) < 0) {
+ pr_debug("failed to mmap events: %d (%s)\n", errno,
+ strerror(errno));
+ goto out_close_fd;
+ }
+
+ for (i = 0; i < nsyscalls; ++i)
+ for (j = 0; j < expected_nr_events[i]; ++j) {
+ int foo = syscalls[i]();
+ ++foo;
+ }
+
+ while ((event = perf_evlist__mmap_read(evlist, 0)) != NULL) {
+ struct perf_sample sample;
+
+ if (event->header.type != PERF_RECORD_SAMPLE) {
+ pr_debug("unexpected %s event\n",
+ perf_event__name(event->header.type));
+ goto out_munmap;
+ }
+
+ err = perf_evlist__parse_sample(evlist, event, &sample);
+ if (err) {
+ pr_err("Can't parse sample, err = %d\n", err);
+ goto out_munmap;
+ }
+
+ evsel = perf_evlist__id2evsel(evlist, sample.id);
+ if (evsel == NULL) {
+ pr_debug("event with id %" PRIu64
+ " doesn't map to an evsel\n", sample.id);
+ goto out_munmap;
+ }
+ nr_events[evsel->idx]++;
+ }
+
+ list_for_each_entry(evsel, &evlist->entries, node) {
+ if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) {
+ pr_debug("expected %d %s events, got %d\n",
+ expected_nr_events[evsel->idx],
+ perf_evsel__name(evsel), nr_events[evsel->idx]);
+ goto out_munmap;
+ }
+ }
+
+ err = 0;
+out_munmap:
+ perf_evlist__munmap(evlist);
+out_close_fd:
+ for (i = 0; i < nsyscalls; ++i)
+ perf_evsel__close_fd(evsels[i], 1, threads->nr);
+out_free_evlist:
+ perf_evlist__delete(evlist);
+out_free_cpus:
+ cpu_map__delete(cpus);
+out_free_threads:
+ thread_map__delete(threads);
+ return err;
+}
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index c2887f2..1a925dd 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -5,6 +5,7 @@
int test__vmlinux_matches_kallsyms(void);
int test__open_syscall_event(void);
int test__open_syscall_event_on_all_cpus(void);
+int test__basic_mmap(void);

/* Util */
int trace_event__id(const char *evname);
--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Nov 18, 2012, 9:40:04 AM11/18/12
to
From: Jiri Olsa <jo...@redhat.com>

Fixing events attributes for groups defined via '{}'.

Currently 'enable_on_exec' attribute in record command and both
'disabled ' and 'enable_on_exec' attributes in stat command are set
based on the 'group' option. This eliminates proper setup for '{}'
defined groups as they don't set 'group' option.

Making above attributes values based on the 'evsel->leader' as this is
common to both group definition.

Moving perf_evlist__set_leader call within builtin-record ahead
perf_evlist__config_attrs call, because the latter needs possible group
leader links in place.

Signed-off-by: Jiri Olsa <jo...@redhat.com>
Acked-by: Namhyung Kim <namh...@kernel.org>
Cc: Corey Ashford <cjas...@linux.vnet.ibm.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Ingo Molnar <mi...@elte.hu>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Link: http://lkml.kernel.org/r/1352741644-16809-2-...@redhat.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-record.c | 8 ++++++--
tools/perf/builtin-stat.c | 11 ++++-------
tools/perf/tests/attr/test-record-group1 | 4 +---
tools/perf/tests/attr/test-stat-group1 | 6 ++----
tools/perf/tests/open-syscall-tp-fields.c | 2 +-
tools/perf/util/evlist.c | 6 ++----
tools/perf/util/evsel.c | 8 +++-----
tools/perf/util/evsel.h | 3 +--
8 files changed, 20 insertions(+), 28 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 5783c32..3717027 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -230,11 +230,15 @@ static int perf_record__open(struct perf_record *rec)
struct perf_record_opts *opts = &rec->opts;
int rc = 0;

- perf_evlist__config_attrs(evlist, opts);
-
+ /*
+ * Set the evsel leader links before we configure attributes,
+ * since some might depend on this info.
+ */
if (opts->group)
perf_evlist__set_leader(evlist);

+ perf_evlist__config_attrs(evlist, opts);
+
list_for_each_entry(pos, &evlist->entries, node) {
struct perf_event_attr *attr = &pos->attr;
/*
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 6888960..557081e 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -129,8 +129,7 @@ static struct stats runtime_itlb_cache_stats[MAX_NR_CPUS];
static struct stats runtime_dtlb_cache_stats[MAX_NR_CPUS];
static struct stats walltime_nsecs_stats;

-static int create_perf_stat_counter(struct perf_evsel *evsel,
- struct perf_evsel *first)
+static int create_perf_stat_counter(struct perf_evsel *evsel)
{
struct perf_event_attr *attr = &evsel->attr;
bool exclude_guest_missing = false;
@@ -153,7 +152,7 @@ retry:
return 0;
}

- if (!perf_target__has_task(&target) && (!group || evsel == first)) {
+ if (!perf_target__has_task(&target) && (!evsel->leader)) {
attr->disabled = 1;
attr->enable_on_exec = 1;
}
@@ -272,7 +271,7 @@ static int read_counter(struct perf_evsel *counter)
static int __run_perf_stat(int argc __maybe_unused, const char **argv)
{
unsigned long long t0, t1;
- struct perf_evsel *counter, *first;
+ struct perf_evsel *counter;
int status = 0;
int child_ready_pipe[2], go_pipe[2];
const bool forks = (argc > 0);
@@ -332,10 +331,8 @@ static int __run_perf_stat(int argc __maybe_unused, const char **argv)
if (group)
perf_evlist__set_leader(evsel_list);

- first = perf_evlist__first(evsel_list);
-
list_for_each_entry(counter, &evsel_list->entries, node) {
- if (create_perf_stat_counter(counter, first) < 0) {
+ if (create_perf_stat_counter(counter) < 0) {
/*
* PPC returns ENXIO for HW counters until 2.6.37
* (behavior changed with commit b0a873e).
diff --git a/tools/perf/tests/attr/test-record-group1 b/tools/perf/tests/attr/test-record-group1
index 39bf860..013572f 100644
--- a/tools/perf/tests/attr/test-record-group1
+++ b/tools/perf/tests/attr/test-record-group1
@@ -15,6 +15,4 @@ config=1
sample_type=327
mmap=0
comm=0
-# TODO this is disabled for --group option, enabled otherwise
-# check why..
-enable_on_exec=1
+enable_on_exec=0
diff --git a/tools/perf/tests/attr/test-stat-group1 b/tools/perf/tests/attr/test-stat-group1
index 5ae2718..2a1f86e 100644
--- a/tools/perf/tests/attr/test-stat-group1
+++ b/tools/perf/tests/attr/test-stat-group1
@@ -11,7 +11,5 @@ group_fd=-1
fd=2
group_fd=1
config=1
-# TODO both disabled and enable_on_exec are disabled for --group option,
-# enabled otherwise, check why..
-disabled=1
-enable_on_exec=1
+disabled=0
+enable_on_exec=0
diff --git a/tools/perf/tests/open-syscall-tp-fields.c b/tools/perf/tests/open-syscall-tp-fields.c
index b05b6a6..1c52fdc 100644
--- a/tools/perf/tests/open-syscall-tp-fields.c
+++ b/tools/perf/tests/open-syscall-tp-fields.c
@@ -41,7 +41,7 @@ int test__syscall_open_tp_fields(void)
goto out_delete_evlist;
}

- perf_evsel__config(evsel, &opts, evsel);
+ perf_evsel__config(evsel, &opts);

evlist->threads->map[0] = getpid();

diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index a41dc4a..04acae0 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -52,15 +52,13 @@ struct perf_evlist *perf_evlist__new(struct cpu_map *cpus,
void perf_evlist__config_attrs(struct perf_evlist *evlist,
struct perf_record_opts *opts)
{
- struct perf_evsel *evsel, *first;
+ struct perf_evsel *evsel;

if (evlist->cpus->map[0] < 0)
opts->no_inherit = true;

- first = perf_evlist__first(evlist);
-
list_for_each_entry(evsel, &evlist->entries, node) {
- perf_evsel__config(evsel, opts, first);
+ perf_evsel__config(evsel, opts);

if (evlist->nr_entries > 1)
evsel->attr.sample_type |= PERF_SAMPLE_ID;
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 618d411..6d4a5f6 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -404,8 +404,8 @@ const char *perf_evsel__name(struct perf_evsel *evsel)
return evsel->name ?: "unknown";
}

-void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts,
- struct perf_evsel *first)
+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 */
@@ -486,10 +486,8 @@ void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts,
attr->mmap = track;
attr->comm = track;

- if (perf_target__none(&opts->target) &&
- (!opts->group || evsel == first)) {
+ if (perf_target__none(&opts->target) && (!evsel->leader))
attr->enable_on_exec = 1;
- }
}

int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 6f94d6d..32d7ec7 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -92,8 +92,7 @@ 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,
- struct perf_evsel *first);
+ struct perf_record_opts *opts);

bool perf_evsel__is_cache_op_valid(u8 type, u8 op);

--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Nov 18, 2012, 9:40:03 AM11/18/12
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

Not just nr_events and period.

Reported-by: Namhyung Kim <namh...@gmail.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Jiri Olsa <jo...@redhat.com>
Cc: Mike Galbraith <efa...@gmx.de>
Cc: Namhyung Kim <namh...@gmail.com>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Stephane Eranian <era...@google.com>
Link: http://lkml.kernel.org/n/tip-8nodd6b4by...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/hist.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 7c6e73b..cb17e2a 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -742,9 +742,8 @@ static struct hist_entry *hists__add_dummy_entry(struct hists *hists,

he = hist_entry__new(pair);
if (he) {
- he->stat.nr_events = 0;
- he->stat.period = 0;
- he->hists = hists;
+ memset(&he->stat, 0, sizeof(he->stat));
+ he->hists = hists;
rb_link_node(&he->rb_node, parent, p);
rb_insert_color(&he->rb_node, &hists->entries);
hists__inc_nr_entries(hists, he);
--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Nov 18, 2012, 9:40:03 AM11/18/12
to
From: David Howells <dhow...@redhat.com>

Fixing:

[acme@sandy linux]$ cd tools
[acme@sandy tools]$ make clean
DESCEND power/cpupower
CC lib/cpufreq.o
CC lib/sysfs.o
LD libcpupower.so.0.0.0
CC utils/helpers/amd.o
utils/helpers/amd.c:7:21: error: pci/pci.h: No such file or directory
In file included from utils/helpers/amd.c:9:
./utils/helpers/helpers.h:137: warning: ‘struct pci_access’ declared inside parameter list
./utils/helpers/helpers.h:137: warning: its scope is only this definition or declaration, which is probably not what you want
./utils/helpers/helpers.h:139: warning: ‘struct pci_access’ declared inside parameter list
utils/helpers/amd.c: In function ‘amd_pci_get_num_boost_states’:
utils/helpers/amd.c:120: warning: passing argument 1 of ‘pci_slot_func_init’ from incompatible pointer type
./utils/helpers/helpers.h:138: note: expected ‘struct pci_access **’ but argument is of type ‘struct pci_access **’
utils/helpers/amd.c:125: warning: implicit declaration of function ‘pci_read_byte’
utils/helpers/amd.c:132: warning: implicit declaration of function ‘pci_cleanup’
make[1]: *** [utils/helpers/amd.o] Error 1
make: *** [cpupower_clean] Error 2
[acme@sandy tools]$

Reported-by: Arnaldo Carvalho de Melo <ac...@ghostprotocols.net>
Signed-off-by: David Howells <dhow...@redhat.com>
Cc: Borislav Petkov <b...@amd64.org>
Cc: Ingo Molnar <mi...@kernel.org>
Cc: Linus Torvalds <torv...@linux-foundation.org>
Cc: Namhyung Kim <namh...@gmail.com>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Thomas Gleixner <tg...@linutronix.de>
Link: http://lkml.kernel.org/n/tip-tviyimq6x6...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/scripts/Makefile.include | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tools/scripts/Makefile.include b/tools/scripts/Makefile.include
index 87467b1..2964b96 100644
--- a/tools/scripts/Makefile.include
+++ b/tools/scripts/Makefile.include
@@ -51,7 +51,7 @@ endif
#
descend = \
+mkdir -p $(OUTPUT)$(1) && \
- $(MAKE) $(COMMAND_O) subdir=$(if $(subdir),$(subdir)/$(1),$(1)) $(PRINT_DIR) -C $(1)
+ $(MAKE) $(COMMAND_O) subdir=$(if $(subdir),$(subdir)/$(1),$(1)) $(PRINT_DIR) -C $(1) $(2)

QUIET_SUBDIR0 = +$(MAKE) $(COMMAND_O) -C # space to separate -C and subdir
QUIET_SUBDIR1 =
@@ -72,6 +72,6 @@ ifndef V
descend = \
@echo ' ' DESCEND $(1); \
mkdir -p $(OUTPUT)$(1) && \
- $(MAKE) $(COMMAND_O) subdir=$(if $(subdir),$(subdir)/$(1),$(1)) $(PRINT_DIR) -C $(1)
+ $(MAKE) $(COMMAND_O) subdir=$(if $(subdir),$(subdir)/$(1),$(1)) $(PRINT_DIR) -C $(1) $(2)
endif
endif
--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Nov 18, 2012, 9:40:04 AM11/18/12
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

To clarify what is being tested, instead of assuming that evsel->leader
== NULL means either an 'isolated' evsel or a 'group leader'.

Cc: David Ahern <dsa...@gmail.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Jiri Olsa <jo...@redhat.com>
Cc: Mike Galbraith <efa...@gmx.de>
Cc: Namhyung Kim <namh...@gmail.com>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Stephane Eranian <era...@google.com>
Link: http://lkml.kernel.org/n/tip-lvdbvimaxw...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-stat.c | 3 ++-
tools/perf/tests/parse-events.c | 20 ++++++++++----------
tools/perf/util/evlist.c | 4 ++--
tools/perf/util/evsel.c | 6 +++---
tools/perf/util/evsel.h | 6 ++++++
5 files changed, 23 insertions(+), 16 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 557081e..c247fac 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -152,7 +152,8 @@ retry:
return 0;
}

- if (!perf_target__has_task(&target) && (!evsel->leader)) {
+ if (!perf_target__has_task(&target) &&
+ !perf_evsel__is_group_member(evsel)) {
attr->disabled = 1;
attr->enable_on_exec = 1;
}
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c
index f2a82d0..42a0c8c 100644
--- a/tools/perf/tests/parse-events.c
+++ b/tools/perf/tests/parse-events.c
@@ -521,7 +521,7 @@ static int test__group1(struct perf_evlist *evlist)
TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
- TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL);
+ TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel));

/* cycles:upp */
evsel = perf_evsel__next(evsel);
@@ -557,7 +557,7 @@ static int test__group2(struct perf_evlist *evlist)
TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
- TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL);
+ TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel));

/* cache-references + :u modifier */
evsel = perf_evsel__next(evsel);
@@ -583,7 +583,7 @@ static int test__group2(struct perf_evlist *evlist)
TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
- TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL);
+ TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel));

return 0;
}
@@ -606,7 +606,7 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused)
TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
- TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL);
+ TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel));
TEST_ASSERT_VAL("wrong group name",
!strcmp(leader->group_name, "group1"));

@@ -636,7 +636,7 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused)
TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
- TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL);
+ TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel));
TEST_ASSERT_VAL("wrong group name",
!strcmp(leader->group_name, "group2"));

@@ -663,7 +663,7 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused)
TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
- TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL);
+ TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel));

return 0;
}
@@ -687,7 +687,7 @@ static int test__group4(struct perf_evlist *evlist __maybe_unused)
TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 1);
TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
- TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL);
+ TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel));

/* instructions:kp + p */
evsel = perf_evsel__next(evsel);
@@ -724,7 +724,7 @@ static int test__group5(struct perf_evlist *evlist __maybe_unused)
TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
- TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL);
+ TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel));

/* instructions + G */
evsel = perf_evsel__next(evsel);
@@ -751,7 +751,7 @@ static int test__group5(struct perf_evlist *evlist __maybe_unused)
TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
- TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL);
+ TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel));

/* instructions:G */
evsel = perf_evsel__next(evsel);
@@ -777,7 +777,7 @@ static int test__group5(struct perf_evlist *evlist __maybe_unused)
TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
- TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL);
+ TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel));

return 0;
}
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index e9d2d5d..7052934 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -222,7 +222,7 @@ void perf_evlist__disable(struct perf_evlist *evlist)

for (cpu = 0; cpu < evlist->cpus->nr; cpu++) {
list_for_each_entry(pos, &evlist->entries, node) {
- if (pos->leader)
+ if (perf_evsel__is_group_member(pos))
continue;
for (thread = 0; thread < evlist->threads->nr; thread++)
ioctl(FD(pos, cpu, thread),
@@ -238,7 +238,7 @@ void perf_evlist__enable(struct perf_evlist *evlist)

for (cpu = 0; cpu < cpu_map__nr(evlist->cpus); cpu++) {
list_for_each_entry(pos, &evlist->entries, node) {
- if (pos->leader)
+ if (perf_evsel__is_group_member(pos))
continue;
for (thread = 0; thread < evlist->threads->nr; thread++)
ioctl(FD(pos, cpu, thread),
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index fc4faaa..1fb636c 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -519,14 +519,14 @@ void perf_evsel__config(struct perf_evsel *evsel,
* Disabling only independent events or group leaders,
* keeping group members enabled.
*/
- if (!evsel->leader)
+ if (!perf_evsel__is_group_member(evsel))
attr->disabled = 1;

/*
* Setting enable_on_exec for independent events and
* group leaders for traced executed by perf.
*/
- if (perf_target__none(&opts->target) && (!evsel->leader))
+ if (perf_target__none(&opts->target) && !perf_evsel__is_group_member(evsel))
attr->enable_on_exec = 1;
}

@@ -707,7 +707,7 @@ static int get_group_fd(struct perf_evsel *evsel, int cpu, int thread)
struct perf_evsel *leader = evsel->leader;
int fd;

- if (!leader)
+ if (!perf_evsel__is_group_member(evsel))
return -1;

/*
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 32d7ec7..a4c1dd4 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -3,6 +3,7 @@

#include <linux/list.h>
#include <stdbool.h>
+#include <stddef.h>
#include "../../../include/uapi/linux/perf_event.h"
#include "types.h"
#include "xyarray.h"
@@ -224,4 +225,9 @@ static inline struct perf_evsel *perf_evsel__next(struct perf_evsel *evsel)
{
return list_entry(evsel->node.next, struct perf_evsel, node);
}
+
+static inline bool perf_evsel__is_group_member(const struct perf_evsel *evsel)
+{
+ return evsel->leader != NULL;
+}
#endif /* __PERF_EVSEL_H */
--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Nov 18, 2012, 9:40:04 AM11/18/12
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

As suggested by tglx long ago.

Cc: David Ahern <dsa...@gmail.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Jiri Olsa <jo...@redhat.com>
Cc: Mike Galbraith <efa...@gmx.de>
Cc: Namhyung Kim <namh...@gmail.com>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Stephane Eranian <era...@google.com>
Link: http://lkml.kernel.org/n/tip-zgcldbjno4...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/pstack.c | 46 +++++++++++++++++++++++-----------------------
1 file changed, 23 insertions(+), 23 deletions(-)

diff --git a/tools/perf/util/pstack.c b/tools/perf/util/pstack.c
index 13d36fa..daa17ae 100644
--- a/tools/perf/util/pstack.c
+++ b/tools/perf/util/pstack.c
@@ -17,59 +17,59 @@ struct pstack {

struct pstack *pstack__new(unsigned short max_nr_entries)
{
- struct pstack *self = zalloc((sizeof(*self) +
- max_nr_entries * sizeof(void *)));
- if (self != NULL)
- self->max_nr_entries = max_nr_entries;
- return self;
+ struct pstack *pstack = zalloc((sizeof(*pstack) +
+ max_nr_entries * sizeof(void *)));
+ if (pstack != NULL)
+ pstack->max_nr_entries = max_nr_entries;
+ return pstack;
}

-void pstack__delete(struct pstack *self)
+void pstack__delete(struct pstack *pstack)
{
- free(self);
+ free(pstack);
}

-bool pstack__empty(const struct pstack *self)
+bool pstack__empty(const struct pstack *pstack)
{
- return self->top == 0;
+ return pstack->top == 0;
}

-void pstack__remove(struct pstack *self, void *key)
+void pstack__remove(struct pstack *pstack, void *key)
{
- unsigned short i = self->top, last_index = self->top - 1;
+ unsigned short i = pstack->top, last_index = pstack->top - 1;

while (i-- != 0) {
- if (self->entries[i] == key) {
+ if (pstack->entries[i] == key) {
if (i < last_index)
- memmove(self->entries + i,
- self->entries + i + 1,
+ memmove(pstack->entries + i,
+ pstack->entries + i + 1,
(last_index - i) * sizeof(void *));
- --self->top;
+ --pstack->top;
return;
}
}
pr_err("%s: %p not on the pstack!\n", __func__, key);
}

-void pstack__push(struct pstack *self, void *key)
+void pstack__push(struct pstack *pstack, void *key)
{
- if (self->top == self->max_nr_entries) {
- pr_err("%s: top=%d, overflow!\n", __func__, self->top);
+ if (pstack->top == pstack->max_nr_entries) {
+ pr_err("%s: top=%d, overflow!\n", __func__, pstack->top);
return;
}
- self->entries[self->top++] = key;
+ pstack->entries[pstack->top++] = key;
}

-void *pstack__pop(struct pstack *self)
+void *pstack__pop(struct pstack *pstack)
{
void *ret;

- if (self->top == 0) {
+ if (pstack->top == 0) {
pr_err("%s: underflow!\n", __func__);
return NULL;
}

- ret = self->entries[--self->top];
- self->entries[self->top] = NULL;
+ ret = pstack->entries[--pstack->top];
+ pstack->entries[pstack->top] = NULL;
return ret;
}
--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Nov 18, 2012, 9:40:04 AM11/18/12
to
From: Namhyung Kim <namhyu...@lge.com>

Add config option for launching GTK browser for the specified command by
default. Currently only 'report' command is supported.

Adding following line to the perfconfig file will have a same effect of
specifying --gtk option on command line (unless other related options
are not given).

$ cat ~/.perfconfig
[gtk]
report = true

Signed-off-by: Namhyung Kim <namh...@kernel.org>
Acked-by: Pekka Enberg <pen...@kernel.org>
Cc: Ingo Molnar <mi...@kernel.org>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Pekka Enberg <pen...@kernel.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Link: http://lkml.kernel.org/r/1352688617-25570-1-gi...@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/perf.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index a0ae290..0f661fb 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -85,21 +85,26 @@ int check_pager_config(const char *cmd)
return c.val;
}

-static int tui_command_config(const char *var, const char *value, void *data)
+static int browser_command_config(const char *var, const char *value, void *data)
{
struct pager_config *c = data;
if (!prefixcmp(var, "tui.") && !strcmp(var + 4, c->cmd))
c->val = perf_config_bool(var, value);
+ if (!prefixcmp(var, "gtk.") && !strcmp(var + 4, c->cmd))
+ c->val = perf_config_bool(var, value) ? 2 : 0;
return 0;
}

-/* returns 0 for "no tui", 1 for "use tui", and -1 for "not specified" */
-static int check_tui_config(const char *cmd)
+/*
+ * returns 0 for "no tui", 1 for "use tui", 2 for "use gtk",
+ * and -1 for "not specified"
+ */
+static int check_browser_config(const char *cmd)
{
struct pager_config c;
c.cmd = cmd;
c.val = -1;
- perf_config(tui_command_config, &c);
+ perf_config(browser_command_config, &c);
return c.val;
}

@@ -302,7 +307,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
prefix = NULL; /* setup_perf_directory(); */

if (use_browser == -1)
- use_browser = check_tui_config(p->cmd);
+ use_browser = check_browser_config(p->cmd);

if (use_pager == -1 && p->option & RUN_SETUP)
use_pager = check_pager_config(p->cmd);
--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Nov 18, 2012, 9:40:04 AM11/18/12
to
From: Jiri Olsa <jo...@redhat.com>

Separating test__vmlinux_matches_kallsyms test from the builtin-test
into vmlinux-kallsyms object.

Signed-off-by: Jiri Olsa <jo...@redhat.com>
Cc: Corey Ashford <cjas...@linux.vnet.ibm.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Ingo Molnar <mi...@elte.hu>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Link: http://lkml.kernel.org/r/1352508412-16914-2-...@redhat.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/Makefile | 1 +
tools/perf/tests/builtin-test.c | 223 +--------------------------------
tools/perf/tests/tests.h | 6 +
tools/perf/tests/vmlinux-kallsyms.c | 230 +++++++++++++++++++++++++++++++++++
4 files changed, 239 insertions(+), 221 deletions(-)
create mode 100644 tools/perf/tests/tests.h
create mode 100644 tools/perf/tests/vmlinux-kallsyms.c

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index cca5bb8..7c7ba4d 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -431,6 +431,7 @@ LIB_OBJS += $(OUTPUT)arch/common.o
LIB_OBJS += $(OUTPUT)tests/parse-events.o
LIB_OBJS += $(OUTPUT)tests/dso-data.o
LIB_OBJS += $(OUTPUT)tests/attr.o
+LIB_OBJS += $(OUTPUT)tests/vmlinux-kallsyms.o

BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 5d4354e..5bc9063 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -21,231 +21,12 @@

#include <sys/mman.h>

-static int vmlinux_matches_kallsyms_filter(struct map *map __maybe_unused,
- struct symbol *sym)
-{
- bool *visited = symbol__priv(sym);
- *visited = true;
- return 0;
-}
-
-static int test__vmlinux_matches_kallsyms(void)
-{
- int err = -1;
- struct rb_node *nd;
- struct symbol *sym;
- struct map *kallsyms_map, *vmlinux_map;
- struct machine kallsyms, vmlinux;
- enum map_type type = MAP__FUNCTION;
- struct ref_reloc_sym ref_reloc_sym = { .name = "_stext", };
-
- /*
- * Step 1:
- *
- * Init the machines that will hold kernel, modules obtained from
- * both vmlinux + .ko files and from /proc/kallsyms split by modules.
- */
- machine__init(&kallsyms, "", HOST_KERNEL_ID);
- machine__init(&vmlinux, "", HOST_KERNEL_ID);
-
- /*
- * Step 2:
- *
- * Create the kernel maps for kallsyms and the DSO where we will then
- * load /proc/kallsyms. Also create the modules maps from /proc/modules
- * and find the .ko files that match them in /lib/modules/`uname -r`/.
- */
- if (machine__create_kernel_maps(&kallsyms) < 0) {
- pr_debug("machine__create_kernel_maps ");
- return -1;
- }
-
- /*
- * Step 3:
- *
- * Load and split /proc/kallsyms into multiple maps, one per module.
- */
- if (machine__load_kallsyms(&kallsyms, "/proc/kallsyms", type, NULL) <= 0) {
- pr_debug("dso__load_kallsyms ");
- goto out;
- }
-
- /*
- * Step 4:
- *
- * kallsyms will be internally on demand sorted by name so that we can
- * find the reference relocation * symbol, i.e. the symbol we will use
- * to see if the running kernel was relocated by checking if it has the
- * same value in the vmlinux file we load.
- */
- kallsyms_map = machine__kernel_map(&kallsyms, type);
-
- sym = map__find_symbol_by_name(kallsyms_map, ref_reloc_sym.name, NULL);
- if (sym == NULL) {
- pr_debug("dso__find_symbol_by_name ");
- goto out;
- }
-
- ref_reloc_sym.addr = sym->start;
-
- /*
- * Step 5:
- *
- * Now repeat step 2, this time for the vmlinux file we'll auto-locate.
- */
- if (machine__create_kernel_maps(&vmlinux) < 0) {
- pr_debug("machine__create_kernel_maps ");
- goto out;
- }
-
- vmlinux_map = machine__kernel_map(&vmlinux, type);
- map__kmap(vmlinux_map)->ref_reloc_sym = &ref_reloc_sym;
-
- /*
- * Step 6:
- *
- * Locate a vmlinux file in the vmlinux path that has a buildid that
- * matches the one of the running kernel.
- *
- * While doing that look if we find the ref reloc symbol, if we find it
- * we'll have its ref_reloc_symbol.unrelocated_addr and then
- * maps__reloc_vmlinux will notice and set proper ->[un]map_ip routines
- * to fixup the symbols.
- */
- if (machine__load_vmlinux_path(&vmlinux, type,
- vmlinux_matches_kallsyms_filter) <= 0) {
- pr_debug("machine__load_vmlinux_path ");
- goto out;
- }
-
- err = 0;
- /*
- * Step 7:
- *
- * Now look at the symbols in the vmlinux DSO and check if we find all of them
- * in the kallsyms dso. For the ones that are in both, check its names and
- * end addresses too.
- */
- for (nd = rb_first(&vmlinux_map->dso->symbols[type]); nd; nd = rb_next(nd)) {
- struct symbol *pair, *first_pair;
- bool backwards = true;
-
- sym = rb_entry(nd, struct symbol, rb_node);
-
- if (sym->start == sym->end)
- continue;
-
- first_pair = machine__find_kernel_symbol(&kallsyms, type, sym->start, NULL, NULL);
- pair = first_pair;
-
- if (pair && pair->start == sym->start) {
-next_pair:
- if (strcmp(sym->name, pair->name) == 0) {
- /*
- * kallsyms don't have the symbol end, so we
- * set that by using the next symbol start - 1,
- * in some cases we get this up to a page
- * wrong, trace_kmalloc when I was developing
- * this code was one such example, 2106 bytes
- * off the real size. More than that and we
- * _really_ have a problem.
- */
- s64 skew = sym->end - pair->end;
- if (llabs(skew) < page_size)
- continue;
-
- pr_debug("%#" PRIx64 ": diff end addr for %s v: %#" PRIx64 " k: %#" PRIx64 "\n",
- sym->start, sym->name, sym->end, pair->end);
- } else {
- struct rb_node *nnd;
-detour:
- nnd = backwards ? rb_prev(&pair->rb_node) :
- rb_next(&pair->rb_node);
- if (nnd) {
- struct symbol *next = rb_entry(nnd, struct symbol, rb_node);
-
- if (next->start == sym->start) {
- pair = next;
- goto next_pair;
- }
- }
-
- if (backwards) {
- backwards = false;
- pair = first_pair;
- goto detour;
- }
-
- pr_debug("%#" PRIx64 ": diff name v: %s k: %s\n",
- sym->start, sym->name, pair->name);
- }
- } else
- pr_debug("%#" PRIx64 ": %s not on kallsyms\n", sym->start, sym->name);
-
- err = -1;
- }
-
- if (!verbose)
- goto out;
-
- pr_info("Maps only in vmlinux:\n");
-
- for (nd = rb_first(&vmlinux.kmaps.maps[type]); nd; nd = rb_next(nd)) {
- struct map *pos = rb_entry(nd, struct map, rb_node), *pair;
- /*
- * If it is the kernel, kallsyms is always "[kernel.kallsyms]", while
- * the kernel will have the path for the vmlinux file being used,
- * so use the short name, less descriptive but the same ("[kernel]" in
- * both cases.
- */
- pair = map_groups__find_by_name(&kallsyms.kmaps, type,
- (pos->dso->kernel ?
- pos->dso->short_name :
- pos->dso->name));
- if (pair)
- pair->priv = 1;
- else
- map__fprintf(pos, stderr);
- }
-
- pr_info("Maps in vmlinux with a different name in kallsyms:\n");
-
- for (nd = rb_first(&vmlinux.kmaps.maps[type]); nd; nd = rb_next(nd)) {
- struct map *pos = rb_entry(nd, struct map, rb_node), *pair;
-
- pair = map_groups__find(&kallsyms.kmaps, type, pos->start);
- if (pair == NULL || pair->priv)
- continue;
-
- if (pair->start == pos->start) {
- pair->priv = 1;
- pr_info(" %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s in kallsyms as",
- pos->start, pos->end, pos->pgoff, pos->dso->name);
- if (pos->pgoff != pair->pgoff || pos->end != pair->end)
- pr_info(": \n*%" PRIx64 "-%" PRIx64 " %" PRIx64 "",
- pair->start, pair->end, pair->pgoff);
- pr_info(" %s\n", pair->dso->name);
- pair->priv = 1;
- }
- }
-
- pr_info("Maps only in kallsyms:\n");
-
- for (nd = rb_first(&kallsyms.kmaps.maps[type]);
- nd; nd = rb_next(nd)) {
- struct map *pos = rb_entry(nd, struct map, rb_node);
-
- if (!pos->priv)
- map__fprintf(pos, stderr);
- }
-out:
- return err;
-}
-
#include "util/cpumap.h"
#include "util/evsel.h"
#include <sys/types.h>

+#include "tests.h"
+
static int trace_event__id(const char *evname)
{
char *filename;
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
new file mode 100644
index 0000000..2223de5
--- /dev/null
+++ b/tools/perf/tests/tests.h
@@ -0,0 +1,6 @@
+#ifndef TESTS_H
+#define TESTS_H
+
+int test__vmlinux_matches_kallsyms(void);
+
+#endif /* TESTS_H */
diff --git a/tools/perf/tests/vmlinux-kallsyms.c b/tools/perf/tests/vmlinux-kallsyms.c
new file mode 100644
index 0000000..0d1cdbe
--- /dev/null
+++ b/tools/perf/tests/vmlinux-kallsyms.c
@@ -0,0 +1,230 @@
+#include <linux/compiler.h>
+#include <linux/rbtree.h>
+#include <string.h>
+#include "map.h"
+#include "symbol.h"
+#include "util.h"
+#include "tests.h"
+#include "debug.h"
+#include "machine.h"
+
+static int vmlinux_matches_kallsyms_filter(struct map *map __maybe_unused,
+ struct symbol *sym)
+{
+ bool *visited = symbol__priv(sym);
+ *visited = true;
+ return 0;
+}
+
+int test__vmlinux_matches_kallsyms(void)
+{
+ int err = -1;
+ struct rb_node *nd;
+ struct symbol *sym;
+ struct map *kallsyms_map, *vmlinux_map;
+ struct machine kallsyms, vmlinux;
+ enum map_type type = MAP__FUNCTION;
+ struct ref_reloc_sym ref_reloc_sym = { .name = "_stext", };
+
+ /*
+ * Step 1:
+ *
+ * Init the machines that will hold kernel, modules obtained from
+ * both vmlinux + .ko files and from /proc/kallsyms split by modules.
+ */
+ machine__init(&kallsyms, "", HOST_KERNEL_ID);
+ machine__init(&vmlinux, "", HOST_KERNEL_ID);
+
+ /*
+ * Step 2:
+ *
+ * Create the kernel maps for kallsyms and the DSO where we will then
+ * load /proc/kallsyms. Also create the modules maps from /proc/modules
+ * and find the .ko files that match them in /lib/modules/`uname -r`/.
+ */
+ if (machine__create_kernel_maps(&kallsyms) < 0) {
+ pr_debug("machine__create_kernel_maps ");
+ return -1;
+ }
+
+ /*
+ * Step 3:
+ *
+ * Load and split /proc/kallsyms into multiple maps, one per module.
+ */
+ if (machine__load_kallsyms(&kallsyms, "/proc/kallsyms", type, NULL) <= 0) {
+ pr_debug("dso__load_kallsyms ");
+ goto out;
+ }
+
+ /*
+ * Step 4:
+ *
+ * kallsyms will be internally on demand sorted by name so that we can
+ * find the reference relocation * symbol, i.e. the symbol we will use
+ * to see if the running kernel was relocated by checking if it has the
+ * same value in the vmlinux file we load.
+ */
+ kallsyms_map = machine__kernel_map(&kallsyms, type);
+
+ sym = map__find_symbol_by_name(kallsyms_map, ref_reloc_sym.name, NULL);
+ if (sym == NULL) {
+ pr_debug("dso__find_symbol_by_name ");
+ goto out;
+ }
+
+ ref_reloc_sym.addr = sym->start;
+
+ /*
+ * Step 5:
+ *
+ * Now repeat step 2, this time for the vmlinux file we'll auto-locate.
+ */
+ if (machine__create_kernel_maps(&vmlinux) < 0) {
+ pr_debug("machine__create_kernel_maps ");
+ goto out;
+ }
+
+ vmlinux_map = machine__kernel_map(&vmlinux, type);
+ map__kmap(vmlinux_map)->ref_reloc_sym = &ref_reloc_sym;
+
+ /*
+ * Step 6:
+ *
+ * Locate a vmlinux file in the vmlinux path that has a buildid that
+ * matches the one of the running kernel.
+ *
+ * While doing that look if we find the ref reloc symbol, if we find it
+ * we'll have its ref_reloc_symbol.unrelocated_addr and then
+ * maps__reloc_vmlinux will notice and set proper ->[un]map_ip routines
+ * to fixup the symbols.
+ */
+ if (machine__load_vmlinux_path(&vmlinux, type,
+ vmlinux_matches_kallsyms_filter) <= 0) {
+ pr_debug("machine__load_vmlinux_path ");
+ goto out;
+ }
+
+ err = 0;
+ /*
+ * Step 7:
+ *
+ * Now look at the symbols in the vmlinux DSO and check if we find all of them
+ * in the kallsyms dso. For the ones that are in both, check its names and
+ * end addresses too.
+ */
+ for (nd = rb_first(&vmlinux_map->dso->symbols[type]); nd; nd = rb_next(nd)) {
+ struct symbol *pair, *first_pair;
+ bool backwards = true;
+
+ sym = rb_entry(nd, struct symbol, rb_node);
+
+ if (sym->start == sym->end)
+ continue;
+
+ first_pair = machine__find_kernel_symbol(&kallsyms, type, sym->start, NULL, NULL);
+ pair = first_pair;
+
+ if (pair && pair->start == sym->start) {
+next_pair:
+ if (strcmp(sym->name, pair->name) == 0) {
+ /*
+ * kallsyms don't have the symbol end, so we
+ * set that by using the next symbol start - 1,
+ * in some cases we get this up to a page
+ * wrong, trace_kmalloc when I was developing
+ * this code was one such example, 2106 bytes
+ * off the real size. More than that and we
+ * _really_ have a problem.
+ */
+ s64 skew = sym->end - pair->end;
+ if (llabs(skew) < page_size)
+ continue;
+
+ pr_debug("%#" PRIx64 ": diff end addr for %s v: %#" PRIx64 " k: %#" PRIx64 "\n",
+ sym->start, sym->name, sym->end, pair->end);
+ } else {
+ struct rb_node *nnd;
+detour:
+ nnd = backwards ? rb_prev(&pair->rb_node) :
+ rb_next(&pair->rb_node);
+ if (nnd) {
+ struct symbol *next = rb_entry(nnd, struct symbol, rb_node);
+
+ if (next->start == sym->start) {
+ pair = next;
+ goto next_pair;
+ }
+ }
+
+ if (backwards) {
+ backwards = false;
+ pair = first_pair;
+ goto detour;
+ }
+
+ pr_debug("%#" PRIx64 ": diff name v: %s k: %s\n",
+ sym->start, sym->name, pair->name);
+ }
+ } else
+ pr_debug("%#" PRIx64 ": %s not on kallsyms\n", sym->start, sym->name);
+
+ err = -1;
+ }
+
+ if (!verbose)
+ goto out;
+
+ pr_info("Maps only in vmlinux:\n");
+
+ for (nd = rb_first(&vmlinux.kmaps.maps[type]); nd; nd = rb_next(nd)) {
+ struct map *pos = rb_entry(nd, struct map, rb_node), *pair;
+ /*
+ * If it is the kernel, kallsyms is always "[kernel.kallsyms]", while
+ * the kernel will have the path for the vmlinux file being used,
+ * so use the short name, less descriptive but the same ("[kernel]" in
+ * both cases.
+ */
+ pair = map_groups__find_by_name(&kallsyms.kmaps, type,
+ (pos->dso->kernel ?
+ pos->dso->short_name :
+ pos->dso->name));
+ if (pair)
+ pair->priv = 1;
+ else
+ map__fprintf(pos, stderr);
+ }
+
+ pr_info("Maps in vmlinux with a different name in kallsyms:\n");
+
+ for (nd = rb_first(&vmlinux.kmaps.maps[type]); nd; nd = rb_next(nd)) {
+ struct map *pos = rb_entry(nd, struct map, rb_node), *pair;
+
+ pair = map_groups__find(&kallsyms.kmaps, type, pos->start);
+ if (pair == NULL || pair->priv)
+ continue;
+
+ if (pair->start == pos->start) {
+ pair->priv = 1;
+ pr_info(" %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s in kallsyms as",
+ pos->start, pos->end, pos->pgoff, pos->dso->name);
+ if (pos->pgoff != pair->pgoff || pos->end != pair->end)
+ pr_info(": \n*%" PRIx64 "-%" PRIx64 " %" PRIx64 "",
+ pair->start, pair->end, pair->pgoff);
+ pr_info(" %s\n", pair->dso->name);
+ pair->priv = 1;
+ }
+ }
+
+ pr_info("Maps only in kallsyms:\n");
+
+ for (nd = rb_first(&kallsyms.kmaps.maps[type]);
+ nd; nd = rb_next(nd)) {
+ struct map *pos = rb_entry(nd, struct map, rb_node);
+
+ if (!pos->priv)
+ map__fprintf(pos, stderr);
+ }
+out:
+ return err;
+}
--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Nov 18, 2012, 9:40:04 AM11/18/12
to
From: Sukadev Bhattiprolu <suk...@linux.vnet.ibm.com>

Use the 'unistd.h' from arch/powerpc/include/uapi to build the perf tool.

Signed-off-by: Sukadev Bhattiprolu <suk...@linux.vnet.ibm.com>
Acked-by: David Howells <dhow...@redhat.com>
Cc: Anton Blanchard <an...@au1.ibm.com>
Cc: Ingo Molnar <mi...@redhat.com>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Cc: Robert Richter <robert....@amd.com>
Cc: linuxp...@ozlabs.org
Link: http://lkml.kernel.org/r/20121107191...@us.ibm.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/perf.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 0047264..f53ee0b 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -26,7 +26,7 @@ void get_term_dimensions(struct winsize *ws);
#endif

#ifdef __powerpc__
-#include "../../arch/powerpc/include/asm/unistd.h"
+#include "../../arch/powerpc/include/uapi/asm/unistd.h"
#define rmb() asm volatile ("sync" ::: "memory")
#define cpu_relax() asm volatile ("" ::: "memory");
#define CPUINFO_PROC "cpu"
--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Nov 18, 2012, 9:40:04 AM11/18/12
to
From: Jiri Olsa <jo...@redhat.com>

There's no need to disable/enable ordinary group member events,
because they are initialy enabled and get scheduled by the leader.

Signed-off-by: Jiri Olsa <jo...@redhat.com>
Acked-by: Namhyung Kim <namh...@kernel.org>
Cc: Corey Ashford <cjas...@linux.vnet.ibm.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Ingo Molnar <mi...@elte.hu>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Link: http://lkml.kernel.org/r/1352741644-16809-5-...@redhat.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/evlist.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 04acae0..e9d2d5d 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -222,6 +222,8 @@ void perf_evlist__disable(struct perf_evlist *evlist)

for (cpu = 0; cpu < evlist->cpus->nr; cpu++) {
list_for_each_entry(pos, &evlist->entries, node) {
+ if (pos->leader)
+ continue;
for (thread = 0; thread < evlist->threads->nr; thread++)
ioctl(FD(pos, cpu, thread),
PERF_EVENT_IOC_DISABLE, 0);
@@ -236,6 +238,8 @@ void perf_evlist__enable(struct perf_evlist *evlist)

for (cpu = 0; cpu < cpu_map__nr(evlist->cpus); cpu++) {
list_for_each_entry(pos, &evlist->entries, node) {
+ if (pos->leader)
+ continue;
for (thread = 0; thread < evlist->threads->nr; thread++)
ioctl(FD(pos, cpu, thread),
PERF_EVENT_IOC_ENABLE, 0);
--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Nov 18, 2012, 9:40:03 AM11/18/12
to
From: Jiri Olsa <jo...@redhat.com>

Separating test__syscall_open_tp_fields test from the builtin-test into
open-syscall-tp-fields object.

Signed-off-by: Jiri Olsa <jo...@redhat.com>
Cc: Corey Ashford <cjas...@linux.vnet.ibm.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Ingo Molnar <mi...@elte.hu>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Link: http://lkml.kernel.org/r/1352508412-16914-10-...@redhat.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/Makefile | 1 +
tools/perf/tests/builtin-test.c | 112 ---------------------------
tools/perf/tests/open-syscall-tp-fields.c | 117 +++++++++++++++++++++++++++++
tools/perf/tests/tests.h | 1 +
4 files changed, 119 insertions(+), 112 deletions(-)
create mode 100644 tools/perf/tests/open-syscall-tp-fields.c

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index e510b53..1e50559 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -434,6 +434,7 @@ LIB_OBJS += $(OUTPUT)tests/attr.o
LIB_OBJS += $(OUTPUT)tests/vmlinux-kallsyms.o
LIB_OBJS += $(OUTPUT)tests/open-syscall.o
LIB_OBJS += $(OUTPUT)tests/open-syscall-all-cpus.o
+LIB_OBJS += $(OUTPUT)tests/open-syscall-tp-fields.o
LIB_OBJS += $(OUTPUT)tests/mmap-basic.o
LIB_OBJS += $(OUTPUT)tests/perf-record.o
LIB_OBJS += $(OUTPUT)tests/rdpmc.o
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index c66caa7..bab8490 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -35,118 +35,6 @@ static int test__perf_pmu(void)
return perf_pmu__test();
}

-static int test__syscall_open_tp_fields(void)
-{
- struct perf_record_opts opts = {
- .target = {
- .uid = UINT_MAX,
- .uses_mmap = true,
- },
- .no_delay = true,
- .freq = 1,
- .mmap_pages = 256,
- .raw_samples = true,
- };
- const char *filename = "/etc/passwd";
- int flags = O_RDONLY | O_DIRECTORY;
- struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
- struct perf_evsel *evsel;
- int err = -1, i, nr_events = 0, nr_polls = 0;
-
- if (evlist == NULL) {
- pr_debug("%s: perf_evlist__new\n", __func__);
- goto out;
- }
-
- evsel = perf_evsel__newtp("syscalls", "sys_enter_open", 0);
- if (evsel == NULL) {
- pr_debug("%s: perf_evsel__newtp\n", __func__);
- goto out_delete_evlist;
- }
-
- perf_evlist__add(evlist, evsel);
-
- err = perf_evlist__create_maps(evlist, &opts.target);
- if (err < 0) {
- pr_debug("%s: perf_evlist__create_maps\n", __func__);
- goto out_delete_evlist;
- }
-
- perf_evsel__config(evsel, &opts, evsel);
-
- evlist->threads->map[0] = getpid();
-
- err = perf_evlist__open(evlist);
- if (err < 0) {
- pr_debug("perf_evlist__open: %s\n", strerror(errno));
- goto out_delete_evlist;
- }
-
- err = perf_evlist__mmap(evlist, UINT_MAX, false);
- if (err < 0) {
- pr_debug("perf_evlist__mmap: %s\n", strerror(errno));
- goto out_delete_evlist;
- }
-
- perf_evlist__enable(evlist);
-
- /*
- * Generate the event:
- */
- open(filename, flags);
-
- while (1) {
- int before = nr_events;
-
- for (i = 0; i < evlist->nr_mmaps; i++) {
- union perf_event *event;
-
- while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
- const u32 type = event->header.type;
- int tp_flags;
- struct perf_sample sample;
-
- ++nr_events;
-
- if (type != PERF_RECORD_SAMPLE)
- continue;
-
- err = perf_evsel__parse_sample(evsel, event, &sample);
- if (err) {
- pr_err("Can't parse sample, err = %d\n", err);
- goto out_munmap;
- }
-
- tp_flags = perf_evsel__intval(evsel, &sample, "flags");
-
- if (flags != tp_flags) {
- pr_debug("%s: Expected flags=%#x, got %#x\n",
- __func__, flags, tp_flags);
- goto out_munmap;
- }
-
- goto out_ok;
- }
- }
-
- if (nr_events == before)
- poll(evlist->pollfd, evlist->nr_fds, 10);
-
- if (++nr_polls > 5) {
- pr_debug("%s: no events!\n", __func__);
- goto out_munmap;
- }
- }
-out_ok:
- err = 0;
-out_munmap:
- perf_evlist__munmap(evlist);
-out_delete_evlist:
- perf_evlist__delete(evlist);
-out:
- return err;
-}
-
static struct test {
const char *desc;
int (*func)(void);
diff --git a/tools/perf/tests/open-syscall-tp-fields.c b/tools/perf/tests/open-syscall-tp-fields.c
new file mode 100644
index 0000000..b05b6a6
--- /dev/null
+++ b/tools/perf/tests/open-syscall-tp-fields.c
@@ -0,0 +1,117 @@
+#include "perf.h"
+#include "evlist.h"
+#include "evsel.h"
+#include "thread_map.h"
+#include "tests.h"
+
+int test__syscall_open_tp_fields(void)
+{
+ struct perf_record_opts opts = {
+ .target = {
+ .uid = UINT_MAX,
+ .uses_mmap = true,
+ },
+ .no_delay = true,
+ .freq = 1,
+ .mmap_pages = 256,
+ .raw_samples = true,
+ };
+ const char *filename = "/etc/passwd";
+ int flags = O_RDONLY | O_DIRECTORY;
+ struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
+ struct perf_evsel *evsel;
+ int err = -1, i, nr_events = 0, nr_polls = 0;
+
+ if (evlist == NULL) {
+ pr_debug("%s: perf_evlist__new\n", __func__);
+ goto out;
+ }
+
+ evsel = perf_evsel__newtp("syscalls", "sys_enter_open", 0);
+ if (evsel == NULL) {
+ pr_debug("%s: perf_evsel__newtp\n", __func__);
+ goto out_delete_evlist;
+ }
+
+ perf_evlist__add(evlist, evsel);
+
+ err = perf_evlist__create_maps(evlist, &opts.target);
+ if (err < 0) {
+ pr_debug("%s: perf_evlist__create_maps\n", __func__);
+ goto out_delete_evlist;
+ }
+
+ perf_evsel__config(evsel, &opts, evsel);
+
+ evlist->threads->map[0] = getpid();
+
+ err = perf_evlist__open(evlist);
+ if (err < 0) {
+ pr_debug("perf_evlist__open: %s\n", strerror(errno));
+ goto out_delete_evlist;
+ }
+
+ err = perf_evlist__mmap(evlist, UINT_MAX, false);
+ if (err < 0) {
+ pr_debug("perf_evlist__mmap: %s\n", strerror(errno));
+ goto out_delete_evlist;
+ }
+
+ perf_evlist__enable(evlist);
+
+ /*
+ * Generate the event:
+ */
+ open(filename, flags);
+
+ while (1) {
+ int before = nr_events;
+
+ for (i = 0; i < evlist->nr_mmaps; i++) {
+ union perf_event *event;
+
+ while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
+ const u32 type = event->header.type;
+ int tp_flags;
+ struct perf_sample sample;
+
+ ++nr_events;
+
+ if (type != PERF_RECORD_SAMPLE)
+ continue;
+
+ err = perf_evsel__parse_sample(evsel, event, &sample);
+ if (err) {
+ pr_err("Can't parse sample, err = %d\n", err);
+ goto out_munmap;
+ }
+
+ tp_flags = perf_evsel__intval(evsel, &sample, "flags");
+
+ if (flags != tp_flags) {
+ pr_debug("%s: Expected flags=%#x, got %#x\n",
+ __func__, flags, tp_flags);
+ goto out_munmap;
+ }
+
+ goto out_ok;
+ }
+ }
+
+ if (nr_events == before)
+ poll(evlist->pollfd, evlist->nr_fds, 10);
+
+ if (++nr_polls > 5) {
+ pr_debug("%s: no events!\n", __func__);
+ goto out_munmap;
+ }
+ }
+out_ok:
+ err = 0;
+out_munmap:
+ perf_evlist__munmap(evlist);
+out_delete_evlist:
+ perf_evlist__delete(evlist);
+out:
+ return err;
+}
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 1ef265d..f70f998 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -10,6 +10,7 @@ int test__PERF_RECORD(void);
int test__rdpmc(void);
int test__perf_evsel__roundtrip_name_test(void);
int test__perf_evsel__tp_sched_test(void);
+int test__syscall_open_tp_fields(void);

/* Util */
int trace_event__id(const char *evname);
--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Nov 18, 2012, 9:40:04 AM11/18/12
to
From: Jiri Olsa <jo...@redhat.com>

Separating perf_evsel__tp_sched_test test from the builtin-test into
evsel-tp-sched object.

Signed-off-by: Jiri Olsa <jo...@redhat.com>
Cc: Corey Ashford <cjas...@linux.vnet.ibm.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Ingo Molnar <mi...@elte.hu>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Link: http://lkml.kernel.org/r/1352508412-16914-9-...@redhat.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/Makefile | 1 +
tools/perf/tests/builtin-test.c | 83 +-----------------------------------
tools/perf/tests/evsel-tp-sched.c | 84 +++++++++++++++++++++++++++++++++++++
tools/perf/tests/tests.h | 1 +
4 files changed, 87 insertions(+), 82 deletions(-)
create mode 100644 tools/perf/tests/evsel-tp-sched.c

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index ad6fcb5..e510b53 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -438,6 +438,7 @@ LIB_OBJS += $(OUTPUT)tests/mmap-basic.o
LIB_OBJS += $(OUTPUT)tests/perf-record.o
LIB_OBJS += $(OUTPUT)tests/rdpmc.o
LIB_OBJS += $(OUTPUT)tests/evsel-roundtrip-name.o
+LIB_OBJS += $(OUTPUT)tests/evsel-tp-sched.o
LIB_OBJS += $(OUTPUT)tests/util.o

BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 93f5e91..c66caa7 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -35,87 +35,6 @@ static int test__perf_pmu(void)
return perf_pmu__test();
}

-static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name,
- int size, bool should_be_signed)
-{
- struct format_field *field = perf_evsel__field(evsel, name);
- int is_signed;
- int ret = 0;
-
- if (field == NULL) {
- pr_debug("%s: \"%s\" field not found!\n", evsel->name, name);
- return -1;
- }
-
- is_signed = !!(field->flags | FIELD_IS_SIGNED);
- if (should_be_signed && !is_signed) {
- pr_debug("%s: \"%s\" signedness(%d) is wrong, should be %d\n",
- evsel->name, name, is_signed, should_be_signed);
- ret = -1;
- }
-
- if (field->size != size) {
- pr_debug("%s: \"%s\" size (%d) should be %d!\n",
- evsel->name, name, field->size, size);
- ret = -1;
- }
-
- return ret;
-}
-
-static int perf_evsel__tp_sched_test(void)
-{
- struct perf_evsel *evsel = perf_evsel__newtp("sched", "sched_switch", 0);
- int ret = 0;
-
- if (evsel == NULL) {
- pr_debug("perf_evsel__new\n");
- return -1;
- }
-
- if (perf_evsel__test_field(evsel, "prev_comm", 16, true))
- ret = -1;
-
- if (perf_evsel__test_field(evsel, "prev_pid", 4, true))
- ret = -1;
-
- if (perf_evsel__test_field(evsel, "prev_prio", 4, true))
- ret = -1;
-
- if (perf_evsel__test_field(evsel, "prev_state", 8, true))
- ret = -1;
-
- if (perf_evsel__test_field(evsel, "next_comm", 16, true))
- ret = -1;
-
- if (perf_evsel__test_field(evsel, "next_pid", 4, true))
- ret = -1;
-
- if (perf_evsel__test_field(evsel, "next_prio", 4, true))
- ret = -1;
-
- perf_evsel__delete(evsel);
-
- evsel = perf_evsel__newtp("sched", "sched_wakeup", 0);
-
- if (perf_evsel__test_field(evsel, "comm", 16, true))
- ret = -1;
-
- if (perf_evsel__test_field(evsel, "pid", 4, true))
- ret = -1;
-
- if (perf_evsel__test_field(evsel, "prio", 4, true))
- ret = -1;
-
- if (perf_evsel__test_field(evsel, "success", 4, true))
- ret = -1;
-
- if (perf_evsel__test_field(evsel, "target_cpu", 4, true))
- ret = -1;
-
- return ret;
-}
-
static int test__syscall_open_tp_fields(void)
{
struct perf_record_opts opts = {
@@ -276,7 +195,7 @@ static struct test {
},
{
.desc = "Check parsing of sched tracepoints fields",
- .func = perf_evsel__tp_sched_test,
+ .func = test__perf_evsel__tp_sched_test,
},
{
.desc = "Generate and check syscalls:sys_enter_open event fields",
diff --git a/tools/perf/tests/evsel-tp-sched.c b/tools/perf/tests/evsel-tp-sched.c
new file mode 100644
index 0000000..a5d2fcc
--- /dev/null
+++ b/tools/perf/tests/evsel-tp-sched.c
@@ -0,0 +1,84 @@
+#include "evsel.h"
+#include "tests.h"
+#include "event-parse.h"
+
+static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name,
+ int size, bool should_be_signed)
+{
+ struct format_field *field = perf_evsel__field(evsel, name);
+ int is_signed;
+ int ret = 0;
+
+ if (field == NULL) {
+ pr_debug("%s: \"%s\" field not found!\n", evsel->name, name);
+ return -1;
+ }
+
+ is_signed = !!(field->flags | FIELD_IS_SIGNED);
+ if (should_be_signed && !is_signed) {
+ pr_debug("%s: \"%s\" signedness(%d) is wrong, should be %d\n",
+ evsel->name, name, is_signed, should_be_signed);
+ ret = -1;
+ }
+
+ if (field->size != size) {
+ pr_debug("%s: \"%s\" size (%d) should be %d!\n",
+ evsel->name, name, field->size, size);
+ ret = -1;
+ }
+
+ return ret;
+}
+
+int test__perf_evsel__tp_sched_test(void)
+{
+ struct perf_evsel *evsel = perf_evsel__newtp("sched", "sched_switch", 0);
+ int ret = 0;
+
+ if (evsel == NULL) {
+ pr_debug("perf_evsel__new\n");
+ return -1;
+ }
+
+ if (perf_evsel__test_field(evsel, "prev_comm", 16, true))
+ ret = -1;
+
+ if (perf_evsel__test_field(evsel, "prev_pid", 4, true))
+ ret = -1;
+
+ if (perf_evsel__test_field(evsel, "prev_prio", 4, true))
+ ret = -1;
+
+ if (perf_evsel__test_field(evsel, "prev_state", 8, true))
+ ret = -1;
+
+ if (perf_evsel__test_field(evsel, "next_comm", 16, true))
+ ret = -1;
+
+ if (perf_evsel__test_field(evsel, "next_pid", 4, true))
+ ret = -1;
+
+ if (perf_evsel__test_field(evsel, "next_prio", 4, true))
+ ret = -1;
+
+ perf_evsel__delete(evsel);
+
+ evsel = perf_evsel__newtp("sched", "sched_wakeup", 0);
+
+ if (perf_evsel__test_field(evsel, "comm", 16, true))
+ ret = -1;
+
+ if (perf_evsel__test_field(evsel, "pid", 4, true))
+ ret = -1;
+
+ if (perf_evsel__test_field(evsel, "prio", 4, true))
+ ret = -1;
+
+ if (perf_evsel__test_field(evsel, "success", 4, true))
+ ret = -1;
+
+ if (perf_evsel__test_field(evsel, "target_cpu", 4, true))
+ ret = -1;
+
+ return ret;
+}
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 5897dd1..1ef265d 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -9,6 +9,7 @@ int test__basic_mmap(void);
int test__PERF_RECORD(void);
int test__rdpmc(void);
int test__perf_evsel__roundtrip_name_test(void);
+int test__perf_evsel__tp_sched_test(void);

/* Util */
int trace_event__id(const char *evname);
--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Nov 18, 2012, 9:40:04 AM11/18/12
to
From: Namhyung Kim <namhyu...@lge.com>

Implement progress update function for GTK2 front end.

Note that since it will be called before gtk main loop so that we should
call gtk event loop handler directly.

Signed-off-by: Namhyung Kim <namh...@kernel.org>
Cc: Ingo Molnar <mi...@kernel.org>
Cc: Pekka Enberg <pen...@kernel.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Link: http://lkml.kernel.org/r/1352813436-14173-3-gi...@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/Makefile | 1 +
tools/perf/ui/gtk/gtk.h | 1 +
tools/perf/ui/gtk/progress.c | 50 ++++++++++++++++++++++++++++++++++++++++++
tools/perf/ui/gtk/setup.c | 2 ++
4 files changed, 54 insertions(+)
create mode 100644 tools/perf/ui/gtk/progress.c

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index f8466b4..5a9075e 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -648,6 +648,7 @@ ifndef NO_GTK2
LIB_OBJS += $(OUTPUT)ui/gtk/setup.o
LIB_OBJS += $(OUTPUT)ui/gtk/util.o
LIB_OBJS += $(OUTPUT)ui/gtk/helpline.o
+ LIB_OBJS += $(OUTPUT)ui/gtk/progress.o
# Make sure that it'd be included only once.
ifeq ($(findstring -DNEWT_SUPPORT,$(BASIC_CFLAGS)),)
LIB_OBJS += $(OUTPUT)ui/setup.o
diff --git a/tools/perf/ui/gtk/gtk.h b/tools/perf/ui/gtk/gtk.h
index 687af0b..856320e 100644
--- a/tools/perf/ui/gtk/gtk.h
+++ b/tools/perf/ui/gtk/gtk.h
@@ -30,6 +30,7 @@ struct perf_gtk_context *perf_gtk__activate_context(GtkWidget *window);
int perf_gtk__deactivate_context(struct perf_gtk_context **ctx);

void perf_gtk__init_helpline(void);
+void perf_gtk__init_progress(void);
void perf_gtk__init_hpp(void);

#ifndef HAVE_GTK_INFO_BAR
diff --git a/tools/perf/ui/gtk/progress.c b/tools/perf/ui/gtk/progress.c
new file mode 100644
index 0000000..903426f
--- /dev/null
+++ b/tools/perf/ui/gtk/progress.c
@@ -0,0 +1,50 @@
+#include <inttypes.h>
+
+#include "gtk.h"
+#include "../progress.h"
+#include "util.h"
+
+static GtkWidget *dialog;
+static GtkWidget *progress;
+
+static void gtk_progress_update(u64 curr, u64 total, const char *title)
+{
+ double fraction = total ? 1.0 * curr / total : 0.0;
+ char buf[1024];
+
+ if (dialog == NULL) {
+ GtkWidget *vbox = gtk_vbox_new(TRUE, 5);
+ GtkWidget *label = gtk_label_new(title);
+
+ dialog = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ progress = gtk_progress_bar_new();
+
+ gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, FALSE, 3);
+ gtk_box_pack_start(GTK_BOX(vbox), progress, TRUE, TRUE, 3);
+
+ gtk_container_add(GTK_CONTAINER(dialog), vbox);
+
+ gtk_window_set_title(GTK_WINDOW(dialog), "perf");
+ gtk_window_resize(GTK_WINDOW(dialog), 300, 80);
+ gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER);
+
+ gtk_widget_show_all(dialog);
+ }
+
+ gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), fraction);
+ snprintf(buf, sizeof(buf), "%"PRIu64" / %"PRIu64, curr, total);
+ gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progress), buf);
+
+ /* we didn't call gtk_main yet, so do it manually */
+ while (gtk_events_pending())
+ gtk_main_iteration();
+}
+
+static struct ui_progress gtk_progress_fns = {
+ .update = gtk_progress_update,
+};
+
+void perf_gtk__init_progress(void)
+{
+ progress_fns = &gtk_progress_fns;
+}
diff --git a/tools/perf/ui/gtk/setup.c b/tools/perf/ui/gtk/setup.c
index 3c4c6ef..6c2dd2e 100644
--- a/tools/perf/ui/gtk/setup.c
+++ b/tools/perf/ui/gtk/setup.c
@@ -8,7 +8,9 @@ int perf_gtk__init(void)
{
perf_error__register(&perf_gtk_eops);
perf_gtk__init_helpline();
+ perf_gtk__init_progress();
perf_gtk__init_hpp();
+
return gtk_init_check(NULL, NULL) ? 0 : -1;
}

--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Nov 18, 2012, 9:40:02 AM11/18/12
to
From: Jiri Olsa <jo...@redhat.com>

Separating test__PERF_RECORD test from the builtin-test into perf-record
object.

Signed-off-by: Jiri Olsa <jo...@redhat.com>
Cc: Corey Ashford <cjas...@linux.vnet.ibm.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Ingo Molnar <mi...@elte.hu>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Link: http://lkml.kernel.org/r/1352508412-16914-6-...@redhat.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/Makefile | 1 +
tools/perf/tests/builtin-test.c | 307 --------------------------------------
tools/perf/tests/perf-record.c | 312 +++++++++++++++++++++++++++++++++++++++
tools/perf/tests/tests.h | 1 +
4 files changed, 314 insertions(+), 307 deletions(-)
create mode 100644 tools/perf/tests/perf-record.c

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 337489e..a2d6153 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -435,6 +435,7 @@ LIB_OBJS += $(OUTPUT)tests/vmlinux-kallsyms.o
LIB_OBJS += $(OUTPUT)tests/open-syscall.o
LIB_OBJS += $(OUTPUT)tests/open-syscall-all-cpus.o
LIB_OBJS += $(OUTPUT)tests/mmap-basic.o
+LIB_OBJS += $(OUTPUT)tests/perf-record.o
LIB_OBJS += $(OUTPUT)tests/util.o

BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 609f592..7cb3928 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -31,313 +31,6 @@



-static int sched__get_first_possible_cpu(pid_t pid, cpu_set_t *maskp)
-{
- int i, cpu = -1, nrcpus = 1024;
-realloc:
- CPU_ZERO(maskp);
-
- if (sched_getaffinity(pid, sizeof(*maskp), maskp) == -1) {
- if (errno == EINVAL && nrcpus < (1024 << 8)) {
- nrcpus = nrcpus << 2;
- goto realloc;
- }
- perror("sched_getaffinity");
- return -1;
- }
-
- for (i = 0; i < nrcpus; i++) {
- if (CPU_ISSET(i, maskp)) {
- if (cpu == -1)
- cpu = i;
- else
- CPU_CLR(i, maskp);
- }
- }
-
- return cpu;
-}
-
-static int test__PERF_RECORD(void)
-{
- struct perf_record_opts opts = {
- .target = {
- .uid = UINT_MAX,
- .uses_mmap = true,
- },
- .no_delay = true,
- .freq = 10,
- .mmap_pages = 256,
- };
- cpu_set_t cpu_mask;
- size_t cpu_mask_size = sizeof(cpu_mask);
- struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
- struct perf_evsel *evsel;
- struct perf_sample sample;
- const char *cmd = "sleep";
- const char *argv[] = { cmd, "1", NULL, };
- char *bname;
- u64 prev_time = 0;
- bool found_cmd_mmap = false,
- found_libc_mmap = false,
- found_vdso_mmap = false,
- found_ld_mmap = false;
- int err = -1, errs = 0, i, wakeups = 0;
- u32 cpu;
- int total_events = 0, nr_events[PERF_RECORD_MAX] = { 0, };
-
- if (evlist == NULL || argv == NULL) {
- pr_debug("Not enough memory to create evlist\n");
- goto out;
- }
-
- /*
- * We need at least one evsel in the evlist, use the default
- * one: "cycles".
- */
- err = perf_evlist__add_default(evlist);
- if (err < 0) {
- pr_debug("Not enough memory to create evsel\n");
- goto out_delete_evlist;
- }
-
- /*
- * Create maps of threads and cpus to monitor. In this case
- * we start with all threads and cpus (-1, -1) but then in
- * perf_evlist__prepare_workload we'll fill in the only thread
- * we're monitoring, the one forked there.
- */
- err = perf_evlist__create_maps(evlist, &opts.target);
- if (err < 0) {
- pr_debug("Not enough memory to create thread/cpu maps\n");
- goto out_delete_evlist;
- }
-
- /*
- * Prepare the workload in argv[] to run, it'll fork it, and then wait
- * for perf_evlist__start_workload() to exec it. This is done this way
- * so that we have time to open the evlist (calling sys_perf_event_open
- * on all the fds) and then mmap them.
- */
- err = perf_evlist__prepare_workload(evlist, &opts, argv);
- if (err < 0) {
- pr_debug("Couldn't run the workload!\n");
- goto out_delete_evlist;
- }
-
- /*
- * Config the evsels, setting attr->comm on the first one, etc.
- */
- evsel = perf_evlist__first(evlist);
- evsel->attr.sample_type |= PERF_SAMPLE_CPU;
- evsel->attr.sample_type |= PERF_SAMPLE_TID;
- evsel->attr.sample_type |= PERF_SAMPLE_TIME;
- perf_evlist__config_attrs(evlist, &opts);
-
- err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask);
- if (err < 0) {
- pr_debug("sched__get_first_possible_cpu: %s\n", strerror(errno));
- goto out_delete_evlist;
- }
-
- cpu = err;
-
- /*
- * So that we can check perf_sample.cpu on all the samples.
- */
- if (sched_setaffinity(evlist->workload.pid, cpu_mask_size, &cpu_mask) < 0) {
- pr_debug("sched_setaffinity: %s\n", strerror(errno));
- goto out_delete_evlist;
- }
-
- /*
- * Call sys_perf_event_open on all the fds on all the evsels,
- * grouping them if asked to.
- */
- err = perf_evlist__open(evlist);
- if (err < 0) {
- pr_debug("perf_evlist__open: %s\n", strerror(errno));
- goto out_delete_evlist;
- }
-
- /*
- * mmap the first fd on a given CPU and ask for events for the other
- * fds in the same CPU to be injected in the same mmap ring buffer
- * (using ioctl(PERF_EVENT_IOC_SET_OUTPUT)).
- */
- err = perf_evlist__mmap(evlist, opts.mmap_pages, false);
- if (err < 0) {
- pr_debug("perf_evlist__mmap: %s\n", strerror(errno));
- goto out_delete_evlist;
- }
-
- /*
- * Now that all is properly set up, enable the events, they will
- * count just on workload.pid, which will start...
- */
- perf_evlist__enable(evlist);
-
- /*
- * Now!
- */
- perf_evlist__start_workload(evlist);
-
- while (1) {
- int before = total_events;
-
- for (i = 0; i < evlist->nr_mmaps; i++) {
- union perf_event *event;
-
- while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
- const u32 type = event->header.type;
- const char *name = perf_event__name(type);
-
- ++total_events;
- if (type < PERF_RECORD_MAX)
- nr_events[type]++;
-
- err = perf_evlist__parse_sample(evlist, event, &sample);
- if (err < 0) {
- if (verbose)
- perf_event__fprintf(event, stderr);
- pr_debug("Couldn't parse sample\n");
- goto out_err;
- }
-
- if (verbose) {
- pr_info("%" PRIu64" %d ", sample.time, sample.cpu);
- perf_event__fprintf(event, stderr);
- }
-
- if (prev_time > sample.time) {
- pr_debug("%s going backwards in time, prev=%" PRIu64 ", curr=%" PRIu64 "\n",
- name, prev_time, sample.time);
- ++errs;
- }
-
- prev_time = sample.time;
-
- if (sample.cpu != cpu) {
- pr_debug("%s with unexpected cpu, expected %d, got %d\n",
- name, cpu, sample.cpu);
- ++errs;
- }
-
- if ((pid_t)sample.pid != evlist->workload.pid) {
- pr_debug("%s with unexpected pid, expected %d, got %d\n",
- name, evlist->workload.pid, sample.pid);
- ++errs;
- }
-
- if ((pid_t)sample.tid != evlist->workload.pid) {
- pr_debug("%s with unexpected tid, expected %d, got %d\n",
- name, evlist->workload.pid, sample.tid);
- ++errs;
- }
-
- if ((type == PERF_RECORD_COMM ||
- type == PERF_RECORD_MMAP ||
- type == PERF_RECORD_FORK ||
- type == PERF_RECORD_EXIT) &&
- (pid_t)event->comm.pid != evlist->workload.pid) {
- pr_debug("%s with unexpected pid/tid\n", name);
- ++errs;
- }
-
- if ((type == PERF_RECORD_COMM ||
- type == PERF_RECORD_MMAP) &&
- event->comm.pid != event->comm.tid) {
- pr_debug("%s with different pid/tid!\n", name);
- ++errs;
- }
-
- switch (type) {
- case PERF_RECORD_COMM:
- if (strcmp(event->comm.comm, cmd)) {
- pr_debug("%s with unexpected comm!\n", name);
- ++errs;
- }
- break;
- case PERF_RECORD_EXIT:
- goto found_exit;
- case PERF_RECORD_MMAP:
- bname = strrchr(event->mmap.filename, '/');
- if (bname != NULL) {
- if (!found_cmd_mmap)
- found_cmd_mmap = !strcmp(bname + 1, cmd);
- if (!found_libc_mmap)
- found_libc_mmap = !strncmp(bname + 1, "libc", 4);
- if (!found_ld_mmap)
- found_ld_mmap = !strncmp(bname + 1, "ld", 2);
- } else if (!found_vdso_mmap)
- found_vdso_mmap = !strcmp(event->mmap.filename, "[vdso]");
- break;
-
- case PERF_RECORD_SAMPLE:
- /* Just ignore samples for now */
- break;
- default:
- pr_debug("Unexpected perf_event->header.type %d!\n",
- type);
- ++errs;
- }
- }
- }
-
- /*
- * We don't use poll here because at least at 3.1 times the
- * PERF_RECORD_{!SAMPLE} events don't honour
- * perf_event_attr.wakeup_events, just PERF_EVENT_SAMPLE does.
- */
- if (total_events == before && false)
- poll(evlist->pollfd, evlist->nr_fds, -1);
-
- sleep(1);
- if (++wakeups > 5) {
- pr_debug("No PERF_RECORD_EXIT event!\n");
- break;
- }
- }
-
-found_exit:
- if (nr_events[PERF_RECORD_COMM] > 1) {
- pr_debug("Excessive number of PERF_RECORD_COMM events!\n");
- ++errs;
- }
-
- if (nr_events[PERF_RECORD_COMM] == 0) {
- pr_debug("Missing PERF_RECORD_COMM for %s!\n", cmd);
- ++errs;
- }
-
- if (!found_cmd_mmap) {
- pr_debug("PERF_RECORD_MMAP for %s missing!\n", cmd);
- ++errs;
- }
-
- if (!found_libc_mmap) {
- pr_debug("PERF_RECORD_MMAP for %s missing!\n", "libc");
- ++errs;
- }
-
- if (!found_ld_mmap) {
- pr_debug("PERF_RECORD_MMAP for %s missing!\n", "ld");
- ++errs;
- }
-
- if (!found_vdso_mmap) {
- pr_debug("PERF_RECORD_MMAP for %s missing!\n", "[vdso]");
- ++errs;
- }
-out_err:
- perf_evlist__munmap(evlist);
-out_delete_evlist:
- perf_evlist__delete(evlist);
-out:
- return (err < 0 || errs > 0) ? -1 : 0;
-}
-
-
#if defined(__x86_64__) || defined(__i386__)

#define barrier() asm volatile("" ::: "memory")
diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c
new file mode 100644
index 0000000..70e0d44
--- /dev/null
+++ b/tools/perf/tests/perf-record.c
@@ -0,0 +1,312 @@
+#include <sched.h>
+#include "evlist.h"
+#include "evsel.h"
+#include "perf.h"
+#include "debug.h"
+#include "tests.h"
+
+static int sched__get_first_possible_cpu(pid_t pid, cpu_set_t *maskp)
+{
+ int i, cpu = -1, nrcpus = 1024;
+realloc:
+ CPU_ZERO(maskp);
+
+ if (sched_getaffinity(pid, sizeof(*maskp), maskp) == -1) {
+ if (errno == EINVAL && nrcpus < (1024 << 8)) {
+ nrcpus = nrcpus << 2;
+ goto realloc;
+ }
+ perror("sched_getaffinity");
+ return -1;
+ }
+
+ for (i = 0; i < nrcpus; i++) {
+ if (CPU_ISSET(i, maskp)) {
+ if (cpu == -1)
+ cpu = i;
+ else
+ CPU_CLR(i, maskp);
+ }
+ }
+
+ return cpu;
+}
+
+int test__PERF_RECORD(void)
+{
+ struct perf_record_opts opts = {
+ .target = {
+ .uid = UINT_MAX,
+ .uses_mmap = true,
+ },
+ .no_delay = true,
+ .freq = 10,
+ .mmap_pages = 256,
+ };
+ cpu_set_t cpu_mask;
+ size_t cpu_mask_size = sizeof(cpu_mask);
+ struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
+ struct perf_evsel *evsel;
+ struct perf_sample sample;
+ const char *cmd = "sleep";
+ const char *argv[] = { cmd, "1", NULL, };
+ char *bname;
+ u64 prev_time = 0;
+ bool found_cmd_mmap = false,
+ found_libc_mmap = false,
+ found_vdso_mmap = false,
+ found_ld_mmap = false;
+ int err = -1, errs = 0, i, wakeups = 0;
+ u32 cpu;
+ int total_events = 0, nr_events[PERF_RECORD_MAX] = { 0, };
+
+ if (evlist == NULL || argv == NULL) {
+ pr_debug("Not enough memory to create evlist\n");
+ goto out;
+ }
+
+ /*
+ * We need at least one evsel in the evlist, use the default
+ * one: "cycles".
+ */
+ err = perf_evlist__add_default(evlist);
+ if (err < 0) {
+ pr_debug("Not enough memory to create evsel\n");
+ goto out_delete_evlist;
+ }
+
+ /*
+ * Create maps of threads and cpus to monitor. In this case
+ * we start with all threads and cpus (-1, -1) but then in
+ * perf_evlist__prepare_workload we'll fill in the only thread
+ * we're monitoring, the one forked there.
+ */
+ err = perf_evlist__create_maps(evlist, &opts.target);
+ if (err < 0) {
+ pr_debug("Not enough memory to create thread/cpu maps\n");
+ goto out_delete_evlist;
+ }
+
+ /*
+ * Prepare the workload in argv[] to run, it'll fork it, and then wait
+ * for perf_evlist__start_workload() to exec it. This is done this way
+ * so that we have time to open the evlist (calling sys_perf_event_open
+ * on all the fds) and then mmap them.
+ */
+ err = perf_evlist__prepare_workload(evlist, &opts, argv);
+ if (err < 0) {
+ pr_debug("Couldn't run the workload!\n");
+ goto out_delete_evlist;
+ }
+
+ /*
+ * Config the evsels, setting attr->comm on the first one, etc.
+ */
+ evsel = perf_evlist__first(evlist);
+ evsel->attr.sample_type |= PERF_SAMPLE_CPU;
+ evsel->attr.sample_type |= PERF_SAMPLE_TID;
+ evsel->attr.sample_type |= PERF_SAMPLE_TIME;
+ perf_evlist__config_attrs(evlist, &opts);
+
+ err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask);
+ if (err < 0) {
+ pr_debug("sched__get_first_possible_cpu: %s\n", strerror(errno));
+ goto out_delete_evlist;
+ }
+
+ cpu = err;
+
+ /*
+ * So that we can check perf_sample.cpu on all the samples.
+ */
+ if (sched_setaffinity(evlist->workload.pid, cpu_mask_size, &cpu_mask) < 0) {
+ pr_debug("sched_setaffinity: %s\n", strerror(errno));
+ goto out_delete_evlist;
+ }
+
+ /*
+ * Call sys_perf_event_open on all the fds on all the evsels,
+ * grouping them if asked to.
+ */
+ err = perf_evlist__open(evlist);
+ if (err < 0) {
+ pr_debug("perf_evlist__open: %s\n", strerror(errno));
+ goto out_delete_evlist;
+ }
+
+ /*
+ * mmap the first fd on a given CPU and ask for events for the other
+ * fds in the same CPU to be injected in the same mmap ring buffer
+ * (using ioctl(PERF_EVENT_IOC_SET_OUTPUT)).
+ */
+ err = perf_evlist__mmap(evlist, opts.mmap_pages, false);
+ if (err < 0) {
+ pr_debug("perf_evlist__mmap: %s\n", strerror(errno));
+ goto out_delete_evlist;
+ }
+
+ /*
+ * Now that all is properly set up, enable the events, they will
+ * count just on workload.pid, which will start...
+ */
+ perf_evlist__enable(evlist);
+
+ /*
+ * Now!
+ */
+ perf_evlist__start_workload(evlist);
+
+ while (1) {
+ int before = total_events;
+
+ for (i = 0; i < evlist->nr_mmaps; i++) {
+ union perf_event *event;
+
+ while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
+ const u32 type = event->header.type;
+ const char *name = perf_event__name(type);
+
+ ++total_events;
+ if (type < PERF_RECORD_MAX)
+ nr_events[type]++;
+
+ err = perf_evlist__parse_sample(evlist, event, &sample);
+ if (err < 0) {
+ if (verbose)
+ perf_event__fprintf(event, stderr);
+ pr_debug("Couldn't parse sample\n");
+ goto out_err;
+ }
+
+ if (verbose) {
+ pr_info("%" PRIu64" %d ", sample.time, sample.cpu);
+ perf_event__fprintf(event, stderr);
+ }
+
+ if (prev_time > sample.time) {
+ pr_debug("%s going backwards in time, prev=%" PRIu64 ", curr=%" PRIu64 "\n",
+ name, prev_time, sample.time);
+ ++errs;
+ }
+
+ prev_time = sample.time;
+
+ if (sample.cpu != cpu) {
+ pr_debug("%s with unexpected cpu, expected %d, got %d\n",
+ name, cpu, sample.cpu);
+ ++errs;
+ }
+
+ if ((pid_t)sample.pid != evlist->workload.pid) {
+ pr_debug("%s with unexpected pid, expected %d, got %d\n",
+ name, evlist->workload.pid, sample.pid);
+ ++errs;
+ }
+
+ if ((pid_t)sample.tid != evlist->workload.pid) {
+ pr_debug("%s with unexpected tid, expected %d, got %d\n",
+ name, evlist->workload.pid, sample.tid);
+ ++errs;
+ }
+
+ if ((type == PERF_RECORD_COMM ||
+ type == PERF_RECORD_MMAP ||
+ type == PERF_RECORD_FORK ||
+ type == PERF_RECORD_EXIT) &&
+ (pid_t)event->comm.pid != evlist->workload.pid) {
+ pr_debug("%s with unexpected pid/tid\n", name);
+ ++errs;
+ }
+
+ if ((type == PERF_RECORD_COMM ||
+ type == PERF_RECORD_MMAP) &&
+ event->comm.pid != event->comm.tid) {
+ pr_debug("%s with different pid/tid!\n", name);
+ ++errs;
+ }
+
+ switch (type) {
+ case PERF_RECORD_COMM:
+ if (strcmp(event->comm.comm, cmd)) {
+ pr_debug("%s with unexpected comm!\n", name);
+ ++errs;
+ }
+ break;
+ case PERF_RECORD_EXIT:
+ goto found_exit;
+ case PERF_RECORD_MMAP:
+ bname = strrchr(event->mmap.filename, '/');
+ if (bname != NULL) {
+ if (!found_cmd_mmap)
+ found_cmd_mmap = !strcmp(bname + 1, cmd);
+ if (!found_libc_mmap)
+ found_libc_mmap = !strncmp(bname + 1, "libc", 4);
+ if (!found_ld_mmap)
+ found_ld_mmap = !strncmp(bname + 1, "ld", 2);
+ } else if (!found_vdso_mmap)
+ found_vdso_mmap = !strcmp(event->mmap.filename, "[vdso]");
+ break;
+
+ case PERF_RECORD_SAMPLE:
+ /* Just ignore samples for now */
+ break;
+ default:
+ pr_debug("Unexpected perf_event->header.type %d!\n",
+ type);
+ ++errs;
+ }
+ }
+ }
+
+ /*
+ * We don't use poll here because at least at 3.1 times the
+ * PERF_RECORD_{!SAMPLE} events don't honour
+ * perf_event_attr.wakeup_events, just PERF_EVENT_SAMPLE does.
+ */
+ if (total_events == before && false)
+ poll(evlist->pollfd, evlist->nr_fds, -1);
+
+ sleep(1);
+ if (++wakeups > 5) {
+ pr_debug("No PERF_RECORD_EXIT event!\n");
+ break;
+ }
+ }
+
+found_exit:
+ if (nr_events[PERF_RECORD_COMM] > 1) {
+ pr_debug("Excessive number of PERF_RECORD_COMM events!\n");
+ ++errs;
+ }
+
+ if (nr_events[PERF_RECORD_COMM] == 0) {
+ pr_debug("Missing PERF_RECORD_COMM for %s!\n", cmd);
+ ++errs;
+ }
+
+ if (!found_cmd_mmap) {
+ pr_debug("PERF_RECORD_MMAP for %s missing!\n", cmd);
+ ++errs;
+ }
+
+ if (!found_libc_mmap) {
+ pr_debug("PERF_RECORD_MMAP for %s missing!\n", "libc");
+ ++errs;
+ }
+
+ if (!found_ld_mmap) {
+ pr_debug("PERF_RECORD_MMAP for %s missing!\n", "ld");
+ ++errs;
+ }
+
+ if (!found_vdso_mmap) {
+ pr_debug("PERF_RECORD_MMAP for %s missing!\n", "[vdso]");
+ ++errs;
+ }
+out_err:
+ perf_evlist__munmap(evlist);
+out_delete_evlist:
+ perf_evlist__delete(evlist);
+out:
+ return (err < 0 || errs > 0) ? -1 : 0;
+}
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 1a925dd..374b039 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -6,6 +6,7 @@ int test__vmlinux_matches_kallsyms(void);
int test__open_syscall_event(void);
int test__open_syscall_event_on_all_cpus(void);
int test__basic_mmap(void);
+int test__PERF_RECORD(void);

/* Util */
int trace_event__id(const char *evname);
--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Nov 18, 2012, 9:40:03 AM11/18/12
to
From: David Howells <dhow...@redhat.com>

Define a Makefile function that can be called with $(call ...) to wrap
the subdir make invocations in tools/Makefile.

This will allow us in the next patch to insert bits in there to honour
O= flags when called from the top-level Makefile.

Signed-off-by: David Howells <dhow...@redhat.com>
Cc: Borislav Petkov <b...@amd64.org>
Cc: Ingo Molnar <mi...@kernel.org>
Cc: Linus Torvalds <torv...@linux-foundation.org>
Cc: Namhyung Kim <namh...@gmail.com>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Thomas Gleixner <tg...@linutronix.de>
Link: http://lkml.kernel.org/r/1378.13...@warthog.procyon.org.uk
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/Makefile | 24 ++++++++++++------------
tools/scripts/Makefile.include | 8 ++++++++
2 files changed, 20 insertions(+), 12 deletions(-)

diff --git a/tools/Makefile b/tools/Makefile
index 3ae4394..1f9a529 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -31,44 +31,44 @@ help:
@echo ' clean: a summary clean target to clean _all_ folders'

cpupower: FORCE
- $(QUIET_SUBDIR0)power/$@/ $(QUIET_SUBDIR1)
+ $(call descend,power/$@)

firewire lguest perf usb virtio vm: FORCE
- $(QUIET_SUBDIR0)$@/ $(QUIET_SUBDIR1)
+ $(call descend,$@)

selftests: FORCE
- $(QUIET_SUBDIR0)testing/$@/ $(QUIET_SUBDIR1)
+ $(call descend,testing/$@)

turbostat x86_energy_perf_policy: FORCE
- $(QUIET_SUBDIR0)power/x86/$@/ $(QUIET_SUBDIR1)
+ $(call descend,power/x86/$@)

cpupower_install:
- $(QUIET_SUBDIR0)power/$(@:_install=)/ $(QUIET_SUBDIR1) install
+ $(call descend,power/$(@:_install=),install)

firewire_install lguest_install perf_install usb_install virtio_install vm_install:
- $(QUIET_SUBDIR0)$(@:_install=)/ $(QUIET_SUBDIR1) install
+ $(call descend,$(@:_install=),install)

selftests_install:
- $(QUIET_SUBDIR0)testing/$(@:_clean=)/ $(QUIET_SUBDIR1) install
+ $(call descend,testing/$(@:_clean=),install)

turbostat_install x86_energy_perf_policy_install:
- $(QUIET_SUBDIR0)power/x86/$(@:_install=)/ $(QUIET_SUBDIR1) install
+ $(call descend,power/x86/$(@:_install=),install)

install: cpupower_install firewire_install lguest_install perf_install \
selftests_install turbostat_install usb_install virtio_install \
vm_install x86_energy_perf_policy_install

cpupower_clean:
- $(QUIET_SUBDIR0)power/cpupower/ $(QUIET_SUBDIR1) clean
+ $(call descend,power/cpupower,clean)

firewire_clean lguest_clean perf_clean usb_clean virtio_clean vm_clean:
- $(QUIET_SUBDIR0)$(@:_clean=)/ $(QUIET_SUBDIR1) clean
+ $(call descend,$(@:_clean=),clean)

selftests_clean:
- $(QUIET_SUBDIR0)testing/$(@:_clean=)/ $(QUIET_SUBDIR1) clean
+ $(call descend,testing/$(@:_clean=),clean)

turbostat_clean x86_energy_perf_policy_clean:
- $(QUIET_SUBDIR0)power/x86/$(@:_clean=)/ $(QUIET_SUBDIR1) clean
+ $(call descend,power/x86/$(@:_clean=),clean)

clean: cpupower_clean firewire_clean lguest_clean perf_clean selftests_clean \
turbostat_clean usb_clean virtio_clean vm_clean \
diff --git a/tools/scripts/Makefile.include b/tools/scripts/Makefile.include
index 96ce80a..4a9e317 100644
--- a/tools/scripts/Makefile.include
+++ b/tools/scripts/Makefile.include
@@ -41,6 +41,14 @@ else
NO_SUBDIR = :
endif

+#
+# Define a callable command for descending to a new directory
+#
+# Call by doing: $(call descend,directory[,target])
+#
+descend = \
+ $(QUIET_SUBDIR0)$(1) $(QUIET_SUBDIR1) $(2)
+
QUIET_SUBDIR0 = +$(MAKE) -C # space to separate -C and subdir
QUIET_SUBDIR1 =

--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Nov 18, 2012, 9:40:04 AM11/18/12
to
From: Jiri Olsa <jo...@redhat.com>

Separating test__rdpmc test from the builtin-test
into rdpmc object.

Signed-off-by: Jiri Olsa <jo...@redhat.com>
Cc: Corey Ashford <cjas...@linux.vnet.ibm.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Ingo Molnar <mi...@elte.hu>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Link: http://lkml.kernel.org/r/1352508412-16914-7-...@redhat.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/Makefile | 1 +
tools/perf/tests/builtin-test.c | 168 -------------------------------------
tools/perf/tests/rdpmc.c | 175 +++++++++++++++++++++++++++++++++++++++
tools/perf/tests/tests.h | 1 +
4 files changed, 177 insertions(+), 168 deletions(-)
create mode 100644 tools/perf/tests/rdpmc.c

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index a2d6153..2e5197a 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -436,6 +436,7 @@ LIB_OBJS += $(OUTPUT)tests/open-syscall.o
LIB_OBJS += $(OUTPUT)tests/open-syscall-all-cpus.o
LIB_OBJS += $(OUTPUT)tests/mmap-basic.o
LIB_OBJS += $(OUTPUT)tests/perf-record.o
+LIB_OBJS += $(OUTPUT)tests/rdpmc.o
LIB_OBJS += $(OUTPUT)tests/util.o

BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 7cb3928..1e9a0ea 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -30,174 +30,6 @@
#include <sched.h>


-
-#if defined(__x86_64__) || defined(__i386__)
-
-#define barrier() asm volatile("" ::: "memory")
-
-static u64 rdpmc(unsigned int counter)
-{
- unsigned int low, high;
-
- asm volatile("rdpmc" : "=a" (low), "=d" (high) : "c" (counter));
-
- return low | ((u64)high) << 32;
-}
-
-static u64 rdtsc(void)
-{
- unsigned int low, high;
-
- asm volatile("rdtsc" : "=a" (low), "=d" (high));
-
- return low | ((u64)high) << 32;
-}
-
-static u64 mmap_read_self(void *addr)
-{
- struct perf_event_mmap_page *pc = addr;
- u32 seq, idx, time_mult = 0, time_shift = 0;
- u64 count, cyc = 0, time_offset = 0, enabled, running, delta;
-
- do {
- seq = pc->lock;
- barrier();
-
- enabled = pc->time_enabled;
- running = pc->time_running;
-
- if (enabled != running) {
- cyc = rdtsc();
- time_mult = pc->time_mult;
- time_shift = pc->time_shift;
- time_offset = pc->time_offset;
- }
-
- idx = pc->index;
- count = pc->offset;
- if (idx)
- count += rdpmc(idx - 1);
-
- barrier();
- } while (pc->lock != seq);
-
- if (enabled != running) {
- u64 quot, rem;
-
- quot = (cyc >> time_shift);
- rem = cyc & ((1 << time_shift) - 1);
- delta = time_offset + quot * time_mult +
- ((rem * time_mult) >> time_shift);
-
- enabled += delta;
- if (idx)
- running += delta;
-
- quot = count / running;
- rem = count % running;
- count = quot * enabled + (rem * enabled) / running;
- }
-
- return count;
-}
-
-/*
- * If the RDPMC instruction faults then signal this back to the test parent task:
- */
-static void segfault_handler(int sig __maybe_unused,
- siginfo_t *info __maybe_unused,
- void *uc __maybe_unused)
-{
- exit(-1);
-}
-
-static int __test__rdpmc(void)
-{
- volatile int tmp = 0;
- u64 i, loops = 1000;
- int n;
- int fd;
- void *addr;
- struct perf_event_attr attr = {
- .type = PERF_TYPE_HARDWARE,
- .config = PERF_COUNT_HW_INSTRUCTIONS,
- .exclude_kernel = 1,
- };
- u64 delta_sum = 0;
- struct sigaction sa;
-
- sigfillset(&sa.sa_mask);
- sa.sa_sigaction = segfault_handler;
- sigaction(SIGSEGV, &sa, NULL);
-
- fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
- if (fd < 0) {
- pr_err("Error: sys_perf_event_open() syscall returned "
- "with %d (%s)\n", fd, strerror(errno));
- return -1;
- }
-
- addr = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0);
- if (addr == (void *)(-1)) {
- pr_err("Error: mmap() syscall returned with (%s)\n",
- strerror(errno));
- goto out_close;
- }
-
- for (n = 0; n < 6; n++) {
- u64 stamp, now, delta;
-
- stamp = mmap_read_self(addr);
-
- for (i = 0; i < loops; i++)
- tmp++;
-
- now = mmap_read_self(addr);
- loops *= 10;
-
- delta = now - stamp;
- pr_debug("%14d: %14Lu\n", n, (long long)delta);
-
- delta_sum += delta;
- }
-
- munmap(addr, page_size);
- pr_debug(" ");
-out_close:
- close(fd);
-
- if (!delta_sum)
- return -1;
-
- return 0;
-}
-
-static int test__rdpmc(void)
-{
- int status = 0;
- int wret = 0;
- int ret;
- int pid;
-
- pid = fork();
- if (pid < 0)
- return -1;
-
- if (!pid) {
- ret = __test__rdpmc();
-
- exit(ret);
- }
-
- wret = waitpid(pid, &status, 0);
- if (wret < 0 || status)
- return -1;
-
- return 0;
-}
-
-#endif
-
static int test__perf_pmu(void)
{
return perf_pmu__test();
diff --git a/tools/perf/tests/rdpmc.c b/tools/perf/tests/rdpmc.c
new file mode 100644
index 0000000..ff94886
--- /dev/null
+++ b/tools/perf/tests/rdpmc.c
@@ -0,0 +1,175 @@
+#include <unistd.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/mman.h>
+#include "types.h"
+#include "perf.h"
+#include "debug.h"
+#include "tests.h"
+
+#if defined(__x86_64__) || defined(__i386__)
+
+#define barrier() asm volatile("" ::: "memory")
+
+static u64 rdpmc(unsigned int counter)
+{
+ unsigned int low, high;
+
+ asm volatile("rdpmc" : "=a" (low), "=d" (high) : "c" (counter));
+
+ return low | ((u64)high) << 32;
+}
+
+static u64 rdtsc(void)
+{
+ unsigned int low, high;
+
+ asm volatile("rdtsc" : "=a" (low), "=d" (high));
+
+ return low | ((u64)high) << 32;
+}
+
+static u64 mmap_read_self(void *addr)
+{
+ struct perf_event_mmap_page *pc = addr;
+ u32 seq, idx, time_mult = 0, time_shift = 0;
+ u64 count, cyc = 0, time_offset = 0, enabled, running, delta;
+
+ do {
+ seq = pc->lock;
+ barrier();
+
+ enabled = pc->time_enabled;
+ running = pc->time_running;
+
+ if (enabled != running) {
+ cyc = rdtsc();
+ time_mult = pc->time_mult;
+ time_shift = pc->time_shift;
+ time_offset = pc->time_offset;
+ }
+
+ idx = pc->index;
+ count = pc->offset;
+ if (idx)
+ count += rdpmc(idx - 1);
+
+ barrier();
+ } while (pc->lock != seq);
+
+ if (enabled != running) {
+ u64 quot, rem;
+
+ quot = (cyc >> time_shift);
+ rem = cyc & ((1 << time_shift) - 1);
+ delta = time_offset + quot * time_mult +
+ ((rem * time_mult) >> time_shift);
+
+ enabled += delta;
+ if (idx)
+ running += delta;
+
+ quot = count / running;
+ rem = count % running;
+ count = quot * enabled + (rem * enabled) / running;
+ }
+
+ return count;
+}
+
+/*
+ * If the RDPMC instruction faults then signal this back to the test parent task:
+ */
+static void segfault_handler(int sig __maybe_unused,
+ siginfo_t *info __maybe_unused,
+ void *uc __maybe_unused)
+{
+ exit(-1);
+}
+
+static int __test__rdpmc(void)
+{
+ volatile int tmp = 0;
+ u64 i, loops = 1000;
+ int n;
+ int fd;
+ void *addr;
+ struct perf_event_attr attr = {
+ .type = PERF_TYPE_HARDWARE,
+ .config = PERF_COUNT_HW_INSTRUCTIONS,
+ .exclude_kernel = 1,
+ };
+ u64 delta_sum = 0;
+ struct sigaction sa;
+
+ sigfillset(&sa.sa_mask);
+ sa.sa_sigaction = segfault_handler;
+ sigaction(SIGSEGV, &sa, NULL);
+
+ fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
+ if (fd < 0) {
+ pr_err("Error: sys_perf_event_open() syscall returned "
+ "with %d (%s)\n", fd, strerror(errno));
+ return -1;
+ }
+
+ addr = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0);
+ if (addr == (void *)(-1)) {
+ pr_err("Error: mmap() syscall returned with (%s)\n",
+ strerror(errno));
+ goto out_close;
+ }
+
+ for (n = 0; n < 6; n++) {
+ u64 stamp, now, delta;
+
+ stamp = mmap_read_self(addr);
+
+ for (i = 0; i < loops; i++)
+ tmp++;
+
+ now = mmap_read_self(addr);
+ loops *= 10;
+
+ delta = now - stamp;
+ pr_debug("%14d: %14Lu\n", n, (long long)delta);
+
+ delta_sum += delta;
+ }
+
+ munmap(addr, page_size);
+ pr_debug(" ");
+out_close:
+ close(fd);
+
+ if (!delta_sum)
+ return -1;
+
+ return 0;
+}
+
+int test__rdpmc(void)
+{
+ int status = 0;
+ int wret = 0;
+ int ret;
+ int pid;
+
+ pid = fork();
+ if (pid < 0)
+ return -1;
+
+ if (!pid) {
+ ret = __test__rdpmc();
+
+ exit(ret);
+ }
+
+ wret = waitpid(pid, &status, 0);
+ if (wret < 0 || status)
+ return -1;
+
+ return 0;
+}
+
+#endif
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 374b039..03d428d 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -7,6 +7,7 @@ int test__open_syscall_event(void);
int test__open_syscall_event_on_all_cpus(void);
int test__basic_mmap(void);
int test__PERF_RECORD(void);
+int test__rdpmc(void);

/* Util */
int trace_event__id(const char *evname);
--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Nov 18, 2012, 9:40:04 AM11/18/12
to
From: Jiri Olsa <jo...@redhat.com>

Separating pmu's object tests into pmu object under tests directory.

Signed-off-by: Jiri Olsa <jo...@redhat.com>
Cc: Corey Ashford <cjas...@linux.vnet.ibm.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Ingo Molnar <mi...@elte.hu>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Link: http://lkml.kernel.org/r/1352508412-16914-11-...@redhat.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/Makefile | 1 +
tools/perf/tests/builtin-test.c | 7 +-
tools/perf/tests/pmu.c | 178 +++++++++++++++++++++++++++++++++++++
tools/perf/tests/tests.h | 1 +
tools/perf/util/pmu.c | 185 ++-------------------------------------
tools/perf/util/pmu.h | 4 +
6 files changed, 191 insertions(+), 185 deletions(-)
create mode 100644 tools/perf/tests/pmu.c

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 1e50559..9af012f 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -440,6 +440,7 @@ LIB_OBJS += $(OUTPUT)tests/perf-record.o
LIB_OBJS += $(OUTPUT)tests/rdpmc.o
LIB_OBJS += $(OUTPUT)tests/evsel-roundtrip-name.o
LIB_OBJS += $(OUTPUT)tests/evsel-tp-sched.o
+LIB_OBJS += $(OUTPUT)tests/pmu.o
LIB_OBJS += $(OUTPUT)tests/util.o

BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index bab8490..d3b95e0 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -30,11 +30,6 @@
#include <sched.h>


-static int test__perf_pmu(void)
-{
- return perf_pmu__test();
-}
-
static struct test {
const char *desc;
int (*func)(void);
@@ -71,7 +66,7 @@ static struct test {
},
{
.desc = "Test perf pmu format parsing",
- .func = test__perf_pmu,
+ .func = test__pmu,
},
{
.desc = "Test dso data interface",
diff --git a/tools/perf/tests/pmu.c b/tools/perf/tests/pmu.c
new file mode 100644
index 0000000..a5f3798
--- /dev/null
+++ b/tools/perf/tests/pmu.c
@@ -0,0 +1,178 @@
+#include "parse-events.h"
+#include "pmu.h"
+#include "util.h"
+#include "tests.h"
+
+/* Simulated format definitions. */
+static struct test_format {
+ const char *name;
+ const char *value;
+} test_formats[] = {
+ { "krava01", "config:0-1,62-63\n", },
+ { "krava02", "config:10-17\n", },
+ { "krava03", "config:5\n", },
+ { "krava11", "config1:0,2,4,6,8,20-28\n", },
+ { "krava12", "config1:63\n", },
+ { "krava13", "config1:45-47\n", },
+ { "krava21", "config2:0-3,10-13,20-23,30-33,40-43,50-53,60-63\n", },
+ { "krava22", "config2:8,18,48,58\n", },
+ { "krava23", "config2:28-29,38\n", },
+};
+
+#define TEST_FORMATS_CNT (sizeof(test_formats) / sizeof(struct test_format))
+
+/* Simulated users input. */
+static struct parse_events__term test_terms[] = {
+ {
+ .config = (char *) "krava01",
+ .val.num = 15,
+ .type_val = PARSE_EVENTS__TERM_TYPE_NUM,
+ .type_term = PARSE_EVENTS__TERM_TYPE_USER,
+ },
+ {
+ .config = (char *) "krava02",
+ .val.num = 170,
+ .type_val = PARSE_EVENTS__TERM_TYPE_NUM,
+ .type_term = PARSE_EVENTS__TERM_TYPE_USER,
+ },
+ {
+ .config = (char *) "krava03",
+ .val.num = 1,
+ .type_val = PARSE_EVENTS__TERM_TYPE_NUM,
+ .type_term = PARSE_EVENTS__TERM_TYPE_USER,
+ },
+ {
+ .config = (char *) "krava11",
+ .val.num = 27,
+ .type_val = PARSE_EVENTS__TERM_TYPE_NUM,
+ .type_term = PARSE_EVENTS__TERM_TYPE_USER,
+ },
+ {
+ .config = (char *) "krava12",
+ .val.num = 1,
+ .type_val = PARSE_EVENTS__TERM_TYPE_NUM,
+ .type_term = PARSE_EVENTS__TERM_TYPE_USER,
+ },
+ {
+ .config = (char *) "krava13",
+ .val.num = 2,
+ .type_val = PARSE_EVENTS__TERM_TYPE_NUM,
+ .type_term = PARSE_EVENTS__TERM_TYPE_USER,
+ },
+ {
+ .config = (char *) "krava21",
+ .val.num = 119,
+ .type_val = PARSE_EVENTS__TERM_TYPE_NUM,
+ .type_term = PARSE_EVENTS__TERM_TYPE_USER,
+ },
+ {
+ .config = (char *) "krava22",
+ .val.num = 11,
+ .type_val = PARSE_EVENTS__TERM_TYPE_NUM,
+ .type_term = PARSE_EVENTS__TERM_TYPE_USER,
+ },
+ {
+ .config = (char *) "krava23",
+ .val.num = 2,
+ .type_val = PARSE_EVENTS__TERM_TYPE_NUM,
+ .type_term = PARSE_EVENTS__TERM_TYPE_USER,
+ },
+};
+#define TERMS_CNT (sizeof(test_terms) / sizeof(struct parse_events__term))
+
+/*
+ * Prepare format directory data, exported by kernel
+ * at /sys/bus/event_source/devices/<dev>/format.
+ */
+static char *test_format_dir_get(void)
+{
+ static char dir[PATH_MAX];
+ unsigned int i;
+
+ snprintf(dir, PATH_MAX, "/tmp/perf-pmu-test-format-XXXXXX");
+ if (!mkdtemp(dir))
+ return NULL;
+
+ for (i = 0; i < TEST_FORMATS_CNT; i++) {
+ static char name[PATH_MAX];
+ struct test_format *format = &test_formats[i];
+ FILE *file;
+
+ snprintf(name, PATH_MAX, "%s/%s", dir, format->name);
+
+ file = fopen(name, "w");
+ if (!file)
+ return NULL;
+
+ if (1 != fwrite(format->value, strlen(format->value), 1, file))
+ break;
+
+ fclose(file);
+ }
+
+ return dir;
+}
+
+/* Cleanup format directory. */
+static int test_format_dir_put(char *dir)
+{
+ char buf[PATH_MAX];
+ snprintf(buf, PATH_MAX, "rm -f %s/*\n", dir);
+ if (system(buf))
+ return -1;
+
+ snprintf(buf, PATH_MAX, "rmdir %s\n", dir);
+ return system(buf);
+}
+
+static struct list_head *test_terms_list(void)
+{
+ static LIST_HEAD(terms);
+ unsigned int i;
+
+ for (i = 0; i < TERMS_CNT; i++)
+ list_add_tail(&test_terms[i].list, &terms);
+
+ return &terms;
+}
+
+#undef TERMS_CNT
+
+int test__pmu(void)
+{
+ char *format = test_format_dir_get();
+ LIST_HEAD(formats);
+ struct list_head *terms = test_terms_list();
+ int ret;
+
+ if (!format)
+ return -EINVAL;
+
+ do {
+ struct perf_event_attr attr;
+
+ memset(&attr, 0, sizeof(attr));
+
+ ret = perf_pmu__format_parse(format, &formats);
+ if (ret)
+ break;
+
+ ret = perf_pmu__config_terms(&formats, &attr, terms);
+ if (ret)
+ break;
+
+ ret = -EINVAL;
+
+ if (attr.config != 0xc00000000002a823)
+ break;
+ if (attr.config1 != 0x8000400000000145)
+ break;
+ if (attr.config2 != 0x0400000020041d07)
+ break;
+
+ ret = 0;
+ } while (0);
+
+ test_format_dir_put(format);
+ return ret;
+}
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index f70f998..88a55df 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -11,6 +11,7 @@ int test__rdpmc(void);
int test__perf_evsel__roundtrip_name_test(void);
int test__perf_evsel__tp_sched_test(void);
int test__syscall_open_tp_fields(void);
+int test__pmu(void);

/* Util */
int trace_event__id(const char *evname);
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 18e8480..9bdc60c 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -22,7 +22,7 @@ static LIST_HEAD(pmus);
* Parse & process all the sysfs attributes located under
* the directory specified in 'dir' parameter.
*/
-static int pmu_format_parse(char *dir, struct list_head *head)
+int perf_pmu__format_parse(char *dir, struct list_head *head)
{
struct dirent *evt_ent;
DIR *format_dir;
@@ -77,7 +77,7 @@ static int pmu_format(char *name, struct list_head *format)
if (stat(path, &st) < 0)
return 0; /* no error if format does not exist */

- if (pmu_format_parse(path, format))
+ if (perf_pmu__format_parse(path, format))
return -1;

return 0;
@@ -446,8 +446,9 @@ static int pmu_config_term(struct list_head *formats,
return 0;
}

-static int pmu_config(struct list_head *formats, struct perf_event_attr *attr,
- struct list_head *head_terms)
+int perf_pmu__config_terms(struct list_head *formats,
+ struct perf_event_attr *attr,
+ struct list_head *head_terms)
{
struct parse_events__term *term;

@@ -467,7 +468,7 @@ int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
struct list_head *head_terms)
{
attr->type = pmu->type;
- return pmu_config(&pmu->format, attr, head_terms);
+ return perf_pmu__config_terms(&pmu->format, attr, head_terms);
}

static struct perf_pmu__alias *pmu_find_alias(struct perf_pmu *pmu,
@@ -551,177 +552,3 @@ void perf_pmu__set_format(unsigned long *bits, long from, long to)
for (b = from; b <= to; b++)
set_bit(b, bits);
}
-
-/* Simulated format definitions. */
-static struct test_format {
- const char *name;
- const char *value;
-} test_formats[] = {
- { "krava01", "config:0-1,62-63\n", },
- { "krava02", "config:10-17\n", },
- { "krava03", "config:5\n", },
- { "krava11", "config1:0,2,4,6,8,20-28\n", },
- { "krava12", "config1:63\n", },
- { "krava13", "config1:45-47\n", },
- { "krava21", "config2:0-3,10-13,20-23,30-33,40-43,50-53,60-63\n", },
- { "krava22", "config2:8,18,48,58\n", },
- { "krava23", "config2:28-29,38\n", },
-};
-
-#define TEST_FORMATS_CNT (sizeof(test_formats) / sizeof(struct test_format))
-
-/* Simulated users input. */
-static struct parse_events__term test_terms[] = {
- {
- .config = (char *) "krava01",
- .val.num = 15,
- .type_val = PARSE_EVENTS__TERM_TYPE_NUM,
- .type_term = PARSE_EVENTS__TERM_TYPE_USER,
- },
- {
- .config = (char *) "krava02",
- .val.num = 170,
- .type_val = PARSE_EVENTS__TERM_TYPE_NUM,
- .type_term = PARSE_EVENTS__TERM_TYPE_USER,
- },
- {
- .config = (char *) "krava03",
- .val.num = 1,
- .type_val = PARSE_EVENTS__TERM_TYPE_NUM,
- .type_term = PARSE_EVENTS__TERM_TYPE_USER,
- },
- {
- .config = (char *) "krava11",
- .val.num = 27,
- .type_val = PARSE_EVENTS__TERM_TYPE_NUM,
- .type_term = PARSE_EVENTS__TERM_TYPE_USER,
- },
- {
- .config = (char *) "krava12",
- .val.num = 1,
- .type_val = PARSE_EVENTS__TERM_TYPE_NUM,
- .type_term = PARSE_EVENTS__TERM_TYPE_USER,
- },
- {
- .config = (char *) "krava13",
- .val.num = 2,
- .type_val = PARSE_EVENTS__TERM_TYPE_NUM,
- .type_term = PARSE_EVENTS__TERM_TYPE_USER,
- },
- {
- .config = (char *) "krava21",
- .val.num = 119,
- .type_val = PARSE_EVENTS__TERM_TYPE_NUM,
- .type_term = PARSE_EVENTS__TERM_TYPE_USER,
- },
- {
- .config = (char *) "krava22",
- .val.num = 11,
- .type_val = PARSE_EVENTS__TERM_TYPE_NUM,
- .type_term = PARSE_EVENTS__TERM_TYPE_USER,
- },
- {
- .config = (char *) "krava23",
- .val.num = 2,
- .type_val = PARSE_EVENTS__TERM_TYPE_NUM,
- .type_term = PARSE_EVENTS__TERM_TYPE_USER,
- },
-};
-#define TERMS_CNT (sizeof(test_terms) / sizeof(struct parse_events__term))
-
-/*
- * Prepare format directory data, exported by kernel
- * at /sys/bus/event_source/devices/<dev>/format.
- */
-static char *test_format_dir_get(void)
-{
- static char dir[PATH_MAX];
- unsigned int i;
-
- snprintf(dir, PATH_MAX, "/tmp/perf-pmu-test-format-XXXXXX");
- if (!mkdtemp(dir))
- return NULL;
-
- for (i = 0; i < TEST_FORMATS_CNT; i++) {
- static char name[PATH_MAX];
- struct test_format *format = &test_formats[i];
- FILE *file;
-
- snprintf(name, PATH_MAX, "%s/%s", dir, format->name);
-
- file = fopen(name, "w");
- if (!file)
- return NULL;
-
- if (1 != fwrite(format->value, strlen(format->value), 1, file))
- break;
-
- fclose(file);
- }
-
- return dir;
-}
-
-/* Cleanup format directory. */
-static int test_format_dir_put(char *dir)
-{
- char buf[PATH_MAX];
- snprintf(buf, PATH_MAX, "rm -f %s/*\n", dir);
- if (system(buf))
- return -1;
-
- snprintf(buf, PATH_MAX, "rmdir %s\n", dir);
- return system(buf);
-}
-
-static struct list_head *test_terms_list(void)
-{
- static LIST_HEAD(terms);
- unsigned int i;
-
- for (i = 0; i < TERMS_CNT; i++)
- list_add_tail(&test_terms[i].list, &terms);
-
- return &terms;
-}
-
-#undef TERMS_CNT
-
-int perf_pmu__test(void)
-{
- char *format = test_format_dir_get();
- LIST_HEAD(formats);
- struct list_head *terms = test_terms_list();
- int ret;
-
- if (!format)
- return -EINVAL;
-
- do {
- struct perf_event_attr attr;
-
- memset(&attr, 0, sizeof(attr));
-
- ret = pmu_format_parse(format, &formats);
- if (ret)
- break;
-
- ret = pmu_config(&formats, &attr, terms);
- if (ret)
- break;
-
- ret = -EINVAL;
-
- if (attr.config != 0xc00000000002a823)
- break;
- if (attr.config1 != 0x8000400000000145)
- break;
- if (attr.config2 != 0x0400000020041d07)
- break;
-
- ret = 0;
- } while (0);
-
- test_format_dir_put(format);
- return ret;
-}
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 39f3aba..07d553f 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -37,6 +37,9 @@ struct perf_pmu {
struct perf_pmu *perf_pmu__find(char *name);
int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
struct list_head *head_terms);
+int perf_pmu__config_terms(struct list_head *formats,
+ struct perf_event_attr *attr,
+ struct list_head *head_terms);
int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms);
struct list_head *perf_pmu__alias(struct perf_pmu *pmu,
struct list_head *head_terms);
@@ -46,6 +49,7 @@ void perf_pmu_error(struct list_head *list, char *name, char const *msg);
int perf_pmu__new_format(struct list_head *list, char *name,
int config, unsigned long *bits);
void perf_pmu__set_format(unsigned long *bits, long from, long to);
+int perf_pmu__format_parse(char *dir, struct list_head *head);

struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu);

--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Nov 18, 2012, 9:40:02 AM11/18/12
to
From: Jiri Olsa <jo...@redhat.com>

Updating event parser to allow any non zero string containing [ukhpGH]
characters for event modifier.

The modifier sanity is checked later in parse-event object logic. The
check validates modifier to contain only one instance of any modifier
(apart from 'p') present.

v2:
- added length check suggested Namhyung Kim

Signed-off-by: Jiri Olsa <jo...@redhat.com>
Acked-by: Namhyung Kim <namh...@kernel.org>
Cc: Corey Ashford <cjas...@linux.vnet.ibm.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Ingo Molnar <mi...@elte.hu>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Link: http://lkml.kernel.org/r/2012111314...@krava.brq.redhat.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/parse-events.c | 24 ++++++++++++++++++++++++
tools/perf/util/parse-events.l | 2 +-
2 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index c0b785b..020323a 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -722,6 +722,27 @@ static int get_event_modifier(struct event_modifier *mod, char *str,
return 0;
}

+/*
+ * Basic modifier sanity check to validate it contains only one
+ * instance of any modifier (apart from 'p') present.
+ */
+static int check_modifier(char *str)
+{
+ char *p = str;
+
+ /* The sizeof includes 0 byte as well. */
+ if (strlen(str) > (sizeof("ukhGHppp") - 1))
+ return -1;
+
+ while (*p) {
+ if (*p != 'p' && strchr(p + 1, *p))
+ return -1;
+ p++;
+ }
+
+ return 0;
+}
+
int parse_events__modifier_event(struct list_head *list, char *str, bool add)
{
struct perf_evsel *evsel;
@@ -730,6 +751,9 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add)
if (str == NULL)
return 0;

+ if (check_modifier(str))
+ return -EINVAL;
+
if (!add && get_event_modifier(&mod, str, NULL))
return -EINVAL;

diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 66959fa..e9d1134 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -82,7 +82,7 @@ num_hex 0x[a-fA-F0-9]+
num_raw_hex [a-fA-F0-9]+
name [a-zA-Z_*?][a-zA-Z0-9_*?]*
name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?]*
-modifier_event [ukhpGH]{1,8}
+modifier_event [ukhpGH]+
modifier_bp [rwx]{1,3}

%%
--
1.7.9.2.358.g22243

Josh Boyer

unread,
Nov 19, 2012, 8:30:01 AM11/19/12
to
On Sun, Nov 18, 2012 at 9:29 AM, Arnaldo Carvalho de Melo
<ac...@infradead.org> wrote:
> From: Sukadev Bhattiprolu <suk...@linux.vnet.ibm.com>
>
> Use the 'unistd.h' from arch/powerpc/include/uapi to build the perf tool.

This would work for powerpc, but at least s390x and ARM have the same
build issue. Why would we fix this piecemeal per-arch?

David Howells has a patch that _should_ fix it for all of them at once.
Is there a reason that isn't going in?

josh

Arnaldo Carvalho de Melo

unread,
Nov 19, 2012, 10:10:02 AM11/19/12
to
Em Mon, Nov 19, 2012 at 08:29:09AM -0500, Josh Boyer escreveu:
> On Sun, Nov 18, 2012 at 9:29 AM, Arnaldo Carvalho de Melo <ac...@infradead.org> wrote:
> > From: Sukadev Bhattiprolu <suk...@linux.vnet.ibm.com>

> > Use the 'unistd.h' from arch/powerpc/include/uapi to build the perf tool.
>
> This would work for powerpc, but at least s390x and ARM have the same
> build issue. Why would we fix this piecemeal per-arch?
>
> David Howells has a patch that _should_ fix it for all of them at once.
> Is there a reason that isn't going in?

David rebased his patch on top of my perf/core branch, I just tested it
and all works as expected, so I'd say he should push that branch
upstream as I can't just cherry pick some csets, it needs a merge that
involves more than just tools/perf AFAIK.

- Arnaldo

Josh Boyer

unread,
Nov 19, 2012, 10:20:02 AM11/19/12
to
On Mon, Nov 19, 2012 at 10:07 AM, Arnaldo Carvalho de Melo
<ac...@ghostprotocols.net> wrote:
> Em Mon, Nov 19, 2012 at 08:29:09AM -0500, Josh Boyer escreveu:
>> On Sun, Nov 18, 2012 at 9:29 AM, Arnaldo Carvalho de Melo <ac...@infradead.org> wrote:
>> > From: Sukadev Bhattiprolu <suk...@linux.vnet.ibm.com>
>
>> > Use the 'unistd.h' from arch/powerpc/include/uapi to build the perf tool.
>>
>> This would work for powerpc, but at least s390x and ARM have the same
>> build issue. Why would we fix this piecemeal per-arch?
>>
>> David Howells has a patch that _should_ fix it for all of them at once.
>> Is there a reason that isn't going in?
>
> David rebased his patch on top of my perf/core branch, I just tested it
> and all works as expected, so I'd say he should push that branch
> upstream as I can't just cherry pick some csets, it needs a merge that
> involves more than just tools/perf AFAIK.

OK... is perf/core (all 32 commits) headed into 3.7? Because the perf
build is broken in 3.7-rcX, and we're at the point where Linus gets kind
of picky about what he accepts. So we'd need your branch and David's to
fix compile issues. And then we'd need Xiao Guangrong's fixes for 'perf
kvm' to only build on x86. That's quite a number of fixes we need just
to get perf to compile. Is someone other than me keeping track of
that?

I would just like people to stop wondering when perf builds on non-x86
architectures will work.

josh

Ingo Molnar

unread,
Dec 8, 2012, 9:30:02 AM12/8/12
to

Note that I had to do a number of conflict resolutions between
perf/urgent (now upstream) and perf/core, related to UAPI fixes:

commit f0b9abfb044649bc452fb2fb975ff2fd599cc6a3
Merge: adc1ef1 1b3c393
Author: Ingo Molnar <mi...@kernel.org>
Date: Sat Dec 8 15:25:06 2012 +0100

Merge branch 'linus' into perf/core

Conflicts:
tools/perf/Makefile
tools/perf/builtin-test.c
tools/perf/perf.h
tools/perf/tests/parse-events.c
tools/perf/util/evsel.h

Signed-off-by: Ingo Molnar <mi...@kernel.org>

I think I managed to resolve them all correctly - but please
double check the end result nevertheless.

Thanks,

Ingo

Ingo Molnar

unread,
Dec 8, 2012, 9:30:01 AM12/8/12
to
Pulled, thanks a lot Arnaldo!

Ingo

Arnaldo Carvalho de Melo

unread,
Dec 11, 2012, 5:50:01 PM12/11/12
to
Hi Ingo,

Please consider pulling.

Jiri, tomorrow I'll go over the hists patches as I think you're fully
ok with Namhyung latest patchset.

Regards,

- Arnaldo

The following changes since commit cc1b39dbf9f55a438e8a21a694394c20e6a17129:

Merge branch 'tip/perf/core' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace into perf/core (2012-12-08 15:54:35 +0100)

are available in the git repository at:


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

for you to fetch changes up to 2376c67a7bbc7849b806688ba2efb8520c21c458:

perf top: Use perf_evlist__config() (2012-12-11 17:22:39 -0300)

----------------------------------------------------------------
perf/core improvements and fixes

. perf build-id cache now can show DSOs present in a perf.data file that are
not in the cache, to integrate with build-id servers being put in place by
organizations such as Fedora.

. perf buildid-list -i an-elf-file-instead-of-a-perf.data is back showing its
build-id.

. No need to do feature checks when doing a 'make tags'

. Fix some 'perf test' errors and make them use the tracepoint evsel constructor.

. perf top now shares more of the evsel config/creation routines with 'record',
paving the way for further integration like 'top' snapshots, etc.

. perf top now supports DWARF callchains.

. perf evlist decodes sample_type and read_format, helping diagnose problems.

. Fix mmap limitations on 32-bit, fix from David Miller.

. perf diff fixes from Jiri Olsa.

. Ignore ABS symbols when loading data maps, fix from Namhyung Kim

. Hists improvements from Namhyung Kim

. Don't check configuration on make clean, from Namhyung Kim

. Fix dso__fprintf() print statement, from Stephane Eranian.

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

----------------------------------------------------------------
Arnaldo Carvalho de Melo (20):
perf top: Add missing newline on pr_err call
perf tools: Don't check configuration on make tags
perf tools: Fix TUI helpline output
perf buildid-list: We need to check if a file is ELF first
perf symbols: Generalize filter in __fprintf_buildid methods
perf buildid-cache: Add option to show build ids that are missing in the cache
perf machine: Move more machine methods to machine.c
perf evsel: Update sample_size when setting sample_type bits
perf test: Fixup error reporting in basic mmap test
perf test: Use perf_evsel__newtp constructor in the tracepoint tests
perf evsel: Introduce method to request IDs be used
perf evsel: No need to always ask for PERF_FORMAT_ID in read_format
perf evsel: No need to always ask for PERF_FORMAT_TOTAL_TIME_{ENABLED,RUNNING}
perf evlist: Set the leader in the perf_evlist__config method
perf evsel: Adopt fprintf routine from 'perf evlist'
perf tools: Add install-bin Makefile target
perf evsel: Decode read_format and sample_type in perf_evsel__fprintf
perf record: Pass perf_record_opts to the callchain cmdline parsing callback
perf record: Export the callchain parsing routine and help
perf top: Use perf_evlist__config()

David Miller (1):
perf tools: Fix mmap limitations on 32-bit

Jiri Olsa (6):
perf hists: Introduce perf_hpp__list for period related columns
perf hists: Fix period symbol_conf.field_sep display
perf diff: Remove displacement from struct hist_entry_diff
perf diff: Change compute methods to work with pair directly
perf diff: Change formula methods to work with pair directly
perf diff: Remove displacement output option

Namhyung Kim (9):
perf ui: Always compile error printing code
perf ui/helpline: Introduce ui_helpline__vshow()
perf tools: Don't check configuration on make clean
perf session: Free environment information when deleting session
perf symbols: Ignore ABS symbols when loading data maps
perf hists: Fix typo on hist__entry_add_pair
perf hists: Link hist entry pairs to leader
perf evsel: Set leader evsel's ->leader to itself
perf evsel: Convert to _is_group_leader method

Stephane Eranian (1):
perf symbols: Fix dso__fprintf() print statement

tools/perf/Documentation/Makefile | 4 +
tools/perf/Documentation/perf-buildid-cache.txt | 3 +
tools/perf/Documentation/perf-diff.txt | 4 -
tools/perf/Documentation/perf-top.txt | 2 +-
tools/perf/Makefile | 51 +-
tools/perf/builtin-buildid-cache.c | 48 +-
tools/perf/builtin-buildid-list.c | 21 +-
tools/perf/builtin-diff.c | 121 ++--
tools/perf/builtin-evlist.c | 81 +--
tools/perf/builtin-record.c | 40 +-
tools/perf/builtin-report.c | 1 +
tools/perf/builtin-stat.c | 2 +-
tools/perf/builtin-top.c | 207 ++-----
tools/perf/builtin-trace.c | 2 +-
tools/perf/tests/attr/base-record | 2 +-
tools/perf/tests/attr/test-record-group | 2 +
tools/perf/tests/attr/test-record-group1 | 2 +
tools/perf/tests/mmap-basic.c | 40 +-
tools/perf/tests/open-syscall-all-cpus.c | 18 +-
tools/perf/tests/open-syscall.c | 17 +-
tools/perf/tests/parse-events.c | 20 +-
tools/perf/tests/perf-record.c | 8 +-
tools/perf/tests/tests.h | 3 -
tools/perf/tests/util.c | 30 -
tools/perf/ui/browsers/hists.c | 20 +-
tools/perf/ui/gtk/browser.c | 30 +-
tools/perf/ui/gtk/helpline.c | 23 +-
tools/perf/ui/helpline.c | 12 +
tools/perf/ui/helpline.h | 22 +-
tools/perf/ui/hist.c | 170 +++---
tools/perf/ui/setup.c | 1 +
tools/perf/ui/stdio/hist.c | 17 +-
tools/perf/ui/tui/helpline.c | 29 +-
tools/perf/ui/util.c | 10 +
tools/perf/util/callchain.h | 5 +
tools/perf/util/debug.c | 28 +-
tools/perf/util/debug.h | 33 +-
tools/perf/util/dso.c | 6 +-
tools/perf/util/dso.h | 2 +-
tools/perf/util/evlist.c | 17 +-
tools/perf/util/evlist.h | 4 +-
tools/perf/util/evsel.c | 186 +++++-
tools/perf/util/evsel.h | 25 +-
tools/perf/util/hist.c | 4 +-
tools/perf/util/hist.h | 22 +-
tools/perf/util/machine.c | 742 +++++++++++++++++++++++
tools/perf/util/machine.h | 11 +-
tools/perf/util/session.c | 256 +-------
tools/perf/util/session.h | 5 +-
tools/perf/util/sort.h | 5 +-
tools/perf/util/symbol-elf.c | 11 +
tools/perf/util/symbol.c | 522 +---------------
tools/perf/util/symbol.h | 4 +
tools/perf/util/thread.c | 20 +-
tools/perf/util/thread.h | 1 +
tools/perf/util/top.c | 22 +-
tools/perf/util/top.h | 8 +-
57 files changed, 1483 insertions(+), 1519 deletions(-)
delete mode 100644 tools/perf/tests/util.c

Arnaldo Carvalho de Melo

unread,
Dec 11, 2012, 5:50:02 PM12/11/12
to
From: Jiri Olsa <jo...@redhat.com>

Currently we don't properly display hist data with symbol_conf.field_sep
separator. We need to display either space or separator.

Signed-off-by: Jiri Olsa <jo...@redhat.com>
Cc: Arnaldo Carvalho de Melo <ac...@ghostprotocols.net>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Cc: Ingo Molnar <mi...@elte.hu>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Corey Ashford <cjas...@linux.vnet.ibm.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Namhyung Kim <namh...@kernel.org>
Link: http://lkml.kernel.org/n/tip-cyggwys0bz...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/ui/hist.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 0a5281f..6e639b5 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -472,11 +472,15 @@ int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he,
return 0;

perf_hpp__for_each_format(fmt) {
+ /*
+ * If there's no field_sep, we still need
+ * to display initial ' '.
+ */
if (!sep || !first) {
ret = scnprintf(hpp->buf, hpp->size, "%s", sep ?: " ");
advance_hpp(hpp, ret);
+ } else
first = false;
- }

if (color && fmt->color)
ret = fmt->color(hpp, he);
--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Dec 11, 2012, 5:50:02 PM12/11/12
to
From: Namhyung Kim <namhyu...@lge.com>

Fix a misplaced underscore. In this case, 'hist_entry' is the name of
data structure and we usually put double underscores between data
structure and actual function name.

Signed-off-by: Namhyung Kim <namh...@kernel.org>
Acked-by: Jiri Olsa <jo...@redhat.com>
Cc: Andi Kleen <an...@firstfloor.org>
Cc: Ingo Molnar <mi...@kernel.org>
Cc: Jiri Olsa <jo...@redhat.com>,
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Cc: Stephane Eranian <era...@google.com>
Link: http://lkml.kernel.org/n/tip-8jdq8g6kl6...@git.kernel.org
[ committer note: put it in front of the patch queue where it came from ]
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/hist.c | 4 ++--
tools/perf/util/sort.h | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index cb17e2a..d2bc05c 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -785,7 +785,7 @@ void hists__match(struct hists *leader, struct hists *other)
pair = hists__find_entry(other, pos);

if (pair)
- hist__entry_add_pair(pos, pair);
+ hist_entry__add_pair(pos, pair);
}
}

@@ -806,7 +806,7 @@ int hists__link(struct hists *leader, struct hists *other)
pair = hists__add_dummy_entry(leader, pos);
if (pair == NULL)
return -1;
- hist__entry_add_pair(pair, pos);
+ hist_entry__add_pair(pair, pos);
}
}

diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index b4e8c3b..91ae274 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -118,7 +118,7 @@ static inline struct hist_entry *hist_entry__next_pair(struct hist_entry *he)
return NULL;
}

-static inline void hist__entry_add_pair(struct hist_entry *he,
+static inline void hist_entry__add_pair(struct hist_entry *he,
struct hist_entry *pair)
{
list_add_tail(&he->pairs.head, &pair->pairs.node);
--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Dec 11, 2012, 5:50:02 PM12/11/12
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

We use evsel->sample_size to detect underflows in
perf_evsel__parse_sample, but we were failing to update it after
perf_evsel__init(), i.e. when we decide, after creating an evsel, that
we want some extra field bit set.

Fix it by introducing methods to set a bit that will take care of
correctly adjusting evsel->sample_size.

Cc: David Ahern <dsa...@gmail.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Jiri Olsa <jo...@redhat.com>
Cc: Mike Galbraith <efa...@gmx.de>
Cc: Namhyung Kim <namh...@gmail.com>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Stephane Eranian <era...@google.com>
Link: http://lkml.kernel.org/n/tip-2ny5pzsing...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>

Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-record.c | 2 +-
tools/perf/builtin-top.c | 11 +++++-----
tools/perf/tests/perf-record.c | 6 +++---
tools/perf/util/evlist.c | 2 +-
tools/perf/util/evsel.c | 45 ++++++++++++++++++++++++++++------------
tools/perf/util/evsel.h | 11 ++++++++++
6 files changed, 54 insertions(+), 23 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index f3151d3..0be6605 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -286,7 +286,7 @@ try_again:
*/
opts->sample_id_all_missing = true;
if (!opts->sample_time && !opts->raw_samples && !time_needed)
- attr->sample_type &= ~PERF_SAMPLE_TIME;
+ perf_evsel__reset_sample_bit(pos, TIME);

goto retry_sample_id;
}
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 987e1b8..31a7c51 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -901,24 +901,25 @@ static void perf_top__start_counters(struct perf_top *top)
list_for_each_entry(counter, &evlist->entries, node) {
struct perf_event_attr *attr = &counter->attr;

- attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
+ perf_evsel__set_sample_bit(counter, IP);
+ perf_evsel__set_sample_bit(counter, TID);

if (top->freq) {
- attr->sample_type |= PERF_SAMPLE_PERIOD;
+ perf_evsel__set_sample_bit(counter, PERIOD);
attr->freq = 1;
attr->sample_freq = top->freq;
}

if (evlist->nr_entries > 1) {
- attr->sample_type |= PERF_SAMPLE_ID;
+ perf_evsel__set_sample_bit(counter, ID);
attr->read_format |= PERF_FORMAT_ID;
}

if (perf_target__has_cpu(&top->target))
- attr->sample_type |= PERF_SAMPLE_CPU;
+ perf_evsel__set_sample_bit(counter, CPU);

if (symbol_conf.use_callchain)
- attr->sample_type |= PERF_SAMPLE_CALLCHAIN;
+ perf_evsel__set_sample_bit(counter, CALLCHAIN);

attr->mmap = 1;
attr->comm = 1;
diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c
index 70e0d44..5902772 100644
--- a/tools/perf/tests/perf-record.c
+++ b/tools/perf/tests/perf-record.c
@@ -103,9 +103,9 @@ int test__PERF_RECORD(void)
* Config the evsels, setting attr->comm on the first one, etc.
*/
evsel = perf_evlist__first(evlist);
- evsel->attr.sample_type |= PERF_SAMPLE_CPU;
- evsel->attr.sample_type |= PERF_SAMPLE_TID;
- evsel->attr.sample_type |= PERF_SAMPLE_TIME;
+ perf_evsel__set_sample_bit(evsel, CPU);
+ perf_evsel__set_sample_bit(evsel, TID);
+ perf_evsel__set_sample_bit(evsel, TIME);
perf_evlist__config_attrs(evlist, &opts);

err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask);
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index d0e1e82..2655659 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -61,7 +61,7 @@ void perf_evlist__config_attrs(struct perf_evlist *evlist,
perf_evsel__config(evsel, opts);

if (evlist->nr_entries > 1)
- evsel->attr.sample_type |= PERF_SAMPLE_ID;
+ perf_evsel__set_sample_bit(evsel, ID);
}
}

diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index bb58b05..fc80f5a 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -50,6 +50,24 @@ void hists__init(struct hists *hists)
pthread_mutex_init(&hists->lock, NULL);
}

+void __perf_evsel__set_sample_bit(struct perf_evsel *evsel,
+ enum perf_event_sample_format bit)
+{
+ if (!(evsel->attr.sample_type & bit)) {
+ evsel->attr.sample_type |= bit;
+ evsel->sample_size += sizeof(u64);
+ }
+}
+
+void __perf_evsel__reset_sample_bit(struct perf_evsel *evsel,
+ enum perf_event_sample_format bit)
+{
+ if (evsel->attr.sample_type & bit) {
+ evsel->attr.sample_type &= ~bit;
+ evsel->sample_size -= sizeof(u64);
+ }
+}
+
void perf_evsel__init(struct perf_evsel *evsel,
struct perf_event_attr *attr, int idx)
{
@@ -445,7 +463,8 @@ void perf_evsel__config(struct perf_evsel *evsel,
PERF_FORMAT_TOTAL_TIME_RUNNING |
PERF_FORMAT_ID;

- attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID;
+ perf_evsel__set_sample_bit(evsel, IP);
+ perf_evsel__set_sample_bit(evsel, TID);

/*
* We default some events to a 1 default interval. But keep
@@ -454,7 +473,7 @@ void perf_evsel__config(struct perf_evsel *evsel,
if (!attr->sample_period || (opts->user_freq != UINT_MAX &&
opts->user_interval != ULLONG_MAX)) {
if (opts->freq) {
- attr->sample_type |= PERF_SAMPLE_PERIOD;
+ perf_evsel__set_sample_bit(evsel, PERIOD);
attr->freq = 1;
attr->sample_freq = opts->freq;
} else {
@@ -469,16 +488,16 @@ void perf_evsel__config(struct perf_evsel *evsel,
attr->inherit_stat = 1;

if (opts->sample_address) {
- attr->sample_type |= PERF_SAMPLE_ADDR;
+ perf_evsel__set_sample_bit(evsel, ADDR);
attr->mmap_data = track;
}

if (opts->call_graph) {
- attr->sample_type |= PERF_SAMPLE_CALLCHAIN;
+ perf_evsel__set_sample_bit(evsel, CALLCHAIN);

if (opts->call_graph == CALLCHAIN_DWARF) {
- attr->sample_type |= PERF_SAMPLE_REGS_USER |
- PERF_SAMPLE_STACK_USER;
+ perf_evsel__set_sample_bit(evsel, REGS_USER);
+ perf_evsel__set_sample_bit(evsel, STACK_USER);
attr->sample_regs_user = PERF_REGS_MASK;
attr->sample_stack_user = opts->stack_dump_size;
attr->exclude_callchain_user = 1;
@@ -486,20 +505,20 @@ void perf_evsel__config(struct perf_evsel *evsel,
}

if (perf_target__has_cpu(&opts->target))
- attr->sample_type |= PERF_SAMPLE_CPU;
+ perf_evsel__set_sample_bit(evsel, CPU);

if (opts->period)
- attr->sample_type |= PERF_SAMPLE_PERIOD;
+ perf_evsel__set_sample_bit(evsel, PERIOD);

if (!opts->sample_id_all_missing &&
(opts->sample_time || !opts->no_inherit ||
perf_target__has_cpu(&opts->target)))
- attr->sample_type |= PERF_SAMPLE_TIME;
+ perf_evsel__set_sample_bit(evsel, TIME);

if (opts->raw_samples) {
- attr->sample_type |= PERF_SAMPLE_TIME;
- attr->sample_type |= PERF_SAMPLE_RAW;
- attr->sample_type |= PERF_SAMPLE_CPU;
+ perf_evsel__set_sample_bit(evsel, TIME);
+ perf_evsel__set_sample_bit(evsel, RAW);
+ perf_evsel__set_sample_bit(evsel, CPU);
}

if (opts->no_delay) {
@@ -507,7 +526,7 @@ void perf_evsel__config(struct perf_evsel *evsel,
attr->wakeup_events = 1;
}
if (opts->branch_stack) {
- attr->sample_type |= PERF_SAMPLE_BRANCH_STACK;
+ perf_evsel__set_sample_bit(evsel, BRANCH_STACK);
attr->branch_sample_type = opts->branch_stack;
}

diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 3f7ff47..7398539 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -118,6 +118,17 @@ void perf_evsel__free_fd(struct perf_evsel *evsel);
void perf_evsel__free_id(struct perf_evsel *evsel);
void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads);

+void __perf_evsel__set_sample_bit(struct perf_evsel *evsel,
+ enum perf_event_sample_format bit);
+void __perf_evsel__reset_sample_bit(struct perf_evsel *evsel,
+ enum perf_event_sample_format bit);
+
+#define perf_evsel__set_sample_bit(evsel, bit) \
+ __perf_evsel__set_sample_bit(evsel, PERF_SAMPLE_##bit)
+
+#define perf_evsel__reset_sample_bit(evsel, bit) \
+ __perf_evsel__reset_sample_bit(evsel, PERF_SAMPLE_##bit)
+
int perf_evsel__set_filter(struct perf_evsel *evsel, int ncpus, int nthreads,
const char *filter);

--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Dec 11, 2012, 5:50:02 PM12/11/12
to
From: Namhyung Kim <namhyu...@lge.com>

Current hists__match/link() link a leader to its pair, so if multiple
pairs were linked, the leader will lose pointer to previous pairs since
it was overwritten. Fix it by making leader the list head.

Signed-off-by: Namhyung Kim <namh...@kernel.org>
Cc: Andi Kleen <an...@firstfloor.org>
Cc: Ingo Molnar <mi...@kernel.org>
Cc: Jiri Olsa <jo...@redhat.com>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Cc: Stephane Eranian <era...@google.com>
Link: http://lkml.kernel.org/r/1354171126-14387-8-gi...@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/hist.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index d2bc05c..82df1b2 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -785,7 +785,7 @@ void hists__match(struct hists *leader, struct hists *other)
pair = hists__find_entry(other, pos);

if (pair)
- hist_entry__add_pair(pos, pair);
+ hist_entry__add_pair(pair, pos);
}
}

@@ -806,7 +806,7 @@ int hists__link(struct hists *leader, struct hists *other)
pair = hists__add_dummy_entry(leader, pos);
if (pair == NULL)
return -1;
- hist_entry__add_pair(pair, pos);
+ hist_entry__add_pair(pos, pair);
}
}

--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Dec 11, 2012, 5:50:01 PM12/11/12
to
From: Namhyung Kim <namhyu...@lge.com>

The ui_helpline__vshow() will be used for pr_* functions.

Signed-off-by: Namhyung Kim <namh...@kernel.org>
Cc: Andi Kleen <a...@linux.intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Ingo Molnar <mi...@kernel.org>
Cc: Jiri Olsa <jo...@redhat.com>
Cc: Pekka Enberg <pen...@kernel.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Steven Rostedt <ros...@goodmis.org>
Link: http://lkml.kernel.org/r/1352911664-24620-3-gi...@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/ui/gtk/helpline.c | 23 ++++++++++++-----------
tools/perf/ui/helpline.c | 12 ++++++++++++
tools/perf/ui/helpline.h | 22 ++--------------------
tools/perf/ui/tui/helpline.c | 29 +++++++++++++++--------------
tools/perf/util/debug.c | 6 ++----
5 files changed, 43 insertions(+), 49 deletions(-)

diff --git a/tools/perf/ui/gtk/helpline.c b/tools/perf/ui/gtk/helpline.c
index 5db4432..3388cbd 100644
--- a/tools/perf/ui/gtk/helpline.c
+++ b/tools/perf/ui/gtk/helpline.c
@@ -24,17 +24,7 @@ static void gtk_helpline_push(const char *msg)
pgctx->statbar_ctx_id, msg);
}

-static struct ui_helpline gtk_helpline_fns = {
- .pop = gtk_helpline_pop,
- .push = gtk_helpline_push,
-};
-
-void perf_gtk__init_helpline(void)
-{
- helpline_fns = &gtk_helpline_fns;
-}
-
-int perf_gtk__show_helpline(const char *fmt, va_list ap)
+static int gtk_helpline_show(const char *fmt, va_list ap)
{
int ret;
char *ptr;
@@ -54,3 +44,14 @@ int perf_gtk__show_helpline(const char *fmt, va_list ap)

return ret;
}
+
+static struct ui_helpline gtk_helpline_fns = {
+ .pop = gtk_helpline_pop,
+ .push = gtk_helpline_push,
+ .show = gtk_helpline_show,
+};
+
+void perf_gtk__init_helpline(void)
+{
+ helpline_fns = &gtk_helpline_fns;
+}
diff --git a/tools/perf/ui/helpline.c b/tools/perf/ui/helpline.c
index a49bcf3..700fb3c 100644
--- a/tools/perf/ui/helpline.c
+++ b/tools/perf/ui/helpline.c
@@ -16,9 +16,16 @@ static void nop_helpline__push(const char *msg __maybe_unused)
{
}

+static int nop_helpline__show(const char *fmt __maybe_unused,
+ va_list ap __maybe_unused)
+{
+ return 0;
+}
+
static struct ui_helpline default_helpline_fns = {
.pop = nop_helpline__pop,
.push = nop_helpline__push,
+ .show = nop_helpline__show,
};

struct ui_helpline *helpline_fns = &default_helpline_fns;
@@ -59,3 +66,8 @@ void ui_helpline__puts(const char *msg)
ui_helpline__pop();
ui_helpline__push(msg);
}
+
+int ui_helpline__vshow(const char *fmt, va_list ap)
+{
+ return helpline_fns->show(fmt, ap);
+}
diff --git a/tools/perf/ui/helpline.h b/tools/perf/ui/helpline.h
index baa28a4..46181f4 100644
--- a/tools/perf/ui/helpline.h
+++ b/tools/perf/ui/helpline.h
@@ -9,6 +9,7 @@
struct ui_helpline {
void (*pop)(void);
void (*push)(const char *msg);
+ int (*show)(const char *fmt, va_list ap);
};

extern struct ui_helpline *helpline_fns;
@@ -20,28 +21,9 @@ void ui_helpline__push(const char *msg);
void ui_helpline__vpush(const char *fmt, va_list ap);
void ui_helpline__fpush(const char *fmt, ...);
void ui_helpline__puts(const char *msg);
+int ui_helpline__vshow(const char *fmt, va_list ap);

extern char ui_helpline__current[512];
-
-#ifdef NEWT_SUPPORT
extern char ui_helpline__last_msg[];
-int ui_helpline__show_help(const char *format, va_list ap);
-#else
-static inline int ui_helpline__show_help(const char *format __maybe_unused,
- va_list ap __maybe_unused)
-{
- return 0;
-}
-#endif /* NEWT_SUPPORT */
-
-#ifdef GTK2_SUPPORT
-int perf_gtk__show_helpline(const char *format, va_list ap);
-#else
-static inline int perf_gtk__show_helpline(const char *format __maybe_unused,
- va_list ap __maybe_unused)
-{
- return 0;
-}
-#endif /* GTK2_SUPPORT */

#endif /* _PERF_UI_HELPLINE_H_ */
diff --git a/tools/perf/ui/tui/helpline.c b/tools/perf/ui/tui/helpline.c
index 2884d2f..1c8b9af 100644
--- a/tools/perf/ui/tui/helpline.c
+++ b/tools/perf/ui/tui/helpline.c
@@ -8,6 +8,8 @@
#include "../ui.h"
#include "../libslang.h"

+char ui_helpline__last_msg[1024];
+
static void tui_helpline__pop(void)
{
}
@@ -23,20 +25,7 @@ static void tui_helpline__push(const char *msg)
strncpy(ui_helpline__current, msg, sz)[sz - 1] = '\0';
}

-struct ui_helpline tui_helpline_fns = {
- .pop = tui_helpline__pop,
- .push = tui_helpline__push,
-};
-
-void ui_helpline__init(void)
-{
- helpline_fns = &tui_helpline_fns;
- ui_helpline__puts(" ");
-}
-
-char ui_helpline__last_msg[1024];
-
-int ui_helpline__show_help(const char *format, va_list ap)
+static int tui_helpline__show(const char *format, va_list ap)
{
int ret;
static int backlog;
@@ -55,3 +44,15 @@ int ui_helpline__show_help(const char *format, va_list ap)

return ret;
}
+
+struct ui_helpline tui_helpline_fns = {
+ .pop = tui_helpline__pop,
+ .push = tui_helpline__push,
+ .show = tui_helpline__show,
+};
+
+void ui_helpline__init(void)
+{
+ helpline_fns = &tui_helpline_fns;
+ ui_helpline__puts(" ");
+}
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index 39861a2a..391c9a9 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -23,10 +23,8 @@ int eprintf(int level, const char *fmt, ...)

if (verbose >= level) {
va_start(args, fmt);
- if (use_browser == 1)
- ret = ui_helpline__show_help(fmt, args);
- else if (use_browser == 2)
- ret = perf_gtk__show_helpline(fmt, args);
+ if (use_browser > 1)
+ ui_helpline__vshow(fmt, args);
else
ret = vfprintf(stderr, fmt, args);
va_end(args);
--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Dec 11, 2012, 6:00:01 PM12/11/12
to
From: Namhyung Kim <namhyu...@lge.com>

When loading symbols in a data mapping, ABS symbols (which has a value
of SHN_ABS in its st_shndx) failed at elf_getscn(). And it marks the
loading as a failure so already loaded symbols cannot be fixed up.

I'm not sure what should be done. Just ignore them for now. :)

Signed-off-by: Namhyung Kim <namh...@kernel.org>
Cc: Andi Kleen <a...@linux.intel.com>
Cc: Ingo Molnar <mi...@elte.hu>
Cc: Jiri Olsa <jo...@redhat.com>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Stephane Eranian <era...@google.com>
Link: http://lkml.kernel.org/r/1353502185-26521-19-g...@google.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/symbol-elf.c | 11 +++++++++++
1 file changed, 11 insertions(+)

diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index db0cc92..f63557b 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -718,6 +718,17 @@ int dso__load_sym(struct dso *dso, struct map *map,
sym.st_value);
used_opd = true;
}
+ /*
+ * When loading symbols in a data mapping, ABS symbols (which
+ * has a value of SHN_ABS in its st_shndx) failed at
+ * elf_getscn(). And it marks the loading as a failure so
+ * already loaded symbols cannot be fixed up.
+ *
+ * I'm not sure what should be done. Just ignore them for now.
+ * - Namhyung Kim
+ */
+ if (sym.st_shndx == SHN_ABS)
+ continue;

sec = elf_getscn(runtime_ss->elf, sym.st_shndx);
if (!sec)
--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Dec 11, 2012, 6:00:01 PM12/11/12
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

The perf_event__process_sample function, when not finding a machine
associated with a sample, was calling pr_err without a newline,
garbling the screen on TUI mode due to a problem introduced by a
recent ui_helpline patch.

On --stdio it would just concatenate the messages for each sample with
no machine associated, fix it by adding the newline.

Cc: David Ahern <dsa...@gmail.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Jiri Olsa <jo...@redhat.com>
Cc: Mike Galbraith <efa...@gmx.de>
Cc: Namhyung Kim <namh...@gmail.com>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Stephane Eranian <era...@google.com>
Link: http://lkml.kernel.org/n/tip-vuz88welqv...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-top.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index c9ff395..987e1b8 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -727,7 +727,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
}

if (!machine) {
- pr_err("%u unprocessable samples recorded.",
+ pr_err("%u unprocessable samples recorded.\n",
top->session->hists.stats.nr_unprocessable_samples++);
return;
}
--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Dec 11, 2012, 6:00:02 PM12/11/12
to
From: Namhyung Kim <namhyu...@lge.com>

Convert perf_evsel__is_group_member to perf_evsel__is_group_leader.
This is because the most usecases are using negative form to check
whether the given evsel is a leader or not and it's IMHO somewhat
ambiguous - leader also *is* a member of the group.

Signed-off-by: Namhyung Kim <namh...@kernel.org>
Acked-by: Jiri Olsa <jo...@redhat.com>
Cc: Andi Kleen <an...@firstfloor.org>
Cc: Ingo Molnar <mi...@kernel.org>
Cc: Jiri Olsa <jo...@redhat.com>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Cc: Stephane Eranian <era...@google.com>
Link: http://lkml.kernel.org/r/1354171126-14387-4-gi...@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-stat.c | 2 +-
tools/perf/tests/parse-events.c | 20 ++++++++++----------
tools/perf/util/evlist.c | 4 ++--
tools/perf/util/evsel.c | 6 +++---
tools/perf/util/evsel.h | 4 ++--
5 files changed, 18 insertions(+), 18 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index c247fac..c12655a 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -153,7 +153,7 @@ retry:
}

if (!perf_target__has_task(&target) &&
- !perf_evsel__is_group_member(evsel)) {
+ perf_evsel__is_group_leader(evsel)) {
attr->disabled = 1;
attr->enable_on_exec = 1;
}
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c
index 32ee478..294ffdd 100644
--- a/tools/perf/tests/parse-events.c
+++ b/tools/perf/tests/parse-events.c
@@ -521,7 +521,7 @@ static int test__group1(struct perf_evlist *evlist)
TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
- TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel));
+ TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));

/* cycles:upp */
evsel = perf_evsel__next(evsel);
@@ -557,7 +557,7 @@ static int test__group2(struct perf_evlist *evlist)
TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
- TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel));
+ TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));

/* cache-references + :u modifier */
evsel = perf_evsel__next(evsel);
@@ -583,7 +583,7 @@ static int test__group2(struct perf_evlist *evlist)
TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
- TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel));
+ TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));

return 0;
}
@@ -606,7 +606,7 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused)
TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
- TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel));
+ TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
TEST_ASSERT_VAL("wrong group name",
!strcmp(leader->group_name, "group1"));

@@ -636,7 +636,7 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused)
TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
- TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel));
+ TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
TEST_ASSERT_VAL("wrong group name",
!strcmp(leader->group_name, "group2"));

@@ -663,7 +663,7 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused)
TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
- TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel));
+ TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));

return 0;
}
@@ -687,7 +687,7 @@ static int test__group4(struct perf_evlist *evlist __maybe_unused)
TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 1);
TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
- TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel));
+ TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));

/* instructions:kp + p */
evsel = perf_evsel__next(evsel);
@@ -724,7 +724,7 @@ static int test__group5(struct perf_evlist *evlist __maybe_unused)
TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
- TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel));
+ TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));

/* instructions + G */
evsel = perf_evsel__next(evsel);
@@ -751,7 +751,7 @@ static int test__group5(struct perf_evlist *evlist __maybe_unused)
TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
- TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel));
+ TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));

/* instructions:G */
evsel = perf_evsel__next(evsel);
@@ -777,7 +777,7 @@ static int test__group5(struct perf_evlist *evlist __maybe_unused)
TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
- TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel));
+ TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));

return 0;
}
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 90db2a1..d0e1e82 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -221,7 +221,7 @@ void perf_evlist__disable(struct perf_evlist *evlist)

for (cpu = 0; cpu < evlist->cpus->nr; cpu++) {
list_for_each_entry(pos, &evlist->entries, node) {
- if (perf_evsel__is_group_member(pos))
+ if (!perf_evsel__is_group_leader(pos))
continue;
for (thread = 0; thread < evlist->threads->nr; thread++)
ioctl(FD(pos, cpu, thread),
@@ -237,7 +237,7 @@ void perf_evlist__enable(struct perf_evlist *evlist)

for (cpu = 0; cpu < cpu_map__nr(evlist->cpus); cpu++) {
list_for_each_entry(pos, &evlist->entries, node) {
- if (perf_evsel__is_group_member(pos))
+ if (!perf_evsel__is_group_leader(pos))
continue;
for (thread = 0; thread < evlist->threads->nr; thread++)
ioctl(FD(pos, cpu, thread),
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 7e93418..bb58b05 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -520,14 +520,14 @@ void perf_evsel__config(struct perf_evsel *evsel,
* Disabling only independent events or group leaders,
* keeping group members enabled.
*/
- if (!perf_evsel__is_group_member(evsel))
+ if (perf_evsel__is_group_leader(evsel))
attr->disabled = 1;

/*
* Setting enable_on_exec for independent events and
* group leaders for traced executed by perf.
*/
- if (perf_target__none(&opts->target) && !perf_evsel__is_group_member(evsel))
+ if (perf_target__none(&opts->target) && perf_evsel__is_group_leader(evsel))
attr->enable_on_exec = 1;
}

@@ -708,7 +708,7 @@ static int get_group_fd(struct perf_evsel *evsel, int cpu, int thread)
struct perf_evsel *leader = evsel->leader;
int fd;

- if (!perf_evsel__is_group_member(evsel))
+ if (perf_evsel__is_group_leader(evsel))
return -1;

/*
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index cbf6d97..3f7ff47 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -226,8 +226,8 @@ static inline struct perf_evsel *perf_evsel__next(struct perf_evsel *evsel)
return list_entry(evsel->node.next, struct perf_evsel, node);
}

-static inline bool perf_evsel__is_group_member(const struct perf_evsel *evsel)
+static inline bool perf_evsel__is_group_leader(const struct perf_evsel *evsel)
{
- return evsel->leader != evsel;
+ return evsel->leader == evsel;
}
#endif /* __PERF_EVSEL_H */
--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Dec 11, 2012, 6:00:01 PM12/11/12
to
From: Jiri Olsa <jo...@redhat.com>

Adding perf_hpp__list list to register and contain all period related
columns the command is interested in.

This way we get rid of static array holding all possible columns and
enable commands to register their own columns.

It'll be handy for diff command in future to process and display data
for multiple files.

Signed-off-by: Jiri Olsa <jo...@redhat.com>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Cc: Ingo Molnar <mi...@elte.hu>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Corey Ashford <cjas...@linux.vnet.ibm.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Namhyung Kim <namh...@kernel.org>
Link: http://lkml.kernel.org/n/tip-kiykge4igr...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-diff.c | 21 ++++-----
tools/perf/builtin-report.c | 1 +
tools/perf/ui/browsers/hists.c | 20 +++++----
tools/perf/ui/gtk/browser.c | 30 +++++--------
tools/perf/ui/hist.c | 96 ++++++++++++++++++++++------------------
tools/perf/ui/setup.c | 1 +
tools/perf/ui/stdio/hist.c | 17 +++----
tools/perf/util/hist.h | 11 ++++-
8 files changed, 101 insertions(+), 96 deletions(-)

diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 93b852f..9fbbc01 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -597,40 +597,35 @@ static const struct option options[] = {

static void ui_init(void)
{
- perf_hpp__init();
-
- /* No overhead column. */
- perf_hpp__column_enable(PERF_HPP__OVERHEAD, false);
-
/*
* Display baseline/delta/ratio/displacement/
* formula/periods columns.
*/
- perf_hpp__column_enable(PERF_HPP__BASELINE, true);
+ perf_hpp__column_enable(PERF_HPP__BASELINE);

switch (compute) {
case COMPUTE_DELTA:
- perf_hpp__column_enable(PERF_HPP__DELTA, true);
+ perf_hpp__column_enable(PERF_HPP__DELTA);
break;
case COMPUTE_RATIO:
- perf_hpp__column_enable(PERF_HPP__RATIO, true);
+ perf_hpp__column_enable(PERF_HPP__RATIO);
break;
case COMPUTE_WEIGHTED_DIFF:
- perf_hpp__column_enable(PERF_HPP__WEIGHTED_DIFF, true);
+ perf_hpp__column_enable(PERF_HPP__WEIGHTED_DIFF);
break;
default:
BUG_ON(1);
};

if (show_displacement)
- perf_hpp__column_enable(PERF_HPP__DISPL, true);
+ perf_hpp__column_enable(PERF_HPP__DISPL);

if (show_formula)
- perf_hpp__column_enable(PERF_HPP__FORMULA, true);
+ perf_hpp__column_enable(PERF_HPP__FORMULA);

if (show_period) {
- perf_hpp__column_enable(PERF_HPP__PERIOD, true);
- perf_hpp__column_enable(PERF_HPP__PERIOD_BASELINE, true);
+ perf_hpp__column_enable(PERF_HPP__PERIOD);
+ perf_hpp__column_enable(PERF_HPP__PERIOD_BASELINE);
}
}

diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index fc25100..5134acf 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -692,6 +692,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
setup_browser(true);
else {
use_browser = 0;
+ perf_hpp__column_enable(PERF_HPP__OVERHEAD);
perf_hpp__init();
}

diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index ccc4bd1..57b82c2 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -587,6 +587,8 @@ HPP__COLOR_FN(overhead_guest_us, period_guest_us)

void hist_browser__init_hpp(void)
{
+ perf_hpp__column_enable(PERF_HPP__OVERHEAD);
+
perf_hpp__init();

perf_hpp__format[PERF_HPP__OVERHEAD].color =
@@ -607,12 +609,13 @@ static int hist_browser__show_entry(struct hist_browser *browser,
{
char s[256];
double percent;
- int i, printed = 0;
+ int printed = 0;
int width = browser->b.width;
char folded_sign = ' ';
bool current_entry = ui_browser__is_current_entry(&browser->b, row);
off_t row_offset = entry->row_offset;
bool first = true;
+ struct perf_hpp_fmt *fmt;

if (current_entry) {
browser->he_selection = entry;
@@ -629,12 +632,11 @@ static int hist_browser__show_entry(struct hist_browser *browser,
.buf = s,
.size = sizeof(s),
};
+ int i = 0;

ui_browser__gotorc(&browser->b, row, 0);

- for (i = 0; i < PERF_HPP__MAX_INDEX; i++) {
- if (!perf_hpp__format[i].cond)
- continue;
+ perf_hpp__for_each_format(fmt) {

if (!first) {
slsmg_printf(" ");
@@ -642,14 +644,14 @@ static int hist_browser__show_entry(struct hist_browser *browser,
}
first = false;

- if (perf_hpp__format[i].color) {
+ if (fmt->color) {
hpp.ptr = &percent;
/* It will set percent for us. See HPP__COLOR_FN above. */
- width -= perf_hpp__format[i].color(&hpp, entry);
+ width -= fmt->color(&hpp, entry);

ui_browser__set_percent_color(&browser->b, percent, current_entry);

- if (i == PERF_HPP__OVERHEAD && symbol_conf.use_callchain) {
+ if (!i && symbol_conf.use_callchain) {
slsmg_printf("%c ", folded_sign);
width -= 2;
}
@@ -659,9 +661,11 @@ static int hist_browser__show_entry(struct hist_browser *browser,
if (!current_entry || !browser->b.navkeypressed)
ui_browser__set_color(&browser->b, HE_COLORSET_NORMAL);
} else {
- width -= perf_hpp__format[i].entry(&hpp, entry);
+ width -= fmt->entry(&hpp, entry);
slsmg_printf("%s", s);
}
+
+ i++;
}

/* The scroll bar isn't being used */
diff --git a/tools/perf/ui/gtk/browser.c b/tools/perf/ui/gtk/browser.c
index 253b621..e59ba33 100644
--- a/tools/perf/ui/gtk/browser.c
+++ b/tools/perf/ui/gtk/browser.c
@@ -74,6 +74,8 @@ HPP__COLOR_FN(overhead_guest_us, period_guest_us)

void perf_gtk__init_hpp(void)
{
+ perf_hpp__column_enable(PERF_HPP__OVERHEAD);
+
perf_hpp__init();

perf_hpp__format[PERF_HPP__OVERHEAD].color =
@@ -90,13 +92,14 @@ void perf_gtk__init_hpp(void)

static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
{
+ struct perf_hpp_fmt *fmt;
GType col_types[MAX_COLUMNS];
GtkCellRenderer *renderer;
struct sort_entry *se;
GtkListStore *store;
struct rb_node *nd;
GtkWidget *view;
- int i, col_idx;
+ int col_idx;
int nr_cols;
char s[512];

@@ -107,12 +110,8 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)

nr_cols = 0;

- for (i = 0; i < PERF_HPP__MAX_INDEX; i++) {
- if (!perf_hpp__format[i].cond)
- continue;
-
+ perf_hpp__for_each_format(fmt)
col_types[nr_cols++] = G_TYPE_STRING;
- }

list_for_each_entry(se, &hist_entry__sort_list, list) {
if (se->elide)
@@ -129,12 +128,8 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)

col_idx = 0;

- for (i = 0; i < PERF_HPP__MAX_INDEX; i++) {
- if (!perf_hpp__format[i].cond)
- continue;
-
- perf_hpp__format[i].header(&hpp);
-
+ perf_hpp__for_each_format(fmt) {
+ fmt->header(&hpp);
gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
-1, s,
renderer, "markup",
@@ -166,14 +161,11 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)

col_idx = 0;

- for (i = 0; i < PERF_HPP__MAX_INDEX; i++) {
- if (!perf_hpp__format[i].cond)
- continue;
-
- if (perf_hpp__format[i].color)
- perf_hpp__format[i].color(&hpp, h);
+ perf_hpp__for_each_format(fmt) {
+ if (fmt->color)
+ fmt->color(&hpp, h);
else
- perf_hpp__format[i].entry(&hpp, h);
+ fmt->entry(&hpp, h);

gtk_list_store_set(store, &iter, col_idx++, s, -1);
}
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index aa84130..0a5281f 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -386,60 +386,71 @@ static int hpp__entry_formula(struct perf_hpp *hpp, struct hist_entry *he)
return scnprintf(hpp->buf, hpp->size, fmt, buf);
}

-#define HPP__COLOR_PRINT_FNS(_name) \
- .header = hpp__header_ ## _name, \
- .width = hpp__width_ ## _name, \
- .color = hpp__color_ ## _name, \
- .entry = hpp__entry_ ## _name
+#define HPP__COLOR_PRINT_FNS(_name) \
+ { \
+ .header = hpp__header_ ## _name, \
+ .width = hpp__width_ ## _name, \
+ .color = hpp__color_ ## _name, \
+ .entry = hpp__entry_ ## _name \
+ }

-#define HPP__PRINT_FNS(_name) \
- .header = hpp__header_ ## _name, \
- .width = hpp__width_ ## _name, \
- .entry = hpp__entry_ ## _name
+#define HPP__PRINT_FNS(_name) \
+ { \
+ .header = hpp__header_ ## _name, \
+ .width = hpp__width_ ## _name, \
+ .entry = hpp__entry_ ## _name \
+ }

struct perf_hpp_fmt perf_hpp__format[] = {
- { .cond = false, HPP__COLOR_PRINT_FNS(baseline) },
- { .cond = true, HPP__COLOR_PRINT_FNS(overhead) },
- { .cond = false, HPP__COLOR_PRINT_FNS(overhead_sys) },
- { .cond = false, HPP__COLOR_PRINT_FNS(overhead_us) },
- { .cond = false, HPP__COLOR_PRINT_FNS(overhead_guest_sys) },
- { .cond = false, HPP__COLOR_PRINT_FNS(overhead_guest_us) },
- { .cond = false, HPP__PRINT_FNS(samples) },
- { .cond = false, HPP__PRINT_FNS(period) },
- { .cond = false, HPP__PRINT_FNS(period_baseline) },
- { .cond = false, HPP__PRINT_FNS(delta) },
- { .cond = false, HPP__PRINT_FNS(ratio) },
- { .cond = false, HPP__PRINT_FNS(wdiff) },
- { .cond = false, HPP__PRINT_FNS(displ) },
- { .cond = false, HPP__PRINT_FNS(formula) }
+ HPP__COLOR_PRINT_FNS(baseline),
+ HPP__COLOR_PRINT_FNS(overhead),
+ HPP__COLOR_PRINT_FNS(overhead_sys),
+ HPP__COLOR_PRINT_FNS(overhead_us),
+ HPP__COLOR_PRINT_FNS(overhead_guest_sys),
+ HPP__COLOR_PRINT_FNS(overhead_guest_us),
+ HPP__PRINT_FNS(samples),
+ HPP__PRINT_FNS(period),
+ HPP__PRINT_FNS(period_baseline),
+ HPP__PRINT_FNS(delta),
+ HPP__PRINT_FNS(ratio),
+ HPP__PRINT_FNS(wdiff),
+ HPP__PRINT_FNS(displ),
+ HPP__PRINT_FNS(formula)
};

+LIST_HEAD(perf_hpp__list);
+
#undef HPP__COLOR_PRINT_FNS
#undef HPP__PRINT_FNS

void perf_hpp__init(void)
{
if (symbol_conf.show_cpu_utilization) {
- perf_hpp__format[PERF_HPP__OVERHEAD_SYS].cond = true;
- perf_hpp__format[PERF_HPP__OVERHEAD_US].cond = true;
+ perf_hpp__column_enable(PERF_HPP__OVERHEAD_SYS);
+ perf_hpp__column_enable(PERF_HPP__OVERHEAD_US);

if (perf_guest) {
- perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_SYS].cond = true;
- perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_US].cond = true;
+ perf_hpp__column_enable(PERF_HPP__OVERHEAD_GUEST_SYS);
+ perf_hpp__column_enable(PERF_HPP__OVERHEAD_GUEST_US);
}
}

if (symbol_conf.show_nr_samples)
- perf_hpp__format[PERF_HPP__SAMPLES].cond = true;
+ perf_hpp__column_enable(PERF_HPP__SAMPLES);

if (symbol_conf.show_total_period)
- perf_hpp__format[PERF_HPP__PERIOD].cond = true;
+ perf_hpp__column_enable(PERF_HPP__PERIOD);
}

-void perf_hpp__column_enable(unsigned col, bool enable)
+void perf_hpp__column_register(struct perf_hpp_fmt *format)
+{
+ list_add_tail(&format->list, &perf_hpp__list);
+}
+
+void perf_hpp__column_enable(unsigned col)
{
BUG_ON(col >= PERF_HPP__MAX_INDEX);
- perf_hpp__format[col].cond = enable;
+ perf_hpp__column_register(&perf_hpp__format[col]);
}

static inline void advance_hpp(struct perf_hpp *hpp, int inc)
@@ -452,27 +463,25 @@ int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he,
bool color)
{
const char *sep = symbol_conf.field_sep;
+ struct perf_hpp_fmt *fmt;
char *start = hpp->buf;
- int i, ret;
+ int ret;
bool first = true;

if (symbol_conf.exclude_other && !he->parent)
return 0;

- for (i = 0; i < PERF_HPP__MAX_INDEX; i++) {
- if (!perf_hpp__format[i].cond)
- continue;
-
+ perf_hpp__for_each_format(fmt) {
if (!sep || !first) {
ret = scnprintf(hpp->buf, hpp->size, "%s", sep ?: " ");
advance_hpp(hpp, ret);
first = false;
}

- if (color && perf_hpp__format[i].color)
- ret = perf_hpp__format[i].color(hpp, he);
+ if (color && fmt->color)
+ ret = fmt->color(hpp, he);
else
- ret = perf_hpp__format[i].entry(hpp, he);
+ ret = fmt->entry(hpp, he);

advance_hpp(hpp, ret);
}
@@ -504,16 +513,15 @@ int hist_entry__sort_snprintf(struct hist_entry *he, char *s, size_t size,
*/
unsigned int hists__sort_list_width(struct hists *hists)
{
+ struct perf_hpp_fmt *fmt;
struct sort_entry *se;
- int i, ret = 0;
+ int i = 0, ret = 0;

- for (i = 0; i < PERF_HPP__MAX_INDEX; i++) {
- if (!perf_hpp__format[i].cond)
- continue;
+ perf_hpp__for_each_format(fmt) {
if (i)
ret += 2;

- ret += perf_hpp__format[i].width(NULL);
+ ret += fmt->width(NULL);
}

list_for_each_entry(se, &hist_entry__sort_list, list)
diff --git a/tools/perf/ui/setup.c b/tools/perf/ui/setup.c
index ebb4cc1..166f13d 100644
--- a/tools/perf/ui/setup.c
+++ b/tools/perf/ui/setup.c
@@ -30,6 +30,7 @@ void setup_browser(bool fallback_to_pager)
if (fallback_to_pager)
setup_pager();

+ perf_hpp__column_enable(PERF_HPP__OVERHEAD);
perf_hpp__init();
break;
}
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index f0ee204..0eae3b2 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -335,13 +335,14 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size,
size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
int max_cols, FILE *fp)
{
+ struct perf_hpp_fmt *fmt;
struct sort_entry *se;
struct rb_node *nd;
size_t ret = 0;
unsigned int width;
const char *sep = symbol_conf.field_sep;
const char *col_width = symbol_conf.col_width_list_str;
- int idx, nr_rows = 0;
+ int nr_rows = 0;
char bf[96];
struct perf_hpp dummy_hpp = {
.buf = bf,
@@ -355,16 +356,14 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
goto print_entries;

fprintf(fp, "# ");
- for (idx = 0; idx < PERF_HPP__MAX_INDEX; idx++) {
- if (!perf_hpp__format[idx].cond)
- continue;

+ perf_hpp__for_each_format(fmt) {
if (!first)
fprintf(fp, "%s", sep ?: " ");
else
first = false;

- perf_hpp__format[idx].header(&dummy_hpp);
+ fmt->header(&dummy_hpp);
fprintf(fp, "%s", bf);
}

@@ -400,18 +399,16 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
first = true;

fprintf(fp, "# ");
- for (idx = 0; idx < PERF_HPP__MAX_INDEX; idx++) {
- unsigned int i;

- if (!perf_hpp__format[idx].cond)
- continue;
+ perf_hpp__for_each_format(fmt) {
+ unsigned int i;

if (!first)
fprintf(fp, "%s", sep ?: " ");
else
first = false;

- width = perf_hpp__format[idx].width(&dummy_hpp);
+ width = fmt->width(&dummy_hpp);
for (i = 0; i < width; i++)
fprintf(fp, ".");
}
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 8b091a5..a935a60 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -126,13 +126,19 @@ struct perf_hpp {
};

struct perf_hpp_fmt {
- bool cond;
int (*header)(struct perf_hpp *hpp);
int (*width)(struct perf_hpp *hpp);
int (*color)(struct perf_hpp *hpp, struct hist_entry *he);
int (*entry)(struct perf_hpp *hpp, struct hist_entry *he);
+
+ struct list_head list;
};

+extern struct list_head perf_hpp__list;
+
+#define perf_hpp__for_each_format(format) \
+ list_for_each_entry(format, &perf_hpp__list, list)
+
extern struct perf_hpp_fmt perf_hpp__format[];

enum {
@@ -155,7 +161,8 @@ enum {
};

void perf_hpp__init(void);
-void perf_hpp__column_enable(unsigned col, bool enable);
+void perf_hpp__column_register(struct perf_hpp_fmt *format);
+void perf_hpp__column_enable(unsigned col);
int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he,
bool color);

--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Dec 11, 2012, 6:00:02 PM12/11/12
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

We had that 'with_hits' filter to show just the build ids for DSOs that
had samples, make that generic so that we can use it in the upcoming
buildid-cache --missing feature, to show just the build ids that are not
in the cache.

Cc: David Ahern <dsa...@gmail.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Jiri Olsa <jo...@redhat.com>
Cc: Mike Galbraith <efa...@gmx.de>
Cc: Namhyung Kim <namh...@gmail.com>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Stephane Eranian <era...@google.com>
Link: http://lkml.kernel.org/n/tip-9nfesdfpnx...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-buildid-list.c | 7 ++++++-
tools/perf/util/dso.c | 4 ++--
tools/perf/util/dso.h | 2 +-
tools/perf/util/machine.h | 8 ++++----
tools/perf/util/session.c | 6 +++---
tools/perf/util/session.h | 4 ++--
tools/perf/util/symbol.c | 12 ++++++------
7 files changed, 24 insertions(+), 19 deletions(-)

diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index 4c770d2..e74366a 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -44,6 +44,11 @@ static int filename__fprintf_build_id(const char *name, FILE *fp)
return fprintf(fp, "%s\n", sbuild_id);
}

+static bool dso__skip_buildid(struct dso *dso, int with_hits)
+{
+ return with_hits && !dso->hit;
+}
+
static int perf_session__list_build_ids(bool force, bool with_hits)
{
struct perf_session *session;
@@ -66,7 +71,7 @@ static int perf_session__list_build_ids(bool force, bool with_hits)
if (with_hits || session->fd_pipe)
perf_session__process_events(session, &build_id__mark_dso_hit_ops);

- perf_session__fprintf_dsos_buildid(session, stdout, with_hits);
+ perf_session__fprintf_dsos_buildid(session, stdout, dso__skip_buildid, with_hits);
perf_session__delete(session);
out:
return 0;
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index be43785..6f7d5a9 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -539,13 +539,13 @@ struct dso *__dsos__findnew(struct list_head *head, const char *name)
}

size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
- bool with_hits)
+ bool (skip)(struct dso *dso, int parm), int parm)
{
struct dso *pos;
size_t ret = 0;

list_for_each_entry(pos, head, node) {
- if (with_hits && !pos->hit)
+ if (skip && skip(pos, parm))
continue;
ret += dso__fprintf_buildid(pos, fp);
ret += fprintf(fp, " %s\n", pos->long_name);
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index e032769..450199a 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -138,7 +138,7 @@ struct dso *__dsos__findnew(struct list_head *head, const char *name);
bool __dsos__read_build_ids(struct list_head *head, bool with_hits);

size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
- bool with_hits);
+ bool (skip)(struct dso *dso, int parm), int parm);
size_t __dsos__fprintf(struct list_head *head, FILE *fp);

size_t dso__fprintf_buildid(struct dso *dso, FILE *fp);
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index b7cde74..646ad13 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -129,11 +129,11 @@ int machine__load_kallsyms(struct machine *machine, const char *filename,
int machine__load_vmlinux_path(struct machine *machine, enum map_type type,
symbol_filter_t filter);

-size_t machine__fprintf_dsos_buildid(struct machine *machine,
- FILE *fp, bool with_hits);
+size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp,
+ bool (skip)(struct dso *dso, int parm), int parm);
size_t machines__fprintf_dsos(struct rb_root *machines, FILE *fp);
-size_t machines__fprintf_dsos_buildid(struct rb_root *machines,
- FILE *fp, bool with_hits);
+size_t machines__fprintf_dsos_buildid(struct rb_root *machines, FILE *fp,
+ bool (skip)(struct dso *dso, int parm), int parm);

void machine__destroy_kernel_maps(struct machine *machine);
int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index aa5e582..8d04dfb 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1552,10 +1552,10 @@ size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp)
}

size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, FILE *fp,
- bool with_hits)
+ bool (skip)(struct dso *dso, int parm), int parm)
{
- size_t ret = machine__fprintf_dsos_buildid(&self->host_machine, fp, with_hits);
- return ret + machines__fprintf_dsos_buildid(&self->machines, fp, with_hits);
+ size_t ret = machine__fprintf_dsos_buildid(&self->host_machine, fp, skip, parm);
+ return ret + machines__fprintf_dsos_buildid(&self->machines, fp, skip, parm);
}

size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index c18fabd..8c23025 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -115,8 +115,8 @@ 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,
- FILE *fp, bool with_hits);
+size_t perf_session__fprintf_dsos_buildid(struct perf_session *session, FILE *fp,
+ bool (fn)(struct dso *dso, int parm), int parm);

size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp);

diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 295f8d4..e5ba984 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1315,21 +1315,21 @@ size_t machines__fprintf_dsos(struct rb_root *machines, FILE *fp)
}

size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp,
- bool with_hits)
+ bool (skip)(struct dso *dso, int parm), int parm)
{
- return __dsos__fprintf_buildid(&machine->kernel_dsos, fp, with_hits) +
- __dsos__fprintf_buildid(&machine->user_dsos, fp, with_hits);
+ return __dsos__fprintf_buildid(&machine->kernel_dsos, fp, skip, parm) +
+ __dsos__fprintf_buildid(&machine->user_dsos, fp, skip, parm);
}

-size_t machines__fprintf_dsos_buildid(struct rb_root *machines,
- FILE *fp, bool with_hits)
+size_t machines__fprintf_dsos_buildid(struct rb_root *machines, FILE *fp,
+ bool (skip)(struct dso *dso, int parm), int parm)
{
struct rb_node *nd;
size_t ret = 0;

for (nd = rb_first(machines); nd; nd = rb_next(nd)) {
struct machine *pos = rb_entry(nd, struct machine, rb_node);
- ret += machine__fprintf_dsos_buildid(pos, fp, with_hits);
+ ret += machine__fprintf_dsos_buildid(pos, fp, skip, parm);
}
return ret;
}
--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Dec 11, 2012, 6:00:02 PM12/11/12
to
From: David Miller <da...@davemloft.net>

This is a suggested patch to fix the bug I reported at:

http://marc.info/?l=linux-kernel&m=135033028924652&w=2

Essentially, there is a hard requirement that when perf analyzes a
trace, it must have the entire thing mmap()'d.

Therefore the scheme used on 32-bit where we have a fixed (8) number of
32MB mmaps, and cycle through them, simply does not work.

One of the reasons this requirement exists is because the iterators
maintain references to perf entry objects and those references don't
just simply go away when this mmap code decides to cycle an old mmap
area out and reuse it. At this point, those entry pointers now point to
garbage resulting in unpredictable behavior and crashes.

It is better to try to mmap() as much as we can and if we do actually
run into address space limitations, the failure of the mmap() call will
indicate that and stop processing.

I noticed that perf_session->mmap_window is set to a constant in one
location, and only used in one other location. So I got rid of it
altogether.

So we adjust the size of the mmaps[] array to the maximum we could need.
On 64-bit we only need one slot. On 32-bit we could need up to 128 (128
* 32MB == 4GB).

I've verified that this allows a large (~600MB) perf.data file to be
analyzed properly with a 32-bit perf binary, which previously was not
possible.

Signed-off-by: David S. Miller <da...@davemloft.net>
Cc: Ingo Molnar <mi...@redhat.com>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Link: http://lkml.kernel.org/r/20121110.141219.5829...@davemloft.net
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/session.c | 25 ++++++++++++++-----------
tools/perf/util/session.h | 1 -
2 files changed, 14 insertions(+), 12 deletions(-)

diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index d5fb607..aa5e582 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -128,15 +128,6 @@ struct perf_session *perf_session__new(const char *filename, int mode,
goto out;

memcpy(self->filename, filename, len);
- /*
- * On 64bit we can mmap the data file in one go. No need for tiny mmap
- * slices. On 32bit we use 32MB.
- */
-#if BITS_PER_LONG == 64
- self->mmap_window = ULLONG_MAX;
-#else
- self->mmap_window = 32 * 1024 * 1024ULL;
-#endif
self->machines = RB_ROOT;
self->repipe = repipe;
INIT_LIST_HEAD(&self->ordered_samples.samples);
@@ -1386,6 +1377,18 @@ fetch_mmaped_event(struct perf_session *session,
return event;
}

+/*
+ * On 64bit we can mmap the data file in one go. No need for tiny mmap
+ * slices. On 32bit we use 32MB.
+ */
+#if BITS_PER_LONG == 64
+#define MMAP_SIZE ULLONG_MAX
+#define NUM_MMAPS 1
+#else
+#define MMAP_SIZE (32 * 1024 * 1024ULL)
+#define NUM_MMAPS 128
+#endif
+
int __perf_session__process_events(struct perf_session *session,
u64 data_offset, u64 data_size,
u64 file_size, struct perf_tool *tool)
@@ -1393,7 +1396,7 @@ int __perf_session__process_events(struct perf_session *session,
u64 head, page_offset, file_offset, file_pos, progress_next;
int err, mmap_prot, mmap_flags, map_idx = 0;
size_t mmap_size;
- char *buf, *mmaps[8];
+ char *buf, *mmaps[NUM_MMAPS];
union perf_event *event;
uint32_t size;

@@ -1408,7 +1411,7 @@ int __perf_session__process_events(struct perf_session *session,

progress_next = file_size / 16;

- mmap_size = session->mmap_window;
+ mmap_size = MMAP_SIZE;
if (mmap_size > file_size)
mmap_size = file_size;

diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index cea133a..c18fabd 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -30,7 +30,6 @@ struct ordered_samples {
struct perf_session {
struct perf_header header;
unsigned long size;
- unsigned long mmap_window;
struct machine host_machine;
struct rb_root machines;
struct perf_evlist *evlist;
--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Dec 11, 2012, 6:00:02 PM12/11/12
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

Doing the same thing done in:

b059dee: perf tools: Don't check configuration on make clean

Cc: David Ahern <dsa...@gmail.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Jiri Olsa <jo...@redhat.com>
Cc: Mike Galbraith <efa...@gmx.de>
Cc: Namhyung Kim <namh...@gmail.com>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Stephane Eranian <era...@google.com>
Link: http://lkml.kernel.org/n/tip-n2ni4riphp...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/Documentation/Makefile | 2 ++
tools/perf/Makefile | 4 ++++
2 files changed, 6 insertions(+)

diff --git a/tools/perf/Documentation/Makefile b/tools/perf/Documentation/Makefile
index f6e5901..eb30044 100644
--- a/tools/perf/Documentation/Makefile
+++ b/tools/perf/Documentation/Makefile
@@ -223,11 +223,13 @@ install-pdf: pdf
# '$(SHELL_PATH_SQ)' ./install-webdoc.sh $(DESTDIR)$(htmldir)

ifneq ($(MAKECMDGOALS),clean)
+ifneq ($(MAKECMDGOALS),tags)
$(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE
$(QUIET_SUBDIR0)../ $(QUIET_SUBDIR1) $(OUTPUT)PERF-VERSION-FILE

-include $(OUTPUT)PERF-VERSION-FILE
endif
+endif

#
# Determine "include::" file references in asciidoc files.
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 08da9fc..2a07b95 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -154,6 +154,7 @@ INSTALL = install
SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__

ifneq ($(MAKECMDGOALS),clean)
+ifneq ($(MAKECMDGOALS),tags)
-include config/feature-tests.mak

ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -fstack-protector-all,-fstack-protector-all),y)
@@ -207,6 +208,7 @@ ifeq ($(call try-cc,$(SOURCE_BIONIC),$(CFLAGS),bionic),y)
EXTLIBS := $(filter-out -lpthread,$(EXTLIBS))
BASIC_CFLAGS += -I.
endif
+endif # MAKECMDGOALS != tags
endif # MAKECMDGOALS != clean

# Guard against environment variables
@@ -525,6 +527,7 @@ PERFLIBS = $(LIB_FILE) $(LIBTRACEEVENT)
# Platform specific tweaks
#
ifneq ($(MAKECMDGOALS),clean)
+ifneq ($(MAKECMDGOALS),tags)

# We choose to avoid "if .. else if .. else .. endif endif"
# because maintaining the nesting to match is a pain. If
@@ -841,6 +844,7 @@ ifdef ASCIIDOC8
export ASCIIDOC8
endif

+endif # MAKECMDGOALS != tags
endif # MAKECMDGOALS != clean

# Shell quote (do not use $(call) to accommodate ancient setups);
--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Dec 11, 2012, 6:00:02 PM12/11/12
to
From: Jiri Olsa <jo...@redhat.com>

It seems not very useful, because it's possible and event more convenient to
lookup related symbol by name. Also the output value for both 'baseline' and
'new' data is quite apparent from diff output.

And above all it complicates hist code factoring ;)

Ditching out PERF_HPP__DISPL column with related output functions.

Suggested-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
Signed-off-by: Jiri Olsa <jo...@redhat.com>
Cc: Corey Ashford <cjas...@linux.vnet.ibm.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Ingo Molnar <mi...@elte.hu>
Cc: Ingo Molnar <mi...@kernel.org>
Cc: Namhyung Kim <namhyu...@lge.com>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Cc: Stephane Eranian <era...@google.com>
Link: http://lkml.kernel.org/r/2012120613...@krava.brq.redhat.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/Documentation/perf-diff.txt | 4 ----
tools/perf/builtin-diff.c | 29 +++++++----------------------
tools/perf/ui/hist.c | 25 -------------------------
tools/perf/util/hist.h | 1 -
4 files changed, 7 insertions(+), 52 deletions(-)

diff --git a/tools/perf/Documentation/perf-diff.txt b/tools/perf/Documentation/perf-diff.txt
index 194f37d..5b3123d 100644
--- a/tools/perf/Documentation/perf-diff.txt
+++ b/tools/perf/Documentation/perf-diff.txt
@@ -22,10 +22,6 @@ specified perf.data files.

OPTIONS
-------
--M::
---displacement::
- Show position displacement relative to baseline.
-
-D::
--dump-raw-trace::
Dump raw trace in ASCII.
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index d869029..b2e7d39 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -23,7 +23,6 @@ static char const *input_old = "perf.data.old",
*input_new = "perf.data";
static char diff__default_sort_order[] = "dso,symbol";
static bool force;
-static bool show_displacement;
static bool show_period;
static bool show_formula;
static bool show_baseline_only;
@@ -296,9 +295,8 @@ static void insert_hist_entry_by_name(struct rb_root *root,
rb_insert_color(&he->rb_node, root);
}

-static void hists__name_resort(struct hists *self, bool sort)
+static void hists__name_resort(struct hists *self)
{
- unsigned long position = 1;
struct rb_root tmp = RB_ROOT;
struct rb_node *next = rb_first(&self->entries);

@@ -306,16 +304,12 @@ static void hists__name_resort(struct hists *self, bool sort)
struct hist_entry *n = rb_entry(next, struct hist_entry, rb_node);

next = rb_next(&n->rb_node);
- n->position = position++;

- if (sort) {
- rb_erase(&n->rb_node, &self->entries);
- insert_hist_entry_by_name(&tmp, n);
- }
+ rb_erase(&n->rb_node, &self->entries);
+ insert_hist_entry_by_name(&tmp, n);
}

- if (sort)
- self->entries = tmp;
+ self->entries = tmp;
}

static struct perf_evsel *evsel_match(struct perf_evsel *evsel,
@@ -339,12 +333,8 @@ static void perf_evlist__resort_hists(struct perf_evlist *evlist, bool name)

hists__output_resort(hists);

- /*
- * The hists__name_resort only sets possition
- * if name is false.
- */
- if (name || ((!name) && show_displacement))
- hists__name_resort(hists, name);
+ if (name)
+ hists__name_resort(hists);
}
}

@@ -549,8 +539,6 @@ static const char * const diff_usage[] = {
static const struct option options[] = {
OPT_INCR('v', "verbose", &verbose,
"be more verbose (show symbol address, etc)"),
- OPT_BOOLEAN('M', "displacement", &show_displacement,
- "Show position displacement relative to baseline"),
OPT_BOOLEAN('b', "baseline-only", &show_baseline_only,
"Show only items with match in baseline"),
OPT_CALLBACK('c', "compute", &compute,
@@ -585,7 +573,7 @@ static const struct option options[] = {
static void ui_init(void)
{
/*
- * Display baseline/delta/ratio/displacement/
+ * Display baseline/delta/ratio
* formula/periods columns.
*/
perf_hpp__column_enable(PERF_HPP__BASELINE);
@@ -604,9 +592,6 @@ static void ui_init(void)
BUG_ON(1);
};

- if (show_displacement)
- perf_hpp__column_enable(PERF_HPP__DISPL);
-
if (show_formula)
perf_hpp__column_enable(PERF_HPP__FORMULA);

diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 1785bab..1889c12 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -351,30 +351,6 @@ static int hpp__entry_wdiff(struct perf_hpp *hpp, struct hist_entry *he)
return scnprintf(hpp->buf, hpp->size, fmt, buf);
}

-static int hpp__header_displ(struct perf_hpp *hpp)
-{
- return scnprintf(hpp->buf, hpp->size, "Displ.");
-}
-
-static int hpp__width_displ(struct perf_hpp *hpp __maybe_unused)
-{
- return 6;
-}
-
-static int hpp__entry_displ(struct perf_hpp *hpp,
- struct hist_entry *he)
-{
- struct hist_entry *pair = hist_entry__next_pair(he);
- long displacement = pair ? pair->position - he->position : 0;
- const char *fmt = symbol_conf.field_sep ? "%s" : "%6.6s";
- char buf[32] = " ";
-
- if (displacement)
- scnprintf(buf, sizeof(buf), "%+4ld", displacement);
-
- return scnprintf(hpp->buf, hpp->size, fmt, buf);
-}
-
static int hpp__header_formula(struct perf_hpp *hpp)
{
const char *fmt = symbol_conf.field_sep ? "%s" : "%70s";
@@ -427,7 +403,6 @@ struct perf_hpp_fmt perf_hpp__format[] = {
HPP__PRINT_FNS(delta),
HPP__PRINT_FNS(ratio),
HPP__PRINT_FNS(wdiff),
- HPP__PRINT_FNS(displ),
HPP__PRINT_FNS(formula)
};

diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index c1b2fad..5b3b007 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -154,7 +154,6 @@ enum {
PERF_HPP__DELTA,
PERF_HPP__RATIO,
PERF_HPP__WEIGHTED_DIFF,
- PERF_HPP__DISPL,
PERF_HPP__FORMULA,

PERF_HPP__MAX_INDEX
--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Dec 11, 2012, 6:00:02 PM12/11/12
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

This will allow to connect with services being put in place by distros such as
Fedora, where one can retrieve DSOs by their build-id.

Example usage:

for buildid in $(perf buildid-cache --missing perf.data | cut -d' ' -f1) ; do
echo "trying to get $buildid"
wget -q https://darkserver.fedoraproject.org/buildids/$buildid
cat $buildid ; echo
rm -f $buildid
done

Now its just a matter of some porcelain to get the details provided by such a
service, retrieve the file and use 'perf buildid-cache --add $FILE' to insert
it in the cache, then use 'perf report' or 'annotate' that will find the
required files in the cache.

More information about the darkserver service at:

https://darkserver.fedoraproject.org/

Cc: David Ahern <dsa...@gmail.com>
Cc: Frank Eigler <fc...@redhat.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Jiri Olsa <jo...@redhat.com>
Cc: Kushal Das <kd...@redhat.com>
Cc: Mark Wielaard <m...@redhat.com>
Cc: Mike Galbraith <efa...@gmx.de>
Cc: Namhyung Kim <namh...@gmail.com>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Stephane Eranian <era...@google.com>
Link: http://lkml.kernel.org/n/tip-6fuktuiyjn...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/Documentation/perf-buildid-cache.txt | 3 ++
tools/perf/builtin-buildid-cache.c | 48 ++++++++++++++++++++++-
2 files changed, 49 insertions(+), 2 deletions(-)

diff --git a/tools/perf/Documentation/perf-buildid-cache.txt b/tools/perf/Documentation/perf-buildid-cache.txt
index c105770..8e798ba 100644
--- a/tools/perf/Documentation/perf-buildid-cache.txt
+++ b/tools/perf/Documentation/perf-buildid-cache.txt
@@ -24,6 +24,9 @@ OPTIONS
-r::
--remove=::
Remove specified file from the cache.
+-M::
+--missing=::
+ List missing build ids in the cache for the specified file.
-v::
--verbose::
Be more verbose.
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index fae8b25..a336014 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -14,6 +14,7 @@
#include "util/parse-options.h"
#include "util/strlist.h"
#include "util/build-id.h"
+#include "util/session.h"
#include "util/symbol.h"

static int build_id_cache__add_file(const char *filename, const char *debugdir)
@@ -58,19 +59,59 @@ static int build_id_cache__remove_file(const char *filename,
return err;
}

+static bool dso__missing_buildid_cache(struct dso *dso, int parm __maybe_unused)
+{
+ char filename[PATH_MAX];
+ u8 build_id[BUILD_ID_SIZE];
+
+ if (dso__build_id_filename(dso, filename, sizeof(filename)) &&
+ filename__read_build_id(filename, build_id,
+ sizeof(build_id)) != sizeof(build_id)) {
+ if (errno == ENOENT)
+ return false;
+
+ pr_warning("Problems with %s file, consider removing it from the cache\n",
+ filename);
+ } else if (memcmp(dso->build_id, build_id, sizeof(dso->build_id))) {
+ pr_warning("Problems with %s file, consider removing it from the cache\n",
+ filename);
+ }
+
+ return true;
+}
+
+static int build_id_cache__fprintf_missing(const char *filename, bool force, FILE *fp)
+{
+ struct perf_session *session = perf_session__new(filename, O_RDONLY,
+ force, false, NULL);
+ if (session == NULL)
+ return -1;
+
+ perf_session__fprintf_dsos_buildid(session, fp, dso__missing_buildid_cache, 0);
+ perf_session__delete(session);
+
+ return 0;
+}
+
int cmd_buildid_cache(int argc, const char **argv,
const char *prefix __maybe_unused)
{
struct strlist *list;
struct str_node *pos;
+ int ret = 0;
+ bool force = false;
char debugdir[PATH_MAX];
char const *add_name_list_str = NULL,
- *remove_name_list_str = NULL;
+ *remove_name_list_str = NULL,
+ *missing_filename = NULL;
const struct option buildid_cache_options[] = {
OPT_STRING('a', "add", &add_name_list_str,
"file list", "file(s) to add"),
OPT_STRING('r', "remove", &remove_name_list_str, "file list",
"file(s) to remove"),
+ OPT_STRING('M', "missing", &missing_filename, "file",
+ "to find missing build ids in the cache"),
+ OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
OPT_INCR('v', "verbose", &verbose, "be more verbose"),
OPT_END()
};
@@ -125,5 +166,8 @@ int cmd_buildid_cache(int argc, const char **argv,
}
}

- return 0;
+ if (missing_filename)
+ ret = build_id_cache__fprintf_missing(missing_filename, force, stdout);
+
+ return ret;
}
--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Dec 11, 2012, 6:00:02 PM12/11/12
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

Mechanical, no functional changes.

Cc: David Ahern <dsa...@gmail.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Jiri Olsa <jo...@redhat.com>
Cc: Mike Galbraith <efa...@gmx.de>
Cc: Namhyung Kim <namh...@gmail.com>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Stephane Eranian <era...@google.com>
Link: http://lkml.kernel.org/n/tip-9ib6qtqge1...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/machine.c | 742 +++++++++++++++++++++++++++++++++++++++++++++
tools/perf/util/machine.h | 3 +-
tools/perf/util/session.c | 210 -------------
tools/perf/util/symbol.c | 522 +------------------------------
tools/perf/util/symbol.h | 4 +
tools/perf/util/thread.c | 20 +-
tools/perf/util/thread.h | 1 +
7 files changed, 756 insertions(+), 746 deletions(-)

diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 1f09d05..71fa903 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -1,10 +1,15 @@
+#include "callchain.h"
#include "debug.h"
#include "event.h"
+#include "evsel.h"
+#include "hist.h"
#include "machine.h"
#include "map.h"
+#include "sort.h"
#include "strlist.h"
#include "thread.h"
#include <stdbool.h>
+#include "unwind.h"

int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
{
@@ -48,6 +53,29 @@ static void dsos__delete(struct list_head *dsos)
}
}

+void machine__delete_dead_threads(struct machine *machine)
+{
+ struct thread *n, *t;
+
+ list_for_each_entry_safe(t, n, &machine->dead_threads, node) {
+ list_del(&t->node);
+ thread__delete(t);
+ }
+}
+
+void machine__delete_threads(struct machine *machine)
+{
+ struct rb_node *nd = rb_first(&machine->threads);
+
+ while (nd) {
+ struct thread *t = rb_entry(nd, struct thread, rb_node);
+
+ rb_erase(&t->rb_node, &machine->threads);
+ nd = rb_next(nd);
+ thread__delete(t);
+ }
+}
+
void machine__exit(struct machine *machine)
{
map_groups__exit(&machine->kmaps);
@@ -264,6 +292,534 @@ int machine__process_lost_event(struct machine *machine __maybe_unused,
return 0;
}

+struct map *machine__new_module(struct machine *machine, u64 start,
+ const char *filename)
+{
+ struct map *map;
+ struct dso *dso = __dsos__findnew(&machine->kernel_dsos, filename);
+
+ if (dso == NULL)
+ return NULL;
+
+ map = map__new2(start, dso, MAP__FUNCTION);
+ if (map == NULL)
+ return NULL;
+
+ if (machine__is_host(machine))
+ dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE;
+ else
+ dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE;
+ map_groups__insert(&machine->kmaps, map);
+ return map;
+}
+
+size_t machines__fprintf_dsos(struct rb_root *machines, FILE *fp)
+{
+ struct rb_node *nd;
+ size_t ret = 0;
+
+ for (nd = rb_first(machines); nd; nd = rb_next(nd)) {
+ struct machine *pos = rb_entry(nd, struct machine, rb_node);
+ ret += __dsos__fprintf(&pos->kernel_dsos, fp);
+ ret += __dsos__fprintf(&pos->user_dsos, fp);
+ }
+
+ return ret;
+}
+
+size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp,
+ bool (skip)(struct dso *dso, int parm), int parm)
+{
+ return __dsos__fprintf_buildid(&machine->kernel_dsos, fp, skip, parm) +
+ __dsos__fprintf_buildid(&machine->user_dsos, fp, skip, parm);
+}
+
+size_t machines__fprintf_dsos_buildid(struct rb_root *machines, FILE *fp,
+ bool (skip)(struct dso *dso, int parm), int parm)
+{
+ struct rb_node *nd;
+ size_t ret = 0;
+
+ for (nd = rb_first(machines); nd; nd = rb_next(nd)) {
+ struct machine *pos = rb_entry(nd, struct machine, rb_node);
+ ret += machine__fprintf_dsos_buildid(pos, fp, skip, parm);
+ }
+ return ret;
+}
+
+size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp)
+{
+ int i;
+ size_t printed = 0;
+ struct dso *kdso = machine->vmlinux_maps[MAP__FUNCTION]->dso;
+
+ if (kdso->has_build_id) {
+ char filename[PATH_MAX];
+ if (dso__build_id_filename(kdso, filename, sizeof(filename)))
+ printed += fprintf(fp, "[0] %s\n", filename);
+ }
+
+ for (i = 0; i < vmlinux_path__nr_entries; ++i)
+ printed += fprintf(fp, "[%d] %s\n",
+ i + kdso->has_build_id, vmlinux_path[i]);
+
+ return printed;
+}
+
+size_t machine__fprintf(struct machine *machine, FILE *fp)
+{
+ size_t ret = 0;
+ struct rb_node *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);
+ }
+
+ return ret;
+}
+
+static struct dso *machine__get_kernel(struct machine *machine)
+{
+ const char *vmlinux_name = NULL;
+ struct dso *kernel;
+
+ if (machine__is_host(machine)) {
+ vmlinux_name = symbol_conf.vmlinux_name;
+ if (!vmlinux_name)
+ vmlinux_name = "[kernel.kallsyms]";
+
+ kernel = dso__kernel_findnew(machine, vmlinux_name,
+ "[kernel]",
+ DSO_TYPE_KERNEL);
+ } else {
+ char bf[PATH_MAX];
+
+ if (machine__is_default_guest(machine))
+ vmlinux_name = symbol_conf.default_guest_vmlinux_name;
+ if (!vmlinux_name)
+ vmlinux_name = machine__mmap_name(machine, bf,
+ sizeof(bf));
+
+ kernel = dso__kernel_findnew(machine, vmlinux_name,
+ "[guest.kernel]",
+ DSO_TYPE_GUEST_KERNEL);
+ }
+
+ if (kernel != NULL && (!kernel->has_build_id))
+ dso__read_running_kernel_build_id(kernel, machine);
+
+ return kernel;
+}
+
+struct process_args {
+ u64 start;
+};
+
+static int symbol__in_kernel(void *arg, const char *name,
+ char type __maybe_unused, u64 start)
+{
+ struct process_args *args = arg;
+
+ if (strchr(name, '['))
+ return 0;
+
+ args->start = start;
+ return 1;
+}
+
+/* Figure out the start address of kernel map from /proc/kallsyms */
+static u64 machine__get_kernel_start_addr(struct machine *machine)
+{
+ const char *filename;
+ char path[PATH_MAX];
+ struct process_args args;
+
+ if (machine__is_host(machine)) {
+ filename = "/proc/kallsyms";
+ } else {
+ if (machine__is_default_guest(machine))
+ filename = (char *)symbol_conf.default_guest_kallsyms;
+ else {
+ sprintf(path, "%s/proc/kallsyms", machine->root_dir);
+ filename = path;
+ }
+ }
+
+ if (symbol__restricted_filename(filename, "/proc/kallsyms"))
+ return 0;
+
+ if (kallsyms__parse(filename, &args, symbol__in_kernel) <= 0)
+ return 0;
+
+ return args.start;
+}
+
+int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel)
+{
+ enum map_type type;
+ u64 start = machine__get_kernel_start_addr(machine);
+
+ for (type = 0; type < MAP__NR_TYPES; ++type) {
+ struct kmap *kmap;
+
+ machine->vmlinux_maps[type] = map__new2(start, kernel, type);
+ if (machine->vmlinux_maps[type] == NULL)
+ return -1;
+
+ machine->vmlinux_maps[type]->map_ip =
+ machine->vmlinux_maps[type]->unmap_ip =
+ identity__map_ip;
+ kmap = map__kmap(machine->vmlinux_maps[type]);
+ kmap->kmaps = &machine->kmaps;
+ map_groups__insert(&machine->kmaps,
+ machine->vmlinux_maps[type]);
+ }
+
+ return 0;
+}
+
+void machine__destroy_kernel_maps(struct machine *machine)
+{
+ enum map_type type;
+
+ for (type = 0; type < MAP__NR_TYPES; ++type) {
+ struct kmap *kmap;
+
+ if (machine->vmlinux_maps[type] == NULL)
+ continue;
+
+ kmap = map__kmap(machine->vmlinux_maps[type]);
+ map_groups__remove(&machine->kmaps,
+ machine->vmlinux_maps[type]);
+ if (kmap->ref_reloc_sym) {
+ /*
+ * ref_reloc_sym is shared among all maps, so free just
+ * on one of them.
+ */
+ if (type == MAP__FUNCTION) {
+ free((char *)kmap->ref_reloc_sym->name);
+ kmap->ref_reloc_sym->name = NULL;
+ free(kmap->ref_reloc_sym);
+ }
+ kmap->ref_reloc_sym = NULL;
+ }
+
+ map__delete(machine->vmlinux_maps[type]);
+ machine->vmlinux_maps[type] = NULL;
+ }
+}
+
+int machines__create_guest_kernel_maps(struct rb_root *machines)
+{
+ int ret = 0;
+ struct dirent **namelist = NULL;
+ int i, items = 0;
+ char path[PATH_MAX];
+ pid_t pid;
+ char *endp;
+
+ if (symbol_conf.default_guest_vmlinux_name ||
+ symbol_conf.default_guest_modules ||
+ symbol_conf.default_guest_kallsyms) {
+ machines__create_kernel_maps(machines, DEFAULT_GUEST_KERNEL_ID);
+ }
+
+ if (symbol_conf.guestmount) {
+ items = scandir(symbol_conf.guestmount, &namelist, NULL, NULL);
+ if (items <= 0)
+ return -ENOENT;
+ for (i = 0; i < items; i++) {
+ if (!isdigit(namelist[i]->d_name[0])) {
+ /* Filter out . and .. */
+ continue;
+ }
+ pid = (pid_t)strtol(namelist[i]->d_name, &endp, 10);
+ if ((*endp != '\0') ||
+ (endp == namelist[i]->d_name) ||
+ (errno == ERANGE)) {
+ pr_debug("invalid directory (%s). Skipping.\n",
+ namelist[i]->d_name);
+ continue;
+ }
+ sprintf(path, "%s/%s/proc/kallsyms",
+ symbol_conf.guestmount,
+ namelist[i]->d_name);
+ ret = access(path, R_OK);
+ if (ret) {
+ pr_debug("Can't access file %s\n", path);
+ goto failure;
+ }
+ machines__create_kernel_maps(machines, pid);
+ }
+failure:
+ free(namelist);
+ }
+
+ return ret;
+}
+
+void machines__destroy_guest_kernel_maps(struct rb_root *machines)
+{
+ struct rb_node *next = rb_first(machines);
+
+ while (next) {
+ struct machine *pos = rb_entry(next, struct machine, rb_node);
+
+ next = rb_next(&pos->rb_node);
+ rb_erase(&pos->rb_node, machines);
+ machine__delete(pos);
+ }
+}
+
+int machines__create_kernel_maps(struct rb_root *machines, pid_t pid)
+{
+ struct machine *machine = machines__findnew(machines, pid);
+
+ if (machine == NULL)
+ return -1;
+
+ return machine__create_kernel_maps(machine);
+}
+
+int machine__load_kallsyms(struct machine *machine, const char *filename,
+ enum map_type type, symbol_filter_t filter)
+{
+ struct map *map = machine->vmlinux_maps[type];
+ int ret = dso__load_kallsyms(map->dso, filename, map, filter);
+
+ if (ret > 0) {
+ dso__set_loaded(map->dso, type);
+ /*
+ * Since /proc/kallsyms will have multiple sessions for the
+ * kernel, with modules between them, fixup the end of all
+ * sections.
+ */
+ __map_groups__fixup_end(&machine->kmaps, type);
+ }
+
+ return ret;
+}
+
+int machine__load_vmlinux_path(struct machine *machine, enum map_type type,
+ symbol_filter_t filter)
+{
+ struct map *map = machine->vmlinux_maps[type];
+ int ret = dso__load_vmlinux_path(map->dso, map, filter);
+
+ if (ret > 0) {
+ dso__set_loaded(map->dso, type);
+ map__reloc_vmlinux(map);
+ }
+
+ return ret;
+}
+
+static void map_groups__fixup_end(struct map_groups *mg)
+{
+ int i;
+ for (i = 0; i < MAP__NR_TYPES; ++i)
+ __map_groups__fixup_end(mg, i);
+}
+
+static char *get_kernel_version(const char *root_dir)
+{
+ char version[PATH_MAX];
+ FILE *file;
+ char *name, *tmp;
+ const char *prefix = "Linux version ";
+
+ sprintf(version, "%s/proc/version", root_dir);
+ file = fopen(version, "r");
+ if (!file)
+ return NULL;
+
+ version[0] = '\0';
+ tmp = fgets(version, sizeof(version), file);
+ fclose(file);
+
+ name = strstr(version, prefix);
+ if (!name)
+ return NULL;
+ name += strlen(prefix);
+ tmp = strchr(name, ' ');
+ if (tmp)
+ *tmp = '\0';
+
+ return strdup(name);
+}
+
+static int map_groups__set_modules_path_dir(struct map_groups *mg,
+ const char *dir_name)
+{
+ struct dirent *dent;
+ DIR *dir = opendir(dir_name);
+ int ret = 0;
+
+ if (!dir) {
+ pr_debug("%s: cannot open %s dir\n", __func__, dir_name);
+ return -1;
+ }
+
+ while ((dent = readdir(dir)) != NULL) {
+ char path[PATH_MAX];
+ struct stat st;
+
+ /*sshfs might return bad dent->d_type, so we have to stat*/
+ snprintf(path, sizeof(path), "%s/%s", dir_name, dent->d_name);
+ if (stat(path, &st))
+ continue;
+
+ if (S_ISDIR(st.st_mode)) {
+ if (!strcmp(dent->d_name, ".") ||
+ !strcmp(dent->d_name, ".."))
+ continue;
+
+ ret = map_groups__set_modules_path_dir(mg, path);
+ if (ret < 0)
+ goto out;
+ } else {
+ char *dot = strrchr(dent->d_name, '.'),
+ dso_name[PATH_MAX];
+ struct map *map;
+ char *long_name;
+
+ if (dot == NULL || strcmp(dot, ".ko"))
+ continue;
+ snprintf(dso_name, sizeof(dso_name), "[%.*s]",
+ (int)(dot - dent->d_name), dent->d_name);
+
+ strxfrchar(dso_name, '-', '_');
+ map = map_groups__find_by_name(mg, MAP__FUNCTION,
+ dso_name);
+ if (map == NULL)
+ continue;
+
+ long_name = strdup(path);
+ if (long_name == NULL) {
+ ret = -1;
+ goto out;
+ }
+ dso__set_long_name(map->dso, long_name);
+ map->dso->lname_alloc = 1;
+ dso__kernel_module_get_build_id(map->dso, "");
+ }
+ }
+
+out:
+ closedir(dir);
+ return ret;
+}
+
+static int machine__set_modules_path(struct machine *machine)
+{
+ char *version;
+ char modules_path[PATH_MAX];
+
+ version = get_kernel_version(machine->root_dir);
+ if (!version)
+ return -1;
+
+ snprintf(modules_path, sizeof(modules_path), "%s/lib/modules/%s/kernel",
+ machine->root_dir, version);
+ free(version);
+
+ return map_groups__set_modules_path_dir(&machine->kmaps, modules_path);
+}
+
+static int machine__create_modules(struct machine *machine)
+{
+ char *line = NULL;
+ size_t n;
+ FILE *file;
+ struct map *map;
+ const char *modules;
+ char path[PATH_MAX];
+
+ if (machine__is_default_guest(machine))
+ modules = symbol_conf.default_guest_modules;
+ else {
+ sprintf(path, "%s/proc/modules", machine->root_dir);
+ modules = path;
+ }
+
+ if (symbol__restricted_filename(path, "/proc/modules"))
+ return -1;
+
+ file = fopen(modules, "r");
+ if (file == NULL)
+ return -1;
+
+ while (!feof(file)) {
+ char name[PATH_MAX];
+ u64 start;
+ char *sep;
+ int line_len;
+
+ line_len = getline(&line, &n, file);
+ if (line_len < 0)
+ break;
+
+ if (!line)
+ goto out_failure;
+
+ line[--line_len] = '\0'; /* \n */
+
+ sep = strrchr(line, 'x');
+ if (sep == NULL)
+ continue;
+
+ hex2u64(sep + 1, &start);
+
+ sep = strchr(line, ' ');
+ if (sep == NULL)
+ continue;
+
+ *sep = '\0';
+
+ snprintf(name, sizeof(name), "[%s]", line);
+ map = machine__new_module(machine, start, name);
+ if (map == NULL)
+ goto out_delete_line;
+ dso__kernel_module_get_build_id(map->dso, machine->root_dir);
+ }
+
+ free(line);
+ fclose(file);
+
+ return machine__set_modules_path(machine);
+
+out_delete_line:
+ free(line);
+out_failure:
+ return -1;
+}
+
+int machine__create_kernel_maps(struct machine *machine)
+{
+ struct dso *kernel = machine__get_kernel(machine);
+
+ if (kernel == NULL ||
+ __machine__create_kernel_maps(machine, kernel) < 0)
+ return -1;
+
+ if (symbol_conf.use_modules && machine__create_modules(machine) < 0) {
+ if (machine__is_host(machine))
+ pr_debug("Problems creating module maps, "
+ "continuing anyway...\n");
+ else
+ pr_debug("Problems creating module maps for guest %d, "
+ "continuing anyway...\n", machine->pid);
+ }
+
+ /*
+ * Now that we have all the maps created, just set the ->end of them:
+ */
+ map_groups__fixup_end(&machine->kmaps);
+ return 0;
+}
+
static void machine__set_kernel_mmap_len(struct machine *machine,
union perf_event *event)
{
@@ -462,3 +1018,189 @@ int machine__process_event(struct machine *machine, union perf_event *event)

return ret;
}
+
+void machine__remove_thread(struct machine *machine, struct thread *th)
+{
+ machine->last_match = NULL;
+ rb_erase(&th->rb_node, &machine->threads);
+ /*
+ * We may have references to this thread, for instance in some hist_entry
+ * instances, so just move them to a separate list.
+ */
+ list_add_tail(&th->node, &machine->dead_threads);
+}
+
+static bool symbol__match_parent_regex(struct symbol *sym)
+{
+ if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0))
+ return 1;
+
+ return 0;
+}
+
+static const u8 cpumodes[] = {
+ PERF_RECORD_MISC_USER,
+ PERF_RECORD_MISC_KERNEL,
+ PERF_RECORD_MISC_GUEST_USER,
+ PERF_RECORD_MISC_GUEST_KERNEL
+};
+#define NCPUMODES (sizeof(cpumodes)/sizeof(u8))
+
+static void ip__resolve_ams(struct machine *machine, struct thread *thread,
+ struct addr_map_symbol *ams,
+ u64 ip)
+{
+ struct addr_location al;
+ size_t i;
+ u8 m;
+
+ memset(&al, 0, sizeof(al));
+
+ for (i = 0; i < NCPUMODES; i++) {
+ m = cpumodes[i];
+ /*
+ * We cannot use the header.misc hint to determine whether a
+ * branch stack address is user, kernel, guest, hypervisor.
+ * Branches may straddle the kernel/user/hypervisor boundaries.
+ * Thus, we have to try consecutively until we find a match
+ * or else, the symbol is unknown
+ */
+ thread__find_addr_location(thread, machine, m, MAP__FUNCTION,
+ ip, &al, NULL);
+ if (al.sym)
+ goto found;
+ }
+found:
+ ams->addr = ip;
+ ams->al_addr = al.addr;
+ ams->sym = al.sym;
+ ams->map = al.map;
+}
+
+struct branch_info *machine__resolve_bstack(struct machine *machine,
+ struct thread *thr,
+ struct branch_stack *bs)
+{
+ struct branch_info *bi;
+ unsigned int i;
+
+ bi = calloc(bs->nr, sizeof(struct branch_info));
+ if (!bi)
+ return NULL;
+
+ for (i = 0; i < bs->nr; i++) {
+ ip__resolve_ams(machine, thr, &bi[i].to, bs->entries[i].to);
+ ip__resolve_ams(machine, thr, &bi[i].from, bs->entries[i].from);
+ bi[i].flags = bs->entries[i].flags;
+ }
+ return bi;
+}
+
+static int machine__resolve_callchain_sample(struct machine *machine,
+ struct thread *thread,
+ struct ip_callchain *chain,
+ struct symbol **parent)
+
+{
+ u8 cpumode = PERF_RECORD_MISC_USER;
+ unsigned int i;
+ int err;
+
+ callchain_cursor_reset(&callchain_cursor);
+
+ if (chain->nr > PERF_MAX_STACK_DEPTH) {
+ pr_warning("corrupted callchain. skipping...\n");
+ return 0;
+ }
+
+ for (i = 0; i < chain->nr; i++) {
+ u64 ip;
+ struct addr_location al;
+
+ if (callchain_param.order == ORDER_CALLEE)
+ ip = chain->ips[i];
+ else
+ ip = chain->ips[chain->nr - i - 1];
+
+ if (ip >= PERF_CONTEXT_MAX) {
+ switch (ip) {
+ case PERF_CONTEXT_HV:
+ cpumode = PERF_RECORD_MISC_HYPERVISOR;
+ break;
+ case PERF_CONTEXT_KERNEL:
+ cpumode = PERF_RECORD_MISC_KERNEL;
+ break;
+ case PERF_CONTEXT_USER:
+ cpumode = PERF_RECORD_MISC_USER;
+ break;
+ default:
+ pr_debug("invalid callchain context: "
+ "%"PRId64"\n", (s64) ip);
+ /*
+ * It seems the callchain is corrupted.
+ * Discard all.
+ */
+ callchain_cursor_reset(&callchain_cursor);
+ return 0;
+ }
+ continue;
+ }
+
+ al.filtered = false;
+ thread__find_addr_location(thread, machine, cpumode,
+ MAP__FUNCTION, ip, &al, NULL);
+ if (al.sym != NULL) {
+ if (sort__has_parent && !*parent &&
+ symbol__match_parent_regex(al.sym))
+ *parent = al.sym;
+ if (!symbol_conf.use_callchain)
+ break;
+ }
+
+ err = callchain_cursor_append(&callchain_cursor,
+ ip, al.map, al.sym);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+static int unwind_entry(struct unwind_entry *entry, void *arg)
+{
+ struct callchain_cursor *cursor = arg;
+ return callchain_cursor_append(cursor, entry->ip,
+ entry->map, entry->sym);
+}
+
+int machine__resolve_callchain(struct machine *machine,
+ struct perf_evsel *evsel,
+ struct thread *thread,
+ struct perf_sample *sample,
+ struct symbol **parent)
+
+{
+ int ret;
+
+ callchain_cursor_reset(&callchain_cursor);
+
+ ret = machine__resolve_callchain_sample(machine, thread,
+ sample->callchain, parent);
+ if (ret)
+ return ret;
+
+ /* Can we do dwarf post unwind? */
+ if (!((evsel->attr.sample_type & PERF_SAMPLE_REGS_USER) &&
+ (evsel->attr.sample_type & PERF_SAMPLE_STACK_USER)))
+ return 0;
+
+ /* Bail out if nothing was captured. */
+ if ((!sample->user_regs.regs) ||
+ (!sample->user_stack.size))
+ return 0;
+
+ return unwind__get_entries(unwind_entry, &callchain_cursor, machine,
+ thread, evsel->attr.sample_regs_user,
+ sample);
+
+}
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 646ad13..e112368 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -61,9 +61,10 @@ char *machine__mmap_name(struct machine *machine, char *bf, size_t size);

int machine__init(struct machine *machine, const char *root_dir, pid_t pid);
void machine__exit(struct machine *machine);
+void machine__delete_dead_threads(struct machine *machine);
+void machine__delete_threads(struct machine *machine);
void machine__delete(struct machine *machine);

-
struct branch_info *machine__resolve_bstack(struct machine *machine,
struct thread *thread,
struct branch_stack *bs);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 8d04dfb..76d6e25 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -16,7 +16,6 @@
#include "cpumap.h"
#include "event-parse.h"
#include "perf_regs.h"
-#include "unwind.h"
#include "vdso.h"

static int perf_session__open(struct perf_session *self, bool force)
@@ -162,34 +161,11 @@ out_delete:
return NULL;
}

-static void machine__delete_dead_threads(struct machine *machine)
-{
- struct thread *n, *t;
-
- list_for_each_entry_safe(t, n, &machine->dead_threads, node) {
- list_del(&t->node);
- thread__delete(t);
- }
-}
-
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);
-
- while (nd) {
- struct thread *t = rb_entry(nd, struct thread, rb_node);
-
- rb_erase(&t->rb_node, &self->threads);
- nd = rb_next(nd);
- thread__delete(t);
- }
-}
-
static void perf_session__delete_threads(struct perf_session *session)
{
machine__delete_threads(&session->host_machine);
@@ -223,192 +199,6 @@ void perf_session__delete(struct perf_session *self)
vdso__exit();
}

-void machine__remove_thread(struct machine *self, struct thread *th)
-{
- self->last_match = NULL;
- rb_erase(&th->rb_node, &self->threads);
- /*
- * We may have references to this thread, for instance in some hist_entry
- * instances, so just move them to a separate list.
- */
- list_add_tail(&th->node, &self->dead_threads);
-}
-
-static bool symbol__match_parent_regex(struct symbol *sym)
-{
- if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0))
- return 1;
-
- return 0;
-}
-
-static const u8 cpumodes[] = {
- PERF_RECORD_MISC_USER,
- PERF_RECORD_MISC_KERNEL,
- PERF_RECORD_MISC_GUEST_USER,
- PERF_RECORD_MISC_GUEST_KERNEL
-};
-#define NCPUMODES (sizeof(cpumodes)/sizeof(u8))
-
-static void ip__resolve_ams(struct machine *self, struct thread *thread,
- struct addr_map_symbol *ams,
- u64 ip)
-{
- struct addr_location al;
- size_t i;
- u8 m;
-
- memset(&al, 0, sizeof(al));
-
- for (i = 0; i < NCPUMODES; i++) {
- m = cpumodes[i];
- /*
- * We cannot use the header.misc hint to determine whether a
- * branch stack address is user, kernel, guest, hypervisor.
- * Branches may straddle the kernel/user/hypervisor boundaries.
- * Thus, we have to try consecutively until we find a match
- * or else, the symbol is unknown
- */
- thread__find_addr_location(thread, self, m, MAP__FUNCTION,
- ip, &al, NULL);
- if (al.sym)
- goto found;
- }
-found:
- ams->addr = ip;
- ams->al_addr = al.addr;
- ams->sym = al.sym;
- ams->map = al.map;
-}
-
-struct branch_info *machine__resolve_bstack(struct machine *self,
- struct thread *thr,
- struct branch_stack *bs)
-{
- struct branch_info *bi;
- unsigned int i;
-
- bi = calloc(bs->nr, sizeof(struct branch_info));
- if (!bi)
- return NULL;
-
- for (i = 0; i < bs->nr; i++) {
- ip__resolve_ams(self, thr, &bi[i].to, bs->entries[i].to);
- ip__resolve_ams(self, thr, &bi[i].from, bs->entries[i].from);
- bi[i].flags = bs->entries[i].flags;
- }
- return bi;
-}
-
-static int machine__resolve_callchain_sample(struct machine *machine,
- struct thread *thread,
- struct ip_callchain *chain,
- struct symbol **parent)
-
-{
- u8 cpumode = PERF_RECORD_MISC_USER;
- unsigned int i;
- int err;
-
- callchain_cursor_reset(&callchain_cursor);
-
- if (chain->nr > PERF_MAX_STACK_DEPTH) {
- pr_warning("corrupted callchain. skipping...\n");
- return 0;
- }
-
- for (i = 0; i < chain->nr; i++) {
- u64 ip;
- struct addr_location al;
-
- if (callchain_param.order == ORDER_CALLEE)
- ip = chain->ips[i];
- else
- ip = chain->ips[chain->nr - i - 1];
-
- if (ip >= PERF_CONTEXT_MAX) {
- switch (ip) {
- case PERF_CONTEXT_HV:
- cpumode = PERF_RECORD_MISC_HYPERVISOR;
- break;
- case PERF_CONTEXT_KERNEL:
- cpumode = PERF_RECORD_MISC_KERNEL;
- break;
- case PERF_CONTEXT_USER:
- cpumode = PERF_RECORD_MISC_USER;
- break;
- default:
- pr_debug("invalid callchain context: "
- "%"PRId64"\n", (s64) ip);
- /*
- * It seems the callchain is corrupted.
- * Discard all.
- */
- callchain_cursor_reset(&callchain_cursor);
- return 0;
- }
- continue;
- }
-
- al.filtered = false;
- thread__find_addr_location(thread, machine, cpumode,
- MAP__FUNCTION, ip, &al, NULL);
- if (al.sym != NULL) {
- if (sort__has_parent && !*parent &&
- symbol__match_parent_regex(al.sym))
- *parent = al.sym;
- if (!symbol_conf.use_callchain)
- break;
- }
-
- err = callchain_cursor_append(&callchain_cursor,
- ip, al.map, al.sym);
- if (err)
- return err;
- }
-
- return 0;
-}
-
-static int unwind_entry(struct unwind_entry *entry, void *arg)
-{
- struct callchain_cursor *cursor = arg;
- return callchain_cursor_append(cursor, entry->ip,
- entry->map, entry->sym);
-}
-
-int machine__resolve_callchain(struct machine *machine,
- struct perf_evsel *evsel,
- struct thread *thread,
- struct perf_sample *sample,
- struct symbol **parent)
-
-{
- int ret;
-
- callchain_cursor_reset(&callchain_cursor);
-
- ret = machine__resolve_callchain_sample(machine, thread,
- sample->callchain, parent);
- if (ret)
- return ret;
-
- /* Can we do dwarf post unwind? */
- if (!((evsel->attr.sample_type & PERF_SAMPLE_REGS_USER) &&
- (evsel->attr.sample_type & PERF_SAMPLE_STACK_USER)))
- return 0;
-
- /* Bail out if nothing was captured. */
- if ((!sample->user_regs.regs) ||
- (!sample->user_stack.size))
- return 0;
-
- return unwind__get_entries(unwind_entry, &callchain_cursor, machine,
- thread, evsel->attr.sample_regs_user,
- sample);
-
-}
-
static int process_event_synth_tracing_data_stub(union perf_event *event
__maybe_unused,
struct perf_session *session
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index e5ba984..2960284 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -28,8 +28,8 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map,
symbol_filter_t filter);
static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,
symbol_filter_t filter);
-static int vmlinux_path__nr_entries;
-static char **vmlinux_path;
+int vmlinux_path__nr_entries;
+char **vmlinux_path;

struct symbol_conf symbol_conf = {
.exclude_other = true,
@@ -202,13 +202,6 @@ void __map_groups__fixup_end(struct map_groups *mg, enum map_type type)
curr->end = ~0ULL;
}

-static void map_groups__fixup_end(struct map_groups *mg)
-{
- int i;
- for (i = 0; i < MAP__NR_TYPES; ++i)
- __map_groups__fixup_end(mg, i);
-}
-
struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name)
{
size_t namelen = strlen(name) + 1;
@@ -652,8 +645,8 @@ discard_symbol: rb_erase(&pos->rb_node, root);
return count + moved;
}

-static bool symbol__restricted_filename(const char *filename,
- const char *restricted_filename)
+bool symbol__restricted_filename(const char *filename,
+ const char *restricted_filename)
{
bool restricted = false;

@@ -887,200 +880,6 @@ struct map *map_groups__find_by_name(struct map_groups *mg,
return NULL;
}

-static int map_groups__set_modules_path_dir(struct map_groups *mg,
- const char *dir_name)
-{
- struct dirent *dent;
- DIR *dir = opendir(dir_name);
- int ret = 0;
-
- if (!dir) {
- pr_debug("%s: cannot open %s dir\n", __func__, dir_name);
- return -1;
- }
-
- while ((dent = readdir(dir)) != NULL) {
- char path[PATH_MAX];
- struct stat st;
-
- /*sshfs might return bad dent->d_type, so we have to stat*/
- snprintf(path, sizeof(path), "%s/%s", dir_name, dent->d_name);
- if (stat(path, &st))
- continue;
-
- if (S_ISDIR(st.st_mode)) {
- if (!strcmp(dent->d_name, ".") ||
- !strcmp(dent->d_name, ".."))
- continue;
-
- ret = map_groups__set_modules_path_dir(mg, path);
- if (ret < 0)
- goto out;
- } else {
- char *dot = strrchr(dent->d_name, '.'),
- dso_name[PATH_MAX];
- struct map *map;
- char *long_name;
-
- if (dot == NULL || strcmp(dot, ".ko"))
- continue;
- snprintf(dso_name, sizeof(dso_name), "[%.*s]",
- (int)(dot - dent->d_name), dent->d_name);
-
- strxfrchar(dso_name, '-', '_');
- map = map_groups__find_by_name(mg, MAP__FUNCTION,
- dso_name);
- if (map == NULL)
- continue;
-
- long_name = strdup(path);
- if (long_name == NULL) {
- ret = -1;
- goto out;
- }
- dso__set_long_name(map->dso, long_name);
- map->dso->lname_alloc = 1;
- dso__kernel_module_get_build_id(map->dso, "");
- }
- }
-
-out:
- closedir(dir);
- return ret;
-}
-
-static char *get_kernel_version(const char *root_dir)
-{
- char version[PATH_MAX];
- FILE *file;
- char *name, *tmp;
- const char *prefix = "Linux version ";
-
- sprintf(version, "%s/proc/version", root_dir);
- file = fopen(version, "r");
- if (!file)
- return NULL;
-
- version[0] = '\0';
- tmp = fgets(version, sizeof(version), file);
- fclose(file);
-
- name = strstr(version, prefix);
- if (!name)
- return NULL;
- name += strlen(prefix);
- tmp = strchr(name, ' ');
- if (tmp)
- *tmp = '\0';
-
- return strdup(name);
-}
-
-static int machine__set_modules_path(struct machine *machine)
-{
- char *version;
- char modules_path[PATH_MAX];
-
- version = get_kernel_version(machine->root_dir);
- if (!version)
- return -1;
-
- snprintf(modules_path, sizeof(modules_path), "%s/lib/modules/%s/kernel",
- machine->root_dir, version);
- free(version);
-
- return map_groups__set_modules_path_dir(&machine->kmaps, modules_path);
-}
-
-struct map *machine__new_module(struct machine *machine, u64 start,
- const char *filename)
-{
- struct map *map;
- struct dso *dso = __dsos__findnew(&machine->kernel_dsos, filename);
-
- if (dso == NULL)
- return NULL;
-
- map = map__new2(start, dso, MAP__FUNCTION);
- if (map == NULL)
- return NULL;
-
- if (machine__is_host(machine))
- dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE;
- else
- dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE;
- map_groups__insert(&machine->kmaps, map);
- return map;
-}
-
-static int machine__create_modules(struct machine *machine)
-{
- char *line = NULL;
- size_t n;
- FILE *file;
- struct map *map;
- const char *modules;
- char path[PATH_MAX];
-
- if (machine__is_default_guest(machine))
- modules = symbol_conf.default_guest_modules;
- else {
- sprintf(path, "%s/proc/modules", machine->root_dir);
- modules = path;
- }
-
- if (symbol__restricted_filename(path, "/proc/modules"))
- return -1;
-
- file = fopen(modules, "r");
- if (file == NULL)
- return -1;
-
- while (!feof(file)) {
- char name[PATH_MAX];
- u64 start;
- char *sep;
- int line_len;
-
- line_len = getline(&line, &n, file);
- if (line_len < 0)
- break;
-
- if (!line)
- goto out_failure;
-
- line[--line_len] = '\0'; /* \n */
-
- sep = strrchr(line, 'x');
- if (sep == NULL)
- continue;
-
- hex2u64(sep + 1, &start);
-
- sep = strchr(line, ' ');
- if (sep == NULL)
- continue;
-
- *sep = '\0';
-
- snprintf(name, sizeof(name), "[%s]", line);
- map = machine__new_module(machine, start, name);
- if (map == NULL)
- goto out_delete_line;
- dso__kernel_module_get_build_id(map->dso, machine->root_dir);
- }
-
- free(line);
- fclose(file);
-
- return machine__set_modules_path(machine);
-
-out_delete_line:
- free(line);
-out_failure:
- return -1;
-}
-
int dso__load_vmlinux(struct dso *dso, struct map *map,
const char *vmlinux, symbol_filter_t filter)
{
@@ -1300,195 +1099,6 @@ out_try_fixup:
return err;
}

-size_t machines__fprintf_dsos(struct rb_root *machines, FILE *fp)
-{
- struct rb_node *nd;
- size_t ret = 0;
-
- for (nd = rb_first(machines); nd; nd = rb_next(nd)) {
- struct machine *pos = rb_entry(nd, struct machine, rb_node);
- ret += __dsos__fprintf(&pos->kernel_dsos, fp);
- ret += __dsos__fprintf(&pos->user_dsos, fp);
- }
-
- return ret;
-}
-
-size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp,
- bool (skip)(struct dso *dso, int parm), int parm)
-{
- return __dsos__fprintf_buildid(&machine->kernel_dsos, fp, skip, parm) +
- __dsos__fprintf_buildid(&machine->user_dsos, fp, skip, parm);
-}
-
-size_t machines__fprintf_dsos_buildid(struct rb_root *machines, FILE *fp,
- bool (skip)(struct dso *dso, int parm), int parm)
-{
- struct rb_node *nd;
- size_t ret = 0;
-
- for (nd = rb_first(machines); nd; nd = rb_next(nd)) {
- struct machine *pos = rb_entry(nd, struct machine, rb_node);
- ret += machine__fprintf_dsos_buildid(pos, fp, skip, parm);
- }
- return ret;
-}
-
-static struct dso *machine__get_kernel(struct machine *machine)
-{
- const char *vmlinux_name = NULL;
- struct dso *kernel;
-
- if (machine__is_host(machine)) {
- vmlinux_name = symbol_conf.vmlinux_name;
- if (!vmlinux_name)
- vmlinux_name = "[kernel.kallsyms]";
-
- kernel = dso__kernel_findnew(machine, vmlinux_name,
- "[kernel]",
- DSO_TYPE_KERNEL);
- } else {
- char bf[PATH_MAX];
-
- if (machine__is_default_guest(machine))
- vmlinux_name = symbol_conf.default_guest_vmlinux_name;
- if (!vmlinux_name)
- vmlinux_name = machine__mmap_name(machine, bf,
- sizeof(bf));
-
- kernel = dso__kernel_findnew(machine, vmlinux_name,
- "[guest.kernel]",
- DSO_TYPE_GUEST_KERNEL);
- }
-
- if (kernel != NULL && (!kernel->has_build_id))
- dso__read_running_kernel_build_id(kernel, machine);
-
- return kernel;
-}
-
-struct process_args {
- u64 start;
-};
-
-static int symbol__in_kernel(void *arg, const char *name,
- char type __maybe_unused, u64 start)
-{
- struct process_args *args = arg;
-
- if (strchr(name, '['))
- return 0;
-
- args->start = start;
- return 1;
-}
-
-/* Figure out the start address of kernel map from /proc/kallsyms */
-static u64 machine__get_kernel_start_addr(struct machine *machine)
-{
- const char *filename;
- char path[PATH_MAX];
- struct process_args args;
-
- if (machine__is_host(machine)) {
- filename = "/proc/kallsyms";
- } else {
- if (machine__is_default_guest(machine))
- filename = (char *)symbol_conf.default_guest_kallsyms;
- else {
- sprintf(path, "%s/proc/kallsyms", machine->root_dir);
- filename = path;
- }
- }
-
- if (symbol__restricted_filename(filename, "/proc/kallsyms"))
- return 0;
-
- if (kallsyms__parse(filename, &args, symbol__in_kernel) <= 0)
- return 0;
-
- return args.start;
-}
-
-int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel)
-{
- enum map_type type;
- u64 start = machine__get_kernel_start_addr(machine);
-
- for (type = 0; type < MAP__NR_TYPES; ++type) {
- struct kmap *kmap;
-
- machine->vmlinux_maps[type] = map__new2(start, kernel, type);
- if (machine->vmlinux_maps[type] == NULL)
- return -1;
-
- machine->vmlinux_maps[type]->map_ip =
- machine->vmlinux_maps[type]->unmap_ip =
- identity__map_ip;
- kmap = map__kmap(machine->vmlinux_maps[type]);
- kmap->kmaps = &machine->kmaps;
- map_groups__insert(&machine->kmaps,
- machine->vmlinux_maps[type]);
- }
-
- return 0;
-}
-
-void machine__destroy_kernel_maps(struct machine *machine)
-{
- enum map_type type;
-
- for (type = 0; type < MAP__NR_TYPES; ++type) {
- struct kmap *kmap;
-
- if (machine->vmlinux_maps[type] == NULL)
- continue;
-
- kmap = map__kmap(machine->vmlinux_maps[type]);
- map_groups__remove(&machine->kmaps,
- machine->vmlinux_maps[type]);
- if (kmap->ref_reloc_sym) {
- /*
- * ref_reloc_sym is shared among all maps, so free just
- * on one of them.
- */
- if (type == MAP__FUNCTION) {
- free((char *)kmap->ref_reloc_sym->name);
- kmap->ref_reloc_sym->name = NULL;
- free(kmap->ref_reloc_sym);
- }
- kmap->ref_reloc_sym = NULL;
- }
-
- map__delete(machine->vmlinux_maps[type]);
- machine->vmlinux_maps[type] = NULL;
- }
-}
-
-int machine__create_kernel_maps(struct machine *machine)
-{
- struct dso *kernel = machine__get_kernel(machine);
-
- if (kernel == NULL ||
- __machine__create_kernel_maps(machine, kernel) < 0)
- return -1;
-
- if (symbol_conf.use_modules && machine__create_modules(machine) < 0) {
- if (machine__is_host(machine))
- pr_debug("Problems creating module maps, "
- "continuing anyway...\n");
- else
- pr_debug("Problems creating module maps for guest %d, "
- "continuing anyway...\n", machine->pid);
- }
-
- /*
- * Now that we have all the maps created, just set the ->end of them:
- */
- map_groups__fixup_end(&machine->kmaps);
- return 0;
-}
-
static void vmlinux_path__exit(void)
{
while (--vmlinux_path__nr_entries >= 0) {
@@ -1549,25 +1159,6 @@ out_fail:
return -1;
}

-size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp)
-{
- int i;
- size_t printed = 0;
- struct dso *kdso = machine->vmlinux_maps[MAP__FUNCTION]->dso;
-
- if (kdso->has_build_id) {
- char filename[PATH_MAX];
- if (dso__build_id_filename(kdso, filename, sizeof(filename)))
- printed += fprintf(fp, "[0] %s\n", filename);
- }
-
- for (i = 0; i < vmlinux_path__nr_entries; ++i)
- printed += fprintf(fp, "[%d] %s\n",
- i + kdso->has_build_id, vmlinux_path[i]);
-
- return printed;
-}
-
static int setup_list(struct strlist **list, const char *list_str,
const char *list_name)
{
@@ -1671,108 +1262,3 @@ void symbol__exit(void)
symbol_conf.sym_list = symbol_conf.dso_list = symbol_conf.comm_list = NULL;
symbol_conf.initialized = false;
}
-
-int machines__create_kernel_maps(struct rb_root *machines, pid_t pid)
-{
- struct machine *machine = machines__findnew(machines, pid);
-
- if (machine == NULL)
- return -1;
-
- return machine__create_kernel_maps(machine);
-}
-
-int machines__create_guest_kernel_maps(struct rb_root *machines)
-{
- int ret = 0;
- struct dirent **namelist = NULL;
- int i, items = 0;
- char path[PATH_MAX];
- pid_t pid;
- char *endp;
-
- if (symbol_conf.default_guest_vmlinux_name ||
- symbol_conf.default_guest_modules ||
- symbol_conf.default_guest_kallsyms) {
- machines__create_kernel_maps(machines, DEFAULT_GUEST_KERNEL_ID);
- }
-
- if (symbol_conf.guestmount) {
- items = scandir(symbol_conf.guestmount, &namelist, NULL, NULL);
- if (items <= 0)
- return -ENOENT;
- for (i = 0; i < items; i++) {
- if (!isdigit(namelist[i]->d_name[0])) {
- /* Filter out . and .. */
- continue;
- }
- pid = (pid_t)strtol(namelist[i]->d_name, &endp, 10);
- if ((*endp != '\0') ||
- (endp == namelist[i]->d_name) ||
- (errno == ERANGE)) {
- pr_debug("invalid directory (%s). Skipping.\n",
- namelist[i]->d_name);
- continue;
- }
- sprintf(path, "%s/%s/proc/kallsyms",
- symbol_conf.guestmount,
- namelist[i]->d_name);
- ret = access(path, R_OK);
- if (ret) {
- pr_debug("Can't access file %s\n", path);
- goto failure;
- }
- machines__create_kernel_maps(machines, pid);
- }
-failure:
- free(namelist);
- }
-
- return ret;
-}
-
-void machines__destroy_guest_kernel_maps(struct rb_root *machines)
-{
- struct rb_node *next = rb_first(machines);
-
- while (next) {
- struct machine *pos = rb_entry(next, struct machine, rb_node);
-
- next = rb_next(&pos->rb_node);
- rb_erase(&pos->rb_node, machines);
- machine__delete(pos);
- }
-}
-
-int machine__load_kallsyms(struct machine *machine, const char *filename,
- enum map_type type, symbol_filter_t filter)
-{
- struct map *map = machine->vmlinux_maps[type];
- int ret = dso__load_kallsyms(map->dso, filename, map, filter);
-
- if (ret > 0) {
- dso__set_loaded(map->dso, type);
- /*
- * Since /proc/kallsyms will have multiple sessions for the
- * kernel, with modules between them, fixup the end of all
- * sections.
- */
- __map_groups__fixup_end(&machine->kmaps, type);
- }
-
- return ret;
-}
-
-int machine__load_vmlinux_path(struct machine *machine, enum map_type type,
- symbol_filter_t filter)
-{
- struct map *map = machine->vmlinux_maps[type];
- int ret = dso__load_vmlinux_path(map->dso, map, filter);
-
- if (ret > 0) {
- dso__set_loaded(map->dso, type);
- map__reloc_vmlinux(map);
- }
-
- return ret;
-}
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index de68f98..ec7b240 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -120,6 +120,8 @@ struct symbol_conf {
};

extern struct symbol_conf symbol_conf;
+extern int vmlinux_path__nr_entries;
+extern char **vmlinux_path;

static inline void *symbol__priv(struct symbol *sym)
{
@@ -223,6 +225,8 @@ size_t symbol__fprintf_symname_offs(const struct symbol *sym,
size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp);
size_t symbol__fprintf(struct symbol *sym, FILE *fp);
bool symbol_type__is_a(char symbol_type, enum map_type map_type);
+bool symbol__restricted_filename(const char *filename,
+ const char *restricted_filename);

int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
struct symsrc *runtime_ss, symbol_filter_t filter,
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index df59623..632e40e 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -54,10 +54,10 @@ int thread__comm_len(struct thread *self)
return self->comm_len;
}

-static size_t thread__fprintf(struct thread *self, FILE *fp)
+size_t thread__fprintf(struct thread *thread, FILE *fp)
{
- return fprintf(fp, "Thread %d %s\n", self->pid, self->comm) +
- map_groups__fprintf(&self->mg, verbose, fp);
+ return fprintf(fp, "Thread %d %s\n", thread->pid, thread->comm) +
+ map_groups__fprintf(&thread->mg, verbose, fp);
}

void thread__insert_map(struct thread *self, struct map *map)
@@ -84,17 +84,3 @@ int thread__fork(struct thread *self, struct thread *parent)
return -ENOMEM;
return 0;
}
-
-size_t machine__fprintf(struct machine *machine, FILE *fp)
-{
- size_t ret = 0;
- struct rb_node *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);
- }
-
- return ret;
-}
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index f2fa17c..5ad2664 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -30,6 +30,7 @@ int thread__set_comm(struct thread *self, const char *comm);
int thread__comm_len(struct thread *self);
void thread__insert_map(struct thread *self, struct map *map);
int thread__fork(struct thread *self, struct thread *parent);
+size_t thread__fprintf(struct thread *thread, FILE *fp);

static inline struct map *thread__find_map(struct thread *self,
enum map_type type, u64 addr)
--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Dec 11, 2012, 6:00:02 PM12/11/12
to
From: Jiri Olsa <jo...@redhat.com>

Changing formula methods to operate over hist entry and its pair
directly. This makes the code more obvious and readable, instead of all
time checking for pair being != NULL.

Signed-off-by: Jiri Olsa <jo...@redhat.com>
Acked-by: Namhyung Kim <namh...@kernel.org>
Cc: Corey Ashford <cjas...@linux.vnet.ibm.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Ingo Molnar <mi...@elte.hu>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Link: http://lkml.kernel.org/r/1354110769-2998-7-g...@redhat.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-diff.c | 35 +++++++++++++----------------------
tools/perf/ui/hist.c | 5 ++++-
tools/perf/util/hist.h | 3 ++-
3 files changed, 19 insertions(+), 24 deletions(-)

diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 342085a..d869029 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -184,13 +184,9 @@ s64 perf_diff__compute_wdiff(struct hist_entry *he, struct hist_entry *pair)
return he->diff.wdiff;
}

-static int formula_delta(struct hist_entry *he, char *buf, size_t size)
+static int formula_delta(struct hist_entry *he, struct hist_entry *pair,
+ char *buf, size_t size)
{
- struct hist_entry *pair = hist_entry__next_pair(he);
-
- if (!pair)
- return -1;
-
return scnprintf(buf, size,
"(%" PRIu64 " * 100 / %" PRIu64 ") - "
"(%" PRIu64 " * 100 / %" PRIu64 ")",
@@ -198,41 +194,36 @@ static int formula_delta(struct hist_entry *he, char *buf, size_t size)
pair->stat.period, pair->hists->stats.total_period);
}

-static int formula_ratio(struct hist_entry *he, char *buf, size_t size)
+static int formula_ratio(struct hist_entry *he, struct hist_entry *pair,
+ char *buf, size_t size)
{
- struct hist_entry *pair = hist_entry__next_pair(he);
double new_period = he->stat.period;
- double old_period = pair ? pair->stat.period : 0;
-
- if (!pair)
- return -1;
+ double old_period = pair->stat.period;

return scnprintf(buf, size, "%.0F / %.0F", new_period, old_period);
}

-static int formula_wdiff(struct hist_entry *he, char *buf, size_t size)
+static int formula_wdiff(struct hist_entry *he, struct hist_entry *pair,
+ char *buf, size_t size)
{
- struct hist_entry *pair = hist_entry__next_pair(he);
u64 new_period = he->stat.period;
- u64 old_period = pair ? pair->stat.period : 0;
-
- if (!pair)
- return -1;
+ u64 old_period = pair->stat.period;

return scnprintf(buf, size,
"(%" PRIu64 " * " "%" PRId64 ") - (%" PRIu64 " * " "%" PRId64 ")",
new_period, compute_wdiff_w2, old_period, compute_wdiff_w1);
}

-int perf_diff__formula(char *buf, size_t size, struct hist_entry *he)
+int perf_diff__formula(struct hist_entry *he, struct hist_entry *pair,
+ char *buf, size_t size)
{
switch (compute) {
case COMPUTE_DELTA:
- return formula_delta(he, buf, size);
+ return formula_delta(he, pair, buf, size);
case COMPUTE_RATIO:
- return formula_ratio(he, buf, size);
+ return formula_ratio(he, pair, buf, size);
case COMPUTE_WEIGHTED_DIFF:
- return formula_wdiff(he, buf, size);
+ return formula_wdiff(he, pair, buf, size);
default:
BUG_ON(1);
}
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 108e5ed..1785bab 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -389,10 +389,13 @@ static int hpp__width_formula(struct perf_hpp *hpp __maybe_unused)

static int hpp__entry_formula(struct perf_hpp *hpp, struct hist_entry *he)
{
+ struct hist_entry *pair = hist_entry__next_pair(he);
const char *fmt = symbol_conf.field_sep ? "%s" : "%-70s";
char buf[96] = " ";

- perf_diff__formula(buf, sizeof(buf), he);
+ if (pair)
+ perf_diff__formula(he, pair, buf, sizeof(buf));
+
return scnprintf(hpp->buf, hpp->size, fmt, buf);
}

diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 235503a..c1b2fad 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -229,6 +229,7 @@ unsigned int hists__sort_list_width(struct hists *self);
double perf_diff__compute_delta(struct hist_entry *he, struct hist_entry *pair);
double perf_diff__compute_ratio(struct hist_entry *he, struct hist_entry *pair);
s64 perf_diff__compute_wdiff(struct hist_entry *he, struct hist_entry *pair);
-int perf_diff__formula(char *buf, size_t size, struct hist_entry *he);
+int perf_diff__formula(struct hist_entry *he, struct hist_entry *pair,
+ char *buf, size_t size);
double perf_diff__period_percent(struct hist_entry *he, u64 period);
#endif /* __PERF_HIST_H */
--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Dec 11, 2012, 6:00:03 PM12/11/12
to
From: Jiri Olsa <jo...@redhat.com>

Changing compute methods to operate over hist entry and its pair
directly. This makes the code more obvious and readable, instead of all
time checking for pair being != NULL.

Signed-off-by: Jiri Olsa <jo...@redhat.com>
Acked-by: Namhyung Kim <namh...@kernel.org>
Cc: Corey Ashford <cjas...@linux.vnet.ibm.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Ingo Molnar <mi...@elte.hu>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Link: http://lkml.kernel.org/r/1354110769-2998-6-g...@redhat.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-diff.c | 38 +++++++++++++++++---------------------
tools/perf/ui/hist.c | 40 +++++++++++++++++++++++++---------------
tools/perf/util/hist.h | 7 ++++---
3 files changed, 46 insertions(+), 39 deletions(-)

diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 9fbbc01..342085a 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -146,47 +146,40 @@ static int setup_compute(const struct option *opt, const char *str,
return -EINVAL;
}

-static double get_period_percent(struct hist_entry *he, u64 period)
+double perf_diff__period_percent(struct hist_entry *he, u64 period)
{
u64 total = he->hists->stats.total_period;
return (period * 100.0) / total;
}

-double perf_diff__compute_delta(struct hist_entry *he)
+double perf_diff__compute_delta(struct hist_entry *he, struct hist_entry *pair)
{
- struct hist_entry *pair = hist_entry__next_pair(he);
- double new_percent = get_period_percent(he, he->stat.period);
- double old_percent = pair ? get_period_percent(pair, pair->stat.period) : 0.0;
+ double new_percent = perf_diff__period_percent(he, he->stat.period);
+ double old_percent = perf_diff__period_percent(pair, pair->stat.period);

he->diff.period_ratio_delta = new_percent - old_percent;
he->diff.computed = true;
return he->diff.period_ratio_delta;
}

-double perf_diff__compute_ratio(struct hist_entry *he)
+double perf_diff__compute_ratio(struct hist_entry *he, struct hist_entry *pair)
{
- struct hist_entry *pair = hist_entry__next_pair(he);
double new_period = he->stat.period;
- double old_period = pair ? pair->stat.period : 0;
+ double old_period = pair->stat.period;

he->diff.computed = true;
- he->diff.period_ratio = pair ? (new_period / old_period) : 0;
+ he->diff.period_ratio = new_period / old_period;
return he->diff.period_ratio;
}

-s64 perf_diff__compute_wdiff(struct hist_entry *he)
+s64 perf_diff__compute_wdiff(struct hist_entry *he, struct hist_entry *pair)
{
- struct hist_entry *pair = hist_entry__next_pair(he);
u64 new_period = he->stat.period;
- u64 old_period = pair ? pair->stat.period : 0;
+ u64 old_period = pair->stat.period;

he->diff.computed = true;
-
- if (!pair)
- he->diff.wdiff = 0;
- else
- he->diff.wdiff = new_period * compute_wdiff_w2 -
- old_period * compute_wdiff_w1;
+ he->diff.wdiff = new_period * compute_wdiff_w2 -
+ old_period * compute_wdiff_w1;

return he->diff.wdiff;
}
@@ -385,18 +378,21 @@ static void hists__precompute(struct hists *hists)

while (next != NULL) {
struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node);
+ struct hist_entry *pair = hist_entry__next_pair(he);

next = rb_next(&he->rb_node);
+ if (!pair)
+ continue;

switch (compute) {
case COMPUTE_DELTA:
- perf_diff__compute_delta(he);
+ perf_diff__compute_delta(he, pair);
break;
case COMPUTE_RATIO:
- perf_diff__compute_ratio(he);
+ perf_diff__compute_ratio(he, pair);
break;
case COMPUTE_WEIGHTED_DIFF:
- perf_diff__compute_wdiff(he);
+ perf_diff__compute_wdiff(he, pair);
break;
default:
BUG_ON(1);
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 6e639b5..108e5ed 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -268,14 +268,18 @@ static int hpp__width_delta(struct perf_hpp *hpp __maybe_unused)

static int hpp__entry_delta(struct perf_hpp *hpp, struct hist_entry *he)
{
+ struct hist_entry *pair = hist_entry__next_pair(he);
const char *fmt = symbol_conf.field_sep ? "%s" : "%7.7s";
char buf[32] = " ";
- double diff;
+ double diff = 0.0;

- if (he->diff.computed)
- diff = he->diff.period_ratio_delta;
- else
- diff = perf_diff__compute_delta(he);
+ if (pair) {
+ if (he->diff.computed)
+ diff = he->diff.period_ratio_delta;
+ else
+ diff = perf_diff__compute_delta(he, pair);
+ } else
+ diff = perf_diff__period_percent(he, he->stat.period);

if (fabs(diff) >= 0.01)
scnprintf(buf, sizeof(buf), "%+4.2F%%", diff);
@@ -297,14 +301,17 @@ static int hpp__width_ratio(struct perf_hpp *hpp __maybe_unused)

static int hpp__entry_ratio(struct perf_hpp *hpp, struct hist_entry *he)
{
+ struct hist_entry *pair = hist_entry__next_pair(he);
const char *fmt = symbol_conf.field_sep ? "%s" : "%14s";
char buf[32] = " ";
- double ratio;
+ double ratio = 0.0;

- if (he->diff.computed)
- ratio = he->diff.period_ratio;
- else
- ratio = perf_diff__compute_ratio(he);
+ if (pair) {
+ if (he->diff.computed)
+ ratio = he->diff.period_ratio;
+ else
+ ratio = perf_diff__compute_ratio(he, pair);
+ }

if (ratio > 0.0)
scnprintf(buf, sizeof(buf), "%+14.6F", ratio);
@@ -326,14 +333,17 @@ static int hpp__width_wdiff(struct perf_hpp *hpp __maybe_unused)

static int hpp__entry_wdiff(struct perf_hpp *hpp, struct hist_entry *he)
{
+ struct hist_entry *pair = hist_entry__next_pair(he);
const char *fmt = symbol_conf.field_sep ? "%s" : "%14s";
char buf[32] = " ";
- s64 wdiff;
+ s64 wdiff = 0;

- if (he->diff.computed)
- wdiff = he->diff.wdiff;
- else
- wdiff = perf_diff__compute_wdiff(he);
+ if (pair) {
+ if (he->diff.computed)
+ wdiff = he->diff.wdiff;
+ else
+ wdiff = perf_diff__compute_wdiff(he, pair);
+ }

if (wdiff != 0)
scnprintf(buf, sizeof(buf), "%14ld", wdiff);
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index a935a60..235503a 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -226,8 +226,9 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __maybe_unused,

unsigned int hists__sort_list_width(struct hists *self);

-double perf_diff__compute_delta(struct hist_entry *he);
-double perf_diff__compute_ratio(struct hist_entry *he);
-s64 perf_diff__compute_wdiff(struct hist_entry *he);
+double perf_diff__compute_delta(struct hist_entry *he, struct hist_entry *pair);
+double perf_diff__compute_ratio(struct hist_entry *he, struct hist_entry *pair);
+s64 perf_diff__compute_wdiff(struct hist_entry *he, struct hist_entry *pair);
int perf_diff__formula(char *buf, size_t size, struct hist_entry *he);
+double perf_diff__period_percent(struct hist_entry *he, u64 period);
#endif /* __PERF_HIST_H */
--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Dec 11, 2012, 6:00:03 PM12/11/12
to
From: Jiri Olsa <jo...@redhat.com>

Removing displacement from struct hist_entry_diff, because it's not
used. Displacement is not used for sorting, so there's no reason to
pre-calculate it.

Signed-off-by: Jiri Olsa <jo...@redhat.com>
Acked-by: Namhyung Kim <namh...@kernel.org>
Cc: Corey Ashford <cjas...@linux.vnet.ibm.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Ingo Molnar <mi...@elte.hu>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Link: http://lkml.kernel.org/r/1354110769-2998-5-g...@redhat.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/sort.h | 3 ---
1 file changed, 3 deletions(-)

diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 91ae274..a1c0d56 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -55,9 +55,6 @@ struct he_stat {
struct hist_entry_diff {
bool computed;

- /* PERF_HPP__DISPL */
- int displacement;
-
/* PERF_HPP__DELTA */
double period_ratio_delta;

--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Dec 11, 2012, 6:00:03 PM12/11/12
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

In two cases this test could detect an error, bail out but return zero.
Fix it by reporting -1 for failure.

Cc: David Ahern <dsa...@gmail.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Jiri Olsa <jo...@redhat.com>
Cc: Mike Galbraith <efa...@gmx.de>
Cc: Namhyung Kim <namh...@gmail.com>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Stephane Eranian <era...@google.com>
Link: http://lkml.kernel.org/n/tip-tjhs9v6nqp...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/tests/mmap-basic.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c
index e174681..8682ecf 100644
--- a/tools/perf/tests/mmap-basic.c
+++ b/tools/perf/tests/mmap-basic.c
@@ -128,6 +128,7 @@ int test__basic_mmap(void)
goto out_munmap;
}

+ err = -1;
evsel = perf_evlist__id2evsel(evlist, sample.id);
if (evsel == NULL) {
pr_debug("event with id %" PRIu64
@@ -137,16 +138,17 @@ int test__basic_mmap(void)
nr_events[evsel->idx]++;
}

+ err = 0;
list_for_each_entry(evsel, &evlist->entries, node) {
if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) {
pr_debug("expected %d %s events, got %d\n",
expected_nr_events[evsel->idx],
perf_evsel__name(evsel), nr_events[evsel->idx]);
+ err = -1;
goto out_munmap;
}
}

- err = 0;
out_munmap:
perf_evlist__munmap(evlist);
out_close_fd:
--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Dec 11, 2012, 6:00:03 PM12/11/12
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

In commit e2f4351 "perf ui/helpline: Introduce ui_helpline__vshow()" the
test for the browser used made ui_helpline__vshow() to be called only
for the GTK browser.

The TUI one then was not used and vfprintf(stderr, ...) was used
instead, making the TUI scroll the screen instead of just printing on
the last line.

Fix it by doing the proper check, that is to call ui_helpline__vshow to
be called for both the TUI and GTK browsers.

Cc: David Ahern <dsa...@gmail.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Jiri Olsa <jo...@redhat.com>
Cc: Mike Galbraith <efa...@gmx.de>
Cc: Namhyung Kim <namh...@gmail.com>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Stephane Eranian <era...@google.com>
Link: http://lkml.kernel.org/n/tip-iad0nw09x4...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/debug.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index 391c9a9..399e74c 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -23,7 +23,7 @@ int eprintf(int level, const char *fmt, ...)

if (verbose >= level) {
va_start(args, fmt);
- if (use_browser > 1)
+ if (use_browser >= 1)
ui_helpline__vshow(fmt, args);
else
ret = vfprintf(stderr, fmt, args);
--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Dec 11, 2012, 6:00:03 PM12/11/12
to
From: Namhyung Kim <namhyu...@lge.com>

Current perf build process checks various system configuration on
invocation to make. But this is not needed just for cleaning.

To do that, move some of python related variables out of conditional
since 'clean' target needs them. Normal path should not be affected by
this.

Signed-off-by: Namhyung Kim <namh...@kernel.org>
Cc: Ingo Molnar <mi...@kernel.org>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Link: http://lkml.kernel.org/r/1352867990-658-1-git...@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/Documentation/Makefile | 2 ++
tools/perf/Makefile | 28 ++++++++++++++++------------
2 files changed, 18 insertions(+), 12 deletions(-)

diff --git a/tools/perf/Documentation/Makefile b/tools/perf/Documentation/Makefile
index ef6d22e..f6e5901 100644
--- a/tools/perf/Documentation/Makefile
+++ b/tools/perf/Documentation/Makefile
@@ -222,10 +222,12 @@ install-pdf: pdf
#install-html: html
# '$(SHELL_PATH_SQ)' ./install-webdoc.sh $(DESTDIR)$(htmldir)

+ifneq ($(MAKECMDGOALS),clean)
$(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE
$(QUIET_SUBDIR0)../ $(QUIET_SUBDIR1) $(OUTPUT)PERF-VERSION-FILE

-include $(OUTPUT)PERF-VERSION-FILE
+endif

#
# Determine "include::" file references in asciidoc files.
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 8fca560..08da9fc 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -153,6 +153,7 @@ INSTALL = install
# explicitly what architecture to check for. Fix this up for yours..
SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__

+ifneq ($(MAKECMDGOALS),clean)
-include config/feature-tests.mak

ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -fstack-protector-all,-fstack-protector-all),y)
@@ -206,6 +207,7 @@ ifeq ($(call try-cc,$(SOURCE_BIONIC),$(CFLAGS),bionic),y)
EXTLIBS := $(filter-out -lpthread,$(EXTLIBS))
BASIC_CFLAGS += -I.
endif
+endif # MAKECMDGOALS != clean

# Guard against environment variables
BUILTIN_OBJS =
@@ -230,11 +232,19 @@ endif
LIBTRACEEVENT = $(TE_PATH)libtraceevent.a
TE_LIB := -L$(TE_PATH) -ltraceevent

+export LIBTRACEEVENT
+
+# python extension build directories
+PYTHON_EXTBUILD := $(OUTPUT)python_ext_build/
+PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/
+PYTHON_EXTBUILD_TMP := $(PYTHON_EXTBUILD)tmp/
+export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP
+
+python-clean := rm -rf $(PYTHON_EXTBUILD) $(OUTPUT)python/perf.so
+
PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources)
PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py

-export LIBTRACEEVENT
-
$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
$(QUIET_GEN)CFLAGS='$(BASIC_CFLAGS)' $(PYTHON_WORD) util/setup.py \
--quiet build_ext; \
@@ -514,6 +524,7 @@ PERFLIBS = $(LIB_FILE) $(LIBTRACEEVENT)
#
# Platform specific tweaks
#
+ifneq ($(MAKECMDGOALS),clean)

# We choose to avoid "if .. else if .. else .. endif endif"
# because maintaining the nesting to match is a pain. If
@@ -703,7 +714,7 @@ disable-python = $(eval $(disable-python_code))
define disable-python_code
BASIC_CFLAGS += -DNO_LIBPYTHON
$(if $(1),$(warning No $(1) was found))
- $(warning Python support won't be built)
+ $(warning Python support will not be built)
endef

override PYTHON := \
@@ -711,19 +722,10 @@ override PYTHON := \

ifndef PYTHON
$(call disable-python,python interpreter)
- python-clean :=
else

PYTHON_WORD := $(call shell-wordify,$(PYTHON))

- # python extension build directories
- PYTHON_EXTBUILD := $(OUTPUT)python_ext_build/
- PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/
- PYTHON_EXTBUILD_TMP := $(PYTHON_EXTBUILD)tmp/
- export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP
-
- python-clean := rm -rf $(PYTHON_EXTBUILD) $(OUTPUT)python/perf.so
-
ifdef NO_LIBPYTHON
$(call disable-python)
else
@@ -839,6 +841,8 @@ ifdef ASCIIDOC8
export ASCIIDOC8
endif

+endif # MAKECMDGOALS != clean
+
# Shell quote (do not use $(call) to accommodate ancient setups);

ETC_PERFCONFIG_SQ = $(subst ','\'',$(ETC_PERFCONFIG))
--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Dec 11, 2012, 6:00:03 PM12/11/12
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

When mmaping multiple events we need to find the right evsel that
matches an event in the ring buffer.

For that we need to set the PERF_FORMAT_ID bit in
perf_event_attr.read_format so that when we read the event fds we get
that id to then hash it and be able later to use perf_evlist__id2evsel
to find the right evsel.

We also need to set the PERF_SAMPLE_ID bit in
perf_event_attr.sample_type to ask for that id to be stashed in each
sample, so that we can demux it.

So add a perf_evsel__set_sample_id() method to do those two things in
one operation.

Cc: David Ahern <dsa...@gmail.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Jiri Olsa <jo...@redhat.com>
Cc: Mike Galbraith <efa...@gmx.de>
Cc: Namhyung Kim <namh...@gmail.com>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Stephane Eranian <era...@google.com>
Link: http://lkml.kernel.org/n/tip-1z4xcmbud3...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-top.c | 6 ++----
tools/perf/tests/mmap-basic.c | 3 +--
tools/perf/util/evsel.c | 6 ++++++
tools/perf/util/evsel.h | 2 ++
4 files changed, 11 insertions(+), 6 deletions(-)

diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 31a7c51..a306474 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -910,10 +910,8 @@ static void perf_top__start_counters(struct perf_top *top)
attr->sample_freq = top->freq;
}

- if (evlist->nr_entries > 1) {
- perf_evsel__set_sample_bit(counter, ID);
- attr->read_format |= PERF_FORMAT_ID;
- }
+ if (evlist->nr_entries > 1)
+ perf_evsel__set_sample_id(counter);

if (perf_target__has_cpu(&top->target))
perf_evsel__set_sample_bit(counter, CPU);
diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c
index 4743b6d..cdd5075 100644
--- a/tools/perf/tests/mmap-basic.c
+++ b/tools/perf/tests/mmap-basic.c
@@ -70,8 +70,7 @@ int test__basic_mmap(void)
}

evsels[i]->attr.wakeup_events = 1;
- evsels[i]->attr.read_format |= PERF_FORMAT_ID;
- perf_evsel__set_sample_bit(evsels[i], ID);
+ perf_evsel__set_sample_id(evsels[i]);

perf_evlist__add(evlist, evsels[i]);

diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index fc80f5a..9dde7e9 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -68,6 +68,12 @@ void __perf_evsel__reset_sample_bit(struct perf_evsel *evsel,
}
}

+void perf_evsel__set_sample_id(struct perf_evsel *evsel)
+{
+ perf_evsel__set_sample_bit(evsel, ID);
+ evsel->attr.read_format |= PERF_FORMAT_ID;
+}
+
void perf_evsel__init(struct perf_evsel *evsel,
struct perf_event_attr *attr, int idx)
{
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 7398539..5c08977 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -129,6 +129,8 @@ void __perf_evsel__reset_sample_bit(struct perf_evsel *evsel,
#define perf_evsel__reset_sample_bit(evsel, bit) \
__perf_evsel__reset_sample_bit(evsel, PERF_SAMPLE_##bit)

+void perf_evsel__set_sample_id(struct perf_evsel *evsel);
+
int perf_evsel__set_filter(struct perf_evsel *evsel, int ncpus, int nthreads,
const char *filter);

--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Dec 11, 2012, 6:00:03 PM12/11/12
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

Its all it uses and makes the parsing callback suitable for use by
'perf top', which will happen in a followup patch.

Cc: David Ahern <dsa...@gmail.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Jiri Olsa <jo...@redhat.com>
Cc: Mike Galbraith <efa...@gmx.de>
Cc: Namhyung Kim <namh...@gmail.com>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Stephane Eranian <era...@google.com>
Link: http://lkml.kernel.org/n/tip-wb9eti78bk...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-record.c | 24 +++++++++++-------------
1 file changed, 11 insertions(+), 13 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index fc4f080..d035040 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -868,11 +868,9 @@ static int get_stack_size(char *str, unsigned long *_size)
}
#endif /* LIBUNWIND_SUPPORT */

-static int
-parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg,
- int unset)
+static int parse_callchain_opt(const struct option *opt, const char *arg, int unset)
{
- struct perf_record *rec = (struct perf_record *)opt->value;
+ struct perf_record_opts *opts = opt->value;
char *tok, *name, *saveptr = NULL;
char *buf;
int ret = -1;
@@ -898,7 +896,7 @@ parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg,
/* Framepointer style */
if (!strncmp(name, "fp", sizeof("fp"))) {
if (!strtok_r(NULL, ",", &saveptr)) {
- rec->opts.call_graph = CALLCHAIN_FP;
+ opts->call_graph = CALLCHAIN_FP;
ret = 0;
} else
pr_err("callchain: No more arguments "
@@ -911,20 +909,20 @@ parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg,
const unsigned long default_stack_dump_size = 8192;

ret = 0;
- rec->opts.call_graph = CALLCHAIN_DWARF;
- rec->opts.stack_dump_size = default_stack_dump_size;
+ opts->call_graph = CALLCHAIN_DWARF;
+ opts->stack_dump_size = default_stack_dump_size;

tok = strtok_r(NULL, ",", &saveptr);
if (tok) {
unsigned long size = 0;

ret = get_stack_size(tok, &size);
- rec->opts.stack_dump_size = size;
+ opts->stack_dump_size = size;
}

if (!ret)
pr_debug("callchain: stack dump size %d\n",
- rec->opts.stack_dump_size);
+ opts->stack_dump_size);
#endif /* LIBUNWIND_SUPPORT */
} else {
pr_err("callchain: Unknown -g option "
@@ -937,7 +935,7 @@ parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg,
free(buf);

if (!ret)
- pr_debug("callchain: type %d\n", rec->opts.call_graph);
+ pr_debug("callchain: type %d\n", opts->call_graph);

return ret;
}
@@ -1021,9 +1019,9 @@ const struct option record_options[] = {
"number of mmap data pages"),
OPT_BOOLEAN(0, "group", &record.opts.group,
"put the counters into a counter group"),
- OPT_CALLBACK_DEFAULT('g', "call-graph", &record, "mode[,dump_size]",
- callchain_help, &parse_callchain_opt,
- "fp"),
+ OPT_CALLBACK_DEFAULT('g', "call-graph", &record.opts,
+ "mode[,dump_size]", callchain_help,
+ &parse_callchain_opt, "fp"),
OPT_INCR('v', "verbose", &verbose,
"be more verbose (show counter open errors, etc)"),
OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Dec 11, 2012, 6:00:03 PM12/11/12
to
From: Namhyung Kim <namhyu...@lge.com>

The perf session environment information was saved (so allocated) during
perf_session__open, but was not freed. As free(3) handles NULL pointer
input properly it won't cause a issue for writing modes - e.g. perf
record

Signed-off-by: Namhyung Kim <namh...@kernel.org>
Cc: Andi Kleen <an...@firstfloor.org>
Cc: Feng Tang <feng...@intel.com>
Cc: Ingo Molnar <mi...@kernel.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Link: http://lkml.kernel.org/r/1353472999-23042-1-gi...@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/session.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)

diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index ce6f511..d5fb607 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -204,11 +204,28 @@ static void perf_session__delete_threads(struct perf_session *session)
machine__delete_threads(&session->host_machine);
}

+static void perf_session_env__delete(struct perf_session_env *env)
+{
+ free(env->hostname);
+ free(env->os_release);
+ free(env->version);
+ free(env->arch);
+ free(env->cpu_desc);
+ free(env->cpuid);
+
+ free(env->cmdline);
+ free(env->sibling_cores);
+ free(env->sibling_threads);
+ free(env->numa_nodes);
+ free(env->pmu_mappings);
+}
+
void perf_session__delete(struct perf_session *self)
{
perf_session__destroy_kernel_maps(self);
perf_session__delete_dead_threads(self);
perf_session__delete_threads(self);
+ perf_session_env__delete(&self->header.env);
machine__exit(&self->host_machine);
close(self->fd);
free(self);
--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Dec 11, 2012, 6:00:03 PM12/11/12
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

So that we can print all the details when debugging other tools,
when we have just evlists and evsels, not a perf.data file.

Cc: David Ahern <dsa...@gmail.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Jiri Olsa <jo...@redhat.com>
Cc: Mike Galbraith <efa...@gmx.de>
Cc: Namhyung Kim <namh...@gmail.com>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Stephane Eranian <era...@google.com>
Link: http://lkml.kernel.org/n/tip-mktq5fy2h5...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-evlist.c | 81 ++-----------------------------------------
tools/perf/util/evsel.c | 77 ++++++++++++++++++++++++++++++++++++++++
tools/perf/util/evsel.h | 8 +++++
3 files changed, 87 insertions(+), 79 deletions(-)

diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
index c20f1dc..1312a5e 100644
--- a/tools/perf/builtin-evlist.c
+++ b/tools/perf/builtin-evlist.c
@@ -15,39 +15,6 @@
#include "util/parse-options.h"
#include "util/session.h"

-struct perf_attr_details {
- bool freq;
- bool verbose;
-};
-
-static int comma_printf(bool *first, const char *fmt, ...)
-{
- va_list args;
- int ret = 0;
-
- if (!*first) {
- ret += printf(",");
- } else {
- ret += printf(":");
- *first = false;
- }
-
- va_start(args, fmt);
- ret += vprintf(fmt, args);
- va_end(args);
- return ret;
-}
-
-static int __if_print(bool *first, const char *field, u64 value)
-{
- if (value == 0)
- return 0;
-
- return comma_printf(first, " %s: %" PRIu64, field, value);
-}
-
-#define if_print(field) __if_print(&first, #field, pos->attr.field)
-
static int __cmd_evlist(const char *file_name, struct perf_attr_details *details)
{
struct perf_session *session;
@@ -57,52 +24,8 @@ static int __cmd_evlist(const char *file_name, struct perf_attr_details *details
if (session == NULL)
return -ENOMEM;

- list_for_each_entry(pos, &session->evlist->entries, node) {
- bool first = true;
-
- printf("%s", perf_evsel__name(pos));
-
- if (details->verbose || details->freq) {
- comma_printf(&first, " sample_freq=%" PRIu64,
- (u64)pos->attr.sample_freq);
- }
-
- if (details->verbose) {
- if_print(type);
- if_print(config);
- if_print(config1);
- if_print(config2);
- if_print(size);
- if_print(sample_type);
- if_print(read_format);
- if_print(disabled);
- if_print(inherit);
- if_print(pinned);
- if_print(exclusive);
- if_print(exclude_user);
- if_print(exclude_kernel);
- if_print(exclude_hv);
- if_print(exclude_idle);
- if_print(mmap);
- if_print(comm);
- if_print(freq);
- if_print(inherit_stat);
- if_print(enable_on_exec);
- if_print(task);
- if_print(watermark);
- if_print(precise_ip);
- if_print(mmap_data);
- if_print(sample_id_all);
- if_print(exclude_host);
- if_print(exclude_guest);
- if_print(__reserved_1);
- if_print(wakeup_events);
- if_print(bp_type);
- if_print(branch_sample_type);
- }
-
- putchar('\n');
- }
+ list_for_each_entry(pos, &session->evlist->entries, node)
+ perf_evsel__fprintf(pos, details, stdout);

perf_session__delete(session);
return 0;
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 2492d32..643df4b 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -1228,3 +1228,80 @@ u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample,

return 0;
}
+
+static int comma_fprintf(FILE *fp, bool *first, const char *fmt, ...)
+{
+ va_list args;
+ int ret = 0;
+
+ if (!*first) {
+ ret += fprintf(fp, ",");
+ } else {
+ ret += fprintf(fp, ":");
+ *first = false;
+ }
+
+ va_start(args, fmt);
+ ret += vfprintf(fp, fmt, args);
+ va_end(args);
+ return ret;
+}
+
+static int __if_fprintf(FILE *fp, bool *first, const char *field, u64 value)
+{
+ if (value == 0)
+ return 0;
+
+ return comma_fprintf(fp, first, " %s: %" PRIu64, field, value);
+}
+
+#define if_print(field) printed += __if_fprintf(fp, &first, #field, evsel->attr.field)
+
+int perf_evsel__fprintf(struct perf_evsel *evsel,
+ struct perf_attr_details *details, FILE *fp)
+{
+ bool first = true;
+ int printed = fprintf(fp, "%s", perf_evsel__name(evsel));
+
+ if (details->verbose || details->freq) {
+ printed += comma_fprintf(fp, &first, " sample_freq=%" PRIu64,
+ (u64)evsel->attr.sample_freq);
+ }
+
+ if (details->verbose) {
+ if_print(type);
+ if_print(config);
+ if_print(config1);
+ if_print(config2);
+ if_print(size);
+ if_print(sample_type);
+ if_print(read_format);
+ if_print(disabled);
+ if_print(inherit);
+ if_print(pinned);
+ if_print(exclusive);
+ if_print(exclude_user);
+ if_print(exclude_kernel);
+ if_print(exclude_hv);
+ if_print(exclude_idle);
+ if_print(mmap);
+ if_print(comm);
+ if_print(freq);
+ if_print(inherit_stat);
+ if_print(enable_on_exec);
+ if_print(task);
+ if_print(watermark);
+ if_print(precise_ip);
+ if_print(mmap_data);
+ if_print(sample_id_all);
+ if_print(exclude_host);
+ if_print(exclude_guest);
+ if_print(__reserved_1);
+ if_print(wakeup_events);
+ if_print(bp_type);
+ if_print(branch_sample_type);
+ }
+
+ fputc('\n', fp);
+ return ++printed;
+}
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 5c08977..9cb8a02 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -243,4 +243,12 @@ static inline bool perf_evsel__is_group_leader(const struct perf_evsel *evsel)
{
return evsel->leader == evsel;
}
+
+struct perf_attr_details {
+ bool freq;
+ bool verbose;
+};
+
+int perf_evsel__fprintf(struct perf_evsel *evsel,
+ struct perf_attr_details *details, FILE *fp);
#endif /* __PERF_EVSEL_H */
--
1.7.9.2.358.g22243

Arnaldo Carvalho de Melo

unread,
Dec 11, 2012, 6:00:04 PM12/11/12
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

Will be used by perf top, that will first setup the symbol system to
deal with callchains and then call these routines to ask the kernel
for callchains.

Cc: David Ahern <dsa...@gmail.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Jiri Olsa <jo...@redhat.com>
Cc: Mike Galbraith <efa...@gmx.de>
Cc: Namhyung Kim <namh...@gmail.com>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Stephane Eranian <era...@google.com>
Link: http://lkml.kernel.org/n/tip-jg0dh8rmlx...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-record.c | 11 ++++++-----
tools/perf/util/callchain.h | 5 +++++
2 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index d035040..028de72 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -868,7 +868,8 @@ static int get_stack_size(char *str, unsigned long *_size)
}
#endif /* LIBUNWIND_SUPPORT */

-static int parse_callchain_opt(const struct option *opt, const char *arg, int unset)
+int record_parse_callchain_opt(const struct option *opt,
+ const char *arg, int unset)
{
struct perf_record_opts *opts = opt->value;
char *tok, *name, *saveptr = NULL;
@@ -973,9 +974,9 @@ static struct perf_record record = {
#define CALLCHAIN_HELP "do call-graph (stack chain/backtrace) recording: "

#ifdef LIBUNWIND_SUPPORT
-static const char callchain_help[] = CALLCHAIN_HELP "[fp] dwarf";
+const char record_callchain_help[] = CALLCHAIN_HELP "[fp] dwarf";
#else
-static const char callchain_help[] = CALLCHAIN_HELP "[fp]";
+const char record_callchain_help[] = CALLCHAIN_HELP "[fp]";
#endif

/*
@@ -1020,8 +1021,8 @@ const struct option record_options[] = {
OPT_BOOLEAN(0, "group", &record.opts.group,
"put the counters into a counter group"),
OPT_CALLBACK_DEFAULT('g', "call-graph", &record.opts,
- "mode[,dump_size]", callchain_help,
- &parse_callchain_opt, "fp"),
+ "mode[,dump_size]", record_callchain_help,
+ &record_parse_callchain_opt, "fp"),
OPT_INCR('v', "verbose", &verbose,
"be more verbose (show counter open errors, etc)"),
OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index eb34057..3ee9f67 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -143,4 +143,9 @@ static inline void callchain_cursor_advance(struct callchain_cursor *cursor)
cursor->curr = cursor->curr->next;
cursor->pos++;
}
+
+struct option;
+
+int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset);
+extern const char record_callchain_help[];
#endif /* __PERF_CALLCHAIN_H */

Arnaldo Carvalho de Melo

unread,
Dec 11, 2012, 6:00:04 PM12/11/12
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

Before those fields showed just a number, now it decodes each bit:

[root@sandy linux]# perf evlist -v
cycles: sample_freq=4000, size: 96, sample_type: IP|TID|TIME|CPU|PERIOD, read_format: TOTAL_TIME_ENABLED|TOTAL_TIME_RUNNING|ID, disabled: 1, inherit: 1, mmap: 1, comm: 1, freq: 1, sample_id_all: 1, exclude_guest: 1

Cc: David Ahern <dsa...@gmail.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Jiri Olsa <jo...@redhat.com>
Cc: Mike Galbraith <efa...@gmx.de>
Cc: Namhyung Kim <namh...@gmail.com>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Stephane Eranian <era...@google.com>
Link: http://lkml.kernel.org/n/tip-64ezdtiijo...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/evsel.c | 52 +++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 50 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 643df4b..7a2a3dc 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -1257,6 +1257,53 @@ static int __if_fprintf(FILE *fp, bool *first, const char *field, u64 value)

#define if_print(field) printed += __if_fprintf(fp, &first, #field, evsel->attr.field)

+struct bit_names {
+ int bit;
+ const char *name;
+};
+
+static int bits__fprintf(FILE *fp, const char *field, u64 value,
+ struct bit_names *bits, bool *first)
+{
+ int i = 0, printed = comma_fprintf(fp, first, " %s: ", field);
+ bool first_bit = true;
+
+ do {
+ if (value & bits[i].bit) {
+ printed += fprintf(fp, "%s%s", first_bit ? "" : "|", bits[i].name);
+ first_bit = false;
+ }
+ } while (bits[++i].name != NULL);
+
+ return printed;
+}
+
+static int sample_type__fprintf(FILE *fp, bool *first, u64 value)
+{
+#define bit_name(n) { PERF_SAMPLE_##n, #n }
+ struct bit_names bits[] = {
+ bit_name(IP), bit_name(TID), bit_name(TIME), bit_name(ADDR),
+ bit_name(READ), bit_name(CALLCHAIN), bit_name(ID), bit_name(CPU),
+ bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW),
+ bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER),
+ { .name = NULL, }
+ };
+#undef bit_name
+ return bits__fprintf(fp, "sample_type", value, bits, first);
+}
+
+static int read_format__fprintf(FILE *fp, bool *first, u64 value)
+{
+#define bit_name(n) { PERF_FORMAT_##n, #n }
+ struct bit_names bits[] = {
+ bit_name(TOTAL_TIME_ENABLED), bit_name(TOTAL_TIME_RUNNING),
+ bit_name(ID), bit_name(GROUP),
+ { .name = NULL, }
+ };
+#undef bit_name
+ return bits__fprintf(fp, "read_format", value, bits, first);
+}
+
int perf_evsel__fprintf(struct perf_evsel *evsel,
struct perf_attr_details *details, FILE *fp)
{
@@ -1274,8 +1321,9 @@ int perf_evsel__fprintf(struct perf_evsel *evsel,
if_print(config1);
if_print(config2);
if_print(size);
- if_print(sample_type);
- if_print(read_format);
+ printed += sample_type__fprintf(fp, &first, evsel->attr.sample_type);
+ if (evsel->attr.read_format)
+ printed += read_format__fprintf(fp, &first, evsel->attr.read_format);
if_print(disabled);
if_print(inherit);
if_print(pinned);

Arnaldo Carvalho de Melo

unread,
Dec 11, 2012, 6:00:04 PM12/11/12
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

This is needed, so far, just in 'perf stat', to scale counters, so don't
unconditionally ask for them in the perf_evsel__config() method.

Cc: David Ahern <dsa...@gmail.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Jiri Olsa <jo...@redhat.com>
Cc: Mike Galbraith <efa...@gmx.de>
Cc: Namhyung Kim <namh...@gmail.com>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Stephane Eranian <era...@google.com>
Link: http://lkml.kernel.org/n/tip-ujpujgscq2...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/tests/attr/base-record | 2 +-
tools/perf/tests/attr/test-record-group | 4 ++--
tools/perf/tests/attr/test-record-group1 | 4 ++--
tools/perf/util/evsel.c | 2 --
4 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/tools/perf/tests/attr/base-record b/tools/perf/tests/attr/base-record
index f9d0464..5bc3880 100644
--- a/tools/perf/tests/attr/base-record
+++ b/tools/perf/tests/attr/base-record
@@ -7,7 +7,7 @@ size=96
config=0
sample_period=4000
sample_type=263
-read_format=3
+read_format=0
disabled=1
inherit=1
pinned=0
diff --git a/tools/perf/tests/attr/test-record-group b/tools/perf/tests/attr/test-record-group
index 0df34ca..57739ca 100644
--- a/tools/perf/tests/attr/test-record-group
+++ b/tools/perf/tests/attr/test-record-group
@@ -6,14 +6,14 @@ args = --group -e cycles,instructions kill >/dev/null 2>&1
fd=1
group_fd=-1
sample_type=327
-read_format=7
+read_format=4

[event-2:base-record]
fd=2
group_fd=1
config=1
sample_type=327
-read_format=7
+read_format=4
mmap=0
comm=0
enable_on_exec=0
diff --git a/tools/perf/tests/attr/test-record-group1 b/tools/perf/tests/attr/test-record-group1
index 18bd926..4d688a1 100644
--- a/tools/perf/tests/attr/test-record-group1
+++ b/tools/perf/tests/attr/test-record-group1
@@ -6,7 +6,7 @@ args = -e '{cycles,instructions}' kill >/tmp/krava 2>&1
fd=1
group_fd=-1
sample_type=327
-read_format=7
+read_format=4

[event-2:base-record]
fd=2
@@ -14,7 +14,7 @@ group_fd=1
type=0
config=1
sample_type=327
-read_format=7
+read_format=4
mmap=0
comm=0
enable_on_exec=0
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index e62d3ae..2492d32 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -465,8 +465,6 @@ void perf_evsel__config(struct perf_evsel *evsel,

attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1;
attr->inherit = !opts->no_inherit;
- attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
- PERF_FORMAT_TOTAL_TIME_RUNNING;

perf_evsel__set_sample_bit(evsel, IP);
perf_evsel__set_sample_bit(evsel, TID);

Arnaldo Carvalho de Melo

unread,
Dec 11, 2012, 6:00:04 PM12/11/12
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

Instead make perf_evlist__confir_attrs use perf_evsel__set_sample_id()
when having more than one event, that way only if we have multiple
events we'll ask to have the event ids returned when we read its file
descriptors.

Cc: David Ahern <dsa...@gmail.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Jiri Olsa <jo...@redhat.com>
Cc: Mike Galbraith <efa...@gmx.de>
Cc: Namhyung Kim <namh...@gmail.com>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Stephane Eranian <era...@google.com>
Link: http://lkml.kernel.org/n/tip-xuho5hrrxy...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/tests/attr/base-record | 2 +-
tools/perf/tests/attr/test-record-group | 2 ++
tools/perf/tests/attr/test-record-group1 | 2 ++
tools/perf/util/evlist.c | 2 +-
tools/perf/util/evsel.c | 3 +--
5 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/tools/perf/tests/attr/base-record b/tools/perf/tests/attr/base-record
index f1485d8..f9d0464 100644
--- a/tools/perf/tests/attr/base-record
+++ b/tools/perf/tests/attr/base-record
@@ -7,7 +7,7 @@ size=96
config=0
sample_period=4000
sample_type=263
-read_format=7
+read_format=3
disabled=1
inherit=1
pinned=0
diff --git a/tools/perf/tests/attr/test-record-group b/tools/perf/tests/attr/test-record-group
index a6599e9..0df34ca 100644
--- a/tools/perf/tests/attr/test-record-group
+++ b/tools/perf/tests/attr/test-record-group
@@ -6,12 +6,14 @@ args = --group -e cycles,instructions kill >/dev/null 2>&1
fd=1
group_fd=-1
sample_type=327
+read_format=7

[event-2:base-record]
fd=2
group_fd=1
config=1
sample_type=327
+read_format=7
mmap=0
comm=0
enable_on_exec=0
diff --git a/tools/perf/tests/attr/test-record-group1 b/tools/perf/tests/attr/test-record-group1
index 5a8359d..18bd926 100644
--- a/tools/perf/tests/attr/test-record-group1
+++ b/tools/perf/tests/attr/test-record-group1
@@ -6,6 +6,7 @@ args = -e '{cycles,instructions}' kill >/tmp/krava 2>&1
fd=1
group_fd=-1
sample_type=327
+read_format=7

[event-2:base-record]
fd=2
@@ -13,6 +14,7 @@ group_fd=1
type=0
config=1
sample_type=327
+read_format=7
mmap=0
comm=0
enable_on_exec=0
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 2655659..5a0878d 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -61,7 +61,7 @@ void perf_evlist__config_attrs(struct perf_evlist *evlist,
perf_evsel__config(evsel, opts);

if (evlist->nr_entries > 1)
- perf_evsel__set_sample_bit(evsel, ID);
+ perf_evsel__set_sample_id(evsel);
}
}

diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 9dde7e9..e62d3ae 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -466,8 +466,7 @@ void perf_evsel__config(struct perf_evsel *evsel,
attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1;
attr->inherit = !opts->no_inherit;
attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
- PERF_FORMAT_TOTAL_TIME_RUNNING |
- PERF_FORMAT_ID;
+ PERF_FORMAT_TOTAL_TIME_RUNNING;

Arnaldo Carvalho de Melo

unread,
Dec 11, 2012, 6:00:04 PM12/11/12
to
From: Stephane Eranian <era...@google.com>

Was ignoring the dso type (function vs. variable) and was therefore
printing bogus information.

Signed-off-by: Stephane Eranian <era...@google.com>
Cc: Ingo Molnar <mi...@elte.hu>
Cc: Namhyung Kim <namhyu...@lge.com>
Cc: Peter Zijlstra <pet...@infradead.org>
Link: http://lkml.kernel.org/r/20121120095101.GA5939@quad
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/dso.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index d6d9a46..be43785 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -583,7 +583,7 @@ size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp)
if (dso->short_name != dso->long_name)
ret += fprintf(fp, "%s, ", dso->long_name);
ret += fprintf(fp, "%s, %sloaded, ", map_type__name[type],
- dso->loaded ? "" : "NOT ");
+ dso__loaded(dso, type) ? "" : "NOT ");
ret += dso__fprintf_buildid(dso, fp);
ret += fprintf(fp, ")\n");
for (nd = rb_first(&dso->symbols[type]); nd; nd = rb_next(nd)) {

Arnaldo Carvalho de Melo

unread,
Dec 11, 2012, 6:00:04 PM12/11/12
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

I.e. before we try to use it as a perf.data file by calling
perf_session__new, otherwise we lose the feature that shows the
build id for the given ELF file, this one:

[root@sandy redhat-perfdata-mtech-15]# perf buildid-list -i /root/.debug/.build-id/97/54896de655b6ac088ec2bf5113b35c06f72709
9754896de655b6ac088ec2bf5113b35c06f72709
[root@sandy redhat-perfdata-mtech-15]# perf buildid-list -i /lib/libc-2.12.so
38adaeff4f7c21899b13b28c1a2e6c199ca4c744
[root@sandy redhat-perfdata-mtech-15]#

Regression introduced in:

efad1415 "perf report: Accept fifos as input file"

Cc: David Ahern <dsa...@gmail.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Jiri Olsa <jo...@redhat.com>
Cc: Mike Galbraith <efa...@gmx.de>
Cc: Namhyung Kim <namh...@gmail.com>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Robert Richter <robert....@amd.com>
Cc: Stephane Eranian <era...@google.com>
Link: http://lkml.kernel.org/n/tip-3ktgyg83fw...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-buildid-list.c | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index a82d99f..4c770d2 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -49,18 +49,16 @@ static int perf_session__list_build_ids(bool force, bool with_hits)
struct perf_session *session;

symbol__elf_init();
-
- session = perf_session__new(input_name, O_RDONLY, force, false,
- &build_id__mark_dso_hit_ops);
- if (session == NULL)
- return -1;
-
/*
* See if this is an ELF file first:
*/
- if (filename__fprintf_build_id(session->filename, stdout))
+ if (filename__fprintf_build_id(input_name, stdout))
goto out;

+ session = perf_session__new(input_name, O_RDONLY, force, false,
+ &build_id__mark_dso_hit_ops);
+ if (session == NULL)
+ return -1;
/*
* in pipe-mode, the only way to get the buildids is to parse
* the record stream. Buildids are stored as RECORD_HEADER_BUILD_ID
@@ -69,8 +67,8 @@ static int perf_session__list_build_ids(bool force, bool with_hits)
perf_session__process_events(session, &build_id__mark_dso_hit_ops);

perf_session__fprintf_dsos_buildid(session, stdout, with_hits);
-out:
perf_session__delete(session);
+out:
return 0;

Arnaldo Carvalho de Melo

unread,
Dec 11, 2012, 6:00:04 PM12/11/12
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

Removing one trace_event__id function, not used anymore.

Cc: David Ahern <dsa...@gmail.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Jiri Olsa <jo...@redhat.com>
Cc: Mike Galbraith <efa...@gmx.de>
Cc: Namhyung Kim <namh...@gmail.com>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Stephane Eranian <era...@google.com>
Link: http://lkml.kernel.org/n/tip-13p2ov2rg1...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>

Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/Makefile | 1 -
tools/perf/tests/mmap-basic.c | 37 +++++++++---------------------
tools/perf/tests/open-syscall-all-cpus.c | 18 +++------------
tools/perf/tests/open-syscall.c | 17 +++-----------
tools/perf/tests/tests.h | 3 ---
tools/perf/tests/util.c | 30 ------------------------
6 files changed, 17 insertions(+), 89 deletions(-)
delete mode 100644 tools/perf/tests/util.c

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 2a07b95..10aa24c 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -487,7 +487,6 @@ LIB_OBJS += $(OUTPUT)tests/rdpmc.o
LIB_OBJS += $(OUTPUT)tests/evsel-roundtrip-name.o
LIB_OBJS += $(OUTPUT)tests/evsel-tp-sched.o
LIB_OBJS += $(OUTPUT)tests/pmu.o
-LIB_OBJS += $(OUTPUT)tests/util.o

BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c
index 8682ecf..4743b6d 100644
--- a/tools/perf/tests/mmap-basic.c
+++ b/tools/perf/tests/mmap-basic.c
@@ -22,36 +22,16 @@ int test__basic_mmap(void)
struct thread_map *threads;
struct cpu_map *cpus;
struct perf_evlist *evlist;
- struct perf_event_attr attr = {
- .type = PERF_TYPE_TRACEPOINT,
- .read_format = PERF_FORMAT_ID,
- .sample_type = PERF_SAMPLE_ID,
- .watermark = 0,
- };
cpu_set_t cpu_set;
const char *syscall_names[] = { "getsid", "getppid", "getpgrp",
"getpgid", };
pid_t (*syscalls[])(void) = { (void *)getsid, getppid, getpgrp,
(void*)getpgid };
#define nsyscalls ARRAY_SIZE(syscall_names)
- int ids[nsyscalls];
unsigned int nr_events[nsyscalls],
expected_nr_events[nsyscalls], i, j;
struct perf_evsel *evsels[nsyscalls], *evsel;

- for (i = 0; i < nsyscalls; ++i) {
- char name[64];
-
- snprintf(name, sizeof(name), "sys_enter_%s", syscall_names[i]);
- ids[i] = trace_event__id(name);
- if (ids[i] < 0) {
- pr_debug("Is debugfs mounted on /sys/kernel/debug?\n");
- return -1;
- }
- nr_events[i] = 0;
- expected_nr_events[i] = random() % 257;
- }
-
threads = thread_map__new(-1, getpid(), UINT_MAX);
if (threads == NULL) {
pr_debug("thread_map__new\n");
@@ -79,18 +59,20 @@ int test__basic_mmap(void)
goto out_free_cpus;
}

- /* anonymous union fields, can't be initialized above */
- attr.wakeup_events = 1;
- attr.sample_period = 1;
-
for (i = 0; i < nsyscalls; ++i) {
- attr.config = ids[i];
- evsels[i] = perf_evsel__new(&attr, i);
+ char name[64];
+
+ snprintf(name, sizeof(name), "sys_enter_%s", syscall_names[i]);
+ evsels[i] = perf_evsel__newtp("syscalls", name, i);
if (evsels[i] == NULL) {
pr_debug("perf_evsel__new\n");
goto out_free_evlist;
}

+ evsels[i]->attr.wakeup_events = 1;
+ evsels[i]->attr.read_format |= PERF_FORMAT_ID;
+ perf_evsel__set_sample_bit(evsels[i], ID);
+
perf_evlist__add(evlist, evsels[i]);

if (perf_evsel__open(evsels[i], cpus, threads) < 0) {
@@ -99,6 +81,9 @@ int test__basic_mmap(void)
strerror(errno));
goto out_close_fd;
}
+
+ nr_events[i] = 0;
+ expected_nr_events[i] = 1 + rand() % 127;
}

if (perf_evlist__mmap(evlist, 128, true) < 0) {
diff --git a/tools/perf/tests/open-syscall-all-cpus.c b/tools/perf/tests/open-syscall-all-cpus.c
index 31072ab..9b920a0 100644
--- a/tools/perf/tests/open-syscall-all-cpus.c
+++ b/tools/perf/tests/open-syscall-all-cpus.c
@@ -7,20 +7,12 @@
int test__open_syscall_event_on_all_cpus(void)
{
int err = -1, fd, cpu;
- struct thread_map *threads;
struct cpu_map *cpus;
struct perf_evsel *evsel;
- struct perf_event_attr attr;
unsigned int nr_open_calls = 111, i;
cpu_set_t cpu_set;
- int id = trace_event__id("sys_enter_open");
+ struct thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX);

- if (id < 0) {
- pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
- return -1;
- }
-
- threads = thread_map__new(-1, getpid(), UINT_MAX);
if (threads == NULL) {
pr_debug("thread_map__new\n");
return -1;
@@ -32,15 +24,11 @@ int test__open_syscall_event_on_all_cpus(void)
goto out_thread_map_delete;
}

-
CPU_ZERO(&cpu_set);

- memset(&attr, 0, sizeof(attr));
- attr.type = PERF_TYPE_TRACEPOINT;
- attr.config = id;
- evsel = perf_evsel__new(&attr, 0);
+ evsel = perf_evsel__newtp("syscalls", "sys_enter_open", 0);
if (evsel == NULL) {
- pr_debug("perf_evsel__new\n");
+ pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
goto out_thread_map_delete;
}

diff --git a/tools/perf/tests/open-syscall.c b/tools/perf/tests/open-syscall.c
index 98be8b5..befc067 100644
--- a/tools/perf/tests/open-syscall.c
+++ b/tools/perf/tests/open-syscall.c
@@ -6,29 +6,18 @@
int test__open_syscall_event(void)
{
int err = -1, fd;
- struct thread_map *threads;
struct perf_evsel *evsel;
- struct perf_event_attr attr;
unsigned int nr_open_calls = 111, i;
- int id = trace_event__id("sys_enter_open");
+ struct thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX);

- if (id < 0) {
- pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
- return -1;
- }
-
- threads = thread_map__new(-1, getpid(), UINT_MAX);
if (threads == NULL) {
pr_debug("thread_map__new\n");
return -1;
}

- memset(&attr, 0, sizeof(attr));
- attr.type = PERF_TYPE_TRACEPOINT;
- attr.config = id;
- evsel = perf_evsel__new(&attr, 0);
+ evsel = perf_evsel__newtp("syscalls", "sys_enter_open", 0);
if (evsel == NULL) {
- pr_debug("perf_evsel__new\n");
+ pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
goto out_thread_map_delete;
}

diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index fc121ed..0fd94657 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -16,7 +16,4 @@ int test__attr(void);
int test__dso_data(void);
int test__parse_events(void);

-/* Util */
-int trace_event__id(const char *evname);
-
#endif /* TESTS_H */
diff --git a/tools/perf/tests/util.c b/tools/perf/tests/util.c
deleted file mode 100644
index 748f2e8..0000000
--- a/tools/perf/tests/util.c
+++ /dev/null
@@ -1,30 +0,0 @@
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include "tests.h"
-#include "debugfs.h"
-
-int trace_event__id(const char *evname)
-{
- char *filename;
- int err = -1, fd;
-
- if (asprintf(&filename,
- "%s/syscalls/%s/id",
- tracing_events_path, evname) < 0)
- return -1;
-
- 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;
-}

Arnaldo Carvalho de Melo

unread,
Dec 11, 2012, 6:00:04 PM12/11/12
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

Since we need to ensure the leader is set before configuring the
evsel perf_event_attrs.

Reducing the boilerplate needed by tools, helping, for instance,
'perf trace', that wasn't setting the leader.

Cc: David Ahern <dsa...@gmail.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Jiri Olsa <jo...@redhat.com>
Cc: Mike Galbraith <efa...@gmx.de>
Cc: Namhyung Kim <namh...@gmail.com>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Stephane Eranian <era...@google.com>
Link: http://lkml.kernel.org/n/tip-22shm0ptkc...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-record.c | 9 +--------
tools/perf/builtin-trace.c | 2 +-
tools/perf/tests/perf-record.c | 2 +-
tools/perf/util/evlist.c | 10 ++++++++--
tools/perf/util/evlist.h | 4 ++--
5 files changed, 13 insertions(+), 14 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 0be6605..fc4f080 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -230,14 +230,7 @@ static int perf_record__open(struct perf_record *rec)
struct perf_record_opts *opts = &rec->opts;
int rc = 0;

- /*
- * Set the evsel leader links before we configure attributes,
- * since some might depend on this info.
- */
- if (opts->group)
- perf_evlist__set_leader(evlist);
-
- perf_evlist__config_attrs(evlist, opts);
+ perf_evlist__config(evlist, opts);

list_for_each_entry(pos, &evlist->entries, node) {
struct perf_event_attr *attr = &pos->attr;
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 7932ffa..d222d7f 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -455,7 +455,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
goto out_delete_evlist;
}

- perf_evlist__config_attrs(evlist, &trace->opts);
+ perf_evlist__config(evlist, &trace->opts);

signal(SIGCHLD, sig_handler);
signal(SIGINT, sig_handler);
diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c
index 5902772..6ea66cf 100644
--- a/tools/perf/tests/perf-record.c
+++ b/tools/perf/tests/perf-record.c
@@ -106,7 +106,7 @@ int test__PERF_RECORD(void)
perf_evsel__set_sample_bit(evsel, CPU);
perf_evsel__set_sample_bit(evsel, TID);
perf_evsel__set_sample_bit(evsel, TIME);
- perf_evlist__config_attrs(evlist, &opts);
+ perf_evlist__config(evlist, &opts);

err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask);
if (err < 0) {
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 5a0878d..dc8aee9 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -49,10 +49,16 @@ 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)
+void perf_evlist__config(struct perf_evlist *evlist,
+ struct perf_record_opts *opts)
{
struct perf_evsel *evsel;
+ /*
+ * Set the evsel leader links before we configure attributes,
+ * since some might depend on this info.
+ */
+ if (opts->group)
+ perf_evlist__set_leader(evlist);

if (evlist->cpus->map[0] < 0)
opts->no_inherit = true;
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 56003f7..457e235 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -76,8 +76,8 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *self, int idx);

int perf_evlist__open(struct perf_evlist *evlist);

-void perf_evlist__config_attrs(struct perf_evlist *evlist,
- struct perf_record_opts *opts);
+void perf_evlist__config(struct perf_evlist *evlist,
+ struct perf_record_opts *opts);

int perf_evlist__prepare_workload(struct perf_evlist *evlist,
struct perf_record_opts *opts,

Arnaldo Carvalho de Melo

unread,
Dec 11, 2012, 6:00:04 PM12/11/12
to
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

Using struct perf_record_opts to specify how to configure the evsel
perf_event_attrs.

This gets top closer to record in the way it sets up evsels, with the
aim of sharing more and more to the point that both will be a single
utility.

In this direction top now uses the same callchain option parsing as
record and that brings DWARF callchains to top, something that was
already available for record.

Cc: David Ahern <dsa...@gmail.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Jiri Olsa <jo...@redhat.com>
Cc: Mike Galbraith <efa...@gmx.de>
Cc: Namhyung Kim <namh...@gmail.com>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Stephane Eranian <era...@google.com>
Link: http://lkml.kernel.org/n/tip-u03o0bsrqc...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/Documentation/perf-top.txt | 2 +-
tools/perf/builtin-top.c | 204 +++++++++++----------------------
tools/perf/util/top.c | 22 ++--
tools/perf/util/top.h | 8 +-
4 files changed, 79 insertions(+), 157 deletions(-)

diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index 5b80d84..a414bc9 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -60,7 +60,7 @@ Default is to monitor all CPUS.

-i::
--inherit::
- Child tasks inherit counters, only makes sens with -p option.
+ Child tasks do not inherit counters.

-k <path>::
--vmlinux=<path>::
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index a306474..b7d2ea6 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -596,7 +596,7 @@ static void *display_thread_tui(void *arg)
* via --uid.
*/
list_for_each_entry(pos, &top->evlist->entries, node)
- pos->hists.uid_filter_str = top->target.uid_str;
+ pos->hists.uid_filter_str = top->record_opts.target.uid_str;

perf_evlist__tui_browse_hists(top->evlist, help, &hbt,
&top->session->header.env);
@@ -894,34 +894,13 @@ static void perf_top__start_counters(struct perf_top *top)
{
struct perf_evsel *counter;
struct perf_evlist *evlist = top->evlist;
+ struct perf_record_opts *opts = &top->record_opts;

- if (top->group)
- perf_evlist__set_leader(evlist);
+ perf_evlist__config(evlist, opts);

list_for_each_entry(counter, &evlist->entries, node) {
struct perf_event_attr *attr = &counter->attr;

- perf_evsel__set_sample_bit(counter, IP);
- perf_evsel__set_sample_bit(counter, TID);
-
- if (top->freq) {
- perf_evsel__set_sample_bit(counter, PERIOD);
- attr->freq = 1;
- attr->sample_freq = top->freq;
- }
-
- if (evlist->nr_entries > 1)
- perf_evsel__set_sample_id(counter);
-
- if (perf_target__has_cpu(&top->target))
- perf_evsel__set_sample_bit(counter, CPU);
-
- if (symbol_conf.use_callchain)
- perf_evsel__set_sample_bit(counter, CALLCHAIN);
-
- attr->mmap = 1;
- attr->comm = 1;
- attr->inherit = top->inherit;
fallback_missing_features:
if (top->exclude_guest_missing)
attr->exclude_guest = attr->exclude_host = 0;
@@ -995,7 +974,7 @@ try_again:
}
}

- if (perf_evlist__mmap(evlist, top->mmap_pages, false) < 0) {
+ if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) {
ui__error("Failed to mmap with %d (%s)\n",
errno, strerror(errno));
goto out_err;
@@ -1015,7 +994,7 @@ static int perf_top__setup_sample_type(struct perf_top *top)
ui__error("Selected -g but \"sym\" not present in --sort/-s.");
return -EINVAL;
}
- } else if (!top->dont_use_callchains && callchain_param.mode != CHAIN_NONE) {
+ } else if (callchain_param.mode != CHAIN_NONE) {
if (callchain_register_param(&callchain_param) < 0) {
ui__error("Can't register callchain params.\n");
return -EINVAL;
@@ -1027,6 +1006,7 @@ static int perf_top__setup_sample_type(struct perf_top *top)

static int __cmd_top(struct perf_top *top)
{
+ struct perf_record_opts *opts = &top->record_opts;
pthread_t thread;
int ret;
/*
@@ -1041,7 +1021,7 @@ static int __cmd_top(struct perf_top *top)
if (ret)
goto out_delete;

- if (perf_target__has_task(&top->target))
+ if (perf_target__has_task(&opts->target))
perf_event__synthesize_thread_map(&top->tool, top->evlist->threads,
perf_event__process,
&top->session->host_machine);
@@ -1052,6 +1032,17 @@ static int __cmd_top(struct perf_top *top)
top->session->evlist = top->evlist;
perf_session__set_id_hdr_size(top->session);

+ /*
+ * When perf is starting the traced process, all the events (apart from
+ * group members) have enable_on_exec=1 set, so don't spoil it by
+ * prematurely enabling them.
+ *
+ * XXX 'top' still doesn't start workloads like record, trace, but should,
+ * so leave the check here.
+ */
+ if (!perf_target__none(&opts->target))
+ perf_evlist__enable(top->evlist);
+
/* Wait for a minimal set of events before starting the snapshot */
poll(top->evlist->pollfd, top->evlist->nr_fds, 100);

@@ -1092,116 +1083,56 @@ out_delete:
static int
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;
-
/*
* --no-call-graph
*/
- if (unset) {
- top->dont_use_callchains = true;
+ if (unset)
return 0;
- }

symbol_conf.use_callchain = true;

- if (!arg)
- return 0;
-
- tok = strtok((char *)arg, ",");
- if (!tok)
- return -1;
-
- /* get the output mode */
- if (!strncmp(tok, "graph", strlen(arg)))
- callchain_param.mode = CHAIN_GRAPH_ABS;
-
- else if (!strncmp(tok, "flat", strlen(arg)))
- callchain_param.mode = CHAIN_FLAT;
-
- else if (!strncmp(tok, "fractal", strlen(arg)))
- callchain_param.mode = CHAIN_GRAPH_REL;
-
- else if (!strncmp(tok, "none", strlen(arg))) {
- callchain_param.mode = CHAIN_NONE;
- symbol_conf.use_callchain = false;
-
- return 0;
- } else
- return -1;
-
- /* get the min percentage */
- tok = strtok(NULL, ",");
- if (!tok)
- goto setup;
-
- callchain_param.min_percent = strtod(tok, &endptr);
- if (tok == endptr)
- return -1;
-
- /* get the print limit */
- tok2 = strtok(NULL, ",");
- if (!tok2)
- goto setup;
-
- if (tok2[0] != 'c') {
- callchain_param.print_limit = strtod(tok2, &endptr);
- tok2 = strtok(NULL, ",");
- if (!tok2)
- goto setup;
- }
-
- /* get the call chain order */
- if (!strcmp(tok2, "caller"))
- callchain_param.order = ORDER_CALLER;
- else if (!strcmp(tok2, "callee"))
- callchain_param.order = ORDER_CALLEE;
- else
- return -1;
-setup:
- if (callchain_register_param(&callchain_param) < 0) {
- fprintf(stderr, "Can't register callchain params\n");
- return -1;
- }
- return 0;
+ return record_parse_callchain_opt(opt, arg, unset);
}

int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
{
- struct perf_evsel *pos;
int status;
char errbuf[BUFSIZ];
struct perf_top top = {
.count_filter = 5,
.delay_secs = 2,
- .freq = 4000, /* 4 KHz */
- .mmap_pages = 128,
- .sym_pcnt_filter = 5,
- .target = {
- .uses_mmap = true,
+ .record_opts = {
+ .mmap_pages = UINT_MAX,
+ .user_freq = UINT_MAX,
+ .user_interval = ULLONG_MAX,
+ .freq = 4000, /* 4 KHz */
+ .target = {
+ .uses_mmap = true,
+ },
},
+ .sym_pcnt_filter = 5,
};
- char callchain_default_opt[] = "fractal,0.5,callee";
+ struct perf_record_opts *opts = &top.record_opts;
+ struct perf_target *target = &opts->target;
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", &top.default_interval,
- "event period to sample"),
- OPT_STRING('p', "pid", &top.target.pid, "pid",
+ OPT_U64('c', "count", &opts->user_interval, "event period to sample"),
+ OPT_STRING('p', "pid", &target->pid, "pid",
"profile events on existing process id"),
- OPT_STRING('t', "tid", &top.target.tid, "tid",
+ OPT_STRING('t', "tid", &target->tid, "tid",
"profile events on existing thread id"),
- OPT_BOOLEAN('a', "all-cpus", &top.target.system_wide,
+ OPT_BOOLEAN('a', "all-cpus", &target->system_wide,
"system-wide collection from all CPUs"),
- OPT_STRING('C', "cpu", &top.target.cpu_list, "cpu",
+ OPT_STRING('C', "cpu", &target->cpu_list, "cpu",
"list of cpus to monitor"),
OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
"file", "vmlinux pathname"),
OPT_BOOLEAN('K', "hide_kernel_symbols", &top.hide_kernel_symbols,
"hide kernel symbols"),
- OPT_UINTEGER('m', "mmap-pages", &top.mmap_pages, "number of mmap data pages"),
+ OPT_UINTEGER('m', "mmap-pages", &opts->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,
@@ -1210,16 +1141,14 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
"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", &top.group,
+ OPT_BOOLEAN('g', "group", &opts->group,
"put the counters into a counter group"),
- OPT_BOOLEAN('i', "inherit", &top.inherit,
- "child tasks inherit counters"),
+ OPT_BOOLEAN('i', "no-inherit", &opts->no_inherit,
+ "child tasks do not inherit counters"),
OPT_STRING(0, "sym-annotate", &top.sym_filter, "symbol name",
"symbol to annotate"),
- OPT_BOOLEAN('z', "zero", &top.zero,
- "zero history across updates"),
- OPT_INTEGER('F', "freq", &top.freq,
- "profile at this frequency"),
+ OPT_BOOLEAN('z', "zero", &top.zero, "zero history across updates"),
+ OPT_UINTEGER('F', "freq", &opts->user_freq, "profile at this frequency"),
OPT_INTEGER('E', "entries", &top.print_entries,
"display this many functions"),
OPT_BOOLEAN('U', "hide_user_symbols", &top.hide_user_symbols,
@@ -1232,10 +1161,9 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
"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", &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),
+ OPT_CALLBACK_DEFAULT('G', "call-graph", &top.record_opts,
+ "mode[,dump_size]", record_callchain_help,
+ &parse_callchain_opt, "fp"),
OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
"Show a column with the sum of periods"),
OPT_STRING(0, "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
@@ -1250,7 +1178,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
"Display raw encoding of assembly instructions (default)"),
OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style",
"Specify disassembler style (e.g. -M intel for intel syntax)"),
- OPT_STRING('u', "uid", &top.target.uid_str, "user", "user to profile"),
+ OPT_STRING('u', "uid", &target->uid_str, "user", "user to profile"),
OPT_END()
};
const char * const top_usage[] = {
@@ -1280,27 +1208,27 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)

setup_browser(false);

- status = perf_target__validate(&top.target);
+ status = perf_target__validate(target);
if (status) {
- perf_target__strerror(&top.target, status, errbuf, BUFSIZ);
+ perf_target__strerror(target, status, errbuf, BUFSIZ);
ui__warning("%s", errbuf);
}

- status = perf_target__parse_uid(&top.target);
+ status = perf_target__parse_uid(target);
if (status) {
int saved_errno = errno;

- perf_target__strerror(&top.target, status, errbuf, BUFSIZ);
+ perf_target__strerror(target, status, errbuf, BUFSIZ);
ui__error("%s", errbuf);

status = -saved_errno;
goto out_delete_evlist;
}

- if (perf_target__none(&top.target))
- top.target.system_wide = true;
+ if (perf_target__none(target))
+ target->system_wide = true;

- if (perf_evlist__create_maps(top.evlist, &top.target) < 0)
+ if (perf_evlist__create_maps(top.evlist, target) < 0)
usage_with_options(top_usage, options);

if (!top.evlist->nr_entries &&
@@ -1314,24 +1242,22 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
if (top.delay_secs < 1)
top.delay_secs = 1;

+ if (opts->user_interval != ULLONG_MAX)
+ opts->default_interval = opts->user_interval;
+ if (opts->user_freq != UINT_MAX)
+ opts->freq = opts->user_freq;
+
/*
* User specified count overrides default frequency.
*/
- if (top.default_interval)
- top.freq = 0;
- else if (top.freq) {
- top.default_interval = top.freq;
+ if (opts->default_interval)
+ opts->freq = 0;
+ else if (opts->freq) {
+ opts->default_interval = opts->freq;
} else {
ui__error("frequency and count are zero, aborting\n");
- exit(EXIT_FAILURE);
- }
-
- list_for_each_entry(pos, &top.evlist->entries, node) {
- /*
- * Fill in the ones not specifically initialized via -c:
- */
- if (!pos->attr.sample_period)
- pos->attr.sample_period = top.default_interval;
+ status = -EINVAL;
+ goto out_delete_evlist;
}

top.sym_evsel = perf_evlist__first(top.evlist);
diff --git a/tools/perf/util/top.c b/tools/perf/util/top.c
index 884dde9..54d37a4 100644
--- a/tools/perf/util/top.c
+++ b/tools/perf/util/top.c
@@ -26,6 +26,8 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size)
float samples_per_sec = top->samples / top->delay_secs;
float ksamples_per_sec = top->kernel_samples / top->delay_secs;
float esamples_percent = (100.0 * top->exact_samples) / top->samples;
+ struct perf_record_opts *opts = &top->record_opts;
+ struct perf_target *target = &opts->target;
size_t ret = 0;

if (!perf_guest) {
@@ -61,31 +63,31 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size)
struct perf_evsel *first = perf_evlist__first(top->evlist);
ret += SNPRINTF(bf + ret, size - ret, "%" PRIu64 "%s ",
(uint64_t)first->attr.sample_period,
- top->freq ? "Hz" : "");
+ opts->freq ? "Hz" : "");
}

ret += SNPRINTF(bf + ret, size - ret, "%s", perf_evsel__name(top->sym_evsel));

ret += SNPRINTF(bf + ret, size - ret, "], ");

- if (top->target.pid)
+ if (target->pid)
ret += SNPRINTF(bf + ret, size - ret, " (target_pid: %s",
- top->target.pid);
- else if (top->target.tid)
+ target->pid);
+ else if (target->tid)
ret += SNPRINTF(bf + ret, size - ret, " (target_tid: %s",
- top->target.tid);
- else if (top->target.uid_str != NULL)
+ target->tid);
+ else if (target->uid_str != NULL)
ret += SNPRINTF(bf + ret, size - ret, " (uid: %s",
- top->target.uid_str);
+ target->uid_str);
else
ret += SNPRINTF(bf + ret, size - ret, " (all");

- if (top->target.cpu_list)
+ if (target->cpu_list)
ret += SNPRINTF(bf + ret, size - ret, ", CPU%s: %s)",
top->evlist->cpus->nr > 1 ? "s" : "",
- top->target.cpu_list);
+ target->cpu_list);
else {
- if (top->target.tid)
+ if (target->tid)
ret += SNPRINTF(bf + ret, size - ret, ")");
else
ret += SNPRINTF(bf + ret, size - ret, ", %d CPU%s)",
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index 86ff1b1..927c229 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -14,7 +14,7 @@ struct perf_session;
struct perf_top {
struct perf_tool tool;
struct perf_evlist *evlist;
- struct perf_target target;
+ struct perf_record_opts record_opts;
/*
* Symbols will be added here in perf_event__process_sample and will
* get out after decayed.
@@ -24,15 +24,11 @@ struct perf_top {
u64 exact_samples;
u64 guest_us_samples, guest_kernel_samples;
int print_entries, count_filter, delay_secs;
- int freq;
bool hide_kernel_symbols, hide_user_symbols, zero;
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_missing;
bool exclude_guest_missing;
bool dump_symtab;
@@ -40,8 +36,6 @@ struct perf_top {
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;

Arnaldo Carvalho de Melo

unread,
Dec 11, 2012, 6:00:04 PM12/11/12
to
From: Namhyung Kim <namhyu...@lge.com>

It is used everywhere so always build it regardless of ui engine.

Signed-off-by: Namhyung Kim <namh...@kernel.org>
Cc: Andi Kleen <a...@linux.intel.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Ingo Molnar <mi...@kernel.org>
Cc: Jiri Olsa <jo...@redhat.com>
Cc: Pekka Enberg <pen...@kernel.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Steven Rostedt <ros...@goodmis.org>
Link: http://lkml.kernel.org/r/1352911664-24620-2-gi...@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/Makefile | 14 +++++---------
tools/perf/ui/util.c | 10 ++++++++++
tools/perf/util/debug.c | 22 ----------------------
tools/perf/util/debug.h | 33 ++-------------------------------
4 files changed, 17 insertions(+), 62 deletions(-)

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 891bc77..8fca560 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -378,8 +378,11 @@ LIB_H += util/rblist.h
LIB_H += util/intlist.h
LIB_H += util/perf_regs.h
LIB_H += util/unwind.h
-LIB_H += ui/helpline.h
LIB_H += util/vdso.h
+LIB_H += ui/helpline.h
+LIB_H += ui/progress.h
+LIB_H += ui/util.h
+LIB_H += ui/ui.h

LIB_OBJS += $(OUTPUT)util/abspath.o
LIB_OBJS += $(OUTPUT)util/alias.o
@@ -453,6 +456,7 @@ LIB_OBJS += $(OUTPUT)util/stat.o
LIB_OBJS += $(OUTPUT)ui/setup.o
LIB_OBJS += $(OUTPUT)ui/helpline.o
LIB_OBJS += $(OUTPUT)ui/progress.o
+LIB_OBJS += $(OUTPUT)ui/util.o
LIB_OBJS += $(OUTPUT)ui/hist.o
LIB_OBJS += $(OUTPUT)ui/stdio/hist.o

@@ -646,7 +650,6 @@ ifndef NO_NEWT
LIB_OBJS += $(OUTPUT)ui/browsers/hists.o
LIB_OBJS += $(OUTPUT)ui/browsers/map.o
LIB_OBJS += $(OUTPUT)ui/browsers/scripts.o
- LIB_OBJS += $(OUTPUT)ui/util.o
LIB_OBJS += $(OUTPUT)ui/tui/setup.o
LIB_OBJS += $(OUTPUT)ui/tui/util.o
LIB_OBJS += $(OUTPUT)ui/tui/helpline.o
@@ -655,9 +658,6 @@ ifndef NO_NEWT
LIB_H += ui/browsers/map.h
LIB_H += ui/keysyms.h
LIB_H += ui/libslang.h
- LIB_H += ui/progress.h
- LIB_H += ui/util.h
- LIB_H += ui/ui.h
endif
endif

@@ -677,10 +677,6 @@ ifndef NO_GTK2
LIB_OBJS += $(OUTPUT)ui/gtk/util.o
LIB_OBJS += $(OUTPUT)ui/gtk/helpline.o
LIB_OBJS += $(OUTPUT)ui/gtk/progress.o
- # Make sure that it'd be included only once.
- ifeq ($(findstring -DNEWT_SUPPORT,$(BASIC_CFLAGS)),)
- LIB_OBJS += $(OUTPUT)ui/util.o
- endif
endif
endif

diff --git a/tools/perf/ui/util.c b/tools/perf/ui/util.c
index 4f98977..3014a7c 100644
--- a/tools/perf/ui/util.c
+++ b/tools/perf/ui/util.c
@@ -52,6 +52,16 @@ int ui__warning(const char *format, ...)
return ret;
}

+int ui__error_paranoid(void)
+{
+ return ui__error("Permission error - are you root?\n"
+ "Consider tweaking /proc/sys/kernel/perf_event_paranoid:\n"
+ " -1 - Not paranoid at all\n"
+ " 0 - Disallow raw tracepoint access for unpriv\n"
+ " 1 - Disallow cpu events for unpriv\n"
+ " 2 - Disallow kernel profiling for unpriv\n");
+}
+

/**
* perf_error__register - Register error logging functions
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index 03f830b..39861a2a 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -49,28 +49,6 @@ int dump_printf(const char *fmt, ...)
return ret;
}

-#if !defined(NEWT_SUPPORT) && !defined(GTK2_SUPPORT)
-int ui__warning(const char *format, ...)
-{
- va_list args;
-
- va_start(args, format);
- vfprintf(stderr, format, args);
- va_end(args);
- return 0;
-}
-#endif
-
-int ui__error_paranoid(void)
-{
- return ui__error("Permission error - are you root?\n"
- "Consider tweaking /proc/sys/kernel/perf_event_paranoid:\n"
- " -1 - Not paranoid at all\n"
- " 0 - Disallow raw tracepoint access for unpriv\n"
- " 1 - Disallow cpu events for unpriv\n"
- " 2 - Disallow kernel profiling for unpriv\n");
-}
-
void trace_event(union perf_event *event)
{
unsigned char *raw_event = (void *)event;
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index 83e8d23..6e2667f 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -5,6 +5,8 @@
#include <stdbool.h>
#include "event.h"
#include "../ui/helpline.h"
+#include "../ui/progress.h"
+#include "../ui/util.h"

extern int verbose;
extern bool quiet, dump_trace;
@@ -12,38 +14,7 @@ extern bool quiet, dump_trace;
int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
void trace_event(union perf_event *event);

-struct ui_progress;
-struct perf_error_ops;
-
-#if defined(NEWT_SUPPORT) || defined(GTK2_SUPPORT)
-
-#include "../ui/progress.h"
int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2)));
-#include "../ui/util.h"
-
-#else
-
-static inline void ui_progress__update(u64 curr __maybe_unused,
- u64 total __maybe_unused,
- const char *title __maybe_unused) {}
-static inline void ui_progress__finish(void) {}
-
-#define ui__error(format, arg...) ui__warning(format, ##arg)
-
-static inline int
-perf_error__register(struct perf_error_ops *eops __maybe_unused)
-{
- return 0;
-}
-
-static inline int
-perf_error__unregister(struct perf_error_ops *eops __maybe_unused)
-{
- return 0;
-}
-
-#endif /* NEWT_SUPPORT || GTK2_SUPPORT */
-
int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
int ui__error_paranoid(void);

Arnaldo Carvalho de Melo

unread,
Dec 11, 2012, 6:00:04 PM12/11/12
to
From: Namhyung Kim <namhyu...@lge.com>

Currently only non-leader members are set ->leader to the leader evsel
of the group and the leader has set NULL. Thus it requires special
casing for leader evsels. Set ->leader to itself will remove this.

Suggested-by: Arnaldo Carvalho de Melo <ac...@ghostprotocols.net>
Signed-off-by: Namhyung Kim <namh...@kernel.org>
Acked-by: Jiri Olsa <jo...@redhat.com>
Cc: Andi Kleen <an...@firstfloor.org>
Cc: Ingo Molnar <mi...@kernel.org>
Cc: Jiri Olsa <jo...@redhat.com>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Cc: Stephane Eranian <era...@google.com>
Link: http://lkml.kernel.org/r/1354171126-14387-3-gi...@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/evlist.c | 1 -
tools/perf/util/evsel.c | 1 +
tools/perf/util/evsel.h | 2 +-
3 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 7052934..90db2a1 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -111,7 +111,6 @@ void __perf_evlist__set_leader(struct list_head *list)
struct perf_evsel *evsel, *leader;

leader = list_entry(list->next, struct perf_evsel, node);
- leader->leader = NULL;

list_for_each_entry(evsel, list, node) {
if (evsel != leader)
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 1b16dd1..7e93418 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -55,6 +55,7 @@ void perf_evsel__init(struct perf_evsel *evsel,
{
evsel->idx = idx;
evsel->attr = *attr;
+ evsel->leader = evsel;
INIT_LIST_HEAD(&evsel->node);
hists__init(&evsel->hists);
evsel->sample_size = __perf_evsel__sample_size(attr->sample_type);
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 3d2b801..cbf6d97 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -228,6 +228,6 @@ static inline struct perf_evsel *perf_evsel__next(struct perf_evsel *evsel)

static inline bool perf_evsel__is_group_member(const struct perf_evsel *evsel)
{
- return evsel->leader != NULL;
+ return evsel->leader != evsel;
}
#endif /* __PERF_EVSEL_H */

Ingo Molnar

unread,
Jan 24, 2013, 10:40:02 AM1/24/13
to

* Arnaldo Carvalho de Melo <ac...@infradead.org> wrote:

> Hi Ingo,
>
> Please consider pulling.
>
> Jiri, tomorrow I'll go over the hists patches as I think you're fully
> ok with Namhyung latest patchset.
>
> Regards,
>
> - Arnaldo
>
> The following changes since commit cc1b39dbf9f55a438e8a21a694394c20e6a17129:
>
> Merge branch 'tip/perf/core' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace into perf/core (2012-12-08 15:54:35 +0100)
>
> are available in the git repository at:
>
>
> git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux tags/perf-core-for-mingo
>
> for you to fetch changes up to 2376c67a7bbc7849b806688ba2efb8520c21c458:
>
> perf top: Use perf_evlist__config() (2012-12-11 17:22:39 -0300)
>
> ----------------------------------------------------------------
> perf/core improvements and fixes
>
> . perf build-id cache now can show DSOs present in a perf.data file that are
> not in the cache, to integrate with build-id servers being put in place by
> organizations such as Fedora.
>
> . perf buildid-list -i an-elf-file-instead-of-a-perf.data is back showing its
> build-id.
>
> . No need to do feature checks when doing a 'make tags'
>
> . Fix some 'perf test' errors and make them use the tracepoint evsel constructor.
>
> . perf top now shares more of the evsel config/creation routines with 'record',
> paving the way for further integration like 'top' snapshots, etc.
>
> . perf top now supports DWARF callchains.
>
> . perf evlist decodes sample_type and read_format, helping diagnose problems.
>
> . Fix mmap limitations on 32-bit, fix from David Miller.
>
> . perf diff fixes from Jiri Olsa.
>
> . Ignore ABS symbols when loading data maps, fix from Namhyung Kim
>
> . Hists improvements from Namhyung Kim
>
> . Don't check configuration on make clean, from Namhyung Kim
>
> . Fix dso__fprintf() print statement, from Stephane Eranian.
>
> Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
>
> ----------------------------------------------------------------
> Arnaldo Carvalho de Melo (20):
> perf top: Add missing newline on pr_err call
> perf tools: Don't check configuration on make tags
> perf tools: Fix TUI helpline output
> perf buildid-list: We need to check if a file is ELF first
> perf symbols: Generalize filter in __fprintf_buildid methods
> perf buildid-cache: Add option to show build ids that are missing in the cache
> perf machine: Move more machine methods to machine.c
> perf evsel: Update sample_size when setting sample_type bits
> perf test: Fixup error reporting in basic mmap test
> perf test: Use perf_evsel__newtp constructor in the tracepoint tests
> perf evsel: Introduce method to request IDs be used
> perf evsel: No need to always ask for PERF_FORMAT_ID in read_format
> perf evsel: No need to always ask for PERF_FORMAT_TOTAL_TIME_{ENABLED,RUNNING}
> perf evlist: Set the leader in the perf_evlist__config method
> perf evsel: Adopt fprintf routine from 'perf evlist'
> perf tools: Add install-bin Makefile target
> perf evsel: Decode read_format and sample_type in perf_evsel__fprintf
> perf record: Pass perf_record_opts to the callchain cmdline parsing callback
> perf record: Export the callchain parsing routine and help
> perf top: Use perf_evlist__config()
>
> David Miller (1):
> perf tools: Fix mmap limitations on 32-bit
>
> Jiri Olsa (6):
> perf hists: Introduce perf_hpp__list for period related columns
> perf hists: Fix period symbol_conf.field_sep display
> perf diff: Remove displacement from struct hist_entry_diff
> perf diff: Change compute methods to work with pair directly
> perf diff: Change formula methods to work with pair directly
> perf diff: Remove displacement output option
>
> Namhyung Kim (9):
> perf ui: Always compile error printing code
> perf ui/helpline: Introduce ui_helpline__vshow()
> perf tools: Don't check configuration on make clean
> perf session: Free environment information when deleting session
> perf symbols: Ignore ABS symbols when loading data maps
> perf hists: Fix typo on hist__entry_add_pair
> perf hists: Link hist entry pairs to leader
> perf evsel: Set leader evsel's ->leader to itself
> perf evsel: Convert to _is_group_leader method
>
> Stephane Eranian (1):
> perf symbols: Fix dso__fprintf() print statement
>
> tools/perf/Documentation/Makefile | 4 +
> tools/perf/Documentation/perf-buildid-cache.txt | 3 +
> tools/perf/Documentation/perf-diff.txt | 4 -
> tools/perf/Documentation/perf-top.txt | 2 +-
> tools/perf/Makefile | 51 +-
> tools/perf/builtin-buildid-cache.c | 48 +-
> tools/perf/builtin-buildid-list.c | 21 +-
> tools/perf/builtin-diff.c | 121 ++--
> tools/perf/builtin-evlist.c | 81 +--
> tools/perf/builtin-record.c | 40 +-
> tools/perf/builtin-report.c | 1 +
> tools/perf/builtin-stat.c | 2 +-
> tools/perf/builtin-top.c | 207 ++-----
> tools/perf/builtin-trace.c | 2 +-
> tools/perf/tests/attr/base-record | 2 +-
> tools/perf/tests/attr/test-record-group | 2 +
> tools/perf/tests/attr/test-record-group1 | 2 +
> tools/perf/tests/mmap-basic.c | 40 +-
> tools/perf/tests/open-syscall-all-cpus.c | 18 +-
> tools/perf/tests/open-syscall.c | 17 +-
> tools/perf/tests/parse-events.c | 20 +-
> tools/perf/tests/perf-record.c | 8 +-
> tools/perf/tests/tests.h | 3 -
> tools/perf/tests/util.c | 30 -
> tools/perf/ui/browsers/hists.c | 20 +-
> tools/perf/ui/gtk/browser.c | 30 +-
> tools/perf/ui/gtk/helpline.c | 23 +-
> tools/perf/ui/helpline.c | 12 +
> tools/perf/ui/helpline.h | 22 +-
> tools/perf/ui/hist.c | 170 +++---
> tools/perf/ui/setup.c | 1 +
> tools/perf/ui/stdio/hist.c | 17 +-
> tools/perf/ui/tui/helpline.c | 29 +-
> tools/perf/ui/util.c | 10 +
> tools/perf/util/callchain.h | 5 +
> tools/perf/util/debug.c | 28 +-
> tools/perf/util/debug.h | 33 +-
> tools/perf/util/dso.c | 6 +-
> tools/perf/util/dso.h | 2 +-
> tools/perf/util/evlist.c | 17 +-
> tools/perf/util/evlist.h | 4 +-
> tools/perf/util/evsel.c | 186 +++++-
> tools/perf/util/evsel.h | 25 +-
> tools/perf/util/hist.c | 4 +-
> tools/perf/util/hist.h | 22 +-
> tools/perf/util/machine.c | 742 +++++++++++++++++++++++
> tools/perf/util/machine.h | 11 +-
> tools/perf/util/session.c | 256 +-------
> tools/perf/util/session.h | 5 +-
> tools/perf/util/sort.h | 5 +-
> tools/perf/util/symbol-elf.c | 11 +
> tools/perf/util/symbol.c | 522 +---------------
> tools/perf/util/symbol.h | 4 +
> tools/perf/util/thread.c | 20 +-
> tools/perf/util/thread.h | 1 +
> tools/perf/util/top.c | 22 +-
> tools/perf/util/top.h | 8 +-
> 57 files changed, 1483 insertions(+), 1519 deletions(-)
> delete mode 100644 tools/perf/tests/util.c

Pulled, thanks a lot Arnaldo!

Ingo
0 new messages