Hi Ingo,
Please consider pulling, this is on top of my previous pull requests,
- Arnaldo
The following changes since commit 0fe7d7e9761ec7e23350b5543ddac470bb3cde1e:
perf symbols: Add description of JIT interface (2012-08-13 14:55:02 -0300)
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 000078bc3ee69efb1124b8478c7527389a826074:
perf hists: Rename and move some functions (2012-08-20 09:47:31 -0300)
----------------------------------------------------------------
perf/core improvements and fixes:
. Fix include order for bison/flex-generated C files, from Ben Hutchings
. Build fixes and documentation corrections from David Ahern
. Group parsing support, from Jiri Olsa
. UI/gtk refactorings and improvements from Namhyung Kim
. NULL deref fix for perf script, from Namhyung Kim
. Assorted cleanups from Robert Richter
. Let O= makes handle relative paths, from Steven Rostedt
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
----------------------------------------------------------------
Arnaldo Carvalho de Melo (3):
perf tools: Add missing files to build the python binding
perf evlist: Rename __group method to __set_leader
perf evlist: Introduce evsel list accessors
Ben Hutchings (1):
perf tools: Fix include order for bison/flex-generated C files
David Ahern (3):
perf script perl/python: Fix libexec scripts path in Documentation
perf: silence GTK2 probing errors
perf symbols: Fix builds with NO_LIBELF set
Jiri Olsa (4):
perf tools: Add support to parse event group syntax
perf tools: Add support to update event modifier
perf tools: Enable grouping logic for parsed events
perf test: Add automated tests for event group parsing
Namhyung Kim (8):
perf script: Fix a NULL pointer dereference
perf ui: Introduce struct ui_helpline
perf ui gtk: Implement helpline_fns
perf ui/gtk: Use helpline API in browser
perf ui gtk: Add perf_gtk__show_helpline() for pr_*
perf ui gtk: Ensure not to call gtk_main_quit() twice
perf hists: Separate out hist print functions
perf hists: Rename and move some functions
Robert Richter (4):
perf tools: Fix type for evsel->ids and add size check for ids
perf tools: Report number of pmu type of unknown events
perf tools: Rename some variables for better understanding
perf tools: Rename global variable 'events' in util/header.c
Steven Rostedt (1):
perf tools: Let O= makes handle relative paths
tools/perf/Documentation/perf-script-perl.txt | 4 +-
tools/perf/Documentation/perf-script-python.txt | 10 +-
tools/perf/Makefile | 20 +-
tools/perf/builtin-record.c | 17 +-
tools/perf/builtin-stat.c | 15 +-
tools/perf/builtin-test.c | 10 +-
tools/perf/builtin-top.c | 18 +-
tools/perf/ui/browsers/hists.c | 4 +-
tools/perf/ui/gtk/browser.c | 5 +-
tools/perf/ui/gtk/gtk.h | 2 +
tools/perf/ui/gtk/helpline.c | 56 ++
tools/perf/ui/gtk/setup.c | 3 +
tools/perf/ui/gtk/util.c | 5 -
tools/perf/ui/helpline.c | 56 +-
tools/perf/ui/helpline.h | 33 +-
tools/perf/ui/setup.c | 4 +
tools/perf/ui/stdio/hist.c | 653 ++++++++++++++++++++++
tools/perf/ui/tui/helpline.c | 57 ++
tools/perf/ui/tui/setup.c | 2 -
tools/perf/util/debug.c | 4 +-
tools/perf/util/debug.h | 8 +-
tools/perf/util/evlist.c | 73 +--
tools/perf/util/evlist.h | 27 +-
tools/perf/util/evsel.c | 52 +-
tools/perf/util/evsel.h | 20 +-
tools/perf/util/header.c | 97 ++--
tools/perf/util/header.h | 2 +-
tools/perf/util/hist.c | 677 +----------------------
tools/perf/util/hist.h | 6 +-
tools/perf/util/parse-events-test.c | 387 ++++++++++---
tools/perf/util/parse-events.c | 93 +++-
tools/perf/util/parse-events.h | 4 +-
tools/perf/util/parse-events.l | 2 +
tools/perf/util/parse-events.y | 93 +++-
tools/perf/util/python-ext-sources | 2 +
tools/perf/util/python.c | 7 +-
tools/perf/util/symbol-elf.c | 3 +
tools/perf/util/symbol.c | 2 +-
tools/perf/util/top.c | 3 +-
tools/perf/util/trace-event-parse.c | 2 +-
tools/scripts/Makefile.include | 6 +-
41 files changed, 1560 insertions(+), 984 deletions(-)
create mode 100644 tools/perf/ui/gtk/helpline.c
create mode 100644 tools/perf/ui/stdio/hist.c
create mode 100644 tools/perf/ui/tui/helpline.c
From: Namhyung Kim <[email protected]>
Add struct ui_helpline in order to provide flexible implementation of
helpline APIs. And convert existing TUI implementation to use it.
Signed-off-by: Namhyung Kim <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/Makefile | 5 ++-
tools/perf/ui/helpline.c | 56 ++++++++++++++---------------------------
tools/perf/ui/helpline.h | 10 ++++++-
tools/perf/ui/tui/helpline.c | 57 ++++++++++++++++++++++++++++++++++++++++++
4 files changed, 88 insertions(+), 40 deletions(-)
create mode 100644 tools/perf/ui/tui/helpline.c
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index e457afa..483fb69 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -335,6 +335,7 @@ 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_OBJS += $(OUTPUT)util/abspath.o
LIB_OBJS += $(OUTPUT)util/alias.o
@@ -402,6 +403,7 @@ LIB_OBJS += $(OUTPUT)util/cgroup.o
LIB_OBJS += $(OUTPUT)util/target.o
LIB_OBJS += $(OUTPUT)util/rblist.o
LIB_OBJS += $(OUTPUT)util/intlist.o
+LIB_OBJS += $(OUTPUT)ui/helpline.o
BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
@@ -567,14 +569,13 @@ else
LIB_OBJS += $(OUTPUT)ui/browsers/annotate.o
LIB_OBJS += $(OUTPUT)ui/browsers/hists.o
LIB_OBJS += $(OUTPUT)ui/browsers/map.o
- LIB_OBJS += $(OUTPUT)ui/helpline.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_H += ui/browser.h
LIB_H += ui/browsers/map.h
- LIB_H += ui/helpline.h
LIB_H += ui/keysyms.h
LIB_H += ui/libslang.h
LIB_H += ui/progress.h
diff --git a/tools/perf/ui/helpline.c b/tools/perf/ui/helpline.c
index 2f950c2..78ba28a 100644
--- a/tools/perf/ui/helpline.c
+++ b/tools/perf/ui/helpline.c
@@ -5,23 +5,32 @@
#include "../debug.h"
#include "helpline.h"
#include "ui.h"
-#include "libslang.h"
-void ui_helpline__pop(void)
+char ui_helpline__current[512];
+
+static void nop_helpline__pop(void)
{
}
-char ui_helpline__current[512];
+static void nop_helpline__push(const char *msg __used)
+{
+}
-void ui_helpline__push(const char *msg)
+static struct ui_helpline default_helpline_fns = {
+ .pop = nop_helpline__pop,
+ .push = nop_helpline__push,
+};
+
+struct ui_helpline *helpline_fns = &default_helpline_fns;
+
+void ui_helpline__pop(void)
{
- const size_t sz = sizeof(ui_helpline__current);
+ helpline_fns->pop();
+}
- SLsmg_gotorc(SLtt_Screen_Rows - 1, 0);
- SLsmg_set_color(0);
- SLsmg_write_nstring((char *)msg, SLtt_Screen_Cols);
- SLsmg_refresh();
- strncpy(ui_helpline__current, msg, sz)[sz - 1] = '\0';
+void ui_helpline__push(const char *msg)
+{
+ helpline_fns->push(msg);
}
void ui_helpline__vpush(const char *fmt, va_list ap)
@@ -50,30 +59,3 @@ void ui_helpline__puts(const char *msg)
ui_helpline__pop();
ui_helpline__push(msg);
}
-
-void ui_helpline__init(void)
-{
- ui_helpline__puts(" ");
-}
-
-char ui_helpline__last_msg[1024];
-
-int ui_helpline__show_help(const char *format, va_list ap)
-{
- int ret;
- static int backlog;
-
- pthread_mutex_lock(&ui__lock);
- ret = vscnprintf(ui_helpline__last_msg + backlog,
- sizeof(ui_helpline__last_msg) - backlog, format, ap);
- backlog += ret;
-
- if (ui_helpline__last_msg[backlog - 1] == '\n') {
- ui_helpline__puts(ui_helpline__last_msg);
- SLsmg_refresh();
- backlog = 0;
- }
- pthread_mutex_unlock(&ui__lock);
-
- return ret;
-}
diff --git a/tools/perf/ui/helpline.h b/tools/perf/ui/helpline.h
index 7bab6b3..61118b2 100644
--- a/tools/perf/ui/helpline.h
+++ b/tools/perf/ui/helpline.h
@@ -4,13 +4,21 @@
#include <stdio.h>
#include <stdarg.h>
+struct ui_helpline {
+ void (*pop)(void);
+ void (*push)(const char *msg);
+};
+
+extern struct ui_helpline *helpline_fns;
+
void ui_helpline__init(void);
+
void ui_helpline__pop(void);
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);
-extern char ui_helpline__current[];
+extern char ui_helpline__current[512];
#endif /* _PERF_UI_HELPLINE_H_ */
diff --git a/tools/perf/ui/tui/helpline.c b/tools/perf/ui/tui/helpline.c
new file mode 100644
index 0000000..2884d2f
--- /dev/null
+++ b/tools/perf/ui/tui/helpline.c
@@ -0,0 +1,57 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+
+#include "../../util/debug.h"
+#include "../helpline.h"
+#include "../ui.h"
+#include "../libslang.h"
+
+static void tui_helpline__pop(void)
+{
+}
+
+static void tui_helpline__push(const char *msg)
+{
+ const size_t sz = sizeof(ui_helpline__current);
+
+ SLsmg_gotorc(SLtt_Screen_Rows - 1, 0);
+ SLsmg_set_color(0);
+ SLsmg_write_nstring((char *)msg, SLtt_Screen_Cols);
+ SLsmg_refresh();
+ 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)
+{
+ int ret;
+ static int backlog;
+
+ pthread_mutex_lock(&ui__lock);
+ ret = vscnprintf(ui_helpline__last_msg + backlog,
+ sizeof(ui_helpline__last_msg) - backlog, format, ap);
+ backlog += ret;
+
+ if (ui_helpline__last_msg[backlog - 1] == '\n') {
+ ui_helpline__puts(ui_helpline__last_msg);
+ SLsmg_refresh();
+ backlog = 0;
+ }
+ pthread_mutex_unlock(&ui__lock);
+
+ return ret;
+}
--
1.7.1
From: Namhyung Kim <[email protected]>
Currently the gtk_main_quit() is called twice when perf exits so the
following warning is emitted:
[penberg@tux perf]$ ./perf report --gtk
^Cperf: Interrupt
(perf:4048): Gtk-CRITICAL **: IA__gtk_main_quit: assertion `main_loops != NULL' failed
Fix it by not to call it unnecessarily.
Reported-by: Pekka Enberg <[email protected]>
Signed-off-by: Namhyung Kim <[email protected]>
Acked-by: Pekka Enberg <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Pekka Enberg <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/ui/gtk/setup.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/tools/perf/ui/gtk/setup.c b/tools/perf/ui/gtk/setup.c
index ad40b36..ec1ee26 100644
--- a/tools/perf/ui/gtk/setup.c
+++ b/tools/perf/ui/gtk/setup.c
@@ -13,6 +13,8 @@ int perf_gtk__init(void)
void perf_gtk__exit(bool wait_for_ok __used)
{
+ if (!perf_gtk__is_active_context(pgctx))
+ return;
perf_error__unregister(&perf_gtk_eops);
gtk_main_quit();
}
--
1.7.1
From: David Ahern <[email protected]>
Build currently fails:
$ make -C tools/perf O=/tmp/pbuild NO_LIBELF=1
util/symbol.c: In function ‘dso__load’:
util/symbol.c:1128:27: error: ‘struct symsrc’ has no member named ‘dynsym’
CC /tmp/pbuild/util/pager.o
make: *** [/tmp/pbuild/util/symbol.o] Error 1
make: *** Waiting for unfinished jobs....
Moving the dynsym reference to symbol-elf.c reveals that NO_LIBELF requires
NO_LIBUNWIND:
$ make -C tools/perf O=/tmp/pbuild NO_LIBELF=1
LINK /tmp/pbuild/perf
/tmp/pbuild/libperf.a(unwind.o): In function `elf_section_offset':
/opt/sw/ahern/perf.git/tools/perf/util/unwind.c:176: undefined reference to `elf_begin'
/opt/sw/ahern/perf.git/tools/perf/util/unwind.c:181: undefined reference to `gelf_getehdr'
/tmp/pbuild/libperf.a(unwind.o): In function `elf_section_by_name':
/opt/sw/ahern/perf.git/tools/perf/util/unwind.c:157: undefined reference to `elf_nextscn'
/opt/sw/ahern/perf.git/tools/perf/util/unwind.c:160: undefined reference to `gelf_getshdr'
/opt/sw/ahern/perf.git/tools/perf/util/unwind.c:161: undefined reference to `elf_strptr'
/tmp/pbuild/libperf.a(unwind.o): In function `elf_section_offset':
/opt/sw/ahern/perf.git/tools/perf/util/unwind.c:190: undefined reference to `elf_end'
/tmp/pbuild/libperf.a(unwind.o): In function `read_unwind_spec':
/opt/sw/ahern/perf.git/tools/perf/util/unwind.c:190: undefined reference to `elf_end'
collect2: ld returned 1 exit status
make: *** [/tmp/pbuild/perf] Error 1
make: Leaving directory `/opt/sw/ahern/perf.git/tools/perf'
This patch fixes both.
Reviewed-by: Namhyung Kim <[email protected]>
Signed-off-by: David Ahern <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Namhyung Kim <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/Makefile | 1 +
tools/perf/util/symbol-elf.c | 3 +++
tools/perf/util/symbol.c | 2 +-
3 files changed, 5 insertions(+), 1 deletions(-)
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 8beff99..90cfecf 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -469,6 +469,7 @@ PYRF_OBJS += $(OUTPUT)util/xyarray.o
ifdef NO_LIBELF
NO_DWARF := 1
NO_DEMANGLE := 1
+ NO_LIBUNWIND := 1
else
FLAGS_LIBELF=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS)
ifneq ($(call try-cc,$(SOURCE_LIBELF),$(FLAGS_LIBELF)),y)
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 5b37e13..db0cc92 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -183,6 +183,9 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *
Elf *elf;
int nr = 0, symidx, err = 0;
+ if (!ss->dynsym)
+ return 0;
+
elf = ss->elf;
ehdr = ss->ehdr;
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 2293a4a..753699a 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1125,7 +1125,7 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
else
ret = -1;
- if (ret > 0 && runtime_ss->dynsym) {
+ if (ret > 0) {
int nr_plt;
nr_plt = dso__synthesize_plt_symbols(dso, runtime_ss, map, filter);
--
1.7.1
From: Namhyung Kim <[email protected]>
As we now have a helpline implementation, use it for displaying help
messages.
Signed-off-by: Namhyung Kim <[email protected]>
Acked-by: Pekka Enberg <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Pekka Enberg <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/ui/gtk/browser.c | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/tools/perf/ui/gtk/browser.c b/tools/perf/ui/gtk/browser.c
index ec12e0b..26b5b65 100644
--- a/tools/perf/ui/gtk/browser.c
+++ b/tools/perf/ui/gtk/browser.c
@@ -3,6 +3,7 @@
#include "../evsel.h"
#include "../sort.h"
#include "../hist.h"
+#include "../helpline.h"
#include "gtk.h"
#include <signal.h>
@@ -166,7 +167,7 @@ static GtkWidget *perf_gtk__setup_statusbar(void)
}
int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
- const char *help __used,
+ const char *help,
void (*timer) (void *arg)__used,
void *arg __used, int delay_secs __used)
{
@@ -233,6 +234,8 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
+ ui_helpline__push(help);
+
gtk_main();
perf_gtk__deactivate_context(&pgctx);
--
1.7.1
From: Namhyung Kim <[email protected]>
Add helpline API implementation to GTK front-end.
Signed-off-by: Namhyung Kim <[email protected]>
Acked-by: Pekka Enberg <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Pekka Enberg <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/Makefile | 1 +
tools/perf/ui/gtk/gtk.h | 2 ++
tools/perf/ui/gtk/helpline.c | 30 ++++++++++++++++++++++++++++++
tools/perf/ui/gtk/setup.c | 1 +
4 files changed, 34 insertions(+), 0 deletions(-)
create mode 100644 tools/perf/ui/gtk/helpline.c
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 483fb69..75af93d 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -600,6 +600,7 @@ else
LIB_OBJS += $(OUTPUT)ui/gtk/browser.o
LIB_OBJS += $(OUTPUT)ui/gtk/setup.o
LIB_OBJS += $(OUTPUT)ui/gtk/util.o
+ LIB_OBJS += $(OUTPUT)ui/gtk/helpline.o
# Make sure that it'd be included only once.
ifneq ($(findstring -DNO_NEWT_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 a4d0f2b..793cb61 100644
--- a/tools/perf/ui/gtk/gtk.h
+++ b/tools/perf/ui/gtk/gtk.h
@@ -29,6 +29,8 @@ static inline bool perf_gtk__is_active_context(struct perf_gtk_context *ctx)
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);
+
#ifndef HAVE_GTK_INFO_BAR
static inline GtkWidget *perf_gtk__setup_info_bar(void)
{
diff --git a/tools/perf/ui/gtk/helpline.c b/tools/perf/ui/gtk/helpline.c
new file mode 100644
index 0000000..2511b37
--- /dev/null
+++ b/tools/perf/ui/gtk/helpline.c
@@ -0,0 +1,30 @@
+#include "gtk.h"
+#include "../helpline.h"
+
+static void gtk_helpline_pop(void)
+{
+ if (!perf_gtk__is_active_context(pgctx))
+ return;
+
+ gtk_statusbar_pop(GTK_STATUSBAR(pgctx->statbar),
+ pgctx->statbar_ctx_id);
+}
+
+static void gtk_helpline_push(const char *msg)
+{
+ if (!perf_gtk__is_active_context(pgctx))
+ return;
+
+ gtk_statusbar_push(GTK_STATUSBAR(pgctx->statbar),
+ 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 = >k_helpline_fns;
+}
diff --git a/tools/perf/ui/gtk/setup.c b/tools/perf/ui/gtk/setup.c
index 92879ce..ad40b36 100644
--- a/tools/perf/ui/gtk/setup.c
+++ b/tools/perf/ui/gtk/setup.c
@@ -7,6 +7,7 @@ extern struct perf_error_ops perf_gtk_eops;
int perf_gtk__init(void)
{
perf_error__register(&perf_gtk_eops);
+ perf_gtk__init_helpline();
return gtk_init_check(NULL, NULL) ? 0 : -1;
}
--
1.7.1
From: David Ahern <[email protected]>
If GTK2 development packages are not installed, make is rather noisy:
$ make -C tools/perf O=/tmp/pbuild
Package gtk+-2.0 was not found in the pkg-config search path.
Perhaps you should add the directory containing `gtk+-2.0.pc'
to the PKG_CONFIG_PATH environment variable
No package 'gtk+-2.0' found
make: Entering directory `/opt/sw/ahern/perf.git/tools/perf'
Makefile:593: GTK2 not found, disables GTK2 support. Please install gtk2-devel or libgtk2.0-dev
PERF_VERSION = 3.6.rc1.205.gdb146f.dirty
make: Leaving directory `/opt/sw/ahern/perf.git/tools/perf'
Package gtk+-2.0 was not found in the pkg-config search path.
Perhaps you should add the directory containing `gtk+-2.0.pc'
to the PKG_CONFIG_PATH environment variable
No package 'gtk+-2.0' found
make: Entering directory `/opt/sw/ahern/perf.git/tools/perf'
Makefile:593: GTK2 not found, disables GTK2 support. Please install gtk2-devel or libgtk2.0-dev
...
Silence the pkg-config errors. Aftewards:
$ make -C tools/perf O=/tmp/pbuild
make: Entering directory `/opt/sw/ahern/perf.git/tools/perf'
Makefile:593: GTK2 not found, disables GTK2 support. Please install gtk2-devel or libgtk2.0-dev
PERF_VERSION = 3.6.rc1.206.gd43ff9.dirty
make: Leaving directory `/opt/sw/ahern/perf.git/tools/perf'
make: Entering directory `/opt/sw/ahern/perf.git/tools/perf'
Makefile:593: GTK2 not found, disables GTK2 support. Please install gtk2-devel or libgtk2.0-dev
...
Signed-off-by: David Ahern <[email protected]>
Acked-by: Namhyung Kim <[email protected]>
Acked-by: Pekka Enberg <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Pekka Enberg <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/Makefile | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 75af93d..8beff99 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -587,7 +587,7 @@ endif
ifdef NO_GTK2
BASIC_CFLAGS += -DNO_GTK2_SUPPORT
else
- FLAGS_GTK2=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) $(shell pkg-config --libs --cflags gtk+-2.0)
+ FLAGS_GTK2=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null)
ifneq ($(call try-cc,$(SOURCE_GTK2),$(FLAGS_GTK2)),y)
msg := $(warning GTK2 not found, disables GTK2 support. Please install gtk2-devel or libgtk2.0-dev);
BASIC_CFLAGS += -DNO_GTK2_SUPPORT
@@ -595,8 +595,8 @@ else
ifeq ($(call try-cc,$(SOURCE_GTK2_INFOBAR),$(FLAGS_GTK2)),y)
BASIC_CFLAGS += -DHAVE_GTK_INFO_BAR
endif
- BASIC_CFLAGS += $(shell pkg-config --cflags gtk+-2.0)
- EXTLIBS += $(shell pkg-config --libs gtk+-2.0)
+ BASIC_CFLAGS += $(shell pkg-config --cflags gtk+-2.0 2>/dev/null)
+ EXTLIBS += $(shell pkg-config --libs gtk+-2.0 2>/dev/null)
LIB_OBJS += $(OUTPUT)ui/gtk/browser.o
LIB_OBJS += $(OUTPUT)ui/gtk/setup.o
LIB_OBJS += $(OUTPUT)ui/gtk/util.o
--
1.7.1
From: Jiri Olsa <[email protected]>
Adding scanner/parser bits to parse event groups.
The grammar for group is:
groups: groups ',' group | group
group: group_name '{' events '}' group_mod
group_name: name | empty
group_mod: ':' group_mods | empty
group_mods: event_mod
It's possible to use standard event modifier as a modifier
for group. It'll be used as an update to existing event
modifiers.
It's necessary to use quoting ("'\) when specifying group on
command line, since {} characters are interpreted by most of
the shells.
It is now possible to specify groups in event syntax like:
'{cycles,faults}'
- anonymous group
'group1{cycles,faults}
- group with name 'group1'
'{cycles,faults}:k
- anonymous group with event modifier 'k'
'{cpu-clock,task-clock},{minor-faults,major-faults}'
- two anonymous groups
The grouping functionality itself is coming shortly.
Reviewed-by: Namhyung Kim <[email protected]>
Signed-off-by: Jiri Olsa <[email protected]>
Acked-by: Peter Zijlstra <[email protected]>
Cc: Andi Kleen <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Ulrich Drepper <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/parse-events.c | 14 +++++-
tools/perf/util/parse-events.h | 4 +-
tools/perf/util/parse-events.l | 2 +
tools/perf/util/parse-events.y | 93 ++++++++++++++++++++++++++++++++++------
4 files changed, 97 insertions(+), 16 deletions(-)
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 3ec4bfc..57d5809 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -611,19 +611,29 @@ int parse_events_add_pmu(struct list_head **list, int *idx,
pmu_event_name(head_config));
}
+int parse_events__modifier_group(struct list_head *list __used,
+ char *event_mod __used)
+{
+ return 0;
+}
+
+void parse_events__group(char *name __used, struct list_head *list __used)
+{
+}
+
void parse_events_update_lists(struct list_head *list_event,
struct list_head *list_all)
{
/*
* Called for single event definition. Update the
- * 'all event' list, and reinit the 'signle event'
+ * 'all event' list, and reinit the 'single event'
* list, for next event definition.
*/
list_splice_tail(list_event, list_all);
free(list_event);
}
-int parse_events_modifier(struct list_head *list, char *str)
+int parse_events__modifier_event(struct list_head *list, char *str)
{
struct perf_evsel *evsel;
int exclude = 0, exclude_GH = 0;
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 00416d7..c3bb04c 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -79,7 +79,8 @@ int parse_events__term_str(struct parse_events__term **_term,
int parse_events__term_clone(struct parse_events__term **new,
struct parse_events__term *term);
void parse_events__free_terms(struct list_head *terms);
-int parse_events_modifier(struct list_head *list, char *str);
+int parse_events__modifier_event(struct list_head *list, char *str);
+int parse_events__modifier_group(struct list_head *list, char *event_mod);
int parse_events_add_tracepoint(struct list_head **list, int *idx,
char *sys, char *event);
int parse_events_add_numeric(struct list_head **list, int *idx,
@@ -91,6 +92,7 @@ int parse_events_add_breakpoint(struct list_head **list, int *idx,
void *ptr, char *type);
int parse_events_add_pmu(struct list_head **list, int *idx,
char *pmu , struct list_head *head_config);
+void parse_events__group(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);
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index e4abdf2..2c0d006 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -151,6 +151,8 @@ r{num_raw_hex} { return raw(yyscanner); }
- { return '-'; }
, { return ','; }
: { return ':'; }
+"{" { return '{'; }
+"}" { return '}'; }
= { return '='; }
\n { }
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 423d331..15e6e97 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -30,7 +30,7 @@ do { \
%token PE_NAME
%token PE_MODIFIER_EVENT PE_MODIFIER_BP
%token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT
-%token PE_PREFIX_MEM PE_PREFIX_RAW
+%token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP
%token PE_ERROR
%type <num> PE_VALUE
%type <num> PE_VALUE_SYM_HW
@@ -53,6 +53,11 @@ do { \
%type <head> event_legacy_numeric
%type <head> event_legacy_raw
%type <head> event_def
+%type <head> event
+%type <head> events
+%type <head> group_def
+%type <head> group
+%type <head> groups
%union
{
@@ -64,33 +69,95 @@ do { \
%%
start:
-PE_START_EVENTS events
+PE_START_EVENTS start_events
|
-PE_START_TERMS terms
+PE_START_TERMS start_terms
+
+start_events: groups
+{
+ struct parse_events_data__events *data = _data;
+
+ parse_events_update_lists($1, &data->list);
+}
+
+groups:
+groups ',' group
+{
+ struct list_head *list = $1;
+ struct list_head *group = $3;
+
+ parse_events_update_lists(group, list);
+ $$ = list;
+}
+|
+groups ',' event
+{
+ struct list_head *list = $1;
+ struct list_head *event = $3;
+
+ parse_events_update_lists(event, list);
+ $$ = list;
+}
+|
+group
+|
+event
+
+group:
+group_def ':' PE_MODIFIER_EVENT
+{
+ struct list_head *list = $1;
+
+ ABORT_ON(parse_events__modifier_group(list, $3));
+ $$ = list;
+}
+|
+group_def
+
+group_def:
+PE_NAME '{' events '}'
+{
+ struct list_head *list = $3;
+
+ parse_events__group($1, list);
+ $$ = list;
+}
+|
+'{' events '}'
+{
+ struct list_head *list = $2;
+
+ parse_events__group(NULL, list);
+ $$ = list;
+}
events:
-events ',' event | event
+events ',' event
+{
+ struct list_head *event = $3;
+ struct list_head *list = $1;
+
+ parse_events_update_lists(event, list);
+ $$ = list;
+}
+|
+event
event:
event_def PE_MODIFIER_EVENT
{
- struct parse_events_data__events *data = _data;
+ struct list_head *list = $1;
/*
* Apply modifier on all events added by single event definition
* (there could be more events added for multiple tracepoint
* definitions via '*?'.
*/
- ABORT_ON(parse_events_modifier($1, $2));
- parse_events_update_lists($1, &data->list);
+ ABORT_ON(parse_events__modifier_event(list, $2));
+ $$ = list;
}
|
event_def
-{
- struct parse_events_data__events *data = _data;
-
- parse_events_update_lists($1, &data->list);
-}
event_def: event_pmu |
event_legacy_symbol |
@@ -222,7 +289,7 @@ PE_RAW
$$ = list;
}
-terms: event_config
+start_terms: event_config
{
struct parse_events_data__terms *data = _data;
data->terms = $1;
--
1.7.1
From: Jiri Olsa <[email protected]>
Adding 5 more tests for new event group syntax. Tests are executed
within the 'perf test parse' test suite.
Reviewed-by: Namhyung Kim <[email protected]>
Signed-off-by: Jiri Olsa <[email protected]>
Acked-by: Peter Zijlstra <[email protected]>
Cc: Andi Kleen <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Ulrich Drepper <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/parse-events-test.c | 302 ++++++++++++++++++++++++++++++++++-
1 files changed, 299 insertions(+), 3 deletions(-)
diff --git a/tools/perf/util/parse-events-test.c b/tools/perf/util/parse-events-test.c
index 127d648..429dd68 100644
--- a/tools/perf/util/parse-events-test.c
+++ b/tools/perf/util/parse-events-test.c
@@ -513,6 +513,285 @@ static int test__checkterms_simple(struct list_head *terms)
return 0;
}
+static int test__group1(struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel, *leader;
+
+ TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
+
+ /* instructions:k */
+ evsel = leader = list_entry(evlist->entries.next,
+ struct perf_evsel, node);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong config",
+ PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
+ 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);
+
+ /* cycles:upp */
+ evsel = list_entry(evsel->node.next, struct perf_evsel, node);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong config",
+ PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
+ 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 == 2);
+ TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
+
+ return 0;
+}
+
+static int test__group2(struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel, *leader;
+
+ TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->nr_entries);
+
+ /* faults + :ku modifier */
+ evsel = leader = list_entry(evlist->entries.next,
+ struct perf_evsel, node);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong config",
+ PERF_COUNT_SW_PAGE_FAULTS == evsel->attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
+ 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);
+
+ /* cache-references + :u modifier */
+ evsel = list_entry(evsel->node.next, struct perf_evsel, node);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong config",
+ PERF_COUNT_HW_CACHE_REFERENCES == evsel->attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
+ 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 == leader);
+
+ /* cycles:k */
+ evsel = list_entry(evsel->node.next, struct perf_evsel, node);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong config",
+ PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
+ 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);
+
+ return 0;
+}
+
+static int test__group3(struct perf_evlist *evlist __used)
+{
+ struct perf_evsel *evsel, *leader;
+
+ TEST_ASSERT_VAL("wrong number of entries", 5 == evlist->nr_entries);
+
+ /* group1 syscalls:sys_enter_open:H */
+ evsel = leader = list_entry(evlist->entries.next,
+ struct perf_evsel, node);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong sample_type",
+ PERF_TP_SAMPLE_TYPE == evsel->attr.sample_type);
+ TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
+ 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 group name",
+ !strcmp(leader->group_name, "group1"));
+
+ /* group1 cycles:kppp */
+ evsel = list_entry(evsel->node.next, struct perf_evsel, node);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong config",
+ PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
+ 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 == 3);
+ TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
+ TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
+
+ /* group2 cycles + G modifier */
+ evsel = leader = list_entry(evsel->node.next, struct perf_evsel, node);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong config",
+ PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
+ 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 group name",
+ !strcmp(leader->group_name, "group2"));
+
+ /* group2 1:3 + G modifier */
+ evsel = list_entry(evsel->node.next, struct perf_evsel, node);
+ TEST_ASSERT_VAL("wrong type", 1 == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong config", 3 == evsel->attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
+ 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 == leader);
+
+ /* instructions:u */
+ evsel = list_entry(evsel->node.next, struct perf_evsel, node);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong config",
+ PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
+ 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);
+
+ return 0;
+}
+
+static int test__group4(struct perf_evlist *evlist __used)
+{
+ struct perf_evsel *evsel, *leader;
+
+ TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
+
+ /* cycles:u + p */
+ evsel = leader = list_entry(evlist->entries.next,
+ struct perf_evsel, node);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong config",
+ PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
+ 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 == 1);
+ TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
+ TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL);
+
+ /* instructions:kp + p */
+ evsel = list_entry(evsel->node.next, struct perf_evsel, node);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong config",
+ PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
+ 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 == 2);
+ TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
+
+ return 0;
+}
+
+static int test__group5(struct perf_evlist *evlist __used)
+{
+ struct perf_evsel *evsel, *leader;
+
+ TEST_ASSERT_VAL("wrong number of entries", 5 == evlist->nr_entries);
+
+ /* cycles + G */
+ evsel = leader = list_entry(evlist->entries.next,
+ struct perf_evsel, node);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong config",
+ PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
+ 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 group name", !evsel->group_name);
+ TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL);
+
+ /* instructions + G */
+ evsel = list_entry(evsel->node.next, struct perf_evsel, node);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong config",
+ PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
+ 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 == leader);
+
+ /* cycles:G */
+ evsel = leader = list_entry(evsel->node.next, struct perf_evsel, node);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong config",
+ PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
+ 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 group name", !evsel->group_name);
+ TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL);
+
+ /* instructions:G */
+ evsel = list_entry(evsel->node.next, struct perf_evsel, node);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong config",
+ PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
+ 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 == leader);
+
+ /* cycles */
+ evsel = list_entry(evsel->node.next, struct perf_evsel, node);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong config",
+ PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
+ TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
+ 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);
+
+ return 0;
+}
+
struct test__event_st {
const char *name;
__u32 type;
@@ -632,6 +911,26 @@ static struct test__event_st test__events[] = {
.name = "mem:0:rw:kp",
.check = test__checkevent_breakpoint_rw_modifier,
},
+ [28] = {
+ .name = "{instructions:k,cycles:upp}",
+ .check = test__group1,
+ },
+ [29] = {
+ .name = "{faults:k,cache-references}:u,cycles:k",
+ .check = test__group2,
+ },
+ [30] = {
+ .name = "group1{syscalls:sys_enter_open:H,cycles:kppp},group2{cycles,1:3}:G,instructions:u",
+ .check = test__group3,
+ },
+ [31] = {
+ .name = "{cycles:u,instructions:kp}:p",
+ .check = test__group4,
+ },
+ [32] = {
+ .name = "{cycles,instructions}:G,{cycles:G,instructions:G},cycles",
+ .check = test__group5,
+ },
};
static struct test__event_st test__events_pmu[] = {
@@ -658,9 +957,6 @@ static struct test__term test__terms[] = {
},
};
-#define TEST__TERMS_CNT (sizeof(test__terms) / \
- sizeof(struct test__term))
-
static int test_event(struct test__event_st *e)
{
struct perf_evlist *evlist;
--
1.7.1
From: Jiri Olsa <[email protected]>
This patch adds a functionality that allows to create event groups
based on the way they are specified on the command line. Adding
functionality to the '{}' group syntax introduced in earlier patch.
The current '--group/-g' option behaviour remains intact. If you
specify it for record/stat/top command, all the specified events
become members of a single group with the first event as a group
leader.
With the new '{}' group syntax you can create group like:
# perf record -e '{cycles,faults}' ls
resulting in single event group containing 'cycles' and 'faults'
events, with cycles event as group leader.
All groups are created with regards to threads and cpus. Thus
recording an event group within a 2 threads on server with
4 CPUs will create 8 separate groups.
Examples (first event in brackets is group leader):
# 1 group (cpu-clock,task-clock)
perf record --group -e cpu-clock,task-clock ls
perf record -e '{cpu-clock,task-clock}' ls
# 2 groups (cpu-clock,task-clock) (minor-faults,major-faults)
perf record -e '{cpu-clock,task-clock},{minor-faults,major-faults}' ls
# 1 group (cpu-clock,task-clock,minor-faults,major-faults)
perf record --group -e cpu-clock,task-clock -e minor-faults,major-faults ls
perf record -e '{cpu-clock,task-clock,minor-faults,major-faults}' ls
# 2 groups (cpu-clock,task-clock) (minor-faults,major-faults)
perf record -e '{cpu-clock,task-clock} -e '{minor-faults,major-faults}' \
-e instructions ls
# 1 group
# (cpu-clock,task-clock,minor-faults,major-faults,instructions)
perf record --group -e cpu-clock,task-clock \
-e minor-faults,major-faults -e instructions ls perf record -e
'{cpu-clock,task-clock,minor-faults,major-faults,instructions}' ls
It's possible to use standard event modifier for a group, which spans
over all events in the group and updates each event modifier settings,
for example:
# perf record -r '{faults:k,cache-references}:p'
resulting in ':kp' modifier being used for 'faults' and ':p' modifier
being used for 'cache-references' event.
Reviewed-by: Namhyung Kim <[email protected]>
Signed-off-by: Jiri Olsa <[email protected]>
Acked-by: Peter Zijlstra <[email protected]>
Cc: Andi Kleen <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Ulrich Drepper <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-record.c | 13 ++++------
tools/perf/builtin-stat.c | 13 ++++------
tools/perf/builtin-test.c | 8 +++---
tools/perf/builtin-top.c | 12 +++------
tools/perf/util/evlist.c | 20 +++++++--------
tools/perf/util/evlist.h | 3 +-
tools/perf/util/evsel.c | 51 ++++++++++++++++++++++++++-------------
tools/perf/util/evsel.h | 11 ++++----
tools/perf/util/parse-events.c | 26 +++++++++++++++++---
tools/perf/util/parse-events.h | 1 +
tools/perf/util/python.c | 7 ++++-
11 files changed, 96 insertions(+), 69 deletions(-)
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 22dd05d..f5b6137 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -185,18 +185,18 @@ static bool perf_evlist__equal(struct perf_evlist *evlist,
static void perf_record__open(struct perf_record *rec)
{
- struct perf_evsel *pos, *first;
+ struct perf_evsel *pos;
struct perf_evlist *evlist = rec->evlist;
struct perf_session *session = rec->session;
struct perf_record_opts *opts = &rec->opts;
- first = list_entry(evlist->entries.next, struct perf_evsel, node);
-
perf_evlist__config_attrs(evlist, opts);
+ if (opts->group)
+ perf_evlist__group(evlist);
+
list_for_each_entry(pos, &evlist->entries, node) {
struct perf_event_attr *attr = &pos->attr;
- struct xyarray *group_fd = NULL;
/*
* Check if parse_single_tracepoint_event has already asked for
* PERF_SAMPLE_TIME.
@@ -211,16 +211,13 @@ static void perf_record__open(struct perf_record *rec)
*/
bool time_needed = attr->sample_type & PERF_SAMPLE_TIME;
- if (opts->group && pos != first)
- group_fd = first->fd;
fallback_missing_features:
if (opts->exclude_guest_missing)
attr->exclude_guest = attr->exclude_host = 0;
retry_sample_id:
attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1;
try_again:
- if (perf_evsel__open(pos, evlist->cpus, evlist->threads,
- opts->group, group_fd) < 0) {
+ if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) {
int err = errno;
if (err == EPERM || err == EACCES) {
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 861f0ae..23908a8 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -281,13 +281,9 @@ static int create_perf_stat_counter(struct perf_evsel *evsel,
struct perf_evsel *first)
{
struct perf_event_attr *attr = &evsel->attr;
- struct xyarray *group_fd = NULL;
bool exclude_guest_missing = false;
int ret;
- if (group && evsel != first)
- group_fd = first->fd;
-
if (scale)
attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
PERF_FORMAT_TOTAL_TIME_RUNNING;
@@ -299,8 +295,7 @@ retry:
evsel->attr.exclude_guest = evsel->attr.exclude_host = 0;
if (perf_target__has_cpu(&target)) {
- ret = perf_evsel__open_per_cpu(evsel, evsel_list->cpus,
- group, group_fd);
+ ret = perf_evsel__open_per_cpu(evsel, evsel_list->cpus);
if (ret)
goto check_ret;
return 0;
@@ -311,8 +306,7 @@ retry:
attr->enable_on_exec = 1;
}
- ret = perf_evsel__open_per_thread(evsel, evsel_list->threads,
- group, group_fd);
+ ret = perf_evsel__open_per_thread(evsel, evsel_list->threads);
if (!ret)
return 0;
/* fall through */
@@ -483,6 +477,9 @@ static int run_perf_stat(int argc __used, const char **argv)
close(child_ready_pipe[0]);
}
+ if (group)
+ perf_evlist__group(evsel_list);
+
first = list_entry(evsel_list->entries.next, struct perf_evsel, node);
list_for_each_entry(counter, &evsel_list->entries, node) {
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c
index 1d592f5..9a479b6 100644
--- a/tools/perf/builtin-test.c
+++ b/tools/perf/builtin-test.c
@@ -294,7 +294,7 @@ static int test__open_syscall_event(void)
goto out_thread_map_delete;
}
- if (perf_evsel__open_per_thread(evsel, threads, false, NULL) < 0) {
+ 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));
@@ -369,7 +369,7 @@ static int test__open_syscall_event_on_all_cpus(void)
goto out_thread_map_delete;
}
- if (perf_evsel__open(evsel, cpus, threads, false, NULL) < 0) {
+ 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));
@@ -533,7 +533,7 @@ static int test__basic_mmap(void)
perf_evlist__add(evlist, evsels[i]);
- if (perf_evsel__open(evsels[i], cpus, threads, false, NULL) < 0) {
+ 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));
@@ -737,7 +737,7 @@ static int test__PERF_RECORD(void)
* Call sys_perf_event_open on all the fds on all the evsels,
* grouping them if asked to.
*/
- err = perf_evlist__open(evlist, opts.group);
+ err = perf_evlist__open(evlist);
if (err < 0) {
pr_debug("perf_evlist__open: %s\n", strerror(errno));
goto out_delete_evlist;
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index e45a1ba..392d219 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -886,17 +886,14 @@ static void perf_top__mmap_read(struct perf_top *top)
static void perf_top__start_counters(struct perf_top *top)
{
- struct perf_evsel *counter, *first;
+ struct perf_evsel *counter;
struct perf_evlist *evlist = top->evlist;
- first = list_entry(evlist->entries.next, struct perf_evsel, node);
+ if (top->group)
+ perf_evlist__group(evlist);
list_for_each_entry(counter, &evlist->entries, node) {
struct perf_event_attr *attr = &counter->attr;
- struct xyarray *group_fd = NULL;
-
- if (top->group && counter != first)
- group_fd = first->fd;
attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
@@ -927,8 +924,7 @@ retry_sample_id:
attr->sample_id_all = top->sample_id_all_missing ? 0 : 1;
try_again:
if (perf_evsel__open(counter, top->evlist->cpus,
- top->evlist->threads, top->group,
- group_fd) < 0) {
+ top->evlist->threads) < 0) {
int err = errno;
if (err == EPERM || err == EACCES) {
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 9b38681..feffee3 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -108,6 +108,12 @@ void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
evlist->nr_entries += nr_entries;
}
+void perf_evlist__group(struct perf_evlist *evlist)
+{
+ if (evlist->nr_entries)
+ parse_events__set_leader(&evlist->entries);
+}
+
int perf_evlist__add_default(struct perf_evlist *evlist)
{
struct perf_event_attr attr = {
@@ -757,21 +763,13 @@ void perf_evlist__set_selected(struct perf_evlist *evlist,
evlist->selected = evsel;
}
-int perf_evlist__open(struct perf_evlist *evlist, bool group)
+int perf_evlist__open(struct perf_evlist *evlist)
{
- struct perf_evsel *evsel, *first;
+ struct perf_evsel *evsel;
int err, ncpus, nthreads;
- first = list_entry(evlist->entries.next, struct perf_evsel, node);
-
list_for_each_entry(evsel, &evlist->entries, node) {
- struct xyarray *group_fd = NULL;
-
- if (group && evsel != first)
- group_fd = first->fd;
-
- err = perf_evsel__open(evsel, evlist->cpus, evlist->threads,
- group, group_fd);
+ err = perf_evsel__open(evsel, evlist->cpus, evlist->threads);
if (err < 0)
goto out_err;
}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 528c1ac..a19ccd7 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -85,7 +85,7 @@ struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id);
union perf_event *perf_evlist__mmap_read(struct perf_evlist *self, int idx);
-int perf_evlist__open(struct perf_evlist *evlist, bool group);
+int perf_evlist__open(struct perf_evlist *evlist);
void perf_evlist__config_attrs(struct perf_evlist *evlist,
struct perf_record_opts *opts);
@@ -132,4 +132,5 @@ void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
struct list_head *list,
int nr_entries);
+void perf_evlist__group(struct perf_evlist *evlist);
#endif /* __PERF_EVLIST_H */
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 9c54e8f..f5b68e7 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -21,7 +21,6 @@
#include "perf_regs.h"
#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
-#define GROUP_FD(group_fd, cpu) (*(int *)xyarray__entry(group_fd, cpu, 0))
static int __perf_evsel__sample_size(u64 sample_type)
{
@@ -493,6 +492,7 @@ void perf_evsel__delete(struct perf_evsel *evsel)
{
perf_evsel__exit(evsel);
close_cgroup(evsel->cgrp);
+ free(evsel->group_name);
free(evsel->name);
free(evsel);
}
@@ -568,9 +568,28 @@ int __perf_evsel__read(struct perf_evsel *evsel,
return 0;
}
+static int get_group_fd(struct perf_evsel *evsel, int cpu, int thread)
+{
+ struct perf_evsel *leader = evsel->leader;
+ int fd;
+
+ if (!leader)
+ return -1;
+
+ /*
+ * Leader must be already processed/open,
+ * if not it's a bug.
+ */
+ BUG_ON(!leader->fd);
+
+ fd = FD(leader, cpu, thread);
+ BUG_ON(fd == -1);
+
+ return fd;
+}
+
static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
- struct thread_map *threads, bool group,
- struct xyarray *group_fds)
+ struct thread_map *threads)
{
int cpu, thread;
unsigned long flags = 0;
@@ -586,13 +605,15 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
}
for (cpu = 0; cpu < cpus->nr; cpu++) {
- int group_fd = group_fds ? GROUP_FD(group_fds, cpu) : -1;
for (thread = 0; thread < threads->nr; thread++) {
+ int group_fd;
if (!evsel->cgrp)
pid = threads->map[thread];
+ group_fd = get_group_fd(evsel, cpu, thread);
+
FD(evsel, cpu, thread) = sys_perf_event_open(&evsel->attr,
pid,
cpus->map[cpu],
@@ -602,8 +623,9 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
goto out_close;
}
- if (group && group_fd == -1)
- group_fd = FD(evsel, cpu, thread);
+ pr_debug("event cpu %d, thread %d, fd %d, group %d\n",
+ cpu, pid, FD(evsel, cpu, thread),
+ group_fd);
}
}
@@ -647,8 +669,7 @@ static struct {
};
int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
- struct thread_map *threads, bool group,
- struct xyarray *group_fd)
+ struct thread_map *threads)
{
if (cpus == NULL) {
/* Work around old compiler warnings about strict aliasing */
@@ -658,23 +679,19 @@ int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
if (threads == NULL)
threads = &empty_thread_map.map;
- return __perf_evsel__open(evsel, cpus, threads, group, group_fd);
+ return __perf_evsel__open(evsel, cpus, threads);
}
int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
- struct cpu_map *cpus, bool group,
- struct xyarray *group_fd)
+ struct cpu_map *cpus)
{
- return __perf_evsel__open(evsel, cpus, &empty_thread_map.map, group,
- group_fd);
+ return __perf_evsel__open(evsel, cpus, &empty_thread_map.map);
}
int perf_evsel__open_per_thread(struct perf_evsel *evsel,
- struct thread_map *threads, bool group,
- struct xyarray *group_fd)
+ struct thread_map *threads)
{
- return __perf_evsel__open(evsel, &empty_cpu_map.map, threads, group,
- group_fd);
+ return __perf_evsel__open(evsel, &empty_cpu_map.map, threads);
}
static int perf_event__parse_id_sample(const union perf_event *event, u64 type,
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 6a258c9..c411b42 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -70,6 +70,8 @@ struct perf_evsel {
bool supported;
/* parse modifier helper */
int exclude_GH;
+ struct perf_evsel *leader;
+ char *group_name;
};
struct cpu_map;
@@ -109,14 +111,11 @@ void perf_evsel__free_id(struct perf_evsel *evsel);
void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
- struct cpu_map *cpus, bool group,
- struct xyarray *group_fds);
+ struct cpu_map *cpus);
int perf_evsel__open_per_thread(struct perf_evsel *evsel,
- struct thread_map *threads, bool group,
- struct xyarray *group_fds);
+ struct thread_map *threads);
int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
- struct thread_map *threads, bool group,
- struct xyarray *group_fds);
+ struct thread_map *threads);
void perf_evsel__close(struct perf_evsel *evsel, int ncpus, int nthreads);
#define perf_evsel__match(evsel, t, c) \
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 4364575..f6453cd 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -611,14 +611,32 @@ int parse_events_add_pmu(struct list_head **list, int *idx,
pmu_event_name(head_config));
}
-int parse_events__modifier_group(struct list_head *list __used,
- char *event_mod __used)
+struct perf_evsel *parse_events__set_leader(struct list_head *list)
{
- return 0;
+ 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)
+ evsel->leader = leader;
+
+ return leader;
}
-void parse_events__group(char *name __used, struct list_head *list __used)
+int parse_events__modifier_group(struct list_head *list,
+ char *event_mod)
{
+ return parse_events__modifier_event(list, event_mod, true);
+}
+
+void parse_events__group(char *name, struct list_head *list)
+{
+ struct perf_evsel *leader;
+
+ leader = parse_events__set_leader(list);
+ leader->group_name = name ? strdup(name) : NULL;
}
void parse_events_update_lists(struct list_head *list_event,
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 75a6800..e1a184c 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -92,6 +92,7 @@ int parse_events_add_breakpoint(struct list_head **list, int *idx,
void *ptr, char *type);
int parse_events_add_pmu(struct list_head **list, int *idx,
char *pmu , struct list_head *head_config);
+struct perf_evsel *parse_events__set_leader(struct list_head *list);
void parse_events__group(char *name, struct list_head *list);
void parse_events_update_lists(struct list_head *list_event,
struct list_head *list_all);
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 0688bfb..f5bba4b 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -627,7 +627,7 @@ static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel,
* This will group just the fds for this single evsel, to group
* multiple events, use evlist.open().
*/
- if (perf_evsel__open(evsel, cpus, threads, group, NULL) < 0) {
+ if (perf_evsel__open(evsel, cpus, threads) < 0) {
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
@@ -824,7 +824,10 @@ static PyObject *pyrf_evlist__open(struct pyrf_evlist *pevlist,
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist, &group))
return NULL;
- if (perf_evlist__open(evlist, group) < 0) {
+ if (group)
+ perf_evlist__group(evlist);
+
+ if (perf_evlist__open(evlist) < 0) {
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
--
1.7.1
From: Jiri Olsa <[email protected]>
Adding support to update already defined event's attribute with
event modifier. This change will allow to use group modifier as
an update to the existing event modifiers.
Adding 'add' parameter to the parse_events__modifier_event function.
Calling it with 'add' = false/true, the event modifier is
initialized/updated respectively.
Added exclude_GH flag to evsel struct, because we need to remember
if one of 'GH' modifiers was used for event. The reason is that the
default settings for exclude_guest is 1 and during the group
modifier processing we have no other way of knowing if it was set
by default or by event modifier.
Keeping the current behaviour, that any event/group modifier reset
the defaults for exclude_host (0) and exclude_guest (1).
Reviewed-by: Namhyung Kim <[email protected]>
Signed-off-by: Jiri Olsa <[email protected]>
Acked-by: Peter Zijlstra <[email protected]>
Cc: Andi Kleen <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Ulrich Drepper <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/evsel.h | 2 +
tools/perf/util/parse-events.c | 74 +++++++++++++++++++++++++++++++++------
tools/perf/util/parse-events.h | 2 +-
tools/perf/util/parse-events.y | 2 +-
4 files changed, 66 insertions(+), 14 deletions(-)
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index a56c457..6a258c9 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -68,6 +68,8 @@ struct perf_evsel {
} handler;
unsigned int sample_size;
bool supported;
+ /* parse modifier helper */
+ int exclude_GH;
};
struct cpu_map;
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 57d5809..4364575 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -633,14 +633,38 @@ void parse_events_update_lists(struct list_head *list_event,
free(list_event);
}
-int parse_events__modifier_event(struct list_head *list, char *str)
+struct event_modifier {
+ int eu;
+ int ek;
+ int eh;
+ int eH;
+ int eG;
+ int precise;
+ int exclude_GH;
+};
+
+static int get_event_modifier(struct event_modifier *mod, char *str,
+ struct perf_evsel *evsel)
{
- struct perf_evsel *evsel;
- int exclude = 0, exclude_GH = 0;
- int eu = 0, ek = 0, eh = 0, eH = 0, eG = 0, precise = 0;
+ int eu = evsel ? evsel->attr.exclude_user : 0;
+ int ek = evsel ? evsel->attr.exclude_kernel : 0;
+ int eh = evsel ? evsel->attr.exclude_hv : 0;
+ int eH = evsel ? evsel->attr.exclude_host : 0;
+ int eG = evsel ? evsel->attr.exclude_guest : 0;
+ int precise = evsel ? evsel->attr.precise_ip : 0;
- if (str == NULL)
- return 0;
+ int exclude = eu | ek | eh;
+ int exclude_GH = evsel ? evsel->exclude_GH : 0;
+
+ /*
+ * We are here for group and 'GH' was not set as event
+ * modifier and whatever event/group modifier override
+ * default 'GH' setup.
+ */
+ if (evsel && !exclude_GH)
+ eH = eG = 0;
+
+ memset(mod, 0, sizeof(*mod));
while (*str) {
if (*str == 'u') {
@@ -684,13 +708,39 @@ int parse_events__modifier_event(struct list_head *list, char *str)
if (precise > 3)
return -EINVAL;
+ mod->eu = eu;
+ mod->ek = ek;
+ mod->eh = eh;
+ mod->eH = eH;
+ mod->eG = eG;
+ mod->precise = precise;
+ mod->exclude_GH = exclude_GH;
+ return 0;
+}
+
+int parse_events__modifier_event(struct list_head *list, char *str, bool add)
+{
+ struct perf_evsel *evsel;
+ struct event_modifier mod;
+
+ if (str == NULL)
+ return 0;
+
+ if (!add && get_event_modifier(&mod, str, NULL))
+ return -EINVAL;
+
list_for_each_entry(evsel, list, node) {
- evsel->attr.exclude_user = eu;
- evsel->attr.exclude_kernel = ek;
- evsel->attr.exclude_hv = eh;
- evsel->attr.precise_ip = precise;
- evsel->attr.exclude_host = eH;
- evsel->attr.exclude_guest = eG;
+
+ if (add && get_event_modifier(&mod, str, evsel))
+ return -EINVAL;
+
+ evsel->attr.exclude_user = mod.eu;
+ evsel->attr.exclude_kernel = mod.ek;
+ evsel->attr.exclude_hv = mod.eh;
+ evsel->attr.precise_ip = mod.precise;
+ evsel->attr.exclude_host = mod.eH;
+ evsel->attr.exclude_guest = mod.eG;
+ evsel->exclude_GH = mod.exclude_GH;
}
return 0;
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index c3bb04c..75a6800 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -79,7 +79,7 @@ int parse_events__term_str(struct parse_events__term **_term,
int parse_events__term_clone(struct parse_events__term **new,
struct parse_events__term *term);
void parse_events__free_terms(struct list_head *terms);
-int parse_events__modifier_event(struct list_head *list, char *str);
+int parse_events__modifier_event(struct list_head *list, char *str, bool add);
int parse_events__modifier_group(struct list_head *list, char *event_mod);
int parse_events_add_tracepoint(struct list_head **list, int *idx,
char *sys, char *event);
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 15e6e97..084c35f 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -153,7 +153,7 @@ event_def PE_MODIFIER_EVENT
* (there could be more events added for multiple tracepoint
* definitions via '*?'.
*/
- ABORT_ON(parse_events__modifier_event(list, $2));
+ ABORT_ON(parse_events__modifier_event(list, $2, false));
$$ = list;
}
|
--
1.7.1
From: Namhyung Kim <[email protected]>
Separate out those functions into ui/stdio/hist.c. This is required for
upcoming changes.
Signed-off-by: Namhyung Kim <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/Makefile | 3 +-
tools/perf/ui/stdio/hist.c | 648 ++++++++++++++++++++++++++++++++++++++++++
tools/perf/util/hist.c | 677 ++------------------------------------------
tools/perf/util/hist.h | 2 +
4 files changed, 669 insertions(+), 661 deletions(-)
create mode 100644 tools/perf/ui/stdio/hist.c
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 77e7ae3..6bd888d 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -404,11 +404,10 @@ LIB_OBJS += $(OUTPUT)util/target.o
LIB_OBJS += $(OUTPUT)util/rblist.o
LIB_OBJS += $(OUTPUT)util/intlist.o
LIB_OBJS += $(OUTPUT)ui/helpline.o
+LIB_OBJS += $(OUTPUT)ui/stdio/hist.o
BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
-
BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
-
# Benchmark modules
BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o
BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
new file mode 100644
index 0000000..7881d62
--- /dev/null
+++ b/tools/perf/ui/stdio/hist.c
@@ -0,0 +1,648 @@
+#include <stdio.h>
+#include <math.h>
+
+#include "../../util/util.h"
+#include "../../util/hist.h"
+#include "../../util/sort.h"
+
+
+static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin)
+{
+ int i;
+ int ret = fprintf(fp, " ");
+
+ for (i = 0; i < left_margin; i++)
+ ret += fprintf(fp, " ");
+
+ return ret;
+}
+
+static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask,
+ int left_margin)
+{
+ int i;
+ size_t ret = callchain__fprintf_left_margin(fp, left_margin);
+
+ for (i = 0; i < depth; i++)
+ if (depth_mask & (1 << i))
+ ret += fprintf(fp, "| ");
+ else
+ ret += fprintf(fp, " ");
+
+ ret += fprintf(fp, "\n");
+
+ return ret;
+}
+
+static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain,
+ int depth, int depth_mask, int period,
+ u64 total_samples, u64 hits,
+ int left_margin)
+{
+ int i;
+ size_t ret = 0;
+
+ ret += callchain__fprintf_left_margin(fp, left_margin);
+ for (i = 0; i < depth; i++) {
+ if (depth_mask & (1 << i))
+ ret += fprintf(fp, "|");
+ else
+ ret += fprintf(fp, " ");
+ if (!period && i == depth - 1) {
+ double percent;
+
+ percent = hits * 100.0 / total_samples;
+ ret += percent_color_fprintf(fp, "--%2.2f%%-- ", percent);
+ } else
+ ret += fprintf(fp, "%s", " ");
+ }
+ if (chain->ms.sym)
+ ret += fprintf(fp, "%s\n", chain->ms.sym->name);
+ else
+ ret += fprintf(fp, "0x%0" PRIx64 "\n", chain->ip);
+
+ return ret;
+}
+
+static struct symbol *rem_sq_bracket;
+static struct callchain_list rem_hits;
+
+static void init_rem_hits(void)
+{
+ rem_sq_bracket = malloc(sizeof(*rem_sq_bracket) + 6);
+ if (!rem_sq_bracket) {
+ fprintf(stderr, "Not enough memory to display remaining hits\n");
+ return;
+ }
+
+ strcpy(rem_sq_bracket->name, "[...]");
+ rem_hits.ms.sym = rem_sq_bracket;
+}
+
+static size_t __callchain__fprintf_graph(FILE *fp, struct rb_root *root,
+ u64 total_samples, int depth,
+ int depth_mask, int left_margin)
+{
+ struct rb_node *node, *next;
+ struct callchain_node *child;
+ struct callchain_list *chain;
+ int new_depth_mask = depth_mask;
+ u64 remaining;
+ size_t ret = 0;
+ int i;
+ uint entries_printed = 0;
+
+ remaining = total_samples;
+
+ node = rb_first(root);
+ while (node) {
+ u64 new_total;
+ u64 cumul;
+
+ child = rb_entry(node, struct callchain_node, rb_node);
+ cumul = callchain_cumul_hits(child);
+ remaining -= cumul;
+
+ /*
+ * The depth mask manages the output of pipes that show
+ * the depth. We don't want to keep the pipes of the current
+ * level for the last child of this depth.
+ * Except if we have remaining filtered hits. They will
+ * supersede the last child
+ */
+ next = rb_next(node);
+ if (!next && (callchain_param.mode != CHAIN_GRAPH_REL || !remaining))
+ new_depth_mask &= ~(1 << (depth - 1));
+
+ /*
+ * But we keep the older depth mask for the line separator
+ * to keep the level link until we reach the last child
+ */
+ ret += ipchain__fprintf_graph_line(fp, depth, depth_mask,
+ left_margin);
+ i = 0;
+ list_for_each_entry(chain, &child->val, list) {
+ ret += ipchain__fprintf_graph(fp, chain, depth,
+ new_depth_mask, i++,
+ total_samples,
+ cumul,
+ left_margin);
+ }
+
+ if (callchain_param.mode == CHAIN_GRAPH_REL)
+ new_total = child->children_hit;
+ else
+ new_total = total_samples;
+
+ ret += __callchain__fprintf_graph(fp, &child->rb_root, new_total,
+ depth + 1,
+ new_depth_mask | (1 << depth),
+ left_margin);
+ node = next;
+ if (++entries_printed == callchain_param.print_limit)
+ break;
+ }
+
+ if (callchain_param.mode == CHAIN_GRAPH_REL &&
+ remaining && remaining != total_samples) {
+
+ if (!rem_sq_bracket)
+ return ret;
+
+ new_depth_mask &= ~(1 << (depth - 1));
+ ret += ipchain__fprintf_graph(fp, &rem_hits, depth,
+ new_depth_mask, 0, total_samples,
+ remaining, left_margin);
+ }
+
+ return ret;
+}
+
+static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
+ u64 total_samples, int left_margin)
+{
+ struct callchain_node *cnode;
+ struct callchain_list *chain;
+ u32 entries_printed = 0;
+ bool printed = false;
+ struct rb_node *node;
+ int i = 0;
+ int ret = 0;
+
+ /*
+ * If have one single callchain root, don't bother printing
+ * its percentage (100 % in fractal mode and the same percentage
+ * than the hist in graph mode). This also avoid one level of column.
+ */
+ node = rb_first(root);
+ if (node && !rb_next(node)) {
+ cnode = rb_entry(node, struct callchain_node, rb_node);
+ list_for_each_entry(chain, &cnode->val, list) {
+ /*
+ * If we sort by symbol, the first entry is the same than
+ * the symbol. No need to print it otherwise it appears as
+ * displayed twice.
+ */
+ if (!i++ && sort__first_dimension == SORT_SYM)
+ continue;
+ if (!printed) {
+ ret += callchain__fprintf_left_margin(fp, left_margin);
+ ret += fprintf(fp, "|\n");
+ ret += callchain__fprintf_left_margin(fp, left_margin);
+ ret += fprintf(fp, "---");
+ left_margin += 3;
+ printed = true;
+ } else
+ ret += callchain__fprintf_left_margin(fp, left_margin);
+
+ if (chain->ms.sym)
+ ret += fprintf(fp, " %s\n", chain->ms.sym->name);
+ else
+ ret += fprintf(fp, " %p\n", (void *)(long)chain->ip);
+
+ if (++entries_printed == callchain_param.print_limit)
+ break;
+ }
+ root = &cnode->rb_root;
+ }
+
+ ret += __callchain__fprintf_graph(fp, root, total_samples,
+ 1, 1, left_margin);
+ ret += fprintf(fp, "\n");
+
+ return ret;
+}
+
+static size_t __callchain__fprintf_flat(FILE *fp,
+ struct callchain_node *self,
+ u64 total_samples)
+{
+ struct callchain_list *chain;
+ size_t ret = 0;
+
+ if (!self)
+ return 0;
+
+ ret += __callchain__fprintf_flat(fp, self->parent, total_samples);
+
+
+ list_for_each_entry(chain, &self->val, list) {
+ if (chain->ip >= PERF_CONTEXT_MAX)
+ continue;
+ if (chain->ms.sym)
+ ret += fprintf(fp, " %s\n", chain->ms.sym->name);
+ else
+ ret += fprintf(fp, " %p\n",
+ (void *)(long)chain->ip);
+ }
+
+ return ret;
+}
+
+static size_t callchain__fprintf_flat(FILE *fp, struct rb_root *self,
+ u64 total_samples)
+{
+ size_t ret = 0;
+ u32 entries_printed = 0;
+ struct rb_node *rb_node;
+ struct callchain_node *chain;
+
+ rb_node = rb_first(self);
+ while (rb_node) {
+ double percent;
+
+ chain = rb_entry(rb_node, struct callchain_node, rb_node);
+ percent = chain->hit * 100.0 / total_samples;
+
+ ret = percent_color_fprintf(fp, " %6.2f%%\n", percent);
+ ret += __callchain__fprintf_flat(fp, chain, total_samples);
+ ret += fprintf(fp, "\n");
+ if (++entries_printed == callchain_param.print_limit)
+ break;
+
+ rb_node = rb_next(rb_node);
+ }
+
+ return ret;
+}
+
+static size_t hist_entry_callchain__fprintf(struct hist_entry *he,
+ u64 total_samples, int left_margin,
+ FILE *fp)
+{
+ switch (callchain_param.mode) {
+ case CHAIN_GRAPH_REL:
+ return callchain__fprintf_graph(fp, &he->sorted_chain, he->period,
+ left_margin);
+ break;
+ case CHAIN_GRAPH_ABS:
+ return callchain__fprintf_graph(fp, &he->sorted_chain, total_samples,
+ left_margin);
+ break;
+ case CHAIN_FLAT:
+ return callchain__fprintf_flat(fp, &he->sorted_chain, total_samples);
+ break;
+ case CHAIN_NONE:
+ break;
+ default:
+ pr_err("Bad callchain mode\n");
+ }
+
+ return 0;
+}
+
+static int hist_entry__pcnt_snprintf(struct hist_entry *he, char *s,
+ size_t size, struct hists *pair_hists,
+ bool show_displacement, long displacement,
+ bool color, u64 total_period)
+{
+ u64 period, total, period_sys, period_us, period_guest_sys, period_guest_us;
+ u64 nr_events;
+ const char *sep = symbol_conf.field_sep;
+ int ret;
+
+ if (symbol_conf.exclude_other && !he->parent)
+ return 0;
+
+ if (pair_hists) {
+ period = he->pair ? he->pair->period : 0;
+ nr_events = he->pair ? he->pair->nr_events : 0;
+ total = pair_hists->stats.total_period;
+ period_sys = he->pair ? he->pair->period_sys : 0;
+ period_us = he->pair ? he->pair->period_us : 0;
+ period_guest_sys = he->pair ? he->pair->period_guest_sys : 0;
+ period_guest_us = he->pair ? he->pair->period_guest_us : 0;
+ } else {
+ period = he->period;
+ nr_events = he->nr_events;
+ total = total_period;
+ period_sys = he->period_sys;
+ period_us = he->period_us;
+ period_guest_sys = he->period_guest_sys;
+ period_guest_us = he->period_guest_us;
+ }
+
+ if (total) {
+ if (color)
+ ret = percent_color_snprintf(s, size,
+ sep ? "%.2f" : " %6.2f%%",
+ (period * 100.0) / total);
+ else
+ ret = scnprintf(s, size, sep ? "%.2f" : " %6.2f%%",
+ (period * 100.0) / total);
+ if (symbol_conf.show_cpu_utilization) {
+ ret += percent_color_snprintf(s + ret, size - ret,
+ sep ? "%.2f" : " %6.2f%%",
+ (period_sys * 100.0) / total);
+ ret += percent_color_snprintf(s + ret, size - ret,
+ sep ? "%.2f" : " %6.2f%%",
+ (period_us * 100.0) / total);
+ if (perf_guest) {
+ ret += percent_color_snprintf(s + ret,
+ size - ret,
+ sep ? "%.2f" : " %6.2f%%",
+ (period_guest_sys * 100.0) /
+ total);
+ ret += percent_color_snprintf(s + ret,
+ size - ret,
+ sep ? "%.2f" : " %6.2f%%",
+ (period_guest_us * 100.0) /
+ total);
+ }
+ }
+ } else
+ ret = scnprintf(s, size, sep ? "%" PRIu64 : "%12" PRIu64 " ", period);
+
+ if (symbol_conf.show_nr_samples) {
+ if (sep)
+ ret += scnprintf(s + ret, size - ret, "%c%" PRIu64, *sep, nr_events);
+ else
+ ret += scnprintf(s + ret, size - ret, "%11" PRIu64, nr_events);
+ }
+
+ if (symbol_conf.show_total_period) {
+ if (sep)
+ ret += scnprintf(s + ret, size - ret, "%c%" PRIu64, *sep, period);
+ else
+ ret += scnprintf(s + ret, size - ret, " %12" PRIu64, period);
+ }
+
+ if (pair_hists) {
+ char bf[32];
+ double old_percent = 0, new_percent = 0, diff;
+
+ if (total > 0)
+ old_percent = (period * 100.0) / total;
+ if (total_period > 0)
+ new_percent = (he->period * 100.0) / total_period;
+
+ diff = new_percent - old_percent;
+
+ if (fabs(diff) >= 0.01)
+ scnprintf(bf, sizeof(bf), "%+4.2F%%", diff);
+ else
+ scnprintf(bf, sizeof(bf), " ");
+
+ if (sep)
+ ret += scnprintf(s + ret, size - ret, "%c%s", *sep, bf);
+ else
+ ret += scnprintf(s + ret, size - ret, "%11.11s", bf);
+
+ if (show_displacement) {
+ if (displacement)
+ scnprintf(bf, sizeof(bf), "%+4ld", displacement);
+ else
+ scnprintf(bf, sizeof(bf), " ");
+
+ if (sep)
+ ret += scnprintf(s + ret, size - ret, "%c%s", *sep, bf);
+ else
+ ret += scnprintf(s + ret, size - ret, "%6.6s", bf);
+ }
+ }
+
+ return ret;
+}
+
+int hist_entry__snprintf(struct hist_entry *he, char *s, size_t size,
+ struct hists *hists)
+{
+ const char *sep = symbol_conf.field_sep;
+ struct sort_entry *se;
+ int ret = 0;
+
+ list_for_each_entry(se, &hist_entry__sort_list, list) {
+ if (se->elide)
+ continue;
+
+ ret += scnprintf(s + ret, size - ret, "%s", sep ?: " ");
+ ret += se->se_snprintf(he, s + ret, size - ret,
+ hists__col_len(hists, se->se_width_idx));
+ }
+
+ return ret;
+}
+
+static int hist_entry__fprintf(struct hist_entry *he, size_t size,
+ struct hists *hists, struct hists *pair_hists,
+ bool show_displacement, long displacement,
+ u64 total_period, FILE *fp)
+{
+ char bf[512];
+ int ret;
+
+ if (size == 0 || size > sizeof(bf))
+ size = sizeof(bf);
+
+ ret = hist_entry__pcnt_snprintf(he, bf, size, pair_hists,
+ show_displacement, displacement,
+ true, total_period);
+ hist_entry__snprintf(he, bf + ret, size - ret, hists);
+ return fprintf(fp, "%s\n", bf);
+}
+
+static size_t hist_entry__fprintf_callchain(struct hist_entry *he,
+ struct hists *hists,
+ u64 total_period, FILE *fp)
+{
+ int left_margin = 0;
+
+ if (sort__first_dimension == SORT_COMM) {
+ struct sort_entry *se = list_first_entry(&hist_entry__sort_list,
+ typeof(*se), list);
+ left_margin = hists__col_len(hists, se->se_width_idx);
+ left_margin -= thread__comm_len(he->thread);
+ }
+
+ return hist_entry_callchain__fprintf(he, total_period, left_margin, fp);
+}
+
+size_t hists__fprintf(struct hists *hists, struct hists *pair,
+ bool show_displacement, bool show_header, int max_rows,
+ int max_cols, FILE *fp)
+{
+ struct sort_entry *se;
+ struct rb_node *nd;
+ size_t ret = 0;
+ u64 total_period;
+ unsigned long position = 1;
+ long displacement = 0;
+ unsigned int width;
+ const char *sep = symbol_conf.field_sep;
+ const char *col_width = symbol_conf.col_width_list_str;
+ int nr_rows = 0;
+
+ init_rem_hits();
+
+ if (!show_header)
+ goto print_entries;
+
+ fprintf(fp, "# %s", pair ? "Baseline" : "Overhead");
+
+ if (symbol_conf.show_cpu_utilization) {
+ if (sep) {
+ ret += fprintf(fp, "%csys", *sep);
+ ret += fprintf(fp, "%cus", *sep);
+ if (perf_guest) {
+ ret += fprintf(fp, "%cguest sys", *sep);
+ ret += fprintf(fp, "%cguest us", *sep);
+ }
+ } else {
+ ret += fprintf(fp, " sys ");
+ ret += fprintf(fp, " us ");
+ if (perf_guest) {
+ ret += fprintf(fp, " guest sys ");
+ ret += fprintf(fp, " guest us ");
+ }
+ }
+ }
+
+ if (symbol_conf.show_nr_samples) {
+ if (sep)
+ fprintf(fp, "%cSamples", *sep);
+ else
+ fputs(" Samples ", fp);
+ }
+
+ if (symbol_conf.show_total_period) {
+ if (sep)
+ ret += fprintf(fp, "%cPeriod", *sep);
+ else
+ ret += fprintf(fp, " Period ");
+ }
+
+ if (pair) {
+ if (sep)
+ ret += fprintf(fp, "%cDelta", *sep);
+ else
+ ret += fprintf(fp, " Delta ");
+
+ if (show_displacement) {
+ if (sep)
+ ret += fprintf(fp, "%cDisplacement", *sep);
+ else
+ ret += fprintf(fp, " Displ");
+ }
+ }
+
+ list_for_each_entry(se, &hist_entry__sort_list, list) {
+ if (se->elide)
+ continue;
+ if (sep) {
+ fprintf(fp, "%c%s", *sep, se->se_header);
+ continue;
+ }
+ width = strlen(se->se_header);
+ if (symbol_conf.col_width_list_str) {
+ if (col_width) {
+ hists__set_col_len(hists, se->se_width_idx,
+ atoi(col_width));
+ col_width = strchr(col_width, ',');
+ if (col_width)
+ ++col_width;
+ }
+ }
+ if (!hists__new_col_len(hists, se->se_width_idx, width))
+ width = hists__col_len(hists, se->se_width_idx);
+ fprintf(fp, " %*s", width, se->se_header);
+ }
+
+ fprintf(fp, "\n");
+ if (max_rows && ++nr_rows >= max_rows)
+ goto out;
+
+ if (sep)
+ goto print_entries;
+
+ fprintf(fp, "# ........");
+ if (symbol_conf.show_cpu_utilization)
+ fprintf(fp, " ....... .......");
+ if (symbol_conf.show_nr_samples)
+ fprintf(fp, " ..........");
+ if (symbol_conf.show_total_period)
+ fprintf(fp, " ............");
+ if (pair) {
+ fprintf(fp, " ..........");
+ if (show_displacement)
+ fprintf(fp, " .....");
+ }
+ list_for_each_entry(se, &hist_entry__sort_list, list) {
+ unsigned int i;
+
+ if (se->elide)
+ continue;
+
+ fprintf(fp, " ");
+ width = hists__col_len(hists, se->se_width_idx);
+ if (width == 0)
+ width = strlen(se->se_header);
+ for (i = 0; i < width; i++)
+ fprintf(fp, ".");
+ }
+
+ fprintf(fp, "\n");
+ if (max_rows && ++nr_rows >= max_rows)
+ goto out;
+
+ fprintf(fp, "#\n");
+ if (max_rows && ++nr_rows >= max_rows)
+ goto out;
+
+print_entries:
+ total_period = hists->stats.total_period;
+
+ for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
+ struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
+
+ if (h->filtered)
+ continue;
+
+ if (show_displacement) {
+ if (h->pair != NULL)
+ displacement = ((long)h->pair->position -
+ (long)position);
+ else
+ displacement = 0;
+ ++position;
+ }
+ ret += hist_entry__fprintf(h, max_cols, hists, pair, show_displacement,
+ displacement, total_period, fp);
+
+ if (symbol_conf.use_callchain)
+ ret += hist_entry__fprintf_callchain(h, hists, total_period, fp);
+ if (max_rows && ++nr_rows >= max_rows)
+ goto out;
+
+ if (h->ms.map == NULL && verbose > 1) {
+ __map_groups__fprintf_maps(&h->thread->mg,
+ MAP__FUNCTION, verbose, fp);
+ fprintf(fp, "%.10s end\n", graph_dotted_line);
+ }
+ }
+out:
+ free(rem_sq_bracket);
+
+ return ret;
+}
+
+size_t hists__fprintf_nr_events(struct hists *hists, FILE *fp)
+{
+ int i;
+ size_t ret = 0;
+
+ for (i = 0; i < PERF_RECORD_HEADER_MAX; ++i) {
+ const char *name;
+
+ if (hists->stats.nr_events[i] == 0)
+ continue;
+
+ name = perf_event__name(i);
+ if (!strcmp(name, "UNKNOWN"))
+ continue;
+
+ ret += fprintf(fp, "%16s events: %10d\n", name,
+ hists->stats.nr_events[i]);
+ }
+
+ return ret;
+}
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index f247ef2..b1817f1 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -45,7 +45,7 @@ bool hists__new_col_len(struct hists *hists, enum hist_column col, u16 len)
return false;
}
-static void hists__reset_col_len(struct hists *hists)
+void hists__reset_col_len(struct hists *hists)
{
enum hist_column col;
@@ -63,7 +63,7 @@ static void hists__set_unres_dso_col_len(struct hists *hists, int dso)
hists__set_col_len(hists, dso, unresolved_col_width);
}
-static void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
+void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
{
const unsigned int unresolved_col_width = BITS_PER_LONG / 4;
u16 len;
@@ -114,6 +114,22 @@ static void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
}
}
+void hists__output_recalc_col_len(struct hists *hists, int max_rows)
+{
+ struct rb_node *next = rb_first(&hists->entries);
+ struct hist_entry *n;
+ int row = 0;
+
+ hists__reset_col_len(hists);
+
+ while (next && row++ < max_rows) {
+ n = rb_entry(next, struct hist_entry, rb_node);
+ if (!n->filtered)
+ hists__calc_col_len(hists, n);
+ next = rb_next(&n->rb_node);
+ }
+}
+
static void hist_entry__add_cpumode_period(struct hist_entry *he,
unsigned int cpumode, u64 period)
{
@@ -547,641 +563,6 @@ void hists__output_resort_threaded(struct hists *hists)
return __hists__output_resort(hists, true);
}
-static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin)
-{
- int i;
- int ret = fprintf(fp, " ");
-
- for (i = 0; i < left_margin; i++)
- ret += fprintf(fp, " ");
-
- return ret;
-}
-
-static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask,
- int left_margin)
-{
- int i;
- size_t ret = callchain__fprintf_left_margin(fp, left_margin);
-
- for (i = 0; i < depth; i++)
- if (depth_mask & (1 << i))
- ret += fprintf(fp, "| ");
- else
- ret += fprintf(fp, " ");
-
- ret += fprintf(fp, "\n");
-
- return ret;
-}
-
-static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain,
- int depth, int depth_mask, int period,
- u64 total_samples, u64 hits,
- int left_margin)
-{
- int i;
- size_t ret = 0;
-
- ret += callchain__fprintf_left_margin(fp, left_margin);
- for (i = 0; i < depth; i++) {
- if (depth_mask & (1 << i))
- ret += fprintf(fp, "|");
- else
- ret += fprintf(fp, " ");
- if (!period && i == depth - 1) {
- double percent;
-
- percent = hits * 100.0 / total_samples;
- ret += percent_color_fprintf(fp, "--%2.2f%%-- ", percent);
- } else
- ret += fprintf(fp, "%s", " ");
- }
- if (chain->ms.sym)
- ret += fprintf(fp, "%s\n", chain->ms.sym->name);
- else
- ret += fprintf(fp, "0x%0" PRIx64 "\n", chain->ip);
-
- return ret;
-}
-
-static struct symbol *rem_sq_bracket;
-static struct callchain_list rem_hits;
-
-static void init_rem_hits(void)
-{
- rem_sq_bracket = malloc(sizeof(*rem_sq_bracket) + 6);
- if (!rem_sq_bracket) {
- fprintf(stderr, "Not enough memory to display remaining hits\n");
- return;
- }
-
- strcpy(rem_sq_bracket->name, "[...]");
- rem_hits.ms.sym = rem_sq_bracket;
-}
-
-static size_t __callchain__fprintf_graph(FILE *fp, struct rb_root *root,
- u64 total_samples, int depth,
- int depth_mask, int left_margin)
-{
- struct rb_node *node, *next;
- struct callchain_node *child;
- struct callchain_list *chain;
- int new_depth_mask = depth_mask;
- u64 remaining;
- size_t ret = 0;
- int i;
- uint entries_printed = 0;
-
- remaining = total_samples;
-
- node = rb_first(root);
- while (node) {
- u64 new_total;
- u64 cumul;
-
- child = rb_entry(node, struct callchain_node, rb_node);
- cumul = callchain_cumul_hits(child);
- remaining -= cumul;
-
- /*
- * The depth mask manages the output of pipes that show
- * the depth. We don't want to keep the pipes of the current
- * level for the last child of this depth.
- * Except if we have remaining filtered hits. They will
- * supersede the last child
- */
- next = rb_next(node);
- if (!next && (callchain_param.mode != CHAIN_GRAPH_REL || !remaining))
- new_depth_mask &= ~(1 << (depth - 1));
-
- /*
- * But we keep the older depth mask for the line separator
- * to keep the level link until we reach the last child
- */
- ret += ipchain__fprintf_graph_line(fp, depth, depth_mask,
- left_margin);
- i = 0;
- list_for_each_entry(chain, &child->val, list) {
- ret += ipchain__fprintf_graph(fp, chain, depth,
- new_depth_mask, i++,
- total_samples,
- cumul,
- left_margin);
- }
-
- if (callchain_param.mode == CHAIN_GRAPH_REL)
- new_total = child->children_hit;
- else
- new_total = total_samples;
-
- ret += __callchain__fprintf_graph(fp, &child->rb_root, new_total,
- depth + 1,
- new_depth_mask | (1 << depth),
- left_margin);
- node = next;
- if (++entries_printed == callchain_param.print_limit)
- break;
- }
-
- if (callchain_param.mode == CHAIN_GRAPH_REL &&
- remaining && remaining != total_samples) {
-
- if (!rem_sq_bracket)
- return ret;
-
- new_depth_mask &= ~(1 << (depth - 1));
- ret += ipchain__fprintf_graph(fp, &rem_hits, depth,
- new_depth_mask, 0, total_samples,
- remaining, left_margin);
- }
-
- return ret;
-}
-
-static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
- u64 total_samples, int left_margin)
-{
- struct callchain_node *cnode;
- struct callchain_list *chain;
- u32 entries_printed = 0;
- bool printed = false;
- struct rb_node *node;
- int i = 0;
- int ret = 0;
-
- /*
- * If have one single callchain root, don't bother printing
- * its percentage (100 % in fractal mode and the same percentage
- * than the hist in graph mode). This also avoid one level of column.
- */
- node = rb_first(root);
- if (node && !rb_next(node)) {
- cnode = rb_entry(node, struct callchain_node, rb_node);
- list_for_each_entry(chain, &cnode->val, list) {
- /*
- * If we sort by symbol, the first entry is the same than
- * the symbol. No need to print it otherwise it appears as
- * displayed twice.
- */
- if (!i++ && sort__first_dimension == SORT_SYM)
- continue;
- if (!printed) {
- ret += callchain__fprintf_left_margin(fp, left_margin);
- ret += fprintf(fp, "|\n");
- ret += callchain__fprintf_left_margin(fp, left_margin);
- ret += fprintf(fp, "---");
- left_margin += 3;
- printed = true;
- } else
- ret += callchain__fprintf_left_margin(fp, left_margin);
-
- if (chain->ms.sym)
- ret += fprintf(fp, " %s\n", chain->ms.sym->name);
- else
- ret += fprintf(fp, " %p\n", (void *)(long)chain->ip);
-
- if (++entries_printed == callchain_param.print_limit)
- break;
- }
- root = &cnode->rb_root;
- }
-
- ret += __callchain__fprintf_graph(fp, root, total_samples,
- 1, 1, left_margin);
- ret += fprintf(fp, "\n");
-
- return ret;
-}
-
-static size_t __callchain__fprintf_flat(FILE *fp,
- struct callchain_node *self,
- u64 total_samples)
-{
- struct callchain_list *chain;
- size_t ret = 0;
-
- if (!self)
- return 0;
-
- ret += __callchain__fprintf_flat(fp, self->parent, total_samples);
-
-
- list_for_each_entry(chain, &self->val, list) {
- if (chain->ip >= PERF_CONTEXT_MAX)
- continue;
- if (chain->ms.sym)
- ret += fprintf(fp, " %s\n", chain->ms.sym->name);
- else
- ret += fprintf(fp, " %p\n",
- (void *)(long)chain->ip);
- }
-
- return ret;
-}
-
-static size_t callchain__fprintf_flat(FILE *fp, struct rb_root *self,
- u64 total_samples)
-{
- size_t ret = 0;
- u32 entries_printed = 0;
- struct rb_node *rb_node;
- struct callchain_node *chain;
-
- rb_node = rb_first(self);
- while (rb_node) {
- double percent;
-
- chain = rb_entry(rb_node, struct callchain_node, rb_node);
- percent = chain->hit * 100.0 / total_samples;
-
- ret = percent_color_fprintf(fp, " %6.2f%%\n", percent);
- ret += __callchain__fprintf_flat(fp, chain, total_samples);
- ret += fprintf(fp, "\n");
- if (++entries_printed == callchain_param.print_limit)
- break;
-
- rb_node = rb_next(rb_node);
- }
-
- return ret;
-}
-
-static size_t hist_entry_callchain__fprintf(struct hist_entry *he,
- u64 total_samples, int left_margin,
- FILE *fp)
-{
- switch (callchain_param.mode) {
- case CHAIN_GRAPH_REL:
- return callchain__fprintf_graph(fp, &he->sorted_chain, he->period,
- left_margin);
- break;
- case CHAIN_GRAPH_ABS:
- return callchain__fprintf_graph(fp, &he->sorted_chain, total_samples,
- left_margin);
- break;
- case CHAIN_FLAT:
- return callchain__fprintf_flat(fp, &he->sorted_chain, total_samples);
- break;
- case CHAIN_NONE:
- break;
- default:
- pr_err("Bad callchain mode\n");
- }
-
- return 0;
-}
-
-void hists__output_recalc_col_len(struct hists *hists, int max_rows)
-{
- struct rb_node *next = rb_first(&hists->entries);
- struct hist_entry *n;
- int row = 0;
-
- hists__reset_col_len(hists);
-
- while (next && row++ < max_rows) {
- n = rb_entry(next, struct hist_entry, rb_node);
- if (!n->filtered)
- hists__calc_col_len(hists, n);
- next = rb_next(&n->rb_node);
- }
-}
-
-static int hist_entry__pcnt_snprintf(struct hist_entry *he, char *s,
- size_t size, struct hists *pair_hists,
- bool show_displacement, long displacement,
- bool color, u64 total_period)
-{
- u64 period, total, period_sys, period_us, period_guest_sys, period_guest_us;
- u64 nr_events;
- const char *sep = symbol_conf.field_sep;
- int ret;
-
- if (symbol_conf.exclude_other && !he->parent)
- return 0;
-
- if (pair_hists) {
- period = he->pair ? he->pair->period : 0;
- nr_events = he->pair ? he->pair->nr_events : 0;
- total = pair_hists->stats.total_period;
- period_sys = he->pair ? he->pair->period_sys : 0;
- period_us = he->pair ? he->pair->period_us : 0;
- period_guest_sys = he->pair ? he->pair->period_guest_sys : 0;
- period_guest_us = he->pair ? he->pair->period_guest_us : 0;
- } else {
- period = he->period;
- nr_events = he->nr_events;
- total = total_period;
- period_sys = he->period_sys;
- period_us = he->period_us;
- period_guest_sys = he->period_guest_sys;
- period_guest_us = he->period_guest_us;
- }
-
- if (total) {
- if (color)
- ret = percent_color_snprintf(s, size,
- sep ? "%.2f" : " %6.2f%%",
- (period * 100.0) / total);
- else
- ret = scnprintf(s, size, sep ? "%.2f" : " %6.2f%%",
- (period * 100.0) / total);
- if (symbol_conf.show_cpu_utilization) {
- ret += percent_color_snprintf(s + ret, size - ret,
- sep ? "%.2f" : " %6.2f%%",
- (period_sys * 100.0) / total);
- ret += percent_color_snprintf(s + ret, size - ret,
- sep ? "%.2f" : " %6.2f%%",
- (period_us * 100.0) / total);
- if (perf_guest) {
- ret += percent_color_snprintf(s + ret,
- size - ret,
- sep ? "%.2f" : " %6.2f%%",
- (period_guest_sys * 100.0) /
- total);
- ret += percent_color_snprintf(s + ret,
- size - ret,
- sep ? "%.2f" : " %6.2f%%",
- (period_guest_us * 100.0) /
- total);
- }
- }
- } else
- ret = scnprintf(s, size, sep ? "%" PRIu64 : "%12" PRIu64 " ", period);
-
- if (symbol_conf.show_nr_samples) {
- if (sep)
- ret += scnprintf(s + ret, size - ret, "%c%" PRIu64, *sep, nr_events);
- else
- ret += scnprintf(s + ret, size - ret, "%11" PRIu64, nr_events);
- }
-
- if (symbol_conf.show_total_period) {
- if (sep)
- ret += scnprintf(s + ret, size - ret, "%c%" PRIu64, *sep, period);
- else
- ret += scnprintf(s + ret, size - ret, " %12" PRIu64, period);
- }
-
- if (pair_hists) {
- char bf[32];
- double old_percent = 0, new_percent = 0, diff;
-
- if (total > 0)
- old_percent = (period * 100.0) / total;
- if (total_period > 0)
- new_percent = (he->period * 100.0) / total_period;
-
- diff = new_percent - old_percent;
-
- if (fabs(diff) >= 0.01)
- scnprintf(bf, sizeof(bf), "%+4.2F%%", diff);
- else
- scnprintf(bf, sizeof(bf), " ");
-
- if (sep)
- ret += scnprintf(s + ret, size - ret, "%c%s", *sep, bf);
- else
- ret += scnprintf(s + ret, size - ret, "%11.11s", bf);
-
- if (show_displacement) {
- if (displacement)
- scnprintf(bf, sizeof(bf), "%+4ld", displacement);
- else
- scnprintf(bf, sizeof(bf), " ");
-
- if (sep)
- ret += scnprintf(s + ret, size - ret, "%c%s", *sep, bf);
- else
- ret += scnprintf(s + ret, size - ret, "%6.6s", bf);
- }
- }
-
- return ret;
-}
-
-int hist_entry__snprintf(struct hist_entry *he, char *s, size_t size,
- struct hists *hists)
-{
- const char *sep = symbol_conf.field_sep;
- struct sort_entry *se;
- int ret = 0;
-
- list_for_each_entry(se, &hist_entry__sort_list, list) {
- if (se->elide)
- continue;
-
- ret += scnprintf(s + ret, size - ret, "%s", sep ?: " ");
- ret += se->se_snprintf(he, s + ret, size - ret,
- hists__col_len(hists, se->se_width_idx));
- }
-
- return ret;
-}
-
-static int hist_entry__fprintf(struct hist_entry *he, size_t size,
- struct hists *hists, struct hists *pair_hists,
- bool show_displacement, long displacement,
- u64 total_period, FILE *fp)
-{
- char bf[512];
- int ret;
-
- if (size == 0 || size > sizeof(bf))
- size = sizeof(bf);
-
- ret = hist_entry__pcnt_snprintf(he, bf, size, pair_hists,
- show_displacement, displacement,
- true, total_period);
- hist_entry__snprintf(he, bf + ret, size - ret, hists);
- return fprintf(fp, "%s\n", bf);
-}
-
-static size_t hist_entry__fprintf_callchain(struct hist_entry *he,
- struct hists *hists,
- u64 total_period, FILE *fp)
-{
- int left_margin = 0;
-
- if (sort__first_dimension == SORT_COMM) {
- struct sort_entry *se = list_first_entry(&hist_entry__sort_list,
- typeof(*se), list);
- left_margin = hists__col_len(hists, se->se_width_idx);
- left_margin -= thread__comm_len(he->thread);
- }
-
- return hist_entry_callchain__fprintf(he, total_period, left_margin, fp);
-}
-
-size_t hists__fprintf(struct hists *hists, struct hists *pair,
- bool show_displacement, bool show_header, int max_rows,
- int max_cols, FILE *fp)
-{
- struct sort_entry *se;
- struct rb_node *nd;
- size_t ret = 0;
- u64 total_period;
- unsigned long position = 1;
- long displacement = 0;
- unsigned int width;
- const char *sep = symbol_conf.field_sep;
- const char *col_width = symbol_conf.col_width_list_str;
- int nr_rows = 0;
-
- init_rem_hits();
-
- if (!show_header)
- goto print_entries;
-
- fprintf(fp, "# %s", pair ? "Baseline" : "Overhead");
-
- if (symbol_conf.show_cpu_utilization) {
- if (sep) {
- ret += fprintf(fp, "%csys", *sep);
- ret += fprintf(fp, "%cus", *sep);
- if (perf_guest) {
- ret += fprintf(fp, "%cguest sys", *sep);
- ret += fprintf(fp, "%cguest us", *sep);
- }
- } else {
- ret += fprintf(fp, " sys ");
- ret += fprintf(fp, " us ");
- if (perf_guest) {
- ret += fprintf(fp, " guest sys ");
- ret += fprintf(fp, " guest us ");
- }
- }
- }
-
- if (symbol_conf.show_nr_samples) {
- if (sep)
- fprintf(fp, "%cSamples", *sep);
- else
- fputs(" Samples ", fp);
- }
-
- if (symbol_conf.show_total_period) {
- if (sep)
- ret += fprintf(fp, "%cPeriod", *sep);
- else
- ret += fprintf(fp, " Period ");
- }
-
- if (pair) {
- if (sep)
- ret += fprintf(fp, "%cDelta", *sep);
- else
- ret += fprintf(fp, " Delta ");
-
- if (show_displacement) {
- if (sep)
- ret += fprintf(fp, "%cDisplacement", *sep);
- else
- ret += fprintf(fp, " Displ");
- }
- }
-
- list_for_each_entry(se, &hist_entry__sort_list, list) {
- if (se->elide)
- continue;
- if (sep) {
- fprintf(fp, "%c%s", *sep, se->se_header);
- continue;
- }
- width = strlen(se->se_header);
- if (symbol_conf.col_width_list_str) {
- if (col_width) {
- hists__set_col_len(hists, se->se_width_idx,
- atoi(col_width));
- col_width = strchr(col_width, ',');
- if (col_width)
- ++col_width;
- }
- }
- if (!hists__new_col_len(hists, se->se_width_idx, width))
- width = hists__col_len(hists, se->se_width_idx);
- fprintf(fp, " %*s", width, se->se_header);
- }
-
- fprintf(fp, "\n");
- if (max_rows && ++nr_rows >= max_rows)
- goto out;
-
- if (sep)
- goto print_entries;
-
- fprintf(fp, "# ........");
- if (symbol_conf.show_cpu_utilization)
- fprintf(fp, " ....... .......");
- if (symbol_conf.show_nr_samples)
- fprintf(fp, " ..........");
- if (symbol_conf.show_total_period)
- fprintf(fp, " ............");
- if (pair) {
- fprintf(fp, " ..........");
- if (show_displacement)
- fprintf(fp, " .....");
- }
- list_for_each_entry(se, &hist_entry__sort_list, list) {
- unsigned int i;
-
- if (se->elide)
- continue;
-
- fprintf(fp, " ");
- width = hists__col_len(hists, se->se_width_idx);
- if (width == 0)
- width = strlen(se->se_header);
- for (i = 0; i < width; i++)
- fprintf(fp, ".");
- }
-
- fprintf(fp, "\n");
- if (max_rows && ++nr_rows >= max_rows)
- goto out;
-
- fprintf(fp, "#\n");
- if (max_rows && ++nr_rows >= max_rows)
- goto out;
-
-print_entries:
- total_period = hists->stats.total_period;
-
- for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
- struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
-
- if (h->filtered)
- continue;
-
- if (show_displacement) {
- if (h->pair != NULL)
- displacement = ((long)h->pair->position -
- (long)position);
- else
- displacement = 0;
- ++position;
- }
- ret += hist_entry__fprintf(h, max_cols, hists, pair, show_displacement,
- displacement, total_period, fp);
-
- if (symbol_conf.use_callchain)
- ret += hist_entry__fprintf_callchain(h, hists, total_period, fp);
- if (max_rows && ++nr_rows >= max_rows)
- goto out;
-
- if (h->ms.map == NULL && verbose > 1) {
- __map_groups__fprintf_maps(&h->thread->mg,
- MAP__FUNCTION, verbose, fp);
- fprintf(fp, "%.10s end\n", graph_dotted_line);
- }
- }
-out:
- free(rem_sq_bracket);
-
- return ret;
-}
-
/*
* See hists__fprintf to match the column widths
*/
@@ -1342,25 +723,3 @@ void hists__inc_nr_events(struct hists *hists, u32 type)
++hists->stats.nr_events[0];
++hists->stats.nr_events[type];
}
-
-size_t hists__fprintf_nr_events(struct hists *hists, FILE *fp)
-{
- int i;
- size_t ret = 0;
-
- for (i = 0; i < PERF_RECORD_HEADER_MAX; ++i) {
- const char *name;
-
- if (hists->stats.nr_events[i] == 0)
- continue;
-
- name = perf_event__name(i);
- if (!strcmp(name, "UNKNOWN"))
- continue;
-
- ret += fprintf(fp, "%16s events: %10d\n", name,
- hists->stats.nr_events[i]);
- }
-
- return ret;
-}
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 0b096c2..69fab7d 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -112,6 +112,8 @@ void hists__filter_by_symbol(struct hists *hists);
u16 hists__col_len(struct hists *self, enum hist_column col);
void hists__set_col_len(struct hists *self, enum hist_column col, u16 len);
bool hists__new_col_len(struct hists *self, enum hist_column col, u16 len);
+void hists__reset_col_len(struct hists *hists);
+void hists__calc_col_len(struct hists *hists, struct hist_entry *he);
struct perf_evlist;
--
1.7.1
From: Namhyung Kim <[email protected]>
Rename functions for consistency and move callchain print function
into hist_entry__fprintf().
Signed-off-by: Namhyung Kim <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/ui/browsers/hists.c | 4 +-
tools/perf/ui/stdio/hist.c | 51 ++++++++++++++++++++++------------------
tools/perf/util/hist.h | 4 +-
3 files changed, 32 insertions(+), 27 deletions(-)
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index b809469..81bd8c2 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -586,7 +586,7 @@ static int hist_browser__show_entry(struct hist_browser *browser,
}
if (row_offset == 0) {
- hist_entry__snprintf(entry, s, sizeof(s), browser->hists);
+ hist_entry__sort_snprintf(entry, s, sizeof(s), browser->hists);
percent = (entry->period * 100.0) / browser->hists->stats.total_period;
ui_browser__set_percent_color(&browser->b, percent, current_entry);
@@ -931,7 +931,7 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser,
if (symbol_conf.use_callchain)
folded_sign = hist_entry__folded(he);
- hist_entry__snprintf(he, s, sizeof(s), browser->hists);
+ hist_entry__sort_snprintf(he, s, sizeof(s), browser->hists);
percent = (he->period * 100.0) / browser->hists->stats.total_period;
if (symbol_conf.use_callchain)
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index 7881d62..9bf7e9e 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -291,7 +291,7 @@ static size_t hist_entry_callchain__fprintf(struct hist_entry *he,
return 0;
}
-static int hist_entry__pcnt_snprintf(struct hist_entry *he, char *s,
+static int hist_entry__period_snprintf(struct hist_entry *he, char *s,
size_t size, struct hists *pair_hists,
bool show_displacement, long displacement,
bool color, u64 total_period)
@@ -404,8 +404,8 @@ static int hist_entry__pcnt_snprintf(struct hist_entry *he, char *s,
return ret;
}
-int hist_entry__snprintf(struct hist_entry *he, char *s, size_t size,
- struct hists *hists)
+int hist_entry__sort_snprintf(struct hist_entry *he, char *s, size_t size,
+ struct hists *hists)
{
const char *sep = symbol_conf.field_sep;
struct sort_entry *se;
@@ -423,6 +423,22 @@ int hist_entry__snprintf(struct hist_entry *he, char *s, size_t size,
return ret;
}
+static size_t hist_entry__callchain_fprintf(struct hist_entry *he,
+ struct hists *hists,
+ u64 total_period, FILE *fp)
+{
+ int left_margin = 0;
+
+ if (sort__first_dimension == SORT_COMM) {
+ struct sort_entry *se = list_first_entry(&hist_entry__sort_list,
+ typeof(*se), list);
+ left_margin = hists__col_len(hists, se->se_width_idx);
+ left_margin -= thread__comm_len(he->thread);
+ }
+
+ return hist_entry_callchain__fprintf(he, total_period, left_margin, fp);
+}
+
static int hist_entry__fprintf(struct hist_entry *he, size_t size,
struct hists *hists, struct hists *pair_hists,
bool show_displacement, long displacement,
@@ -434,27 +450,18 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size,
if (size == 0 || size > sizeof(bf))
size = sizeof(bf);
- ret = hist_entry__pcnt_snprintf(he, bf, size, pair_hists,
- show_displacement, displacement,
- true, total_period);
- hist_entry__snprintf(he, bf + ret, size - ret, hists);
- return fprintf(fp, "%s\n", bf);
-}
+ ret = hist_entry__period_snprintf(he, bf, size, pair_hists,
+ show_displacement, displacement,
+ true, total_period);
+ hist_entry__sort_snprintf(he, bf + ret, size - ret, hists);
-static size_t hist_entry__fprintf_callchain(struct hist_entry *he,
- struct hists *hists,
- u64 total_period, FILE *fp)
-{
- int left_margin = 0;
+ ret = fprintf(fp, "%s\n", bf);
- if (sort__first_dimension == SORT_COMM) {
- struct sort_entry *se = list_first_entry(&hist_entry__sort_list,
- typeof(*se), list);
- left_margin = hists__col_len(hists, se->se_width_idx);
- left_margin -= thread__comm_len(he->thread);
- }
+ if (symbol_conf.use_callchain)
+ ret += hist_entry__callchain_fprintf(he, hists,
+ total_period, fp);
- return hist_entry_callchain__fprintf(he, total_period, left_margin, fp);
+ return ret;
}
size_t hists__fprintf(struct hists *hists, struct hists *pair,
@@ -608,8 +615,6 @@ print_entries:
ret += hist_entry__fprintf(h, max_cols, hists, pair, show_displacement,
displacement, total_period, fp);
- if (symbol_conf.use_callchain)
- ret += hist_entry__fprintf_callchain(h, hists, total_period, fp);
if (max_rows && ++nr_rows >= max_rows)
goto out;
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 69fab7d..2e650ff 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -75,8 +75,8 @@ struct hist_entry *__hists__add_entry(struct hists *self,
struct symbol *parent, u64 period);
int64_t hist_entry__cmp(struct hist_entry *left, struct hist_entry *right);
int64_t hist_entry__collapse(struct hist_entry *left, struct hist_entry *right);
-int hist_entry__snprintf(struct hist_entry *self, char *bf, size_t size,
- struct hists *hists);
+int hist_entry__sort_snprintf(struct hist_entry *self, char *bf, size_t size,
+ struct hists *hists);
void hist_entry__free(struct hist_entry *);
struct hist_entry *__hists__add_branch_entry(struct hists *self,
--
1.7.1
From: Steven Rostedt <[email protected]>
When I did a compile of perf using a relative path for the output
directory, the build failed when it tried to compile libtraceevent. This
is because it continues to use the same relative path when the new
working directory is in a different path.
SUBDIR ../lib/traceevent/
/bin/sh: line 0: cd: ../../../nobackup/perf/: No such file or directory
Makefile:74: *** output directory "../../../nobackup/perf/" does not exist. Stop.
make: *** [../../../nobackup/perf///libtraceevent.a] Error 2
Make the path used an absolute path when building perf with O=.
Boris:
Teach Makefile to check whether the supplied O= directory exists and
bail out if not. Reportedly, kernel dudes are idiots and need to be
guarded so as not to shoot themselves in the foot when playing in the
sandbox.
Signed-off-by: Borislav Petkov <[email protected]>
Signed-off-by: Steven Rostedt <[email protected]>
Acked-by: Steven Rostedt <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/scripts/Makefile.include | 6 ++++--
1 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/tools/scripts/Makefile.include b/tools/scripts/Makefile.include
index bde8521..96ce80a 100644
--- a/tools/scripts/Makefile.include
+++ b/tools/scripts/Makefile.include
@@ -1,6 +1,8 @@
ifeq ("$(origin O)", "command line")
- OUTPUT := $(O)/
- COMMAND_O := O=$(O)
+ dummy := $(if $(shell test -d $(O) || echo $(O)),$(error O=$(O) does not exist),)
+ ABSOLUTE_O := $(shell cd $(O) ; pwd)
+ OUTPUT := $(ABSOLUTE_O)/
+ COMMAND_O := O=$(ABSOLUTE_O)
endif
ifneq ($(OUTPUT),)
--
1.7.1
From: Namhyung Kim <[email protected]>
If 'perf script --gen-script' was called with a perf.data which contains
no tracepoint event, it'd segfault due to NULL pevent pointer. Fix it.
Signed-off-by: Namhyung Kim <[email protected]>
Cc: Feng Tang <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/trace-event-parse.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index 4cb7f38..a5a554e 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -293,7 +293,7 @@ struct event_format *trace_find_next_event(struct pevent *pevent,
{
static int idx;
- if (!pevent->events)
+ if (!pevent || !pevent->events)
return NULL;
if (!event) {
--
1.7.1
From: Robert Richter <[email protected]>
Trivial patch to improve understanding of code.
Varible attr is usually used for struct perf_event_attr. Using it in a
different context is irritating. Thus, renaming it.
Signed-off-by: Robert Richter <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/header.c | 42 +++++++++++++++++++++---------------------
1 files changed, 21 insertions(+), 21 deletions(-)
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 471b0c4..e2e5129 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -608,11 +608,11 @@ static int write_nrcpus(int fd, struct perf_header *h __used,
static int write_event_desc(int fd, struct perf_header *h __used,
struct perf_evlist *evlist)
{
- struct perf_evsel *attr;
+ struct perf_evsel *evsel;
u32 nre = 0, nri, sz;
int ret;
- list_for_each_entry(attr, &evlist->entries, node)
+ list_for_each_entry(evsel, &evlist->entries, node)
nre++;
/*
@@ -625,14 +625,14 @@ static int write_event_desc(int fd, struct perf_header *h __used,
/*
* size of perf_event_attr struct
*/
- sz = (u32)sizeof(attr->attr);
+ sz = (u32)sizeof(evsel->attr);
ret = do_write(fd, &sz, sizeof(sz));
if (ret < 0)
return ret;
- list_for_each_entry(attr, &evlist->entries, node) {
+ list_for_each_entry(evsel, &evlist->entries, node) {
- ret = do_write(fd, &attr->attr, sz);
+ ret = do_write(fd, &evsel->attr, sz);
if (ret < 0)
return ret;
/*
@@ -642,7 +642,7 @@ static int write_event_desc(int fd, struct perf_header *h __used,
* copy into an nri to be independent of the
* type of ids,
*/
- nri = attr->ids;
+ nri = evsel->ids;
ret = do_write(fd, &nri, sizeof(nri));
if (ret < 0)
return ret;
@@ -650,13 +650,13 @@ static int write_event_desc(int fd, struct perf_header *h __used,
/*
* write event string as passed on cmdline
*/
- ret = do_write_string(fd, perf_evsel__name(attr));
+ ret = do_write_string(fd, perf_evsel__name(evsel));
if (ret < 0)
return ret;
/*
* write unique ids for this event
*/
- ret = do_write(fd, attr->id, attr->ids * sizeof(u64));
+ ret = do_write(fd, evsel->id, evsel->ids * sizeof(u64));
if (ret < 0)
return ret;
}
@@ -1683,7 +1683,7 @@ int perf_session__write_header(struct perf_session *session,
struct perf_file_header f_header;
struct perf_file_attr f_attr;
struct perf_header *header = &session->header;
- struct perf_evsel *attr, *pair = NULL;
+ struct perf_evsel *evsel, *pair = NULL;
int err;
lseek(fd, sizeof(f_header), SEEK_SET);
@@ -1691,9 +1691,9 @@ int perf_session__write_header(struct perf_session *session,
if (session->evlist != evlist)
pair = perf_evlist__first(session->evlist);
- list_for_each_entry(attr, &evlist->entries, node) {
- attr->id_offset = lseek(fd, 0, SEEK_CUR);
- err = do_write(fd, attr->id, attr->ids * sizeof(u64));
+ list_for_each_entry(evsel, &evlist->entries, node) {
+ evsel->id_offset = lseek(fd, 0, SEEK_CUR);
+ err = do_write(fd, evsel->id, evsel->ids * sizeof(u64));
if (err < 0) {
out_err_write:
pr_debug("failed to write perf header\n");
@@ -1703,19 +1703,19 @@ out_err_write:
err = do_write(fd, pair->id, pair->ids * sizeof(u64));
if (err < 0)
goto out_err_write;
- attr->ids += pair->ids;
+ evsel->ids += pair->ids;
pair = perf_evsel__next(pair);
}
}
header->attr_offset = lseek(fd, 0, SEEK_CUR);
- list_for_each_entry(attr, &evlist->entries, node) {
+ list_for_each_entry(evsel, &evlist->entries, node) {
f_attr = (struct perf_file_attr){
- .attr = attr->attr,
+ .attr = evsel->attr,
.ids = {
- .offset = attr->id_offset,
- .size = attr->ids * sizeof(u64),
+ .offset = evsel->id_offset,
+ .size = evsel->ids * sizeof(u64),
}
};
err = do_write(fd, &f_attr, sizeof(f_attr));
@@ -2277,12 +2277,12 @@ int perf_event__synthesize_attrs(struct perf_tool *tool,
struct perf_session *session,
perf_event__handler_t process)
{
- struct perf_evsel *attr;
+ struct perf_evsel *evsel;
int err = 0;
- list_for_each_entry(attr, &session->evlist->entries, node) {
- err = perf_event__synthesize_attr(tool, &attr->attr, attr->ids,
- attr->id, process);
+ list_for_each_entry(evsel, &session->evlist->entries, node) {
+ err = perf_event__synthesize_attr(tool, &evsel->attr, evsel->ids,
+ evsel->id, process);
if (err) {
pr_debug("failed to create perf header attribute\n");
return err;
--
1.7.1
From: Robert Richter <[email protected]>
If detection fails and an event name is unknown, report the type number.
Example perf header output:
# Samples: 10K of event 'unknown attr type: 7'
Signed-off-by: Robert Richter <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/evsel.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 6c7dcc1..7ff3c8f 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -319,7 +319,8 @@ const char *perf_evsel__name(struct perf_evsel *evsel)
break;
default:
- scnprintf(bf, sizeof(bf), "%s", "unknown attr type");
+ scnprintf(bf, sizeof(bf), "unknown attr type: %d",
+ evsel->attr.type);
break;
}
--
1.7.1
From: Robert Richter <[email protected]>
Use same type for ids everywhere.
In case of writing to perf.data the size is u32. In pipe mode it is
limited to header.size (less than u16). Adding a size check here.
Size overflow due to casting shouldn't actually happen in practice, but
during development this may cause type missmatch warninngs/errors,
unifying types avoids this.
Signed-off-by: Robert Richter <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/evsel.h | 2 +-
tools/perf/util/header.c | 11 +++++++----
tools/perf/util/header.h | 2 +-
3 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 65f39fd..94f6ba1 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -53,7 +53,7 @@ struct perf_evsel {
u64 *id;
struct perf_counts *counts;
int idx;
- int ids;
+ u32 ids;
struct hists hists;
char *name;
struct event_format *tp_format;
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 77832b8..471b0c4 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2240,7 +2240,7 @@ out_delete_evlist:
}
int perf_event__synthesize_attr(struct perf_tool *tool,
- struct perf_event_attr *attr, u16 ids, u64 *id,
+ struct perf_event_attr *attr, u32 ids, u64 *id,
perf_event__handler_t process)
{
union perf_event *ev;
@@ -2261,9 +2261,12 @@ int perf_event__synthesize_attr(struct perf_tool *tool,
memcpy(ev->attr.id, id, ids * sizeof(u64));
ev->attr.header.type = PERF_RECORD_HEADER_ATTR;
- ev->attr.header.size = size;
+ ev->attr.header.size = (u16)size;
- err = process(tool, ev, NULL, NULL);
+ if (ev->attr.header.size == size)
+ err = process(tool, ev, NULL, NULL);
+ else
+ err = -E2BIG;
free(ev);
@@ -2292,7 +2295,7 @@ int perf_event__synthesize_attrs(struct perf_tool *tool,
int perf_event__process_attr(union perf_event *event,
struct perf_evlist **pevlist)
{
- unsigned int i, ids, n_ids;
+ u32 i, ids, n_ids;
struct perf_evsel *evsel;
struct perf_evlist *evlist = *pevlist;
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 2d42b3e..24962e7 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -99,7 +99,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir);
int perf_event__synthesize_attr(struct perf_tool *tool,
- struct perf_event_attr *attr, u16 ids, u64 *id,
+ struct perf_event_attr *attr, u32 ids, u64 *id,
perf_event__handler_t process);
int perf_event__synthesize_attrs(struct perf_tool *tool,
struct perf_session *session,
--
1.7.1
From: Ben Hutchings <[email protected]>
When we use a separate output directory, we add util/ to the include
path for the generated C files. However, this is currently added to the
end of the path, behind /usr/include/slang and /usr/include/gtk-2.0 if
use of the respective libraries is enabled. Thus the '#include
"../perf.h"' in util/parse-events.l can actually include
/usr/include/perf.h if it exists.
Move '-Iutil/' ahead of all the other preprocessor options.
Reported-by: Sedat Dilek <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Sedat Dilek <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/Makefile | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 90cfecf..77e7ae3 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -841,10 +841,10 @@ $(OUTPUT)perf.o perf.spec \
# over the general rule for .o
$(OUTPUT)util/%-flex.o: $(OUTPUT)util/%-flex.c $(OUTPUT)PERF-CFLAGS
- $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -Iutil/ -w $<
+ $(QUIET_CC)$(CC) -o $@ -c -Iutil/ $(ALL_CFLAGS) -w $<
$(OUTPUT)util/%-bison.o: $(OUTPUT)util/%-bison.c $(OUTPUT)PERF-CFLAGS
- $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -Iutil/ -w $<
+ $(QUIET_CC)$(CC) -o $@ -c -Iutil/ $(ALL_CFLAGS) -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w $<
$(OUTPUT)%.o: %.c $(OUTPUT)PERF-CFLAGS
$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $<
--
1.7.1
From: David Ahern <[email protected]>
The libexec path is /libexec/perf-core/scripts/*/Perf-Trace-Util.
Signed-off-by: David Ahern <[email protected]>
Cc: Ingo Molnar <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/Documentation/perf-script-perl.txt | 4 ++--
tools/perf/Documentation/perf-script-python.txt | 10 +++++-----
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/tools/perf/Documentation/perf-script-perl.txt b/tools/perf/Documentation/perf-script-perl.txt
index 3152cca..d00bef2 100644
--- a/tools/perf/Documentation/perf-script-perl.txt
+++ b/tools/perf/Documentation/perf-script-perl.txt
@@ -116,8 +116,8 @@ search path and 'use'ing a few support modules (see module
descriptions below):
----
- use lib "$ENV{'PERF_EXEC_PATH'}/scripts/perl/perf-script-Util/lib";
- use lib "./perf-script-Util/lib";
+ use lib "$ENV{'PERF_EXEC_PATH'}/scripts/perl/Perf-Trace-Util/lib";
+ use lib "./Perf-Trace-Util/lib";
use Perf::Trace::Core;
use Perf::Trace::Context;
use Perf::Trace::Util;
diff --git a/tools/perf/Documentation/perf-script-python.txt b/tools/perf/Documentation/perf-script-python.txt
index 4710220..a4027f2 100644
--- a/tools/perf/Documentation/perf-script-python.txt
+++ b/tools/perf/Documentation/perf-script-python.txt
@@ -129,7 +129,7 @@ import os
import sys
sys.path.append(os.environ['PERF_EXEC_PATH'] + \
- '/scripts/python/perf-script-Util/lib/Perf/Trace')
+ '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
from perf_trace_context import *
from Core import *
@@ -216,7 +216,7 @@ import os
import sys
sys.path.append(os.environ['PERF_EXEC_PATH'] + \
- '/scripts/python/perf-script-Util/lib/Perf/Trace')
+ '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
from perf_trace_context import *
from Core import *
@@ -279,7 +279,7 @@ import os
import sys
sys.path.append(os.environ['PERF_EXEC_PATH'] + \
- '/scripts/python/perf-script-Util/lib/Perf/Trace')
+ '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
from perf_trace_context import *
from Core import *
@@ -391,7 +391,7 @@ drwxr-xr-x 4 trz trz 4096 2010-01-26 22:30 .
drwxr-xr-x 4 trz trz 4096 2010-01-26 22:29 ..
drwxr-xr-x 2 trz trz 4096 2010-01-26 22:29 bin
-rw-r--r-- 1 trz trz 2548 2010-01-26 22:29 check-perf-script.py
-drwxr-xr-x 3 trz trz 4096 2010-01-26 22:49 perf-script-Util
+drwxr-xr-x 3 trz trz 4096 2010-01-26 22:49 Perf-Trace-Util
-rw-r--r-- 1 trz trz 1462 2010-01-26 22:30 syscall-counts.py
----
@@ -518,7 +518,7 @@ descriptions below):
import sys
sys.path.append(os.environ['PERF_EXEC_PATH'] + \
- '/scripts/python/perf-script-Util/lib/Perf/Trace')
+ '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
from perf_trace_context import *
from Core import *
--
1.7.1
From: Arnaldo Carvalho de Melo <[email protected]>
Just like was done for parse_events__set_leader.
Also we need to have the list_entry set_leader method in evlist.c so that we
don't grow another dep in the python binding:
# ~acme/git/linux/tools/perf/python/twatch.py
Traceback (most recent call last):
File "/home/acme/git/linux/tools/perf/python/twatch.py", line 16, in <module>
import perf
ImportError: /home/acme/git/build/perf/python/perf.so: undefined symbol: parse_events__set_leader
And also remove a pr_debug from evsel.c so that we avoid this one too:
# ~acme/git/linux/tools/perf/python/twatch.py
Traceback (most recent call last):
File "/home/acme/git/linux/tools/perf/python/twatch.py", line 16, in <module>
import perf
ImportError: /home/acme/git/build/perf/python/perf.so: undefined symbol: eprintf
Acked-by: Jiri Olsa <[email protected]>
Acked-by: Namhyung Kim <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-record.c | 2 +-
tools/perf/builtin-stat.c | 2 +-
tools/perf/builtin-top.c | 2 +-
tools/perf/util/evlist.c | 17 +++++++++++++++--
tools/perf/util/evlist.h | 5 +++--
tools/perf/util/evsel.c | 4 ----
tools/perf/util/parse-events.c | 19 +++----------------
tools/perf/util/parse-events.h | 3 +--
tools/perf/util/parse-events.y | 4 ++--
tools/perf/util/python.c | 2 +-
10 files changed, 28 insertions(+), 32 deletions(-)
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index f5b6137..c4e3b68 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -193,7 +193,7 @@ static void perf_record__open(struct perf_record *rec)
perf_evlist__config_attrs(evlist, opts);
if (opts->group)
- perf_evlist__group(evlist);
+ perf_evlist__set_leader(evlist);
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 23908a8..7b9c463 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -478,7 +478,7 @@ static int run_perf_stat(int argc __used, const char **argv)
}
if (group)
- perf_evlist__group(evsel_list);
+ perf_evlist__set_leader(evsel_list);
first = list_entry(evsel_list->entries.next, struct perf_evsel, node);
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 392d219..5a097be 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -890,7 +890,7 @@ static void perf_top__start_counters(struct perf_top *top)
struct perf_evlist *evlist = top->evlist;
if (top->group)
- perf_evlist__group(evlist);
+ perf_evlist__set_leader(evlist);
list_for_each_entry(counter, &evlist->entries, node) {
struct perf_event_attr *attr = &counter->attr;
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index feffee3..6d09451 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -108,10 +108,23 @@ void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
evlist->nr_entries += nr_entries;
}
-void perf_evlist__group(struct perf_evlist *evlist)
+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)
+ evsel->leader = leader;
+ }
+}
+
+void perf_evlist__set_leader(struct perf_evlist *evlist)
{
if (evlist->nr_entries)
- parse_events__set_leader(&evlist->entries);
+ __perf_evlist__set_leader(&evlist->entries);
}
int perf_evlist__add_default(struct perf_evlist *evlist)
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index a19ccd7..7fe677e 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -118,6 +118,9 @@ int perf_evlist__create_maps(struct perf_evlist *evlist,
void perf_evlist__delete_maps(struct perf_evlist *evlist);
int perf_evlist__set_filters(struct perf_evlist *evlist);
+void __perf_evlist__set_leader(struct list_head *list);
+void perf_evlist__set_leader(struct perf_evlist *evlist);
+
u64 perf_evlist__sample_type(const struct perf_evlist *evlist);
bool perf_evlist__sample_id_all(const const struct perf_evlist *evlist);
u16 perf_evlist__id_hdr_size(const struct perf_evlist *evlist);
@@ -131,6 +134,4 @@ bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist);
void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
struct list_head *list,
int nr_entries);
-
-void perf_evlist__group(struct perf_evlist *evlist);
#endif /* __PERF_EVLIST_H */
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index f5b68e7..6c7dcc1 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -622,10 +622,6 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
err = -errno;
goto out_close;
}
-
- pr_debug("event cpu %d, thread %d, fd %d, group %d\n",
- cpu, pid, FD(evsel, cpu, thread),
- group_fd);
}
}
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index f6453cd..4393a6b 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -611,31 +611,18 @@ int parse_events_add_pmu(struct list_head **list, int *idx,
pmu_event_name(head_config));
}
-struct perf_evsel *parse_events__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)
- evsel->leader = leader;
-
- return leader;
-}
-
int parse_events__modifier_group(struct list_head *list,
char *event_mod)
{
return parse_events__modifier_event(list, event_mod, true);
}
-void parse_events__group(char *name, struct list_head *list)
+void parse_events__set_leader(char *name, struct list_head *list)
{
struct perf_evsel *leader;
- leader = parse_events__set_leader(list);
+ __perf_evlist__set_leader(list);
+ leader = list_entry(list->next, struct perf_evsel, node);
leader->group_name = name ? strdup(name) : NULL;
}
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index e1a184c..0b9782d 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -92,8 +92,7 @@ int parse_events_add_breakpoint(struct list_head **list, int *idx,
void *ptr, char *type);
int parse_events_add_pmu(struct list_head **list, int *idx,
char *pmu , struct list_head *head_config);
-struct perf_evsel *parse_events__set_leader(struct list_head *list);
-void parse_events__group(char *name, struct list_head *list);
+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);
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 084c35f..66850f8 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -119,7 +119,7 @@ PE_NAME '{' events '}'
{
struct list_head *list = $3;
- parse_events__group($1, list);
+ parse_events__set_leader($1, list);
$$ = list;
}
|
@@ -127,7 +127,7 @@ PE_NAME '{' events '}'
{
struct list_head *list = $2;
- parse_events__group(NULL, list);
+ parse_events__set_leader(NULL, list);
$$ = list;
}
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index f5bba4b..27187f0 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -825,7 +825,7 @@ static PyObject *pyrf_evlist__open(struct pyrf_evlist *pevlist,
return NULL;
if (group)
- perf_evlist__group(evlist);
+ perf_evlist__set_leader(evlist);
if (perf_evlist__open(evlist) < 0) {
PyErr_SetFromErrno(PyExc_OSError);
--
1.7.1
From: Arnaldo Carvalho de Melo <[email protected]>
To replace the longer list_entry constructs for things that are widely
used:
perf_evlist__{first,last}(evlist)
perf_evsel__next(evsel)
Acked-by: Jiri Olsa <[email protected]>
Acked-by: Namhyung Kim <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-record.c | 4 +-
tools/perf/builtin-stat.c | 2 +-
tools/perf/builtin-test.c | 2 +-
tools/perf/builtin-top.c | 6 +-
tools/perf/util/evlist.c | 40 ++++-------
tools/perf/util/evlist.h | 23 ++++--
tools/perf/util/evsel.h | 5 ++
tools/perf/util/header.c | 4 +-
tools/perf/util/parse-events-test.c | 129 +++++++++++++----------------------
tools/perf/util/parse-events.c | 2 +-
tools/perf/util/top.c | 3 +-
11 files changed, 95 insertions(+), 125 deletions(-)
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index c4e3b68..479ff2a 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -172,12 +172,12 @@ static bool perf_evlist__equal(struct perf_evlist *evlist,
if (evlist->nr_entries != other->nr_entries)
return false;
- pair = list_entry(other->entries.next, struct perf_evsel, node);
+ pair = perf_evlist__first(other);
list_for_each_entry(pos, &evlist->entries, node) {
if (memcmp(&pos->attr, &pair->attr, sizeof(pos->attr) != 0))
return false;
- pair = list_entry(pair->node.next, struct perf_evsel, node);
+ pair = perf_evsel__next(pair);
}
return true;
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 7b9c463..d53d8ab 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -480,7 +480,7 @@ static int run_perf_stat(int argc __used, const char **argv)
if (group)
perf_evlist__set_leader(evsel_list);
- first = list_entry(evsel_list->entries.next, struct perf_evsel, node);
+ first = perf_evlist__first(evsel_list);
list_for_each_entry(counter, &evsel_list->entries, node) {
if (create_perf_stat_counter(counter, first) < 0) {
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c
index 9a479b6..381d5ab 100644
--- a/tools/perf/builtin-test.c
+++ b/tools/perf/builtin-test.c
@@ -710,7 +710,7 @@ static int test__PERF_RECORD(void)
/*
* Config the evsels, setting attr->comm on the first one, etc.
*/
- evsel = list_entry(evlist->entries.next, struct perf_evsel, node);
+ 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;
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 5a097be..0513aaa 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -509,7 +509,7 @@ static void perf_top__handle_keypress(struct perf_top *top, int c)
prompt_integer(&counter, "Enter details event counter");
if (counter >= top->evlist->nr_entries) {
- top->sym_evsel = list_entry(top->evlist->entries.next, struct perf_evsel, node);
+ top->sym_evsel = perf_evlist__first(top->evlist);
fprintf(stderr, "Sorry, no such event, using %s.\n", perf_evsel__name(top->sym_evsel));
sleep(1);
break;
@@ -518,7 +518,7 @@ static void perf_top__handle_keypress(struct perf_top *top, int c)
if (top->sym_evsel->idx == counter)
break;
} else
- top->sym_evsel = list_entry(top->evlist->entries.next, struct perf_evsel, node);
+ top->sym_evsel = perf_evlist__first(top->evlist);
break;
case 'f':
prompt_integer(&top->count_filter, "Enter display event count filter");
@@ -1326,7 +1326,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
pos->attr.sample_period = top.default_interval;
}
- top.sym_evsel = list_entry(top.evlist->entries.next, struct perf_evsel, node);
+ top.sym_evsel = perf_evlist__first(top.evlist);
symbol_conf.priv_size = sizeof(struct annotation);
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 6d09451..4774ac1 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -57,7 +57,7 @@ void perf_evlist__config_attrs(struct perf_evlist *evlist,
if (evlist->cpus->map[0] < 0)
opts->no_inherit = true;
- first = list_entry(evlist->entries.next, struct perf_evsel, node);
+ first = perf_evlist__first(evlist);
list_for_each_entry(evsel, &evlist->entries, node) {
perf_evsel__config(evsel, opts, first);
@@ -376,7 +376,7 @@ struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id)
int hash;
if (evlist->nr_entries == 1)
- return list_entry(evlist->entries.next, struct perf_evsel, node);
+ return perf_evlist__first(evlist);
hash = hash_64(id, PERF_EVLIST__HLIST_BITS);
head = &evlist->heads[hash];
@@ -386,7 +386,7 @@ struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id)
return sid->evsel;
if (!perf_evlist__sample_id_all(evlist))
- return list_entry(evlist->entries.next, struct perf_evsel, node);
+ return perf_evlist__first(evlist);
return NULL;
}
@@ -694,11 +694,9 @@ int perf_evlist__set_filters(struct perf_evlist *evlist)
return 0;
}
-bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist)
+bool perf_evlist__valid_sample_type(struct perf_evlist *evlist)
{
- struct perf_evsel *pos, *first;
-
- pos = first = list_entry(evlist->entries.next, struct perf_evsel, node);
+ struct perf_evsel *first = perf_evlist__first(evlist), *pos = first;
list_for_each_entry_continue(pos, &evlist->entries, node) {
if (first->attr.sample_type != pos->attr.sample_type)
@@ -708,23 +706,19 @@ bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist)
return true;
}
-u64 perf_evlist__sample_type(const struct perf_evlist *evlist)
+u64 perf_evlist__sample_type(struct perf_evlist *evlist)
{
- struct perf_evsel *first;
-
- first = list_entry(evlist->entries.next, struct perf_evsel, node);
+ struct perf_evsel *first = perf_evlist__first(evlist);
return first->attr.sample_type;
}
-u16 perf_evlist__id_hdr_size(const struct perf_evlist *evlist)
+u16 perf_evlist__id_hdr_size(struct perf_evlist *evlist)
{
- struct perf_evsel *first;
+ struct perf_evsel *first = perf_evlist__first(evlist);
struct perf_sample *data;
u64 sample_type;
u16 size = 0;
- first = list_entry(evlist->entries.next, struct perf_evsel, node);
-
if (!first->attr.sample_id_all)
goto out;
@@ -748,11 +742,9 @@ out:
return size;
}
-bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist)
+bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist)
{
- struct perf_evsel *pos, *first;
-
- pos = first = list_entry(evlist->entries.next, struct perf_evsel, node);
+ struct perf_evsel *first = perf_evlist__first(evlist), *pos = first;
list_for_each_entry_continue(pos, &evlist->entries, node) {
if (first->attr.sample_id_all != pos->attr.sample_id_all)
@@ -762,11 +754,9 @@ bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist)
return true;
}
-bool perf_evlist__sample_id_all(const struct perf_evlist *evlist)
+bool perf_evlist__sample_id_all(struct perf_evlist *evlist)
{
- struct perf_evsel *first;
-
- first = list_entry(evlist->entries.next, struct perf_evsel, node);
+ struct perf_evsel *first = perf_evlist__first(evlist);
return first->attr.sample_id_all;
}
@@ -896,6 +886,6 @@ int perf_evlist__start_workload(struct perf_evlist *evlist)
int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event,
struct perf_sample *sample, bool swapped)
{
- struct perf_evsel *e = list_entry(evlist->entries.next, struct perf_evsel, node);
- return perf_evsel__parse_sample(e, event, sample, swapped);
+ struct perf_evsel *evsel = perf_evlist__first(evlist);
+ return perf_evsel__parse_sample(evsel, event, sample, swapped);
}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 7fe677e..2ed2557 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -5,6 +5,7 @@
#include <stdio.h>
#include "../perf.h"
#include "event.h"
+#include "evsel.h"
#include "util.h"
#include <unistd.h>
@@ -41,8 +42,6 @@ struct perf_evsel_str_handler {
void *handler;
};
-struct perf_evsel;
-
struct perf_evlist *perf_evlist__new(struct cpu_map *cpus,
struct thread_map *threads);
void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus,
@@ -121,17 +120,27 @@ int perf_evlist__set_filters(struct perf_evlist *evlist);
void __perf_evlist__set_leader(struct list_head *list);
void perf_evlist__set_leader(struct perf_evlist *evlist);
-u64 perf_evlist__sample_type(const struct perf_evlist *evlist);
-bool perf_evlist__sample_id_all(const const struct perf_evlist *evlist);
-u16 perf_evlist__id_hdr_size(const struct perf_evlist *evlist);
+u64 perf_evlist__sample_type(struct perf_evlist *evlist);
+bool perf_evlist__sample_id_all(struct perf_evlist *evlist);
+u16 perf_evlist__id_hdr_size(struct perf_evlist *evlist);
int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event,
struct perf_sample *sample, bool swapped);
-bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist);
-bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist);
+bool perf_evlist__valid_sample_type(struct perf_evlist *evlist);
+bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist);
void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
struct list_head *list,
int nr_entries);
+
+static inline struct perf_evsel *perf_evlist__first(struct perf_evlist *evlist)
+{
+ return list_entry(evlist->entries.next, struct perf_evsel, node);
+}
+
+static inline struct perf_evsel *perf_evlist__last(struct perf_evlist *evlist)
+{
+ return list_entry(evlist->entries.prev, struct perf_evsel, node);
+}
#endif /* __PERF_EVLIST_H */
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index c411b42..65f39fd 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -184,4 +184,9 @@ void hists__init(struct hists *hists);
int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
struct perf_sample *sample, bool swapped);
+
+static inline struct perf_evsel *perf_evsel__next(struct perf_evsel *evsel)
+{
+ return list_entry(evsel->node.next, struct perf_evsel, node);
+}
#endif /* __PERF_EVSEL_H */
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 7e7d34f..77832b8 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1689,7 +1689,7 @@ int perf_session__write_header(struct perf_session *session,
lseek(fd, sizeof(f_header), SEEK_SET);
if (session->evlist != evlist)
- pair = list_entry(session->evlist->entries.next, struct perf_evsel, node);
+ pair = perf_evlist__first(session->evlist);
list_for_each_entry(attr, &evlist->entries, node) {
attr->id_offset = lseek(fd, 0, SEEK_CUR);
@@ -1704,7 +1704,7 @@ out_err_write:
if (err < 0)
goto out_err_write;
attr->ids += pair->ids;
- pair = list_entry(pair->node.next, struct perf_evsel, node);
+ pair = perf_evsel__next(pair);
}
}
diff --git a/tools/perf/util/parse-events-test.c b/tools/perf/util/parse-events-test.c
index 429dd68..bf055ce 100644
--- a/tools/perf/util/parse-events-test.c
+++ b/tools/perf/util/parse-events-test.c
@@ -18,8 +18,7 @@ do { \
static int test__checkevent_tracepoint(struct perf_evlist *evlist)
{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
+ struct perf_evsel *evsel = perf_evlist__first(evlist);
TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type);
@@ -48,8 +47,7 @@ static int test__checkevent_tracepoint_multi(struct perf_evlist *evlist)
static int test__checkevent_raw(struct perf_evlist *evlist)
{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
+ struct perf_evsel *evsel = perf_evlist__first(evlist);
TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
@@ -59,8 +57,7 @@ static int test__checkevent_raw(struct perf_evlist *evlist)
static int test__checkevent_numeric(struct perf_evlist *evlist)
{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
+ struct perf_evsel *evsel = perf_evlist__first(evlist);
TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
TEST_ASSERT_VAL("wrong type", 1 == evsel->attr.type);
@@ -70,8 +67,7 @@ static int test__checkevent_numeric(struct perf_evlist *evlist)
static int test__checkevent_symbolic_name(struct perf_evlist *evlist)
{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
+ struct perf_evsel *evsel = perf_evlist__first(evlist);
TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
@@ -82,8 +78,7 @@ static int test__checkevent_symbolic_name(struct perf_evlist *evlist)
static int test__checkevent_symbolic_name_config(struct perf_evlist *evlist)
{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
+ struct perf_evsel *evsel = perf_evlist__first(evlist);
TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
@@ -100,8 +95,7 @@ static int test__checkevent_symbolic_name_config(struct perf_evlist *evlist)
static int test__checkevent_symbolic_alias(struct perf_evlist *evlist)
{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
+ struct perf_evsel *evsel = perf_evlist__first(evlist);
TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->attr.type);
@@ -112,8 +106,7 @@ static int test__checkevent_symbolic_alias(struct perf_evlist *evlist)
static int test__checkevent_genhw(struct perf_evlist *evlist)
{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
+ struct perf_evsel *evsel = perf_evlist__first(evlist);
TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
TEST_ASSERT_VAL("wrong type", PERF_TYPE_HW_CACHE == evsel->attr.type);
@@ -123,8 +116,7 @@ static int test__checkevent_genhw(struct perf_evlist *evlist)
static int test__checkevent_breakpoint(struct perf_evlist *evlist)
{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
+ struct perf_evsel *evsel = perf_evlist__first(evlist);
TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type);
@@ -138,8 +130,7 @@ static int test__checkevent_breakpoint(struct perf_evlist *evlist)
static int test__checkevent_breakpoint_x(struct perf_evlist *evlist)
{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
+ struct perf_evsel *evsel = perf_evlist__first(evlist);
TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type);
@@ -152,8 +143,7 @@ static int test__checkevent_breakpoint_x(struct perf_evlist *evlist)
static int test__checkevent_breakpoint_r(struct perf_evlist *evlist)
{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
+ struct perf_evsel *evsel = perf_evlist__first(evlist);
TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
TEST_ASSERT_VAL("wrong type",
@@ -168,8 +158,7 @@ static int test__checkevent_breakpoint_r(struct perf_evlist *evlist)
static int test__checkevent_breakpoint_w(struct perf_evlist *evlist)
{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
+ struct perf_evsel *evsel = perf_evlist__first(evlist);
TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
TEST_ASSERT_VAL("wrong type",
@@ -184,8 +173,7 @@ static int test__checkevent_breakpoint_w(struct perf_evlist *evlist)
static int test__checkevent_breakpoint_rw(struct perf_evlist *evlist)
{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
+ struct perf_evsel *evsel = perf_evlist__first(evlist);
TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
TEST_ASSERT_VAL("wrong type",
@@ -200,8 +188,7 @@ static int test__checkevent_breakpoint_rw(struct perf_evlist *evlist)
static int test__checkevent_tracepoint_modifier(struct perf_evlist *evlist)
{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
+ struct perf_evsel *evsel = perf_evlist__first(evlist);
TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
@@ -232,8 +219,7 @@ test__checkevent_tracepoint_multi_modifier(struct perf_evlist *evlist)
static int test__checkevent_raw_modifier(struct perf_evlist *evlist)
{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
+ struct perf_evsel *evsel = perf_evlist__first(evlist);
TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
@@ -245,8 +231,7 @@ static int test__checkevent_raw_modifier(struct perf_evlist *evlist)
static int test__checkevent_numeric_modifier(struct perf_evlist *evlist)
{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
+ struct perf_evsel *evsel = perf_evlist__first(evlist);
TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
@@ -258,8 +243,7 @@ static int test__checkevent_numeric_modifier(struct perf_evlist *evlist)
static int test__checkevent_symbolic_name_modifier(struct perf_evlist *evlist)
{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
+ struct perf_evsel *evsel = perf_evlist__first(evlist);
TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
@@ -271,8 +255,7 @@ static int test__checkevent_symbolic_name_modifier(struct perf_evlist *evlist)
static int test__checkevent_exclude_host_modifier(struct perf_evlist *evlist)
{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
+ struct perf_evsel *evsel = perf_evlist__first(evlist);
TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
@@ -282,8 +265,7 @@ static int test__checkevent_exclude_host_modifier(struct perf_evlist *evlist)
static int test__checkevent_exclude_guest_modifier(struct perf_evlist *evlist)
{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
+ struct perf_evsel *evsel = perf_evlist__first(evlist);
TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
@@ -293,8 +275,7 @@ static int test__checkevent_exclude_guest_modifier(struct perf_evlist *evlist)
static int test__checkevent_symbolic_alias_modifier(struct perf_evlist *evlist)
{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
+ struct perf_evsel *evsel = perf_evlist__first(evlist);
TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
@@ -306,8 +287,7 @@ static int test__checkevent_symbolic_alias_modifier(struct perf_evlist *evlist)
static int test__checkevent_genhw_modifier(struct perf_evlist *evlist)
{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
+ struct perf_evsel *evsel = perf_evlist__first(evlist);
TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
@@ -319,8 +299,7 @@ static int test__checkevent_genhw_modifier(struct perf_evlist *evlist)
static int test__checkevent_breakpoint_modifier(struct perf_evlist *evlist)
{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
+ struct perf_evsel *evsel = perf_evlist__first(evlist);
TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
@@ -334,8 +313,7 @@ static int test__checkevent_breakpoint_modifier(struct perf_evlist *evlist)
static int test__checkevent_breakpoint_x_modifier(struct perf_evlist *evlist)
{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
+ struct perf_evsel *evsel = perf_evlist__first(evlist);
TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
@@ -349,8 +327,7 @@ static int test__checkevent_breakpoint_x_modifier(struct perf_evlist *evlist)
static int test__checkevent_breakpoint_r_modifier(struct perf_evlist *evlist)
{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
+ struct perf_evsel *evsel = perf_evlist__first(evlist);
TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
@@ -364,8 +341,7 @@ static int test__checkevent_breakpoint_r_modifier(struct perf_evlist *evlist)
static int test__checkevent_breakpoint_w_modifier(struct perf_evlist *evlist)
{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
+ struct perf_evsel *evsel = perf_evlist__first(evlist);
TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
@@ -379,8 +355,7 @@ static int test__checkevent_breakpoint_w_modifier(struct perf_evlist *evlist)
static int test__checkevent_breakpoint_rw_modifier(struct perf_evlist *evlist)
{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
+ struct perf_evsel *evsel = perf_evlist__first(evlist);
TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
@@ -395,8 +370,7 @@ static int test__checkevent_breakpoint_rw_modifier(struct perf_evlist *evlist)
static int test__checkevent_pmu(struct perf_evlist *evlist)
{
- struct perf_evsel *evsel = list_entry(evlist->entries.next,
- struct perf_evsel, node);
+ struct perf_evsel *evsel = perf_evlist__first(evlist);
TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
@@ -410,12 +384,11 @@ static int test__checkevent_pmu(struct perf_evlist *evlist)
static int test__checkevent_list(struct perf_evlist *evlist)
{
- struct perf_evsel *evsel;
+ struct perf_evsel *evsel = perf_evlist__first(evlist);
TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->nr_entries);
/* r1 */
- evsel = list_entry(evlist->entries.next, struct perf_evsel, node);
TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config);
TEST_ASSERT_VAL("wrong config1", 0 == evsel->attr.config1);
@@ -426,7 +399,7 @@ static int test__checkevent_list(struct perf_evlist *evlist)
TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
/* syscalls:sys_enter_open:k */
- evsel = list_entry(evsel->node.next, struct perf_evsel, node);
+ evsel = perf_evsel__next(evsel);
TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type);
TEST_ASSERT_VAL("wrong sample_type",
PERF_TP_SAMPLE_TYPE == evsel->attr.sample_type);
@@ -437,7 +410,7 @@ static int test__checkevent_list(struct perf_evlist *evlist)
TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
/* 1:1:hp */
- evsel = list_entry(evsel->node.next, struct perf_evsel, node);
+ evsel = perf_evsel__next(evsel);
TEST_ASSERT_VAL("wrong type", 1 == evsel->attr.type);
TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config);
TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
@@ -450,17 +423,16 @@ static int test__checkevent_list(struct perf_evlist *evlist)
static int test__checkevent_pmu_name(struct perf_evlist *evlist)
{
- struct perf_evsel *evsel;
+ struct perf_evsel *evsel = perf_evlist__first(evlist);
/* cpu/config=1,name=krava/u */
- evsel = list_entry(evlist->entries.next, struct perf_evsel, node);
TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config);
TEST_ASSERT_VAL("wrong name", !strcmp(perf_evsel__name(evsel), "krava"));
/* cpu/config=2/u" */
- evsel = list_entry(evsel->node.next, struct perf_evsel, node);
+ evsel = perf_evsel__next(evsel);
TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
TEST_ASSERT_VAL("wrong config", 2 == evsel->attr.config);
@@ -520,8 +492,7 @@ static int test__group1(struct perf_evlist *evlist)
TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
/* instructions:k */
- evsel = leader = list_entry(evlist->entries.next,
- struct perf_evsel, node);
+ evsel = leader = perf_evlist__first(evlist);
TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
TEST_ASSERT_VAL("wrong config",
PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config);
@@ -534,7 +505,7 @@ static int test__group1(struct perf_evlist *evlist)
TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL);
/* cycles:upp */
- evsel = list_entry(evsel->node.next, struct perf_evsel, node);
+ evsel = perf_evsel__next(evsel);
TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
TEST_ASSERT_VAL("wrong config",
PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
@@ -556,8 +527,7 @@ static int test__group2(struct perf_evlist *evlist)
TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->nr_entries);
/* faults + :ku modifier */
- evsel = leader = list_entry(evlist->entries.next,
- struct perf_evsel, node);
+ evsel = leader = perf_evlist__first(evlist);
TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->attr.type);
TEST_ASSERT_VAL("wrong config",
PERF_COUNT_SW_PAGE_FAULTS == evsel->attr.config);
@@ -570,7 +540,7 @@ static int test__group2(struct perf_evlist *evlist)
TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL);
/* cache-references + :u modifier */
- evsel = list_entry(evsel->node.next, struct perf_evsel, node);
+ evsel = perf_evsel__next(evsel);
TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
TEST_ASSERT_VAL("wrong config",
PERF_COUNT_HW_CACHE_REFERENCES == evsel->attr.config);
@@ -583,7 +553,7 @@ static int test__group2(struct perf_evlist *evlist)
TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
/* cycles:k */
- evsel = list_entry(evsel->node.next, struct perf_evsel, node);
+ evsel = perf_evsel__next(evsel);
TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
TEST_ASSERT_VAL("wrong config",
PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
@@ -605,8 +575,7 @@ static int test__group3(struct perf_evlist *evlist __used)
TEST_ASSERT_VAL("wrong number of entries", 5 == evlist->nr_entries);
/* group1 syscalls:sys_enter_open:H */
- evsel = leader = list_entry(evlist->entries.next,
- struct perf_evsel, node);
+ evsel = leader = perf_evlist__first(evlist);
TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type);
TEST_ASSERT_VAL("wrong sample_type",
PERF_TP_SAMPLE_TYPE == evsel->attr.sample_type);
@@ -622,7 +591,7 @@ static int test__group3(struct perf_evlist *evlist __used)
!strcmp(leader->group_name, "group1"));
/* group1 cycles:kppp */
- evsel = list_entry(evsel->node.next, struct perf_evsel, node);
+ evsel = perf_evsel__next(evsel);
TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
TEST_ASSERT_VAL("wrong config",
PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
@@ -636,7 +605,7 @@ static int test__group3(struct perf_evlist *evlist __used)
TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
/* group2 cycles + G modifier */
- evsel = leader = list_entry(evsel->node.next, struct perf_evsel, node);
+ evsel = leader = perf_evsel__next(evsel);
TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
TEST_ASSERT_VAL("wrong config",
PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
@@ -651,7 +620,7 @@ static int test__group3(struct perf_evlist *evlist __used)
!strcmp(leader->group_name, "group2"));
/* group2 1:3 + G modifier */
- evsel = list_entry(evsel->node.next, struct perf_evsel, node);
+ evsel = perf_evsel__next(evsel);
TEST_ASSERT_VAL("wrong type", 1 == evsel->attr.type);
TEST_ASSERT_VAL("wrong config", 3 == evsel->attr.config);
TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
@@ -663,7 +632,7 @@ static int test__group3(struct perf_evlist *evlist __used)
TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
/* instructions:u */
- evsel = list_entry(evsel->node.next, struct perf_evsel, node);
+ evsel = perf_evsel__next(evsel);
TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
TEST_ASSERT_VAL("wrong config",
PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config);
@@ -685,8 +654,7 @@ static int test__group4(struct perf_evlist *evlist __used)
TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
/* cycles:u + p */
- evsel = leader = list_entry(evlist->entries.next,
- struct perf_evsel, node);
+ evsel = leader = perf_evlist__first(evlist);
TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
TEST_ASSERT_VAL("wrong config",
PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
@@ -700,7 +668,7 @@ static int test__group4(struct perf_evlist *evlist __used)
TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL);
/* instructions:kp + p */
- evsel = list_entry(evsel->node.next, struct perf_evsel, node);
+ evsel = perf_evsel__next(evsel);
TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
TEST_ASSERT_VAL("wrong config",
PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config);
@@ -722,8 +690,7 @@ static int test__group5(struct perf_evlist *evlist __used)
TEST_ASSERT_VAL("wrong number of entries", 5 == evlist->nr_entries);
/* cycles + G */
- evsel = leader = list_entry(evlist->entries.next,
- struct perf_evsel, node);
+ evsel = leader = perf_evlist__first(evlist);
TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
TEST_ASSERT_VAL("wrong config",
PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
@@ -737,7 +704,7 @@ static int test__group5(struct perf_evlist *evlist __used)
TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL);
/* instructions + G */
- evsel = list_entry(evsel->node.next, struct perf_evsel, node);
+ evsel = perf_evsel__next(evsel);
TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
TEST_ASSERT_VAL("wrong config",
PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config);
@@ -750,7 +717,7 @@ static int test__group5(struct perf_evlist *evlist __used)
TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
/* cycles:G */
- evsel = leader = list_entry(evsel->node.next, struct perf_evsel, node);
+ evsel = leader = perf_evsel__next(evsel);
TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
TEST_ASSERT_VAL("wrong config",
PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
@@ -764,7 +731,7 @@ static int test__group5(struct perf_evlist *evlist __used)
TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL);
/* instructions:G */
- evsel = list_entry(evsel->node.next, struct perf_evsel, node);
+ evsel = perf_evsel__next(evsel);
TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
TEST_ASSERT_VAL("wrong config",
PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config);
@@ -777,7 +744,7 @@ static int test__group5(struct perf_evlist *evlist __used)
TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
/* cycles */
- evsel = list_entry(evsel->node.next, struct perf_evsel, node);
+ evsel = perf_evsel__next(evsel);
TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
TEST_ASSERT_VAL("wrong config",
PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 4393a6b..925784a 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -834,7 +834,7 @@ int parse_filter(const struct option *opt, const char *str,
struct perf_evsel *last = NULL;
if (evlist->nr_entries > 0)
- last = list_entry(evlist->entries.prev, struct perf_evsel, node);
+ last = perf_evlist__last(evlist);
if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) {
fprintf(stderr,
diff --git a/tools/perf/util/top.c b/tools/perf/util/top.c
index 7eeebce..884dde9 100644
--- a/tools/perf/util/top.c
+++ b/tools/perf/util/top.c
@@ -58,8 +58,7 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size)
}
if (top->evlist->nr_entries == 1) {
- struct perf_evsel *first;
- first = list_entry(top->evlist->entries.next, struct perf_evsel, node);
+ 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" : "");
--
1.7.1
From: Namhyung Kim <[email protected]>
Use helpline for printing error/debug messages. The code resembles a TUI
counter part and only print the first line of the message.
Signed-off-by: Namhyung Kim <[email protected]>
Acked-by: Pekka Enberg <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Pekka Enberg <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/ui/gtk/helpline.c | 26 ++++++++++++++++++++++++++
tools/perf/ui/gtk/util.c | 5 -----
tools/perf/ui/helpline.h | 23 +++++++++++++++++++++++
tools/perf/ui/setup.c | 4 ++++
tools/perf/ui/tui/setup.c | 2 --
tools/perf/util/debug.c | 4 +++-
tools/perf/util/debug.h | 8 +-------
7 files changed, 57 insertions(+), 15 deletions(-)
diff --git a/tools/perf/ui/gtk/helpline.c b/tools/perf/ui/gtk/helpline.c
index 2511b37..5db4432 100644
--- a/tools/perf/ui/gtk/helpline.c
+++ b/tools/perf/ui/gtk/helpline.c
@@ -1,5 +1,10 @@
+#include <stdio.h>
+#include <string.h>
+
#include "gtk.h"
+#include "../ui.h"
#include "../helpline.h"
+#include "../../util/debug.h"
static void gtk_helpline_pop(void)
{
@@ -28,3 +33,24 @@ void perf_gtk__init_helpline(void)
{
helpline_fns = >k_helpline_fns;
}
+
+int perf_gtk__show_helpline(const char *fmt, va_list ap)
+{
+ int ret;
+ char *ptr;
+ static int backlog;
+
+ ret = vscnprintf(ui_helpline__current + backlog,
+ sizeof(ui_helpline__current) - backlog, fmt, ap);
+ backlog += ret;
+
+ /* only first line can be displayed */
+ ptr = strchr(ui_helpline__current, '\n');
+ if (ptr && (ptr - ui_helpline__current) <= backlog) {
+ *ptr = '\0';
+ ui_helpline__puts(ui_helpline__current);
+ backlog = 0;
+ }
+
+ return ret;
+}
diff --git a/tools/perf/ui/gtk/util.c b/tools/perf/ui/gtk/util.c
index 0ead373..b8efb96 100644
--- a/tools/perf/ui/gtk/util.c
+++ b/tools/perf/ui/gtk/util.c
@@ -117,11 +117,6 @@ struct perf_error_ops perf_gtk_eops = {
* For now, just add stubs for NO_NEWT=1 build.
*/
#ifdef NO_NEWT_SUPPORT
-int ui_helpline__show_help(const char *format __used, va_list ap __used)
-{
- return 0;
-}
-
void ui_progress__update(u64 curr __used, u64 total __used,
const char *title __used)
{
diff --git a/tools/perf/ui/helpline.h b/tools/perf/ui/helpline.h
index 61118b2..a2487f9 100644
--- a/tools/perf/ui/helpline.h
+++ b/tools/perf/ui/helpline.h
@@ -4,6 +4,8 @@
#include <stdio.h>
#include <stdarg.h>
+#include "../util/cache.h"
+
struct ui_helpline {
void (*pop)(void);
void (*push)(const char *msg);
@@ -21,4 +23,25 @@ void ui_helpline__puts(const char *msg);
extern char ui_helpline__current[512];
+#ifdef NO_NEWT_SUPPORT
+static inline int ui_helpline__show_help(const char *format __used,
+ va_list ap __used)
+{
+ return 0;
+}
+#else
+extern char ui_helpline__last_msg[];
+int ui_helpline__show_help(const char *format, va_list ap);
+#endif /* NO_NEWT_SUPPORT */
+
+#ifdef NO_GTK2_SUPPORT
+static inline int perf_gtk__show_helpline(const char *format __used,
+ va_list ap __used)
+{
+ return 0;
+}
+#else
+int perf_gtk__show_helpline(const char *format, va_list ap);
+#endif /* NO_GTK2_SUPPORT */
+
#endif /* _PERF_UI_HELPLINE_H_ */
diff --git a/tools/perf/ui/setup.c b/tools/perf/ui/setup.c
index 791fb15..c7820e5 100644
--- a/tools/perf/ui/setup.c
+++ b/tools/perf/ui/setup.c
@@ -1,7 +1,11 @@
+#include <pthread.h>
+
#include "../cache.h"
#include "../debug.h"
+pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER;
+
void setup_browser(bool fallback_to_pager)
{
if (!isatty(1) || dump_trace)
diff --git a/tools/perf/ui/tui/setup.c b/tools/perf/ui/tui/setup.c
index e813c1d..4c936e0 100644
--- a/tools/perf/ui/tui/setup.c
+++ b/tools/perf/ui/tui/setup.c
@@ -11,8 +11,6 @@
#include "../libslang.h"
#include "../keysyms.h"
-pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER;
-
static volatile int ui__need_resize;
extern struct perf_error_ops perf_tui_eops;
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index 4dfe0bb..66eb382 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -23,8 +23,10 @@ int eprintf(int level, const char *fmt, ...)
if (verbose >= level) {
va_start(args, fmt);
- if (use_browser > 0)
+ if (use_browser == 1)
ret = ui_helpline__show_help(fmt, args);
+ else if (use_browser == 2)
+ ret = perf_gtk__show_helpline(fmt, args);
else
ret = vfprintf(stderr, fmt, args);
va_end(args);
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index 015c91d..05e660c 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -4,6 +4,7 @@
#include <stdbool.h>
#include "event.h"
+#include "../ui/helpline.h"
extern int verbose;
extern bool quiet, dump_trace;
@@ -15,11 +16,6 @@ struct ui_progress;
struct perf_error_ops;
#if defined(NO_NEWT_SUPPORT) && defined(NO_GTK2_SUPPORT)
-static inline int ui_helpline__show_help(const char *format __used, va_list ap __used)
-{
- return 0;
-}
-
static inline void ui_progress__update(u64 curr __used, u64 total __used,
const char *title __used) {}
@@ -39,8 +35,6 @@ perf_error__unregister(struct perf_error_ops *eops __used)
#else /* NO_NEWT_SUPPORT && NO_GTK2_SUPPORT */
-extern char ui_helpline__last_msg[];
-int ui_helpline__show_help(const char *format, va_list ap);
#include "../ui/progress.h"
int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2)));
#include "../ui/util.h"
--
1.7.1
From: Robert Richter <[email protected]>
Trivial patch that renames global variable 'events' in util/header.c.
Use a more specific naming to avoid conflicts. Same for variable
'event_count'.
Signed-off-by: Robert Richter <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/header.c | 40 ++++++++++++++++++++--------------------
1 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index e2e5129..1e5b6aa 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -23,8 +23,8 @@
static bool no_buildid_cache = false;
-static int event_count;
-static struct perf_trace_event_type *events;
+static int trace_event_count;
+static struct perf_trace_event_type *trace_events;
static u32 header_argc;
static const char **header_argv;
@@ -36,24 +36,24 @@ int perf_header__push_event(u64 id, const char *name)
if (strlen(name) > MAX_EVENT_NAME)
pr_warning("Event %s will be truncated\n", name);
- nevents = realloc(events, (event_count + 1) * sizeof(*events));
+ nevents = realloc(trace_events, (trace_event_count + 1) * sizeof(*trace_events));
if (nevents == NULL)
return -ENOMEM;
- events = nevents;
+ trace_events = nevents;
- memset(&events[event_count], 0, sizeof(struct perf_trace_event_type));
- events[event_count].event_id = id;
- strncpy(events[event_count].name, name, MAX_EVENT_NAME - 1);
- event_count++;
+ memset(&trace_events[trace_event_count], 0, sizeof(struct perf_trace_event_type));
+ trace_events[trace_event_count].event_id = id;
+ strncpy(trace_events[trace_event_count].name, name, MAX_EVENT_NAME - 1);
+ trace_event_count++;
return 0;
}
char *perf_header__find_event(u64 id)
{
int i;
- for (i = 0 ; i < event_count; i++) {
- if (events[i].event_id == id)
- return events[i].name;
+ for (i = 0 ; i < trace_event_count; i++) {
+ if (trace_events[i].event_id == id)
+ return trace_events[i].name;
}
return NULL;
}
@@ -1726,9 +1726,9 @@ out_err_write:
}
header->event_offset = lseek(fd, 0, SEEK_CUR);
- header->event_size = event_count * sizeof(struct perf_trace_event_type);
- if (events) {
- err = do_write(fd, events, header->event_size);
+ header->event_size = trace_event_count * sizeof(struct perf_trace_event_type);
+ if (trace_events) {
+ err = do_write(fd, trace_events, header->event_size);
if (err < 0) {
pr_debug("failed to write perf header events\n");
return err;
@@ -2211,13 +2211,13 @@ int perf_session__read_header(struct perf_session *session, int fd)
if (f_header.event_types.size) {
lseek(fd, f_header.event_types.offset, SEEK_SET);
- events = malloc(f_header.event_types.size);
- if (events == NULL)
+ trace_events = malloc(f_header.event_types.size);
+ if (trace_events == NULL)
return -ENOMEM;
- if (perf_header__getbuffer64(header, fd, events,
+ if (perf_header__getbuffer64(header, fd, trace_events,
f_header.event_types.size))
goto out_errno;
- event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type);
+ trace_event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type);
}
perf_header__process_sections(header, fd, &session->pevent,
@@ -2362,8 +2362,8 @@ int perf_event__synthesize_event_types(struct perf_tool *tool,
struct perf_trace_event_type *type;
int i, err = 0;
- for (i = 0; i < event_count; i++) {
- type = &events[i];
+ for (i = 0; i < trace_event_count; i++) {
+ type = &trace_events[i];
err = perf_event__synthesize_event_type(tool, type->event_id,
type->name, process,
--
1.7.1
From: Arnaldo Carvalho de Melo <[email protected]>
Changeset 0f6a3015:
"perf tools: Support user regs and stack in sample parsing"
uses hweight_long in evsel.c, so we need to drag util/hweight.c
to the python binding.
Ditto for ee8dd3c:
"perf tools: Change strlist to use the new rblist"
where we need to add util/rblist.c.
Now twatch.py works again:
# export PYTHONPATH=~acme/git/build/perf/python/
# ~acme/git/linux/tools/perf/python/twatch.py
cpu: 4, pid: 23639, tid: 23639 { type: fork, pid: 30659, ppid: 23639, tid: 30659, ptid: 23639, time: 36287872076780}
cpu: 5, pid: 30659, tid: 30659 { type: comm, pid: 30659, tid: 30659, comm: ls }
cpu: 5, pid: 30659, tid: 30659 { type: exit, pid: 30659, ppid: 30659, tid: 30659, ptid: 30659, time: 36287873681539}
cpu: 4, pid: 23639, tid: 23639 { type: fork, pid: 30660, ppid: 23639, tid: 30660, ptid: 23639, time: 36291720420480}
cpu: 5, pid: 30659, tid: 30659 { type: exit, pid: 30659, ppid: 30659, tid: 30659, ptid: 30659, time: 36287873685714}
cpu: 5, pid: 30660, tid: 30660 { type: comm, pid: 30660, tid: 30660, comm: git }
^C
KeyboardInterrupt
Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/python-ext-sources | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources
index 2884e67..2133628 100644
--- a/tools/perf/util/python-ext-sources
+++ b/tools/perf/util/python-ext-sources
@@ -10,10 +10,12 @@ util/ctype.c
util/evlist.c
util/evsel.c
util/cpumap.c
+util/hweight.c
util/thread_map.c
util/util.c
util/xyarray.c
util/cgroup.c
util/debugfs.c
+util/rblist.c
util/strlist.c
../../lib/rbtree.c
--
1.7.1
* Arnaldo Carvalho de Melo <[email protected]> wrote:
> Hi Ingo,
>
> Please consider pulling, this is on top of my previous pull requests,
>
> - Arnaldo
>
> The following changes since commit 0fe7d7e9761ec7e23350b5543ddac470bb3cde1e:
>
> perf symbols: Add description of JIT interface (2012-08-13 14:55:02 -0300)
>
> 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 000078bc3ee69efb1124b8478c7527389a826074:
>
> perf hists: Rename and move some functions (2012-08-20 09:47:31 -0300)
>
> ----------------------------------------------------------------
> perf/core improvements and fixes:
>
> . Fix include order for bison/flex-generated C files, from Ben Hutchings
>
> . Build fixes and documentation corrections from David Ahern
>
> . Group parsing support, from Jiri Olsa
>
> . UI/gtk refactorings and improvements from Namhyung Kim
>
> . NULL deref fix for perf script, from Namhyung Kim
>
> . Assorted cleanups from Robert Richter
>
> . Let O= makes handle relative paths, from Steven Rostedt
>
> Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
>
> ----------------------------------------------------------------
> Arnaldo Carvalho de Melo (3):
> perf tools: Add missing files to build the python binding
> perf evlist: Rename __group method to __set_leader
> perf evlist: Introduce evsel list accessors
>
> Ben Hutchings (1):
> perf tools: Fix include order for bison/flex-generated C files
>
> David Ahern (3):
> perf script perl/python: Fix libexec scripts path in Documentation
> perf: silence GTK2 probing errors
> perf symbols: Fix builds with NO_LIBELF set
>
> Jiri Olsa (4):
> perf tools: Add support to parse event group syntax
> perf tools: Add support to update event modifier
> perf tools: Enable grouping logic for parsed events
> perf test: Add automated tests for event group parsing
>
> Namhyung Kim (8):
> perf script: Fix a NULL pointer dereference
> perf ui: Introduce struct ui_helpline
> perf ui gtk: Implement helpline_fns
> perf ui/gtk: Use helpline API in browser
> perf ui gtk: Add perf_gtk__show_helpline() for pr_*
> perf ui gtk: Ensure not to call gtk_main_quit() twice
> perf hists: Separate out hist print functions
> perf hists: Rename and move some functions
>
> Robert Richter (4):
> perf tools: Fix type for evsel->ids and add size check for ids
> perf tools: Report number of pmu type of unknown events
> perf tools: Rename some variables for better understanding
> perf tools: Rename global variable 'events' in util/header.c
>
> Steven Rostedt (1):
> perf tools: Let O= makes handle relative paths
>
> tools/perf/Documentation/perf-script-perl.txt | 4 +-
> tools/perf/Documentation/perf-script-python.txt | 10 +-
> tools/perf/Makefile | 20 +-
> tools/perf/builtin-record.c | 17 +-
> tools/perf/builtin-stat.c | 15 +-
> tools/perf/builtin-test.c | 10 +-
> tools/perf/builtin-top.c | 18 +-
> tools/perf/ui/browsers/hists.c | 4 +-
> tools/perf/ui/gtk/browser.c | 5 +-
> tools/perf/ui/gtk/gtk.h | 2 +
> tools/perf/ui/gtk/helpline.c | 56 ++
> tools/perf/ui/gtk/setup.c | 3 +
> tools/perf/ui/gtk/util.c | 5 -
> tools/perf/ui/helpline.c | 56 +-
> tools/perf/ui/helpline.h | 33 +-
> tools/perf/ui/setup.c | 4 +
> tools/perf/ui/stdio/hist.c | 653 ++++++++++++++++++++++
> tools/perf/ui/tui/helpline.c | 57 ++
> tools/perf/ui/tui/setup.c | 2 -
> tools/perf/util/debug.c | 4 +-
> tools/perf/util/debug.h | 8 +-
> tools/perf/util/evlist.c | 73 +--
> tools/perf/util/evlist.h | 27 +-
> tools/perf/util/evsel.c | 52 +-
> tools/perf/util/evsel.h | 20 +-
> tools/perf/util/header.c | 97 ++--
> tools/perf/util/header.h | 2 +-
> tools/perf/util/hist.c | 677 +----------------------
> tools/perf/util/hist.h | 6 +-
> tools/perf/util/parse-events-test.c | 387 ++++++++++---
> tools/perf/util/parse-events.c | 93 +++-
> tools/perf/util/parse-events.h | 4 +-
> tools/perf/util/parse-events.l | 2 +
> tools/perf/util/parse-events.y | 93 +++-
> tools/perf/util/python-ext-sources | 2 +
> tools/perf/util/python.c | 7 +-
> tools/perf/util/symbol-elf.c | 3 +
> tools/perf/util/symbol.c | 2 +-
> tools/perf/util/top.c | 3 +-
> tools/perf/util/trace-event-parse.c | 2 +-
> tools/scripts/Makefile.include | 6 +-
> 41 files changed, 1560 insertions(+), 984 deletions(-)
> create mode 100644 tools/perf/ui/gtk/helpline.c
> create mode 100644 tools/perf/ui/stdio/hist.c
> create mode 100644 tools/perf/ui/tui/helpline.c
Pulled this and the previous two pull requests, thanks a lot
Arnaldo!
One minor observation, the Makefile tells us:
Makefile:496: No libunwind found. Please install libunwind >= 0.99
I guess that should be libunwind-dev[el], right? Plain libunwind
is not enough.
Thanks,
Ingo
On Tue, Aug 21, 2012 at 11:32:31AM +0200, Ingo Molnar wrote:
>
> * Arnaldo Carvalho de Melo <[email protected]> wrote:
>
SNIP
>
> One minor observation, the Makefile tells us:
>
> Makefile:496: No libunwind found. Please install libunwind >= 0.99
>
> I guess that should be libunwind-dev[el], right? Plain libunwind
> is not enough.
right, will fix it
thanks,
jirka
On Tue, Aug 21, 2012 at 11:36:28AM +0200, Jiri Olsa wrote:
> On Tue, Aug 21, 2012 at 11:32:31AM +0200, Ingo Molnar wrote:
> >
> > * Arnaldo Carvalho de Melo <[email protected]> wrote:
> >
>
> SNIP
>
> >
> > One minor observation, the Makefile tells us:
> >
> > Makefile:496: No libunwind found. Please install libunwind >= 0.99
> >
> > I guess that should be libunwind-dev[el], right? Plain libunwind
> > is not enough.
>
> right, will fix it
>
> thanks,
> jirka
---
Changing error message when libunwind support is not found
to inform properly to install libunwind-dev[el] package.
Reported-by: Ingo Molnar <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Signed-off-by: Jiri Olsa <[email protected]>
---
tools/perf/Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 6bd888d..218cdb5 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -493,7 +493,7 @@ endif
FLAGS_UNWIND=$(LIBUNWIND_CFLAGS) $(ALL_CFLAGS) $(LIBUNWIND_LDFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) $(LIBUNWIND_LIBS)
ifneq ($(call try-cc,$(SOURCE_LIBUNWIND),$(FLAGS_UNWIND)),y)
- msg := $(warning No libunwind found. Please install libunwind >= 0.99);
+ msg := $(warning No libunwind found, disables post unwind support. Please install libunwind-dev[el] >= 0.99);
NO_LIBUNWIND := 1
endif # Libunwind support
endif # NO_LIBUNWIND
--
1.7.11.4
* Jiri Olsa <[email protected]> wrote:
> On Tue, Aug 21, 2012 at 11:36:28AM +0200, Jiri Olsa wrote:
> > On Tue, Aug 21, 2012 at 11:32:31AM +0200, Ingo Molnar wrote:
> > >
> > > * Arnaldo Carvalho de Melo <[email protected]> wrote:
> > >
> >
> > SNIP
> >
> > >
> > > One minor observation, the Makefile tells us:
> > >
> > > Makefile:496: No libunwind found. Please install libunwind >= 0.99
> > >
> > > I guess that should be libunwind-dev[el], right? Plain libunwind
> > > is not enough.
> >
> > right, will fix it
> >
> > thanks,
> > jirka
>
> ---
> Changing error message when libunwind support is not found
> to inform properly to install libunwind-dev[el] package.
>
> Reported-by: Ingo Molnar <[email protected]>
> Cc: Arnaldo Carvalho de Melo <[email protected]>
> Cc: Peter Zijlstra <[email protected]>
> Cc: Ingo Molnar <[email protected]>
> Cc: Paul Mackerras <[email protected]>
> Cc: Corey Ashford <[email protected]>
> Cc: Frederic Weisbecker <[email protected]>
> Signed-off-by: Jiri Olsa <[email protected]>
> ---
> tools/perf/Makefile | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/tools/perf/Makefile b/tools/perf/Makefile
> index 6bd888d..218cdb5 100644
> --- a/tools/perf/Makefile
> +++ b/tools/perf/Makefile
> @@ -493,7 +493,7 @@ endif
>
> FLAGS_UNWIND=$(LIBUNWIND_CFLAGS) $(ALL_CFLAGS) $(LIBUNWIND_LDFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) $(LIBUNWIND_LIBS)
> ifneq ($(call try-cc,$(SOURCE_LIBUNWIND),$(FLAGS_UNWIND)),y)
> - msg := $(warning No libunwind found. Please install libunwind >= 0.99);
> + msg := $(warning No libunwind found, disables post unwind support. Please install libunwind-dev[el] >= 0.99);
s/disables/disable
Thanks,
Ingo
On Wed, 2012-08-22 at 10:40 +0200, Ingo Molnar wrote:
>
> > FLAGS_UNWIND=$(LIBUNWIND_CFLAGS) $(ALL_CFLAGS) $(LIBUNWIND_LDFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) $(LIBUNWIND_LIBS)
> > ifneq ($(call try-cc,$(SOURCE_LIBUNWIND),$(FLAGS_UNWIND)),y)
> > - msg := $(warning No libunwind found. Please install libunwind >= 0.99);
> > + msg := $(warning No libunwind found, disables post unwind support. Please install libunwind-dev[el] >= 0.99);
>
> s/disables/disable
Is it a command for the user to do, or something it is about to do for
the user? If the latter, then "disabling" may be the better word.
-- Steve
* Steven Rostedt <[email protected]> wrote:
> On Wed, 2012-08-22 at 10:40 +0200, Ingo Molnar wrote:
> >
> > > FLAGS_UNWIND=$(LIBUNWIND_CFLAGS) $(ALL_CFLAGS) $(LIBUNWIND_LDFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) $(LIBUNWIND_LIBS)
> > > ifneq ($(call try-cc,$(SOURCE_LIBUNWIND),$(FLAGS_UNWIND)),y)
> > > - msg := $(warning No libunwind found. Please install libunwind >= 0.99);
> > > + msg := $(warning No libunwind found, disables post unwind support. Please install libunwind-dev[el] >= 0.99);
> >
> > s/disables/disable
>
> Is it a command for the user to do, or something it is about to do for
> the user? If the latter, then "disabling" may be the better word.
Yeah, agreed 'disabling' is even better.
Thanks,
Ingo
Commit-ID: d45a3e00687bb52a20d9256d3d1068eea271013f
Gitweb: http://git.kernel.org/tip/d45a3e00687bb52a20d9256d3d1068eea271013f
Author: Jiri Olsa <[email protected]>
AuthorDate: Wed, 22 Aug 2012 10:38:12 +0200
Committer: Arnaldo Carvalho de Melo <[email protected]>
CommitDate: Wed, 22 Aug 2012 13:32:13 -0300
perf tools: Fix 'No libunwind found' make warning message
Changing error message when libunwind support is not found to inform
properly to install libunwind-dev[el] package.
Reported-by: Ingo Molnar <[email protected]>
Signed-off-by: Jiri Olsa <[email protected]>
Cc: Andi Kleen <[email protected]>
Cc: Ben Hutchings <[email protected]>
Cc: Borislav Petkov <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Feng Tang <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Pekka Enberg <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Robert Richter <[email protected]>
Cc: Sedat Dilek <[email protected]>
Cc: Stephane Eranian <[email protected]>
Cc: Steven Rostedt <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Ulrich Drepper <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
[ committer note: s/disable/disabling/g rewording suggested by Steven Rostedt ]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/Makefile | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 6bd888d..722ddee 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -493,7 +493,7 @@ endif
FLAGS_UNWIND=$(LIBUNWIND_CFLAGS) $(ALL_CFLAGS) $(LIBUNWIND_LDFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) $(LIBUNWIND_LIBS)
ifneq ($(call try-cc,$(SOURCE_LIBUNWIND),$(FLAGS_UNWIND)),y)
- msg := $(warning No libunwind found. Please install libunwind >= 0.99);
+ msg := $(warning No libunwind found, disabling post unwind support. Please install libunwind-dev[el] >= 0.99);
NO_LIBUNWIND := 1
endif # Libunwind support
endif # NO_LIBUNWIND