2012-11-18 14:31:00

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [GIT PULL 00/32] perf/core improvements and fixes

Hi Ingo,

Please consider pulling,

- Arnaldo

The following changes since commit ffadcf090d468e9c4938b718649f38dd10cfdb02:

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

are available in the git repository at:

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

for you to fetch changes up to 07ac002f2fcc74c5be47b656d9201d5de84dc53d:

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

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

. UAPI fixes, from David Howels

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

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

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

. Implement ui_progress for GTK, from Namhyung Kim

Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


2012-11-18 14:30:33

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 14/32] perf hists: Initialize all of he->stat with zeroes

From: Arnaldo Carvalho de Melo <[email protected]>

Not just nr_events and period.

Reported-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/util/hist.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)

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

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

2012-11-18 14:30:32

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 08/32] perf tests: Move perf_evsel__tp_sched_test into separate object

From: Jiri Olsa <[email protected]>

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

Signed-off-by: Jiri Olsa <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[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 | 1 +
tools/perf/tests/builtin-test.c | 83 +-----------------------------------
tools/perf/tests/evsel-tp-sched.c | 84 +++++++++++++++++++++++++++++++++++++
tools/perf/tests/tests.h | 1 +
4 files changed, 87 insertions(+), 82 deletions(-)
create mode 100644 tools/perf/tests/evsel-tp-sched.c

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

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

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

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

2012-11-18 14:30:31

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 03/32] perf tests: Move test__open_syscall_event_on_all_cpus into separate object

From: Jiri Olsa <[email protected]>

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

Signed-off-by: Jiri Olsa <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[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 | 1 +
tools/perf/tests/builtin-test.c | 114 ----------------------------
tools/perf/tests/open-syscall-all-cpus.c | 120 ++++++++++++++++++++++++++++++
tools/perf/tests/tests.h | 1 +
4 files changed, 122 insertions(+), 114 deletions(-)
create mode 100644 tools/perf/tests/open-syscall-all-cpus.c

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

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

#include <sched.h>

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

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

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

2012-11-18 14:30:30

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 26/32] perf ui: Add ui_progress__finish()

From: Namhyung Kim <[email protected]>

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

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

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

Signed-off-by: Namhyung Kim <[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/progress.c | 9 +++++++++
tools/perf/ui/progress.c | 6 ++++++
tools/perf/ui/progress.h | 2 ++
tools/perf/util/debug.h | 1 +
tools/perf/util/session.c | 1 +
5 files changed, 19 insertions(+)

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

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

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

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

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

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

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

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

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

2012-11-18 14:30:28

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 17/32] perf tools: Use sscanf for parsing /proc/pid/maps

From: Namhyung Kim <[email protected]>

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

Signed-off-by: Namhyung Kim <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/event.c | 74 ++++++++++++++++++++---------------------------
1 file changed, 31 insertions(+), 43 deletions(-)

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

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

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

--
1.7.9.2.358.g22243

2012-11-18 14:30:27

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 25/32] perf ui gtk: Implement ui_progress functions

From: Namhyung Kim <[email protected]>

Implement progress update function for GTK2 front end.

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

Signed-off-by: Namhyung Kim <[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/Makefile | 1 +
tools/perf/ui/gtk/gtk.h | 1 +
tools/perf/ui/gtk/progress.c | 50 ++++++++++++++++++++++++++++++++++++++++++
tools/perf/ui/gtk/setup.c | 2 ++
4 files changed, 54 insertions(+)
create mode 100644 tools/perf/ui/gtk/progress.c

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

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

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

--
1.7.9.2.358.g22243

2012-11-18 14:30:26

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 10/32] perf tests: Move pmu tests into separate object

From: Jiri Olsa <[email protected]>

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

Signed-off-by: Jiri Olsa <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[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 | 1 +
tools/perf/tests/builtin-test.c | 7 +-
tools/perf/tests/pmu.c | 178 +++++++++++++++++++++++++++++++++++++
tools/perf/tests/tests.h | 1 +
tools/perf/util/pmu.c | 185 ++-------------------------------------
tools/perf/util/pmu.h | 4 +
6 files changed, 191 insertions(+), 185 deletions(-)
create mode 100644 tools/perf/tests/pmu.c

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

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


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

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

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

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

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

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

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

struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu);

--
1.7.9.2.358.g22243

2012-11-18 14:30:24

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 16/32] perf tools: Add gtk.<command> config option for launching GTK browser

From: Namhyung Kim <[email protected]>

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

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

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

Signed-off-by: Namhyung Kim <[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/perf.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)

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

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

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

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

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

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

2012-11-18 14:30:23

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 07/32] perf tests: Move perf_evsel__roundtrip_name_test into separate object

From: Jiri Olsa <[email protected]>

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

Signed-off-by: Jiri Olsa <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[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 | 1 +
tools/perf/tests/builtin-test.c | 112 +-----------------------------
tools/perf/tests/evsel-roundtrip-name.c | 114 +++++++++++++++++++++++++++++++
tools/perf/tests/tests.h | 1 +
4 files changed, 117 insertions(+), 111 deletions(-)
create mode 100644 tools/perf/tests/evsel-roundtrip-name.c

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

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

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

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

2012-11-18 14:30:21

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 27/32] perf ui: Always compile browser setup code

From: Namhyung Kim <[email protected]>

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

Signed-off-by: Namhyung Kim <[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/Makefile | 3 +--
tools/perf/ui/ui.h | 28 ++++++++++++++++++++++++++++
tools/perf/util/cache.h | 39 +--------------------------------------
3 files changed, 30 insertions(+), 40 deletions(-)

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

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

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

extern pthread_mutex_t ui__lock;

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

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

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

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

--
1.7.9.2.358.g22243

2012-11-18 14:33:11

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 31/32] perf powerpc: Use uapi/unistd.h to fix build error

From: Sukadev Bhattiprolu <[email protected]>

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

Signed-off-by: Sukadev Bhattiprolu <[email protected]>
Acked-by: David Howells <[email protected]>
Cc: Anton Blanchard <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Robert Richter <[email protected]>
Cc: [email protected]
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/perf.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

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

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

2012-11-18 14:33:10

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 29/32] tools: Honour the O= flag when tool build called from a higher Makefile

From: David Howells <[email protected]>

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

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

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

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

and if O= is not set, we get:

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

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

Signed-off-by: David Howells <[email protected]>
Cc: Borislav Petkov <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Linus Torvalds <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
Makefile | 6 ++++--
tools/scripts/Makefile.include | 17 +++++++++++++----
2 files changed, 17 insertions(+), 6 deletions(-)

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

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

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

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

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

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

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

2012-11-18 14:30:19

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 02/32] perf tests: Move test__open_syscall_event into separate object

From: Jiri Olsa <[email protected]>

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

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

Signed-off-by: Jiri Olsa <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[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 | 2 +
tools/perf/tests/builtin-test.c | 84 ---------------------------------------
tools/perf/tests/open-syscall.c | 66 ++++++++++++++++++++++++++++++
tools/perf/tests/tests.h | 5 +++
tools/perf/tests/util.c | 30 ++++++++++++++
5 files changed, 103 insertions(+), 84 deletions(-)
create mode 100644 tools/perf/tests/open-syscall.c
create mode 100644 tools/perf/tests/util.c

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

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

#include "tests.h"

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

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

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

#endif /* TESTS_H */
diff --git a/tools/perf/tests/util.c b/tools/perf/tests/util.c
new file mode 100644
index 0000000..748f2e8
--- /dev/null
+++ b/tools/perf/tests/util.c
@@ -0,0 +1,30 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "tests.h"
+#include "debugfs.h"
+
+int trace_event__id(const char *evname)
+{
+ char *filename;
+ int err = -1, fd;
+
+ if (asprintf(&filename,
+ "%s/syscalls/%s/id",
+ tracing_events_path, evname) < 0)
+ return -1;
+
+ fd = open(filename, O_RDONLY);
+ if (fd >= 0) {
+ char id[16];
+ if (read(fd, id, sizeof(id)) > 0)
+ err = atoi(id);
+ close(fd);
+ }
+
+ free(filename);
+ return err;
+}
--
1.7.9.2.358.g22243

2012-11-18 14:33:46

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 19/32] perf tools: Fix 'disabled' attribute config for record command

From: Jiri Olsa <[email protected]>

Currently the record command sets all events initially as disabled.

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

What we actually want is:

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

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

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

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

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

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

Fixing appropriate perf_event_attr test case to cover this change.

Signed-off-by: Jiri Olsa <[email protected]>
Acked-by: Namhyung Kim <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[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/builtin-record.c | 15 +++++++++--
tools/perf/tests/attr/test-record-group | 1 +
tools/perf/tests/attr/test-record-group1 | 1 +
tools/perf/util/evsel.c | 42 +++++++++++++++++++++++++++++-
4 files changed, 56 insertions(+), 3 deletions(-)

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

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

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

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

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

+/*
+ * The enable_on_exec/disabled value strategy:
+ *
+ * 1) For any type of traced program:
+ * - all independent events and group leaders are disabled
+ * - all group members are enabled
+ *
+ * Group members are ruled by group leaders. They need to
+ * be enabled, because the group scheduling relies on that.
+ *
+ * 2) For traced programs executed by perf:
+ * - all independent events and group leaders have
+ * enable_on_exec set
+ * - we don't specifically enable or disable any event during
+ * the record command
+ *
+ * Independent events and group leaders are initially disabled
+ * and get enabled by exec. Group members are ruled by group
+ * leaders as stated in 1).
+ *
+ * 3) For traced programs attached by perf (pid/tid):
+ * - we specifically enable or disable all events during
+ * the record command
+ *
+ * When attaching events to already running traced we
+ * enable/disable events specifically, as there's no
+ * initial traced exec call.
+ */
void perf_evsel__config(struct perf_evsel *evsel,
struct perf_record_opts *opts)
{
struct perf_event_attr *attr = &evsel->attr;
int track = !evsel->idx; /* only the first counter needs these */

- attr->disabled = 1;
attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1;
attr->inherit = !opts->no_inherit;
attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
@@ -486,6 +513,19 @@ void perf_evsel__config(struct perf_evsel *evsel,
attr->mmap = track;
attr->comm = track;

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

2012-11-18 14:33:44

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 30/32] tools: Pass the target in descend

From: David Howells <[email protected]>

Fixing:

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

Reported-by: Arnaldo Carvalho de Melo <[email protected]>
Signed-off-by: David Howells <[email protected]>
Cc: Borislav Petkov <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Linus Torvalds <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/scripts/Makefile.include | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

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

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

2012-11-18 14:33:42

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 05/32] perf tests: Move test__PERF_RECORD into separate object

From: Jiri Olsa <[email protected]>

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

Signed-off-by: Jiri Olsa <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[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 | 1 +
tools/perf/tests/builtin-test.c | 307 --------------------------------------
tools/perf/tests/perf-record.c | 312 +++++++++++++++++++++++++++++++++++++++
tools/perf/tests/tests.h | 1 +
4 files changed, 314 insertions(+), 307 deletions(-)
create mode 100644 tools/perf/tests/perf-record.c

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

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



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

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

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

2012-11-18 14:34:32

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 28/32] tools: Define a Makefile function to do subdir processing

From: David Howells <[email protected]>

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

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

Signed-off-by: David Howells <[email protected]>
Cc: Borislav Petkov <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Linus Torvalds <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/Makefile | 24 ++++++++++++------------
tools/scripts/Makefile.include | 8 ++++++++
2 files changed, 20 insertions(+), 12 deletions(-)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

--
1.7.9.2.358.g22243

2012-11-18 14:34:31

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 22/32] perf tools: Add basic event modifier sanity check

From: Jiri Olsa <[email protected]>

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

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

v2:
- added length check suggested Namhyung Kim

Signed-off-by: Jiri Olsa <[email protected]>
Acked-by: Namhyung Kim <[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]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/parse-events.c | 24 ++++++++++++++++++++++++
tools/perf/util/parse-events.l | 2 +-
2 files changed, 25 insertions(+), 1 deletion(-)

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

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

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

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

%%
--
1.7.9.2.358.g22243

2012-11-18 14:35:08

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 09/32] perf tests: Move test__syscall_open_tp_fields into separate object

From: Jiri Olsa <[email protected]>

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

Signed-off-by: Jiri Olsa <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[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 | 1 +
tools/perf/tests/builtin-test.c | 112 ---------------------------
tools/perf/tests/open-syscall-tp-fields.c | 117 +++++++++++++++++++++++++++++
tools/perf/tests/tests.h | 1 +
4 files changed, 119 insertions(+), 112 deletions(-)
create mode 100644 tools/perf/tests/open-syscall-tp-fields.c

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

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

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

2012-11-18 14:35:06

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 04/32] perf tests: Move test__basic_mmap into separate object

From: Jiri Olsa <[email protected]>

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

Signed-off-by: Jiri Olsa <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[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 | 1 +
tools/perf/tests/builtin-test.c | 157 -------------------------------------
tools/perf/tests/mmap-basic.c | 162 +++++++++++++++++++++++++++++++++++++++
tools/perf/tests/tests.h | 1 +
4 files changed, 164 insertions(+), 157 deletions(-)
create mode 100644 tools/perf/tests/mmap-basic.c

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

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


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

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

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

2012-11-18 14:35:04

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 20/32] perf tools: Ensure single disable call per event in record comand

From: Jiri Olsa <[email protected]>

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

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

Signed-off-by: Jiri Olsa <[email protected]>
Acked-by: Namhyung Kim <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[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/builtin-record.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)

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

rec->progname = argv[0];

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

if (quiet || signr == SIGUSR1)
--
1.7.9.2.358.g22243

2012-11-18 14:35:01

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 18/32] perf tools: Fix attributes for '{}' defined event groups

From: Jiri Olsa <[email protected]>

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

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

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

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

Signed-off-by: Jiri Olsa <[email protected]>
Acked-by: Namhyung Kim <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[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/builtin-record.c | 8 ++++++--
tools/perf/builtin-stat.c | 11 ++++-------
tools/perf/tests/attr/test-record-group1 | 4 +---
tools/perf/tests/attr/test-stat-group1 | 6 ++----
tools/perf/tests/open-syscall-tp-fields.c | 2 +-
tools/perf/util/evlist.c | 6 ++----
tools/perf/util/evsel.c | 8 +++-----
tools/perf/util/evsel.h | 3 +--
8 files changed, 20 insertions(+), 28 deletions(-)

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

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

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

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

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

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

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

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

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

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

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

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

-void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts,
- struct perf_evsel *first)
+void perf_evsel__config(struct perf_evsel *evsel,
+ struct perf_record_opts *opts)
{
struct perf_event_attr *attr = &evsel->attr;
int track = !evsel->idx; /* only the first counter needs these */
@@ -486,10 +486,8 @@ void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts,
attr->mmap = track;
attr->comm = track;

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

int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 6f94d6d..32d7ec7 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -92,8 +92,7 @@ void perf_evsel__exit(struct perf_evsel *evsel);
void perf_evsel__delete(struct perf_evsel *evsel);

void perf_evsel__config(struct perf_evsel *evsel,
- struct perf_record_opts *opts,
- struct perf_evsel *first);
+ struct perf_record_opts *opts);

bool perf_evsel__is_cache_op_valid(u8 type, u8 op);

--
1.7.9.2.358.g22243

2012-11-18 14:35:00

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 06/32] perf tests: Move test__rdpmc into separate object

From: Jiri Olsa <[email protected]>

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

Signed-off-by: Jiri Olsa <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[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 | 1 +
tools/perf/tests/builtin-test.c | 168 -------------------------------------
tools/perf/tests/rdpmc.c | 175 +++++++++++++++++++++++++++++++++++++++
tools/perf/tests/tests.h | 1 +
4 files changed, 177 insertions(+), 168 deletions(-)
create mode 100644 tools/perf/tests/rdpmc.c

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

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


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

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

2012-11-18 14:36:32

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 11/32] perf tests: Final cleanup for builtin-test move

From: Jiri Olsa <[email protected]>

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

Signed-off-by: Jiri Olsa <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[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/perf.h | 1 -
tools/perf/tests/attr.c | 3 ++-
tools/perf/tests/builtin-test.c | 34 +++++++---------------------------
tools/perf/tests/dso-data.c | 3 ++-
tools/perf/tests/parse-events.c | 3 ++-
tools/perf/tests/tests.h | 3 +++
tools/perf/util/parse-events.h | 1 -
tools/perf/util/symbol.h | 1 -
8 files changed, 16 insertions(+), 33 deletions(-)

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

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

#define ENV "PERF_TEST_ATTR"

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

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

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

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

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

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

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

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

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

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

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

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

2012-11-18 14:36:42

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 01/32] perf tests: Move test__vmlinux_matches_kallsyms into separate object

From: Jiri Olsa <[email protected]>

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

Signed-off-by: Jiri Olsa <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[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 | 1 +
tools/perf/tests/builtin-test.c | 223 +--------------------------------
tools/perf/tests/tests.h | 6 +
tools/perf/tests/vmlinux-kallsyms.c | 230 +++++++++++++++++++++++++++++++++++
4 files changed, 239 insertions(+), 221 deletions(-)
create mode 100644 tools/perf/tests/tests.h
create mode 100644 tools/perf/tests/vmlinux-kallsyms.c

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

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

#include <sys/mman.h>

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

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

2012-11-18 14:36:40

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 13/32] perf tools: Stop using 'self' in pstack

From: Arnaldo Carvalho de Melo <[email protected]>

As suggested by tglx long ago.

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/pstack.c | 46 +++++++++++++++++++++++-----------------------
1 file changed, 23 insertions(+), 23 deletions(-)

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

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

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

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

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

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

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

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

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

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

2012-11-18 14:36:39

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 21/32] perf tools: Omit group members from perf_evlist__disable/enable

From: Jiri Olsa <[email protected]>

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

Signed-off-by: Jiri Olsa <[email protected]>
Acked-by: Namhyung Kim <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[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/evlist.c | 4 ++++
1 file changed, 4 insertions(+)

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

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

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

2012-11-18 14:36:38

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 23/32] perf ui tui: Move progress.c under ui/tui directory

From: Namhyung Kim <[email protected]>

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

Signed-off-by: Namhyung Kim <[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/Makefile | 2 +-
tools/perf/ui/progress.c | 32 --------------------------------
tools/perf/ui/tui/progress.c | 32 ++++++++++++++++++++++++++++++++
3 files changed, 33 insertions(+), 33 deletions(-)
delete mode 100644 tools/perf/ui/progress.c
create mode 100644 tools/perf/ui/tui/progress.c

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

2012-11-18 14:36:37

by Arnaldo Carvalho de Melo

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

From: Namhyung Kim <[email protected]>

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

Signed-off-by: Namhyung Kim <[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/Makefile | 1 +
tools/perf/ui/gtk/util.c | 11 -----------
tools/perf/ui/progress.c | 20 ++++++++++++++++++++
tools/perf/ui/progress.h | 8 ++++++++
tools/perf/ui/tui/progress.c | 12 +++++++++++-
tools/perf/ui/tui/setup.c | 1 +
6 files changed, 41 insertions(+), 12 deletions(-)
create mode 100644 tools/perf/ui/progress.c

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

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

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

#include <../types.h>

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

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

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

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

2012-11-18 14:36:35

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 32/32] perf evsel: Introduce is_group_member method

From: Arnaldo Carvalho de Melo <[email protected]>

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

Cc: David Ahern <[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-stat.c | 3 ++-
tools/perf/tests/parse-events.c | 20 ++++++++++----------
tools/perf/util/evlist.c | 4 ++--
tools/perf/util/evsel.c | 6 +++---
tools/perf/util/evsel.h | 6 ++++++
5 files changed, 23 insertions(+), 16 deletions(-)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2012-11-18 14:36:33

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 15/32] perf tools: Fix compile error on NO_NEWT=1 build

From: Namhyung Kim <[email protected]>

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

Signed-off-by: Namhyung Kim <[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/hist.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

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

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

2012-11-18 14:36:31

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 12/32] perf tests: Check for mkstemp return value in dso-data test

From: Jiri Olsa <[email protected]>

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

Reported-by: Arnaldo Carvalho de Melo <[email protected]>
Signed-off-by: Jiri Olsa <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[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/tests/dso-data.c | 4 ++++
1 file changed, 4 insertions(+)

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

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

buf = malloc(size);
if (!buf) {
--
1.7.9.2.358.g22243

2012-11-19 13:29:12

by Josh Boyer

[permalink] [raw]
Subject: Re: [PATCH 31/32] perf powerpc: Use uapi/unistd.h to fix build error

On Sun, Nov 18, 2012 at 9:29 AM, Arnaldo Carvalho de Melo
<[email protected]> wrote:
> From: Sukadev Bhattiprolu <[email protected]>
>
> Use the 'unistd.h' from arch/powerpc/include/uapi to build the perf tool.

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

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

josh

2012-11-19 15:08:03

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: Re: [PATCH 31/32] perf powerpc: Use uapi/unistd.h to fix build error

Em Mon, Nov 19, 2012 at 08:29:09AM -0500, Josh Boyer escreveu:
> On Sun, Nov 18, 2012 at 9:29 AM, Arnaldo Carvalho de Melo <[email protected]> wrote:
> > From: Sukadev Bhattiprolu <[email protected]>

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

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

- Arnaldo

2012-11-19 15:18:40

by Josh Boyer

[permalink] [raw]
Subject: Re: [PATCH 31/32] perf powerpc: Use uapi/unistd.h to fix build error

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

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

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

josh