From d53e57d039c323fe3a43630e9f729df48134e2c9 Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Fri, 25 Oct 2013 20:25:49 -0400 Subject: perf ui tui progress: Don't force a refresh during progress update Each call to tui_progress__update() would forcibly refresh the entire screen. This is somewhat inefficient and causes noticable flickering during the startup of perf-report, especially on large/slow terminals. It looks like the force-refresh in tui_progress__update() serves no purpose other than to clear the screen so that the progress bar of a previous operation does not subsume that of a subsequent operation. But we can do just that in a much more efficient manner by clearing only the region that a previous progress bar may have occupied before repainting the new progress bar. Then the force-refresh could be removed with no change in visuals. This patch disables the slow force-refresh in tui_progress__update() and instead calls SLsmg_fill_region() on the entire area that the progress bar may occupy before repainting it. This change makes the startup of perf-report much faster and appear much "smoother". It turns out that this was a big bottleneck in the startup speed of perf-report -- with this patch, perf-report starts up ~2x faster (1.1s vs 0.55s) on my machines. (These numbers were measured by running "time perf report" on an 8MB perf.data and pressing 'q' immediately.) Signed-off-by: Patrick Palka Acked-by: Ingo Molnar Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1382747149-9716-1-git-send-email-patrick@parcs.ath.cx Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/tui/progress.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/ui/tui/progress.c b/tools/perf/ui/tui/progress.c index 3e2d936d7443..c61d14b101e0 100644 --- a/tools/perf/ui/tui/progress.c +++ b/tools/perf/ui/tui/progress.c @@ -18,13 +18,14 @@ static void tui_progress__update(struct ui_progress *p) if (p->total == 0) return; - ui__refresh_dimensions(true); + ui__refresh_dimensions(false); 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 *)p->title); + SLsmg_fill_region(y, 1, 1, SLtt_Screen_Cols - 2, ' '); SLsmg_set_color(HE_COLORSET_SELECTED); bar = ((SLtt_Screen_Cols - 2) * p->curr) / p->total; SLsmg_fill_region(y, 1, 1, bar, ' '); -- cgit v1.2.3-58-ga151 From ef503831d8d64e12c6dad5547875cfcd4c5d043c Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 7 Nov 2013 16:41:19 -0300 Subject: perf evsel: Remove idx parm from constructor Most uses of the evsel constructor are followed by a call to perf_evlist__add with an idex of evlist->nr_entries, so make rename the current constructor to perf_evsel__new_idx and remove the need for passing the constructor for the common case. We still need the new_idx variant because the way groups are handled, with evsel->nr_members holding the number of entries in an evlist, partitioning the evlist into sublists inside a single linked list. This asks for a clarifying refactoring, but for now simplify the non parser cases, so that tool writers don't have to bother with evsel idx setting. Cc: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-zy9tskx6jqm2rmw7468zze2a@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 13 +++++-------- tools/perf/tests/evsel-tp-sched.c | 4 ++-- tools/perf/tests/mmap-basic.c | 2 +- tools/perf/tests/open-syscall-all-cpus.c | 2 +- tools/perf/tests/open-syscall-tp-fields.c | 2 +- tools/perf/tests/open-syscall.c | 2 +- tools/perf/tests/sw-clock.c | 2 +- tools/perf/util/evlist.c | 9 +++++---- tools/perf/util/evsel.c | 4 ++-- tools/perf/util/evsel.h | 15 +++++++++++++-- tools/perf/util/header.c | 4 ++-- tools/perf/util/parse-events.c | 6 +++--- 12 files changed, 37 insertions(+), 28 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 329b7832b5da..68943cad70d4 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -149,10 +149,9 @@ static void perf_evsel__delete_priv(struct perf_evsel *evsel) perf_evsel__delete(evsel); } -static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction, - void *handler, int idx) +static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction, void *handler) { - struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction, idx); + struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction); if (evsel) { evsel->priv = malloc(sizeof(struct syscall_tp)); @@ -186,17 +185,16 @@ static int perf_evlist__add_syscall_newtp(struct perf_evlist *evlist, void *sys_exit_handler) { int ret = -1; - int idx = evlist->nr_entries; struct perf_evsel *sys_enter, *sys_exit; - sys_enter = perf_evsel__syscall_newtp("sys_enter", sys_enter_handler, idx++); + sys_enter = perf_evsel__syscall_newtp("sys_enter", sys_enter_handler); if (sys_enter == NULL) goto out; if (perf_evsel__init_sc_tp_ptr_field(sys_enter, args)) goto out_delete_sys_enter; - sys_exit = perf_evsel__syscall_newtp("sys_exit", sys_exit_handler, idx++); + sys_exit = perf_evsel__syscall_newtp("sys_exit", sys_exit_handler); if (sys_exit == NULL) goto out_delete_sys_enter; @@ -1824,8 +1822,7 @@ static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp); static void perf_evlist__add_vfs_getname(struct perf_evlist *evlist) { - struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname", - evlist->nr_entries); + struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname"); if (evsel == NULL) return; diff --git a/tools/perf/tests/evsel-tp-sched.c b/tools/perf/tests/evsel-tp-sched.c index 9b98c1554833..4774f7fbb758 100644 --- a/tools/perf/tests/evsel-tp-sched.c +++ b/tools/perf/tests/evsel-tp-sched.c @@ -32,7 +32,7 @@ static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name, int test__perf_evsel__tp_sched_test(void) { - struct perf_evsel *evsel = perf_evsel__newtp("sched", "sched_switch", 0); + struct perf_evsel *evsel = perf_evsel__newtp("sched", "sched_switch"); int ret = 0; if (evsel == NULL) { @@ -63,7 +63,7 @@ int test__perf_evsel__tp_sched_test(void) perf_evsel__delete(evsel); - evsel = perf_evsel__newtp("sched", "sched_wakeup", 0); + evsel = perf_evsel__newtp("sched", "sched_wakeup"); if (perf_evsel__test_field(evsel, "comm", 16, true)) ret = -1; diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c index a7232c204eb9..d64ab79c6d35 100644 --- a/tools/perf/tests/mmap-basic.c +++ b/tools/perf/tests/mmap-basic.c @@ -65,7 +65,7 @@ int test__basic_mmap(void) char name[64]; snprintf(name, sizeof(name), "sys_enter_%s", syscall_names[i]); - evsels[i] = perf_evsel__newtp("syscalls", name, i); + evsels[i] = perf_evsel__newtp("syscalls", name); if (evsels[i] == NULL) { pr_debug("perf_evsel__new\n"); goto out_free_evlist; diff --git a/tools/perf/tests/open-syscall-all-cpus.c b/tools/perf/tests/open-syscall-all-cpus.c index b0657a9ccda6..5fecdbd2f5f7 100644 --- a/tools/perf/tests/open-syscall-all-cpus.c +++ b/tools/perf/tests/open-syscall-all-cpus.c @@ -26,7 +26,7 @@ int test__open_syscall_event_on_all_cpus(void) CPU_ZERO(&cpu_set); - evsel = perf_evsel__newtp("syscalls", "sys_enter_open", 0); + evsel = perf_evsel__newtp("syscalls", "sys_enter_open"); if (evsel == NULL) { pr_debug("is debugfs mounted on /sys/kernel/debug?\n"); goto out_thread_map_delete; diff --git a/tools/perf/tests/open-syscall-tp-fields.c b/tools/perf/tests/open-syscall-tp-fields.c index 524b221b829b..41cc0badb74b 100644 --- a/tools/perf/tests/open-syscall-tp-fields.c +++ b/tools/perf/tests/open-syscall-tp-fields.c @@ -27,7 +27,7 @@ int test__syscall_open_tp_fields(void) goto out; } - evsel = perf_evsel__newtp("syscalls", "sys_enter_open", 0); + evsel = perf_evsel__newtp("syscalls", "sys_enter_open"); if (evsel == NULL) { pr_debug("%s: perf_evsel__newtp\n", __func__); goto out_delete_evlist; diff --git a/tools/perf/tests/open-syscall.c b/tools/perf/tests/open-syscall.c index befc0671f95d..c1dc7d25f38c 100644 --- a/tools/perf/tests/open-syscall.c +++ b/tools/perf/tests/open-syscall.c @@ -15,7 +15,7 @@ int test__open_syscall_event(void) return -1; } - evsel = perf_evsel__newtp("syscalls", "sys_enter_open", 0); + evsel = perf_evsel__newtp("syscalls", "sys_enter_open"); if (evsel == NULL) { pr_debug("is debugfs mounted on /sys/kernel/debug?\n"); goto out_thread_map_delete; diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c index 6e2b44ec0749..73c5c37cb27b 100644 --- a/tools/perf/tests/sw-clock.c +++ b/tools/perf/tests/sw-clock.c @@ -42,7 +42,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id) return -1; } - evsel = perf_evsel__new(&attr, 0); + evsel = perf_evsel__new(&attr); if (evsel == NULL) { pr_debug("perf_evsel__new\n"); goto out_free_evlist; diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index b939221efd8d..99dc58e5dcc3 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -117,6 +117,8 @@ void perf_evlist__delete(struct perf_evlist *evlist) void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry) { list_add_tail(&entry->node, &evlist->entries); + entry->idx = evlist->nr_entries; + if (!evlist->nr_entries++) perf_evlist__set_id_pos(evlist); } @@ -165,7 +167,7 @@ int perf_evlist__add_default(struct perf_evlist *evlist) event_attr_init(&attr); - evsel = perf_evsel__new(&attr, 0); + evsel = perf_evsel__new(&attr); if (evsel == NULL) goto error; @@ -190,7 +192,7 @@ static int perf_evlist__add_attrs(struct perf_evlist *evlist, size_t i; for (i = 0; i < nr_attrs; i++) { - evsel = perf_evsel__new(attrs + i, evlist->nr_entries + i); + evsel = perf_evsel__new_idx(attrs + i, evlist->nr_entries + i); if (evsel == NULL) goto out_delete_partial_list; list_add_tail(&evsel->node, &head); @@ -249,9 +251,8 @@ perf_evlist__find_tracepoint_by_name(struct perf_evlist *evlist, int perf_evlist__add_newtp(struct perf_evlist *evlist, const char *sys, const char *name, void *handler) { - struct perf_evsel *evsel; + struct perf_evsel *evsel = perf_evsel__newtp(sys, name); - evsel = perf_evsel__newtp(sys, name, evlist->nr_entries); if (evsel == NULL) return -1; diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 5280820ed389..f95653a639a6 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -168,7 +168,7 @@ void perf_evsel__init(struct perf_evsel *evsel, perf_evsel__calc_id_pos(evsel); } -struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx) +struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx) { struct perf_evsel *evsel = zalloc(sizeof(*evsel)); @@ -219,7 +219,7 @@ out: return format; } -struct perf_evsel *perf_evsel__newtp(const char *sys, const char *name, int idx) +struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx) { struct perf_evsel *evsel = zalloc(sizeof(*evsel)); diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 64ec8e1a7a28..0178233abd64 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -96,8 +96,19 @@ struct thread_map; struct perf_evlist; struct perf_record_opts; -struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx); -struct perf_evsel *perf_evsel__newtp(const char *sys, const char *name, int idx); +struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx); + +static inline struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr) +{ + return perf_evsel__new_idx(attr, 0); +} + +struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx); + +static inline struct perf_evsel *perf_evsel__newtp(const char *sys, const char *name) +{ + return perf_evsel__newtp_idx(sys, name, 0); +} struct event_format *event_format__new(const char *sys, const char *name); diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 26d9520a0c1b..369c03648f88 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -2797,7 +2797,7 @@ int perf_session__read_header(struct perf_session *session) perf_event__attr_swap(&f_attr.attr); tmp = lseek(fd, 0, SEEK_CUR); - evsel = perf_evsel__new(&f_attr.attr, i); + evsel = perf_evsel__new(&f_attr.attr); if (evsel == NULL) goto out_delete_evlist; @@ -2916,7 +2916,7 @@ int perf_event__process_attr(struct perf_tool *tool __maybe_unused, return -ENOMEM; } - evsel = perf_evsel__new(&event->attr.attr, evlist->nr_entries); + evsel = perf_evsel__new(&event->attr.attr); if (evsel == NULL) return -ENOMEM; diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index c90e55cf7e82..6de6f89c2a61 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -277,7 +277,7 @@ static int __add_event(struct list_head *list, int *idx, event_attr_init(attr); - evsel = perf_evsel__new(attr, (*idx)++); + evsel = perf_evsel__new_idx(attr, (*idx)++); if (!evsel) return -ENOMEM; @@ -378,7 +378,7 @@ static int add_tracepoint(struct list_head *list, int *idx, { struct perf_evsel *evsel; - evsel = perf_evsel__newtp(sys_name, evt_name, (*idx)++); + evsel = perf_evsel__newtp_idx(sys_name, evt_name, (*idx)++); if (!evsel) return -ENOMEM; @@ -1097,7 +1097,7 @@ static bool is_event_supported(u8 type, unsigned config) .threads = { 0 }, }; - evsel = perf_evsel__new(&attr, 0); + evsel = perf_evsel__new(&attr); if (evsel) { ret = perf_evsel__open(evsel, NULL, &tmap.map) >= 0; perf_evsel__delete(evsel); -- cgit v1.2.3-58-ga151 From 62605dc50c27bf0e4ff69b7b3166f226586aff02 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 11 Nov 2013 09:44:09 -0300 Subject: perf record: Synthesize non-exec MMAP records when --data used When perf_event_attr.mmap_data is set the kernel will generate PERF_RECORD_MMAP events when non-exec (data, SysV mem) mmaps are created, so we need to synthesize from /proc/pid/maps for existing threads, as we do for exec mmaps. Right now just 'perf record' does it, but any other tool that uses perf_event__synthesize_thread(s|map) can request it. Reported-by: Don Zickus Tested-by: Don Zickus Cc: Adrian Hunter Cc: Bill Gray Cc: David Ahern Cc: Don Zickus Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Joe Mario Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Richard Fowles Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-ihwzraikx23ian9txinogvv2@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-kvm.c | 4 ++-- tools/perf/builtin-record.c | 6 ++--- tools/perf/builtin-top.c | 4 ++-- tools/perf/builtin-trace.c | 4 ++-- tools/perf/tests/code-reading.c | 2 +- tools/perf/util/event.c | 50 ++++++++++++++++++++++++----------------- tools/perf/util/event.h | 4 ++-- 7 files changed, 42 insertions(+), 32 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index cd9f92078aba..f36e8209c300 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -1550,10 +1550,10 @@ static int kvm_events_live(struct perf_kvm_stat *kvm, perf_event__synthesize_thread_map(&kvm->tool, kvm->evlist->threads, perf_event__process, - &kvm->session->machines.host); + &kvm->session->machines.host, false); else perf_event__synthesize_threads(&kvm->tool, perf_event__process, - &kvm->session->machines.host); + &kvm->session->machines.host, false); err = kvm_live_open_events(kvm); diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 15280b5e5574..afb252cf6eca 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -482,11 +482,11 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) if (perf_target__has_task(&opts->target)) err = perf_event__synthesize_thread_map(tool, evsel_list->threads, - process_synthesized_event, - machine); + process_synthesized_event, + machine, opts->sample_address); else if (perf_target__has_cpu(&opts->target)) err = perf_event__synthesize_threads(tool, process_synthesized_event, - machine); + machine, opts->sample_address); else /* command specified */ err = 0; diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 9acca8856ccb..cc96d753db96 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -953,10 +953,10 @@ static int __cmd_top(struct perf_top *top) if (perf_target__has_task(&opts->target)) perf_event__synthesize_thread_map(&top->tool, top->evlist->threads, perf_event__process, - &top->session->machines.host); + &top->session->machines.host, false); else perf_event__synthesize_threads(&top->tool, perf_event__process, - &top->session->machines.host); + &top->session->machines.host, false); ret = perf_top__start_counters(top); if (ret) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 68943cad70d4..277c2367e0cf 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1343,10 +1343,10 @@ static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist) if (perf_target__has_task(&trace->opts.target)) { err = perf_event__synthesize_thread_map(&trace->tool, evlist->threads, trace__tool_process, - trace->host); + trace->host, false); } else { err = perf_event__synthesize_threads(&trace->tool, trace__tool_process, - trace->host); + trace->host, false); } if (err) diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index 49ccc3b2995e..6d9dc198a200 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c @@ -441,7 +441,7 @@ static int do_test_code_reading(bool try_kcore) } ret = perf_event__synthesize_thread_map(NULL, threads, - perf_event__process, machine); + perf_event__process, machine, false); if (ret < 0) { pr_debug("perf_event__synthesize_thread_map failed\n"); goto out_err; diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index ec9ae1114ed4..6e3a846aed0e 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -170,7 +170,8 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool, union perf_event *event, pid_t pid, pid_t tgid, perf_event__handler_t process, - struct machine *machine) + struct machine *machine, + bool mmap_data) { char filename[PATH_MAX]; FILE *fp; @@ -188,10 +189,6 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool, } event->header.type = PERF_RECORD_MMAP; - /* - * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c - */ - event->header.misc = PERF_RECORD_MISC_USER; while (1) { char bf[BUFSIZ]; @@ -215,9 +212,17 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool, if (n != 5) continue; + /* + * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c + */ + event->header.misc = PERF_RECORD_MISC_USER; - if (prot[2] != 'x') - continue; + if (prot[2] != 'x') { + if (!mmap_data || prot[0] != 'r') + continue; + + event->header.misc |= PERF_RECORD_MISC_MMAP_DATA; + } if (!strcmp(execname, "")) strcpy(execname, anonstr); @@ -304,20 +309,21 @@ static int __event__synthesize_thread(union perf_event *comm_event, pid_t pid, int full, perf_event__handler_t process, struct perf_tool *tool, - struct machine *machine) + struct machine *machine, bool mmap_data) { pid_t tgid = perf_event__synthesize_comm(tool, comm_event, pid, full, process, machine); if (tgid == -1) return -1; return perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid, - process, machine); + process, machine, mmap_data); } int perf_event__synthesize_thread_map(struct perf_tool *tool, struct thread_map *threads, perf_event__handler_t process, - struct machine *machine) + struct machine *machine, + bool mmap_data) { union perf_event *comm_event, *mmap_event; int err = -1, thread, j; @@ -334,7 +340,8 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool, for (thread = 0; thread < threads->nr; ++thread) { if (__event__synthesize_thread(comm_event, mmap_event, threads->map[thread], 0, - process, tool, machine)) { + process, tool, machine, + mmap_data)) { err = -1; break; } @@ -356,10 +363,10 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool, /* if not, generate events for it */ if (need_leader && - __event__synthesize_thread(comm_event, - mmap_event, - comm_event->comm.pid, 0, - process, tool, machine)) { + __event__synthesize_thread(comm_event, mmap_event, + comm_event->comm.pid, 0, + process, tool, machine, + mmap_data)) { err = -1; break; } @@ -374,7 +381,7 @@ out: int perf_event__synthesize_threads(struct perf_tool *tool, perf_event__handler_t process, - struct machine *machine) + struct machine *machine, bool mmap_data) { DIR *proc; struct dirent dirent, *next; @@ -404,7 +411,7 @@ int perf_event__synthesize_threads(struct perf_tool *tool, * one thread couldn't be synthesized. */ __event__synthesize_thread(comm_event, mmap_event, pid, 1, - process, tool, machine); + process, tool, machine, mmap_data); } err = 0; @@ -528,19 +535,22 @@ int perf_event__process_lost(struct perf_tool *tool __maybe_unused, size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp) { - return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %s\n", + return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %c %s\n", event->mmap.pid, event->mmap.tid, event->mmap.start, - event->mmap.len, event->mmap.pgoff, event->mmap.filename); + event->mmap.len, event->mmap.pgoff, + (event->header.misc & PERF_RECORD_MISC_MMAP_DATA) ? 'r' : 'x', + event->mmap.filename); } size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp) { return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 - " %02x:%02x %"PRIu64" %"PRIu64"]: %s\n", + " %02x:%02x %"PRIu64" %"PRIu64"]: %c %s\n", event->mmap2.pid, event->mmap2.tid, event->mmap2.start, event->mmap2.len, event->mmap2.pgoff, event->mmap2.maj, event->mmap2.min, event->mmap2.ino, event->mmap2.ino_generation, + (event->header.misc & PERF_RECORD_MISC_MMAP_DATA) ? 'r' : 'x', event->mmap2.filename); } diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index f8d70f3003ab..30fec9901e44 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -208,10 +208,10 @@ typedef int (*perf_event__handler_t)(struct perf_tool *tool, int perf_event__synthesize_thread_map(struct perf_tool *tool, struct thread_map *threads, perf_event__handler_t process, - struct machine *machine); + struct machine *machine, bool mmap_data); int perf_event__synthesize_threads(struct perf_tool *tool, perf_event__handler_t process, - struct machine *machine); + struct machine *machine, bool mmap_data); int perf_event__synthesize_kernel_mmap(struct perf_tool *tool, perf_event__handler_t process, struct machine *machine, -- cgit v1.2.3-58-ga151 From 58d925dcede9e8765876707a33a3406011fe1c11 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 11 Nov 2013 11:28:02 -0300 Subject: perf machine: Introduce synthesize_threads method out of open coded equivalent Further simplifications to be done on following patch, as most tools don't use the callback, using instead just the canned machine__process_event one. Cc: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-r1m0vuuj3cat4bampno9yc8d@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-kvm.c | 15 +++------------ tools/perf/builtin-record.c | 12 ++---------- tools/perf/builtin-top.c | 11 +++-------- tools/perf/builtin-trace.c | 11 ++--------- tools/perf/util/machine.c | 12 ++++++++++++ tools/perf/util/machine.h | 4 ++++ 6 files changed, 26 insertions(+), 39 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index f36e8209c300..f5d2c4bccbec 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -1544,18 +1544,9 @@ static int kvm_events_live(struct perf_kvm_stat *kvm, } kvm->session->evlist = kvm->evlist; perf_session__set_id_hdr_size(kvm->session); - - - if (perf_target__has_task(&kvm->opts.target)) - perf_event__synthesize_thread_map(&kvm->tool, - kvm->evlist->threads, - perf_event__process, - &kvm->session->machines.host, false); - else - perf_event__synthesize_threads(&kvm->tool, perf_event__process, - &kvm->session->machines.host, false); - - + machine__synthesize_threads(&kvm->session->machines.host, &kvm->tool, + &kvm->opts.target, kvm->evlist->threads, + perf_event__process, false); err = kvm_live_open_events(kvm); if (err) goto out; diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index afb252cf6eca..41d1f37f5348 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -480,16 +480,8 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) perf_event__synthesize_guest_os, tool); } - if (perf_target__has_task(&opts->target)) - err = perf_event__synthesize_thread_map(tool, evsel_list->threads, - process_synthesized_event, - machine, opts->sample_address); - else if (perf_target__has_cpu(&opts->target)) - err = perf_event__synthesize_threads(tool, process_synthesized_event, - machine, opts->sample_address); - else /* command specified */ - err = 0; - + err = machine__synthesize_threads(machine, tool, &opts->target, evsel_list->threads, + process_synthesized_event, opts->sample_address); if (err != 0) goto out_delete_session; diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index cc96d753db96..c3a936ef7688 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -950,14 +950,9 @@ static int __cmd_top(struct perf_top *top) if (ret) goto out_delete; - if (perf_target__has_task(&opts->target)) - perf_event__synthesize_thread_map(&top->tool, top->evlist->threads, - perf_event__process, - &top->session->machines.host, false); - else - perf_event__synthesize_threads(&top->tool, perf_event__process, - &top->session->machines.host, false); - + machine__synthesize_threads(&top->session->machines.host, &top->tool, + &opts->target, top->evlist->threads, + perf_event__process, false); ret = perf_top__start_counters(top); if (ret) goto out_delete; diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 277c2367e0cf..7690324824db 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1340,15 +1340,8 @@ static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist) if (trace->host == NULL) return -ENOMEM; - if (perf_target__has_task(&trace->opts.target)) { - err = perf_event__synthesize_thread_map(&trace->tool, evlist->threads, - trace__tool_process, - trace->host, false); - } else { - err = perf_event__synthesize_threads(&trace->tool, trace__tool_process, - trace->host, false); - } - + err = machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target, + evlist->threads, trace__tool_process, false); if (err) symbol__exit(); diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index ce034c183a7e..9f2c61d5a9ed 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -1394,3 +1394,15 @@ int machine__for_each_thread(struct machine *machine, } return rc; } + +int machine__synthesize_threads(struct machine *machine, struct perf_tool *tool, + struct perf_target *target, struct thread_map *threads, + perf_event__handler_t process, bool data_mmap) +{ + if (perf_target__has_task(target)) + return perf_event__synthesize_thread_map(tool, threads, process, machine, data_mmap); + else if (perf_target__has_cpu(target)) + return perf_event__synthesize_threads(tool, process, machine, data_mmap); + /* command specified */ + return 0; +} diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h index 2389ba81fafe..14a89d2aecaf 100644 --- a/tools/perf/util/machine.h +++ b/tools/perf/util/machine.h @@ -4,6 +4,7 @@ #include #include #include "map.h" +#include "event.h" struct addr_location; struct branch_stack; @@ -178,4 +179,7 @@ int machine__for_each_thread(struct machine *machine, int (*fn)(struct thread *thread, void *p), void *priv); +int machine__synthesize_threads(struct machine *machine, struct perf_tool *tool, + struct perf_target *target, struct thread_map *threads, + perf_event__handler_t process, bool data_mmap); #endif /* __PERF_MACHINE_H */ -- cgit v1.2.3-58-ga151 From a33fbd56ec83b5421090b4d8f2032f635e6a9488 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 11 Nov 2013 11:36:12 -0300 Subject: perf machine: Simplify synthesize_threads method Several tools (top, kvm) don't need to be called back to process each of the syntheiszed records, instead relying on the machine__process_event function to change the per machine data structures that represent threads and mmaps, so provide a way to ask for this common idiom. Cc: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-pusqibp8n3c4ynegd1frn4zd@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-kvm.c | 5 ++--- tools/perf/builtin-record.c | 4 ++-- tools/perf/builtin-top.c | 5 ++--- tools/perf/builtin-trace.c | 4 ++-- tools/perf/util/machine.c | 6 +++--- tools/perf/util/machine.h | 14 +++++++++++--- 6 files changed, 22 insertions(+), 16 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index f5d2c4bccbec..346bb5909e3d 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -1544,9 +1544,8 @@ static int kvm_events_live(struct perf_kvm_stat *kvm, } kvm->session->evlist = kvm->evlist; perf_session__set_id_hdr_size(kvm->session); - machine__synthesize_threads(&kvm->session->machines.host, &kvm->tool, - &kvm->opts.target, kvm->evlist->threads, - perf_event__process, false); + machine__synthesize_threads(&kvm->session->machines.host, &kvm->opts.target, + kvm->evlist->threads, false); err = kvm_live_open_events(kvm); if (err) goto out; diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 41d1f37f5348..fc68b26d58f9 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -480,8 +480,8 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) perf_event__synthesize_guest_os, tool); } - err = machine__synthesize_threads(machine, tool, &opts->target, evsel_list->threads, - process_synthesized_event, opts->sample_address); + err = __machine__synthesize_threads(machine, tool, &opts->target, evsel_list->threads, + process_synthesized_event, opts->sample_address); if (err != 0) goto out_delete_session; diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index c3a936ef7688..8c520d9fecfc 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -950,9 +950,8 @@ static int __cmd_top(struct perf_top *top) if (ret) goto out_delete; - machine__synthesize_threads(&top->session->machines.host, &top->tool, - &opts->target, top->evlist->threads, - perf_event__process, false); + machine__synthesize_threads(&top->session->machines.host, &opts->target, + top->evlist->threads, false); ret = perf_top__start_counters(top); if (ret) goto out_delete; diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 7690324824db..c3008b1c369c 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1340,8 +1340,8 @@ static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist) if (trace->host == NULL) return -ENOMEM; - err = machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target, - evlist->threads, trace__tool_process, false); + err = __machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target, + evlist->threads, trace__tool_process, false); if (err) symbol__exit(); diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 9f2c61d5a9ed..680700b6d779 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -1395,9 +1395,9 @@ int machine__for_each_thread(struct machine *machine, return rc; } -int machine__synthesize_threads(struct machine *machine, struct perf_tool *tool, - struct perf_target *target, struct thread_map *threads, - perf_event__handler_t process, bool data_mmap) +int __machine__synthesize_threads(struct machine *machine, struct perf_tool *tool, + struct perf_target *target, struct thread_map *threads, + perf_event__handler_t process, bool data_mmap) { if (perf_target__has_task(target)) return perf_event__synthesize_thread_map(tool, threads, process, machine, data_mmap); diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h index 14a89d2aecaf..fedd1dfaf715 100644 --- a/tools/perf/util/machine.h +++ b/tools/perf/util/machine.h @@ -179,7 +179,15 @@ int machine__for_each_thread(struct machine *machine, int (*fn)(struct thread *thread, void *p), void *priv); -int machine__synthesize_threads(struct machine *machine, struct perf_tool *tool, - struct perf_target *target, struct thread_map *threads, - perf_event__handler_t process, bool data_mmap); +int __machine__synthesize_threads(struct machine *machine, struct perf_tool *tool, + struct perf_target *target, struct thread_map *threads, + perf_event__handler_t process, bool data_mmap); +static inline +int machine__synthesize_threads(struct machine *machine, struct perf_target *target, + struct thread_map *threads, bool data_mmap) +{ + return __machine__synthesize_threads(machine, NULL, target, threads, + perf_event__process, data_mmap); +} + #endif /* __PERF_MACHINE_H */ -- cgit v1.2.3-58-ga151 From 7524f63b997cc02a80aa073558728ae3ee242cf8 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Fri, 8 Nov 2013 17:53:42 +0900 Subject: perf tools: Prevent condition that all sort keys are elided If given sort keys are all elided there'll be no output except for the overhead column - actually the TUI shows a noisy output. In this case it'd be better to show up the sort keys rather than elide. Before: $ perf report -s comm -c perf (...) # Overhead # ........ # 100.00% After: $ perf report -s comm -c perf (...) # Overhead Command # ........ ....... # 100.00% perf Signed-off-by: Namhyung Kim Acked-by: Ingo Molnar Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1383900822-14609-1-git-send-email-namhyung@kernel.org [ Us curly braces around multi-line statements, as requested by Ingo Molnar ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/sort.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'tools') diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 3c1b75c8b9a6..8b0bb1f4494a 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -1137,6 +1137,8 @@ static void sort_entry__setup_elide(struct sort_entry *se, void sort__setup_elide(FILE *output) { + struct sort_entry *se; + sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "dso", output); sort_entry__setup_elide(&sort_comm, symbol_conf.comm_list, @@ -1172,4 +1174,15 @@ void sort__setup_elide(FILE *output) "snoop", output); } + /* + * It makes no sense to elide all of sort entries. + * Just revert them to show up again. + */ + list_for_each_entry(se, &hist_entry__sort_list, list) { + if (!se->elide) + return; + } + + list_for_each_entry(se, &hist_entry__sort_list, list) + se->elide = false; } -- cgit v1.2.3-58-ga151 From 410f17860318f36b999a90138f50350e3dc49933 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 8 Nov 2013 12:27:50 +0200 Subject: perf record: Use correct return type for write() write() returns a 'ssize_t' not an 'int'. Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1383906470-21002-1-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-record.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index fc68b26d58f9..8f5af32d6451 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -81,7 +81,7 @@ static int write_output(struct perf_record *rec, void *buf, size_t size) struct perf_data_file *file = &rec->file; while (size) { - int ret = write(file->fd, buf, size); + ssize_t ret = write(file->fd, buf, size); if (ret < 0) { pr_err("failed to write perf data, error: %m\n"); -- cgit v1.2.3-58-ga151 From a9986fad6645b98d5bb3c2f83c22efb0761ca272 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Thu, 7 Nov 2013 21:23:24 -0700 Subject: perf record: Move existing write_output into helper function Code move only; no logic changes. In preparation for the mmap based output option in the next patch. Signed-off-by: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1383884605-30968-2-git-send-email-dsahern@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-record.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 8f5af32d6451..880227eae20f 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -76,7 +76,7 @@ struct perf_record { long samples; }; -static int write_output(struct perf_record *rec, void *buf, size_t size) +static int do_write_output(struct perf_record *rec, void *buf, size_t size) { struct perf_data_file *file = &rec->file; @@ -97,6 +97,11 @@ static int write_output(struct perf_record *rec, void *buf, size_t size) return 0; } +static int write_output(struct perf_record *rec, void *buf, size_t size) +{ + return do_write_output(rec, buf, size); +} + static int process_synthesized_event(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample __maybe_unused, -- cgit v1.2.3-58-ga151 From d0b849e9bced36cf279881294c07c43b0b9dce86 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 11 Nov 2013 16:28:42 -0300 Subject: perf tests: Check return of perf_evlist__open sw clock event period test We were not checking if we successfully opened the counters, i.e. if sys_perf_event_open worked, when it doesn't in this test, we were continuing anyway and then segfaulting when trying to access the file descriptor array, that at that point had been freed in perf_evlist__open error path: [root@ssdandy ~]# perf test -v 19 19: Test software clock events have valid period values : --- start --- Segmentation fault (core dumped) [root@ssdandy ~]# Do the check and bail out instead. Cc: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-6qy8ljkn0e9hm7bh7keo5z68@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/sw-clock.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c index 73c5c37cb27b..ed777728dfe7 100644 --- a/tools/perf/tests/sw-clock.c +++ b/tools/perf/tests/sw-clock.c @@ -57,7 +57,11 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id) goto out_delete_maps; } - perf_evlist__open(evlist); + if (perf_evlist__open(evlist)) { + err = -errno; + pr_debug("Couldn't open evlist: %s\n", strerror(errno)); + goto out_delete_maps; + } err = perf_evlist__mmap(evlist, 128, true); if (err < 0) { -- cgit v1.2.3-58-ga151 From 67c1e4a53b17894e6a24f95057cc374c4be051cb Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 11 Nov 2013 16:33:18 -0300 Subject: perf tests: Use lower sample_freq in sw clock event period test We were using it at 10 kHz, which doesn't work in machines where somehow the max freq was auto reduced by the kernel: [root@ssdandy ~]# perf test 19 19: Test software clock events have valid period values : FAILED! [root@ssdandy ~]# perf test -v 19 19: Test software clock events have valid period values : --- start --- Couldn't open evlist: Invalid argument ---- end ---- Test software clock events have valid period values: FAILED! [root@ssdandy ~]# [root@ssdandy ~]# cat /proc/sys/kernel/perf_event_max_sample_rate 7000 Reducing it to 500 Hz should be good enough for this test and also shouldn't affect what it is testing. But warn the user if it fails, informing the knob and the freq tried. Cc: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-548rhj1uo6xbwnxa95kw3hqe@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/sw-clock.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c index ed777728dfe7..93a7139ff5f7 100644 --- a/tools/perf/tests/sw-clock.c +++ b/tools/perf/tests/sw-clock.c @@ -34,7 +34,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id) .freq = 1, }; - attr.sample_freq = 10000; + attr.sample_freq = 500; evlist = perf_evlist__new(); if (evlist == NULL) { @@ -58,8 +58,11 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id) } if (perf_evlist__open(evlist)) { + const char *knob = "/proc/sys/kernel/perf_event_max_sample_rate"; + err = -errno; - pr_debug("Couldn't open evlist: %s\n", strerror(errno)); + pr_debug("Couldn't open evlist: %s\nHint: check %s, using %" PRIu64 " in this test.\n", + strerror(errno), knob, (u64)attr.sample_freq); goto out_delete_maps; } -- cgit v1.2.3-58-ga151 From 73faab3a421351c342b10b0177fec9eea1a1d809 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 12 Nov 2013 15:24:59 +0900 Subject: perf trace: Beautify fifth argument of mmap() as fd The fifth argument of mmap syscall is fd and it often contains -1 as a value for anon mappings. Without this patch it doesn't show the file name as well as it shows -1 as 4294967295. Signed-off-by: Namhyung Kim Acked-by: David Ahern Cc: David Ahern Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1384237500-22991-1-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index c3008b1c369c..aeb6296a76bd 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -951,7 +951,8 @@ static struct syscall_fmt { { .name = "mmap", .hexret = true, .arg_scnprintf = { [0] = SCA_HEX, /* addr */ [2] = SCA_MMAP_PROT, /* prot */ - [3] = SCA_MMAP_FLAGS, /* flags */ }, }, + [3] = SCA_MMAP_FLAGS, /* flags */ + [4] = SCA_FD, /* fd */ }, }, { .name = "mprotect", .errmsg = true, .arg_scnprintf = { [0] = SCA_HEX, /* start */ [2] = SCA_MMAP_PROT, /* prot */ }, }, -- cgit v1.2.3-58-ga151 From 96695d440242aca871ef8d797bd98d9cbd7ad8a0 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 12 Nov 2013 08:51:45 -0300 Subject: perf trace: Separate tp syscall field caching into init routine to be reused We need to set this in evsels coming out of a perf.data file header, not just for new ones created for live sessions. So separate the code that caches the syscall entry/exit tracepoint format fields into a new function that will be used in the next changeset. Signed-off-by: Namhyung Kim Cc: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/20131112115700.GC4053@ghostprotocols.net Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index aeb6296a76bd..3fa1dce6d43e 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -149,20 +149,32 @@ static void perf_evsel__delete_priv(struct perf_evsel *evsel) perf_evsel__delete(evsel); } +static int perf_evsel__init_syscall_tp(struct perf_evsel *evsel, void *handler) +{ + evsel->priv = malloc(sizeof(struct syscall_tp)); + if (evsel->priv != NULL) { + if (perf_evsel__init_sc_tp_uint_field(evsel, id)) + goto out_delete; + + evsel->handler = handler; + return 0; + } + + return -ENOMEM; + +out_delete: + free(evsel->priv); + evsel->priv = NULL; + return -ENOENT; +} + static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction, void *handler) { struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction); if (evsel) { - evsel->priv = malloc(sizeof(struct syscall_tp)); - - if (evsel->priv == NULL) + if (perf_evsel__init_syscall_tp(evsel, handler)) goto out_delete; - - if (perf_evsel__init_sc_tp_uint_field(evsel, id)) - goto out_delete; - - evsel->handler = handler; } return evsel; -- cgit v1.2.3-58-ga151 From 003824e8c27eeb8d3eec54cfab5845ec01ab532e Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 12 Nov 2013 15:25:00 +0900 Subject: perf trace: Fix segfault on perf trace -i perf.data When replaying a previous record session, it'll get a segfault since it doesn't initialize raw_syscalls enter/exit tracepoint's evsel->priv for caching the format fields. So fix it by properly initializing sys_enter/exit evsels that comes from reading the perf.data file header. Signed-off-by: Namhyung Kim Cc: David Ahern Cc: Ingo Molnar Cc: Paul Mackerras Cc: Pekka Enberg Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1384237500-22991-2-git-send-email-namhyung@kernel.org [ Split the syscall tp field caching part in the previous patch ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 3fa1dce6d43e..8d6ea8fbf476 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1766,16 +1766,6 @@ static int trace__process_sample(struct perf_tool *tool, return err; } -static bool -perf_session__has_tp(struct perf_session *session, const char *name) -{ - struct perf_evsel *evsel; - - evsel = perf_evlist__find_tracepoint_by_name(session->evlist, name); - - return evsel != NULL; -} - static int parse_target_str(struct trace *trace) { if (trace->opts.target.pid) { @@ -2012,8 +2002,6 @@ out_error: static int trace__replay(struct trace *trace) { const struct perf_evsel_str_handler handlers[] = { - { "raw_syscalls:sys_enter", trace__sys_enter, }, - { "raw_syscalls:sys_exit", trace__sys_exit, }, { "probe:vfs_getname", trace__vfs_getname, }, }; struct perf_data_file file = { @@ -2021,6 +2009,7 @@ static int trace__replay(struct trace *trace) .mode = PERF_DATA_MODE_READ, }; struct perf_session *session; + struct perf_evsel *evsel; int err = -1; trace->tool.sample = trace__process_sample; @@ -2052,13 +2041,29 @@ static int trace__replay(struct trace *trace) if (err) goto out; - if (!perf_session__has_tp(session, "raw_syscalls:sys_enter")) { - pr_err("Data file does not have raw_syscalls:sys_enter events\n"); + evsel = perf_evlist__find_tracepoint_by_name(session->evlist, + "raw_syscalls:sys_enter"); + if (evsel == NULL) { + pr_err("Data file does not have raw_syscalls:sys_enter event\n"); + goto out; + } + + if (perf_evsel__init_syscall_tp(evsel, trace__sys_enter) < 0 || + perf_evsel__init_sc_tp_ptr_field(evsel, args)) { + pr_err("Error during initialize raw_syscalls:sys_enter event\n"); + goto out; + } + + evsel = perf_evlist__find_tracepoint_by_name(session->evlist, + "raw_syscalls:sys_exit"); + if (evsel == NULL) { + pr_err("Data file does not have raw_syscalls:sys_exit event\n"); goto out; } - if (!perf_session__has_tp(session, "raw_syscalls:sys_exit")) { - pr_err("Data file does not have raw_syscalls:sys_exit events\n"); + if (perf_evsel__init_syscall_tp(evsel, trace__sys_exit) < 0 || + perf_evsel__init_sc_tp_uint_field(evsel, ret)) { + pr_err("Error during initialize raw_syscalls:sys_exit event\n"); goto out; } -- cgit v1.2.3-58-ga151 From 3fe2130523b2e098085eb4d38cd5b737a97cbee6 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 12 Nov 2013 11:45:21 -0300 Subject: perf tests: Compensate lower sample freq with longer test loop Doesn't work for me: ./perf test -v 19 19: Test software clock events have valid period values : --- start --- mmap size 528384B mmap size 528384B All (0) samples have period value of 1! ---- end ---- Test software clock events have valid period values: FAILED! Compensate the lower freq introduced in 67c1e4a53b17 with a longer loop, Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/5281D3B8.2030104@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/sw-clock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c index 93a7139ff5f7..6664a7cd828c 100644 --- a/tools/perf/tests/sw-clock.c +++ b/tools/perf/tests/sw-clock.c @@ -9,7 +9,7 @@ #include "util/cpumap.h" #include "util/thread_map.h" -#define NR_LOOPS 1000000 +#define NR_LOOPS 10000000 /* * This test will open software clock events (cpu-clock, task-clock) -- cgit v1.2.3-58-ga151 From 7f7a4138c66e857cc5bbf6e248a47379765349b5 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Tue, 12 Nov 2013 16:10:10 +0200 Subject: perf trace: Change syscall summary duration order Switch duration order to minimum, average, maximum for the '--summary' command line option because it's more natural to read. Signed-off-by: Pekka Enberg Acked-by: David Ahern Cc: David Ahern Cc: Ingo Molnar Link: http://lkml.kernel.org/r/1384265410-12344-1-git-send-email-penberg@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 8d6ea8fbf476..8990fbeb8b41 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -2093,7 +2093,7 @@ static size_t trace__fprintf_threads_header(FILE *fp) printed = fprintf(fp, "\n _____________________________________________________________________________\n"); printed += fprintf(fp, " __) Summary of events (__\n\n"); printed += fprintf(fp, " [ task - pid ] [ events ] [ ratio ] [ runtime ]\n"); - printed += fprintf(fp, " syscall count min max avg stddev\n"); + printed += fprintf(fp, " syscall count min avg max stddev\n"); printed += fprintf(fp, " msec msec msec %%\n"); printed += fprintf(fp, " _____________________________________________________________________________\n\n"); @@ -2129,8 +2129,8 @@ static size_t thread__dump_stats(struct thread_trace *ttrace, sc = &trace->syscalls.table[inode->i]; printed += fprintf(fp, "%24s %14s : ", "", sc->name); printed += fprintf(fp, "%5" PRIu64 " %8.3f %8.3f", - n, min, max); - printed += fprintf(fp, " %8.3f %6.2f\n", avg, pct); + n, min, avg); + printed += fprintf(fp, " %8.3f %6.2f\n", max, pct); } inode = intlist__next(inode); -- cgit v1.2.3-58-ga151 From 99ff7150547382ee612c40d8d6a0670ddec7c9fc Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Tue, 12 Nov 2013 16:42:14 +0200 Subject: perf trace: Simplify '--summary' output The output of 'perf trace --summary' tries to be too cute with formatting and makes it very hard to read. Simplify it in the spirit of "strace -c": [penberg@localhost libtrading]$ perf trace -a --duration 10000 --summary -- sleep 1 ^C Summary of events: dbus-daemon (555), 10 events, 0.0%, 0.000 msec msec/call syscall calls min avg max stddev --------------- -------- -------- -------- -------- ------ sendmsg 2 0.002 0.005 0.008 55.00 recvmsg 2 0.002 0.003 0.005 44.00 epoll_wait 1 0.000 0.000 0.000 0.00 NetworkManager (667), 56 events, 0.0%, 0.000 msec msec/call syscall calls min avg max stddev --------------- -------- -------- -------- -------- ------ poll 2 0.000 0.002 0.003 100.00 sendmsg 10 0.004 0.007 0.016 15.41 recvmsg 16 0.002 0.003 0.005 8.24 zfs-fuse (669), 4 events, 0.0%, 0.000 msec msec/call syscall calls min avg max stddev --------------- -------- -------- -------- -------- ------ futex 2 0.000 0.001 0.002 100.00 Signed-off-by: Pekka Enberg Cc: David Ahern Cc: Ingo Molnar Link: http://lkml.kernel.org/r/1384267334-18953-1-git-send-email-penberg@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 8990fbeb8b41..0964c0cdc982 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -2090,12 +2090,7 @@ static size_t trace__fprintf_threads_header(FILE *fp) { size_t printed; - printed = fprintf(fp, "\n _____________________________________________________________________________\n"); - printed += fprintf(fp, " __) Summary of events (__\n\n"); - printed += fprintf(fp, " [ task - pid ] [ events ] [ ratio ] [ runtime ]\n"); - printed += fprintf(fp, " syscall count min avg max stddev\n"); - printed += fprintf(fp, " msec msec msec %%\n"); - printed += fprintf(fp, " _____________________________________________________________________________\n\n"); + printed = fprintf(fp, "\n Summary of events:\n\n"); return printed; } @@ -2113,6 +2108,10 @@ static size_t thread__dump_stats(struct thread_trace *ttrace, printed += fprintf(fp, "\n"); + printed += fprintf(fp, " msec/call\n"); + printed += fprintf(fp, " syscall calls min avg max stddev\n"); + printed += fprintf(fp, " --------------- -------- -------- -------- -------- ------\n"); + /* each int_node is a syscall */ while (inode) { stats = inode->priv; @@ -2127,10 +2126,10 @@ static size_t thread__dump_stats(struct thread_trace *ttrace, avg /= NSEC_PER_MSEC; sc = &trace->syscalls.table[inode->i]; - printed += fprintf(fp, "%24s %14s : ", "", sc->name); - printed += fprintf(fp, "%5" PRIu64 " %8.3f %8.3f", + printed += fprintf(fp, " %-15s", sc->name); + printed += fprintf(fp, " %8" PRIu64 " %8.3f %8.3f", n, min, avg); - printed += fprintf(fp, " %8.3f %6.2f\n", max, pct); + printed += fprintf(fp, " %8.3f %6.2f\n", max, pct); } inode = intlist__next(inode); @@ -2171,10 +2170,10 @@ static int trace__fprintf_one_thread(struct thread *thread, void *priv) else if (ratio > 5.0) color = PERF_COLOR_YELLOW; - printed += color_fprintf(fp, color, "%20s", thread__comm_str(thread)); - printed += fprintf(fp, " - %-5d :%11lu [", thread->tid, ttrace->nr_events); - printed += color_fprintf(fp, color, "%5.1f%%", ratio); - printed += fprintf(fp, " ] %10.3f ms\n", ttrace->runtime_ms); + printed += color_fprintf(fp, color, " %s (%d), ", thread__comm_str(thread), thread->tid); + printed += fprintf(fp, "%lu events, ", ttrace->nr_events); + printed += color_fprintf(fp, color, "%.1f%%", ratio); + printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms); printed += thread__dump_stats(ttrace, trace, fp); data->printed += printed; -- cgit v1.2.3-58-ga151 From fd2eabaf16984bc75695e43f4b76e6f20ed4ea41 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Tue, 12 Nov 2013 09:31:15 -0700 Subject: perf trace: Add summary only option Per request from Pekka make --summary a summary only option meaning do not show the individual system calls. Add another option to see all syscalls along with the summary. In addition use 's' and 'S' as shortcuts for the options. Requested-by: Pekka Enberg Signed-off-by: David Ahern Tested-by: Pekka Enberg Cc: Adrian Hunter Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Pekka Enberg Link: http://lkml.kernel.org/r/1384273875-3751-1-git-send-email-dsahern@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-trace.txt | 10 ++++++++-- tools/perf/builtin-trace.c | 16 +++++++++++++--- 2 files changed, 21 insertions(+), 5 deletions(-) (limited to 'tools') diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt index 7b0497f95a75..fae38d9a44a4 100644 --- a/tools/perf/Documentation/perf-trace.txt +++ b/tools/perf/Documentation/perf-trace.txt @@ -93,9 +93,15 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs. --comm:: Show process COMM right beside its ID, on by default, disable with --no-comm. +-s:: --summary:: - Show a summary of syscalls by thread with min, max, and average times (in - msec) and relative stddev. + Show only a summary of syscalls by thread with min, max, and average times + (in msec) and relative stddev. + +-S:: +--with-summary:: + Show all syscalls followed by a summary by thread with min, max, and + average times (in msec) and relative stddev. --tool_stats:: Show tool stats such as number of times fd->pathname was discovered thru diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 0964c0cdc982..aa5702ffa2cb 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1168,6 +1168,7 @@ struct trace { bool sched; bool multiple_threads; bool summary; + bool summary_only; bool show_comm; bool show_tool_stats; double duration_filter; @@ -1611,7 +1612,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, args, trace, thread); if (!strcmp(sc->name, "exit_group") || !strcmp(sc->name, "exit")) { - if (!trace->duration_filter) { + if (!trace->duration_filter && !trace->summary_only) { trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output); fprintf(trace->output, "%-70s\n", ttrace->entry_str); } @@ -1664,6 +1665,9 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, } else if (trace->duration_filter) goto out; + if (trace->summary_only) + goto out; + trace__fprintf_entry_head(trace, thread, duration, sample->time, trace->output); if (ttrace->entry_pending) { @@ -2282,8 +2286,10 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) OPT_INCR('v', "verbose", &verbose, "be more verbose"), OPT_BOOLEAN('T', "time", &trace.full_time, "Show full timestamp, not time relative to first start"), - OPT_BOOLEAN(0, "summary", &trace.summary, - "Show syscall summary with statistics"), + OPT_BOOLEAN('s', "summary", &trace.summary_only, + "Show only syscall summary with statistics"), + OPT_BOOLEAN('S', "with-summary", &trace.summary, + "Show all syscalls and summary with statistics"), OPT_END() }; int err; @@ -2294,6 +2300,10 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) argc = parse_options(argc, argv, trace_options, trace_usage, 0); + /* summary_only implies summary option, but don't overwrite summary if set */ + if (trace.summary_only) + trace.summary = trace.summary_only; + if (output_name != NULL) { err = trace__open_output(&trace, output_name); if (err < 0) { -- cgit v1.2.3-58-ga151 From 8973504be70b2986a2081eeff7d9a4210dec295d Mon Sep 17 00:00:00 2001 From: David Ahern Date: Tue, 12 Nov 2013 07:46:53 -0700 Subject: perf record: Fix segfault with --no-mmap-pages Adrian reported a segfault when using --no-out-pages: $ tools/perf/perf record -vv --no-out-pages uname Segmentation fault (core dumped) The same occurs with --no-mmap-pages. Fix by checking that str is non-NULL before parsing it. Signed-off-by: David Ahern Reported-by: Adrian Hunter Cc: Adrian Hunter Cc: Ingo Molnar Cc: Jiri Olsa Link: http://lkml.kernel.org/r/1384267617-3446-2-git-send-email-dsahern@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evlist.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'tools') diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 99dc58e5dcc3..3960560f873a 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -719,6 +719,9 @@ int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str, { .tag = 0 }, }; + if (str == NULL) + return -1; + val = parse_tag_value(str, tags); if (val != (unsigned long) -1) { /* we got file size value */ -- cgit v1.2.3-58-ga151 From 9639837e95db90d056f4683c911717921519320e Mon Sep 17 00:00:00 2001 From: David Ahern Date: Tue, 12 Nov 2013 07:46:54 -0700 Subject: perf evlist: Round mmap pages to power 2 - v2 Currently perf requires the -m / --mmap_pages option to be a power of 2. To be more user friendly perf should automatically round this up to the next power of 2. Currently: $ perf record -m 3 -a -- sleep 1 --mmap_pages/-m value must be a power of two.sleep: Terminated With patch: $ perf record -m 3 -a -- sleep 1 rounding mmap pages size to 16384 (4 pages) ... v2: Add bytes units to rounding message per Ingo's request. Other suggestions (e.g., prefixing INFO) should be addressed by wrapping pr_info to catch all instances. Suggested-by: Ingo Molnar Signed-off-by: David Ahern Cc: Ingo Molnar Cc: Jiri Olsa Link: http://lkml.kernel.org/r/1384267617-3446-3-git-send-email-dsahern@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evlist.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 3960560f873a..fb4727d3df85 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -710,7 +710,6 @@ int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str, { unsigned int *mmap_pages = opt->value; unsigned long pages, val; - size_t size; static struct parse_tag tags[] = { { .tag = 'B', .mult = 1 }, { .tag = 'K', .mult = 1 << 10 }, @@ -726,11 +725,6 @@ int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str, if (val != (unsigned long) -1) { /* we got file size value */ pages = PERF_ALIGN(val, page_size) / page_size; - if (pages < (1UL << 31) && !is_power_of_2(pages)) { - pages = next_pow2(pages); - pr_info("rounding mmap pages size to %lu (%lu pages)\n", - pages * page_size, pages); - } } else { /* we got pages count value */ char *eptr; @@ -741,14 +735,14 @@ int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str, } } - if (pages > UINT_MAX || pages > SIZE_MAX / page_size) { - pr_err("--mmap_pages/-m value too big\n"); - return -1; + if (pages < (1UL << 31) && !is_power_of_2(pages)) { + pages = next_pow2(pages); + pr_info("rounding mmap pages size to %lu bytes (%lu pages)\n", + pages * page_size, pages); } - size = perf_evlist__mmap_size(pages); - if (!size) { - pr_err("--mmap_pages/-m value must be a power of two."); + if (pages > UINT_MAX || pages > SIZE_MAX / page_size) { + pr_err("--mmap_pages/-m value too big\n"); return -1; } -- cgit v1.2.3-58-ga151 From 33c2dcfdfe7f114cc656bcb4c839f5939d5e60ba Mon Sep 17 00:00:00 2001 From: David Ahern Date: Tue, 12 Nov 2013 07:46:55 -0700 Subject: perf evlist: Refactor mmap_pages parsing Logic will be re-used for the out-pages argument for mmap based writes in perf-record. Signed-off-by: David Ahern Cc: Adrian Hunter Cc: Ingo Molnar Cc: Jiri Olsa Link: http://lkml.kernel.org/r/1384267617-3446-4-git-send-email-dsahern@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evlist.c | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index fb4727d3df85..cb19044601bb 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -705,10 +705,9 @@ static size_t perf_evlist__mmap_size(unsigned long pages) return (pages + 1) * page_size; } -int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str, - int unset __maybe_unused) +static long parse_pages_arg(const char *str, unsigned long min, + unsigned long max) { - unsigned int *mmap_pages = opt->value; unsigned long pages, val; static struct parse_tag tags[] = { { .tag = 'B', .mult = 1 }, @@ -719,7 +718,7 @@ int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str, }; if (str == NULL) - return -1; + return -EINVAL; val = parse_tag_value(str, tags); if (val != (unsigned long) -1) { @@ -729,20 +728,38 @@ int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str, /* we got pages count value */ char *eptr; pages = strtoul(str, &eptr, 10); - if (*eptr != '\0') { - pr_err("failed to parse --mmap_pages/-m value\n"); - return -1; - } + if (*eptr != '\0') + return -EINVAL; } - if (pages < (1UL << 31) && !is_power_of_2(pages)) { + if ((pages == 0) && (min == 0)) { + /* leave number of pages at 0 */ + } else if (pages < (1UL << 31) && !is_power_of_2(pages)) { + /* round pages up to next power of 2 */ pages = next_pow2(pages); pr_info("rounding mmap pages size to %lu bytes (%lu pages)\n", pages * page_size, pages); } - if (pages > UINT_MAX || pages > SIZE_MAX / page_size) { - pr_err("--mmap_pages/-m value too big\n"); + if (pages > max) + return -EINVAL; + + return pages; +} + +int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str, + int unset __maybe_unused) +{ + unsigned int *mmap_pages = opt->value; + unsigned long max = UINT_MAX; + long pages; + + if (max < SIZE_MAX / page_size) + max = SIZE_MAX / page_size; + + pages = parse_pages_arg(str, 1, max); + if (pages < 0) { + pr_err("Invalid argument for --mmap_pages/-m\n"); return -1; } -- cgit v1.2.3-58-ga151 From 48095b721ca54ffa70427185c00473530f4aef06 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 12 Nov 2013 09:59:33 +0200 Subject: perf tests: Handle throttle events in 'object code reading' test Unhandled events cause an error that fails the test, fix it. Reported-by: Arnaldo Carvalho de Melo Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/5281DFE5.3000909@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/code-reading.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index 6d9dc198a200..85d4919dd623 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c @@ -275,8 +275,19 @@ static int process_event(struct machine *machine, struct perf_evlist *evlist, if (event->header.type == PERF_RECORD_SAMPLE) return process_sample_event(machine, evlist, event, state); - if (event->header.type < PERF_RECORD_MAX) - return machine__process_event(machine, event, NULL); + if (event->header.type == PERF_RECORD_THROTTLE || + event->header.type == PERF_RECORD_UNTHROTTLE) + return 0; + + if (event->header.type < PERF_RECORD_MAX) { + int ret; + + ret = machine__process_event(machine, event, NULL); + if (ret < 0) + pr_debug("machine__process_event failed, event type %u\n", + event->header.type); + return ret; + } return 0; } -- cgit v1.2.3-58-ga151 From 602ad878d41ef097cc9aa2def7830d5bb27a15d8 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 12 Nov 2013 16:46:16 -0300 Subject: perf target: Shorten perf_target__ to target__ Getting unwieldly long, for this app domain should be descriptive enough and the use of __ to separate the class from the method names should help with avoiding clashes with other code bases. Reported-by: David Ahern Suggested-by: Ingo Molnar Cc: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/20131112113427.GA4053@ghostprotocols.net Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-kvm.c | 6 ++--- tools/perf/builtin-record.c | 14 ++++++------ tools/perf/builtin-stat.c | 21 ++++++++--------- tools/perf/builtin-top.c | 14 ++++++------ tools/perf/builtin-trace.c | 10 ++++---- tools/perf/perf.h | 2 +- tools/perf/tests/task-exit.c | 2 +- tools/perf/util/evlist.c | 12 ++++------ tools/perf/util/evlist.h | 5 ++-- tools/perf/util/evsel.c | 9 ++++---- tools/perf/util/evsel.h | 3 +-- tools/perf/util/machine.c | 6 ++--- tools/perf/util/machine.h | 4 ++-- tools/perf/util/target.c | 54 +++++++++++++++++++++----------------------- tools/perf/util/target.h | 44 +++++++++++++++++------------------- tools/perf/util/top.c | 2 +- 16 files changed, 99 insertions(+), 109 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index 346bb5909e3d..f8bf5f244d77 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -1510,13 +1510,13 @@ static int kvm_events_live(struct perf_kvm_stat *kvm, /* * target related setups */ - err = perf_target__validate(&kvm->opts.target); + err = target__validate(&kvm->opts.target); if (err) { - perf_target__strerror(&kvm->opts.target, err, errbuf, BUFSIZ); + target__strerror(&kvm->opts.target, err, errbuf, BUFSIZ); ui__warning("%s", errbuf); } - if (perf_target__none(&kvm->opts.target)) + if (target__none(&kvm->opts.target)) kvm->opts.target.system_wide = true; diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 880227eae20f..4d644fe2d5b7 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -506,7 +506,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) * (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)) + if (!target__none(&opts->target)) perf_evlist__enable(evsel_list); /* @@ -535,7 +535,7 @@ 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 && !disabled && !perf_target__none(&opts->target)) { + if (done && !disabled && !target__none(&opts->target)) { perf_evlist__disable(evsel_list); disabled = true; } @@ -906,7 +906,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) argc = parse_options(argc, argv, record_options, record_usage, PARSE_OPT_STOP_AT_NON_OPTION); - if (!argc && perf_target__none(&rec->opts.target)) + if (!argc && target__none(&rec->opts.target)) usage_with_options(record_usage, record_options); if (nr_cgroups && !rec->opts.target.system_wide) { @@ -936,17 +936,17 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) goto out_symbol_exit; } - err = perf_target__validate(&rec->opts.target); + err = target__validate(&rec->opts.target); if (err) { - perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); + target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); ui__warning("%s", errbuf); } - err = perf_target__parse_uid(&rec->opts.target); + err = target__parse_uid(&rec->opts.target); if (err) { int saved_errno = errno; - perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); + target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); ui__error("%s", errbuf); err = -saved_errno; diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 0fc1c941a73c..ee0d565f83e3 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -108,7 +108,7 @@ enum { static struct perf_evlist *evsel_list; -static struct perf_target target = { +static struct target target = { .uid = UINT_MAX, }; @@ -294,11 +294,10 @@ static int create_perf_stat_counter(struct perf_evsel *evsel) attr->inherit = !no_inherit; - if (perf_target__has_cpu(&target)) + if (target__has_cpu(&target)) return perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel)); - if (!perf_target__has_task(&target) && - perf_evsel__is_group_leader(evsel)) { + if (!target__has_task(&target) && perf_evsel__is_group_leader(evsel)) { attr->disabled = 1; if (!initial_delay) attr->enable_on_exec = 1; @@ -1236,7 +1235,7 @@ static void print_stat(int argc, const char **argv) fprintf(output, "\'system wide"); else if (target.cpu_list) fprintf(output, "\'CPU(s) %s", target.cpu_list); - else if (!perf_target__has_task(&target)) { + else if (!target__has_task(&target)) { fprintf(output, "\'%s", argv[0]); for (i = 1; i < argc; i++) fprintf(output, " %s", argv[i]); @@ -1667,7 +1666,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) } else if (big_num_opt == 0) /* User passed --no-big-num */ big_num = false; - if (!argc && perf_target__none(&target)) + if (!argc && target__none(&target)) usage_with_options(stat_usage, options); if (run_count < 0) { @@ -1680,8 +1679,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) } /* no_aggr, cgroup are for system-wide only */ - if ((aggr_mode != AGGR_GLOBAL || nr_cgroups) - && !perf_target__has_cpu(&target)) { + if ((aggr_mode != AGGR_GLOBAL || nr_cgroups) && + !target__has_cpu(&target)) { fprintf(stderr, "both cgroup and no-aggregation " "modes only available in system-wide mode\n"); @@ -1694,14 +1693,14 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) if (add_default_attributes()) goto out; - perf_target__validate(&target); + target__validate(&target); if (perf_evlist__create_maps(evsel_list, &target) < 0) { - if (perf_target__has_task(&target)) { + if (target__has_task(&target)) { pr_err("Problems finding threads of monitor\n"); parse_options_usage(stat_usage, options, "p", 1); parse_options_usage(NULL, options, "t", 1); - } else if (perf_target__has_cpu(&target)) { + } else if (target__has_cpu(&target)) { perror("failed to parse CPUs map"); parse_options_usage(stat_usage, options, "C", 1); parse_options_usage(NULL, options, "a", 1); diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 8c520d9fecfc..b8f8e29db332 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -967,7 +967,7 @@ static int __cmd_top(struct perf_top *top) * XXX 'top' still doesn't start workloads like record, trace, but should, * so leave the check here. */ - if (!perf_target__none(&opts->target)) + if (!target__none(&opts->target)) perf_evlist__enable(top->evlist); /* Wait for a minimal set of events before starting the snapshot */ @@ -1053,7 +1053,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) .sym_pcnt_filter = 5, }; struct perf_record_opts *opts = &top.record_opts; - struct perf_target *target = &opts->target; + struct target *target = &opts->target; const struct option options[] = { OPT_CALLBACK('e', "event", &top.evlist, "event", "event selector. use 'perf list' to list available events", @@ -1169,24 +1169,24 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) setup_browser(false); - status = perf_target__validate(target); + status = target__validate(target); if (status) { - perf_target__strerror(target, status, errbuf, BUFSIZ); + target__strerror(target, status, errbuf, BUFSIZ); ui__warning("%s", errbuf); } - status = perf_target__parse_uid(target); + status = target__parse_uid(target); if (status) { int saved_errno = errno; - perf_target__strerror(target, status, errbuf, BUFSIZ); + target__strerror(target, status, errbuf, BUFSIZ); ui__error("%s", errbuf); status = -saved_errno; goto out_delete_evlist; } - if (perf_target__none(target)) + if (target__none(target)) target->system_wide = true; if (perf_evlist__create_maps(top.evlist, target) < 0) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index aa5702ffa2cb..6b230af940e2 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -2327,21 +2327,21 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) } } - err = perf_target__validate(&trace.opts.target); + err = target__validate(&trace.opts.target); if (err) { - perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf)); + target__strerror(&trace.opts.target, err, bf, sizeof(bf)); fprintf(trace.output, "%s", bf); goto out_close; } - err = perf_target__parse_uid(&trace.opts.target); + err = target__parse_uid(&trace.opts.target); if (err) { - perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf)); + target__strerror(&trace.opts.target, err, bf, sizeof(bf)); fprintf(trace.output, "%s", bf); goto out_close; } - if (!argc && perf_target__none(&trace.opts.target)) + if (!argc && target__none(&trace.opts.target)) trace.opts.target.system_wide = true; if (input_name) diff --git a/tools/perf/perf.h b/tools/perf/perf.h index 6a587e84fdfe..b079304bd53d 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h @@ -248,7 +248,7 @@ enum perf_call_graph_mode { }; struct perf_record_opts { - struct perf_target target; + struct target target; int call_graph; bool group; bool inherit_stat; diff --git a/tools/perf/tests/task-exit.c b/tools/perf/tests/task-exit.c index c33d95f9559a..d09ab579119e 100644 --- a/tools/perf/tests/task-exit.c +++ b/tools/perf/tests/task-exit.c @@ -28,7 +28,7 @@ int test__task_exit(void) union perf_event *event; struct perf_evsel *evsel; struct perf_evlist *evlist; - struct perf_target target = { + struct target target = { .uid = UINT_MAX, .uses_mmap = true, }; diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index cb19044601bb..dc6fa3fbb180 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -811,8 +811,7 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages, return perf_evlist__mmap_per_cpu(evlist, prot, mask); } -int perf_evlist__create_maps(struct perf_evlist *evlist, - struct perf_target *target) +int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target) { evlist->threads = thread_map__new_str(target->pid, target->tid, target->uid); @@ -820,9 +819,9 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, if (evlist->threads == NULL) return -1; - if (perf_target__has_task(target)) + if (target__has_task(target)) evlist->cpus = cpu_map__dummy_new(); - else if (!perf_target__has_cpu(target) && !target->uses_mmap) + else if (!target__has_cpu(target) && !target->uses_mmap) evlist->cpus = cpu_map__dummy_new(); else evlist->cpus = cpu_map__new(target->cpu_list); @@ -1031,8 +1030,7 @@ out_err: return err; } -int perf_evlist__prepare_workload(struct perf_evlist *evlist, - struct perf_target *target, +int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *target, const char *argv[], bool pipe_output, bool want_signal) { @@ -1084,7 +1082,7 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, exit(-1); } - if (perf_target__none(target)) + if (target__none(target)) evlist->threads->map[0] = evlist->workload.pid; close(child_ready_pipe[1]); diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index ecaa582f40e2..649d6ea98a84 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -102,7 +102,7 @@ void perf_evlist__config(struct perf_evlist *evlist, int perf_record_opts__config(struct perf_record_opts *opts); int perf_evlist__prepare_workload(struct perf_evlist *evlist, - struct perf_target *target, + struct target *target, const char *argv[], bool pipe_output, bool want_signal); int perf_evlist__start_workload(struct perf_evlist *evlist); @@ -134,8 +134,7 @@ static inline void perf_evlist__set_maps(struct perf_evlist *evlist, evlist->threads = threads; } -int perf_evlist__create_maps(struct perf_evlist *evlist, - struct perf_target *target); +int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target); void perf_evlist__delete_maps(struct perf_evlist *evlist); int perf_evlist__apply_filters(struct perf_evlist *evlist); diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index f95653a639a6..18f7c188ff63 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -645,7 +645,7 @@ void perf_evsel__config(struct perf_evsel *evsel, } } - if (perf_target__has_cpu(&opts->target)) + if (target__has_cpu(&opts->target)) perf_evsel__set_sample_bit(evsel, CPU); if (opts->period) @@ -653,7 +653,7 @@ void perf_evsel__config(struct perf_evsel *evsel, if (!perf_missing_features.sample_id_all && (opts->sample_time || !opts->no_inherit || - perf_target__has_cpu(&opts->target))) + target__has_cpu(&opts->target))) perf_evsel__set_sample_bit(evsel, TIME); if (opts->raw_samples) { @@ -696,7 +696,7 @@ void perf_evsel__config(struct perf_evsel *evsel, * Setting enable_on_exec for independent events and * group leaders for traced executed by perf. */ - if (perf_target__none(&opts->target) && perf_evsel__is_group_leader(evsel)) + if (target__none(&opts->target) && perf_evsel__is_group_leader(evsel)) attr->enable_on_exec = 1; } @@ -2006,8 +2006,7 @@ bool perf_evsel__fallback(struct perf_evsel *evsel, int err, return false; } -int perf_evsel__open_strerror(struct perf_evsel *evsel, - struct perf_target *target, +int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target, int err, char *msg, size_t size) { switch (err) { diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 0178233abd64..f5029653dcd7 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -318,8 +318,7 @@ int perf_evsel__fprintf(struct perf_evsel *evsel, bool perf_evsel__fallback(struct perf_evsel *evsel, int err, char *msg, size_t msgsize); -int perf_evsel__open_strerror(struct perf_evsel *evsel, - struct perf_target *target, +int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target, int err, char *msg, size_t size); static inline int perf_evsel__group_idx(struct perf_evsel *evsel) diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 680700b6d779..0393912d8033 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -1396,12 +1396,12 @@ int machine__for_each_thread(struct machine *machine, } int __machine__synthesize_threads(struct machine *machine, struct perf_tool *tool, - struct perf_target *target, struct thread_map *threads, + struct target *target, struct thread_map *threads, perf_event__handler_t process, bool data_mmap) { - if (perf_target__has_task(target)) + if (target__has_task(target)) return perf_event__synthesize_thread_map(tool, threads, process, machine, data_mmap); - else if (perf_target__has_cpu(target)) + else if (target__has_cpu(target)) return perf_event__synthesize_threads(tool, process, machine, data_mmap); /* command specified */ return 0; diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h index fedd1dfaf715..477133015440 100644 --- a/tools/perf/util/machine.h +++ b/tools/perf/util/machine.h @@ -180,10 +180,10 @@ int machine__for_each_thread(struct machine *machine, void *priv); int __machine__synthesize_threads(struct machine *machine, struct perf_tool *tool, - struct perf_target *target, struct thread_map *threads, + struct target *target, struct thread_map *threads, perf_event__handler_t process, bool data_mmap); static inline -int machine__synthesize_threads(struct machine *machine, struct perf_target *target, +int machine__synthesize_threads(struct machine *machine, struct target *target, struct thread_map *threads, bool data_mmap) { return __machine__synthesize_threads(machine, NULL, target, threads, diff --git a/tools/perf/util/target.c b/tools/perf/util/target.c index 065528b7563e..3c778a07b7cc 100644 --- a/tools/perf/util/target.c +++ b/tools/perf/util/target.c @@ -13,9 +13,9 @@ #include -enum perf_target_errno perf_target__validate(struct perf_target *target) +enum target_errno target__validate(struct target *target) { - enum perf_target_errno ret = PERF_ERRNO_TARGET__SUCCESS; + enum target_errno ret = TARGET_ERRNO__SUCCESS; if (target->pid) target->tid = target->pid; @@ -23,42 +23,42 @@ enum perf_target_errno perf_target__validate(struct perf_target *target) /* CPU and PID are mutually exclusive */ if (target->tid && target->cpu_list) { target->cpu_list = NULL; - if (ret == PERF_ERRNO_TARGET__SUCCESS) - ret = PERF_ERRNO_TARGET__PID_OVERRIDE_CPU; + if (ret == TARGET_ERRNO__SUCCESS) + ret = TARGET_ERRNO__PID_OVERRIDE_CPU; } /* UID and PID are mutually exclusive */ if (target->tid && target->uid_str) { target->uid_str = NULL; - if (ret == PERF_ERRNO_TARGET__SUCCESS) - ret = PERF_ERRNO_TARGET__PID_OVERRIDE_UID; + if (ret == TARGET_ERRNO__SUCCESS) + ret = TARGET_ERRNO__PID_OVERRIDE_UID; } /* UID and CPU are mutually exclusive */ if (target->uid_str && target->cpu_list) { target->cpu_list = NULL; - if (ret == PERF_ERRNO_TARGET__SUCCESS) - ret = PERF_ERRNO_TARGET__UID_OVERRIDE_CPU; + if (ret == TARGET_ERRNO__SUCCESS) + ret = TARGET_ERRNO__UID_OVERRIDE_CPU; } /* PID and SYSTEM are mutually exclusive */ if (target->tid && target->system_wide) { target->system_wide = false; - if (ret == PERF_ERRNO_TARGET__SUCCESS) - ret = PERF_ERRNO_TARGET__PID_OVERRIDE_SYSTEM; + if (ret == TARGET_ERRNO__SUCCESS) + ret = TARGET_ERRNO__PID_OVERRIDE_SYSTEM; } /* UID and SYSTEM are mutually exclusive */ if (target->uid_str && target->system_wide) { target->system_wide = false; - if (ret == PERF_ERRNO_TARGET__SUCCESS) - ret = PERF_ERRNO_TARGET__UID_OVERRIDE_SYSTEM; + if (ret == TARGET_ERRNO__SUCCESS) + ret = TARGET_ERRNO__UID_OVERRIDE_SYSTEM; } return ret; } -enum perf_target_errno perf_target__parse_uid(struct perf_target *target) +enum target_errno target__parse_uid(struct target *target) { struct passwd pwd, *result; char buf[1024]; @@ -66,7 +66,7 @@ enum perf_target_errno perf_target__parse_uid(struct perf_target *target) target->uid = UINT_MAX; if (str == NULL) - return PERF_ERRNO_TARGET__SUCCESS; + return TARGET_ERRNO__SUCCESS; /* Try user name first */ getpwnam_r(str, &pwd, buf, sizeof(buf), &result); @@ -79,22 +79,22 @@ enum perf_target_errno perf_target__parse_uid(struct perf_target *target) int uid = strtol(str, &endptr, 10); if (*endptr != '\0') - return PERF_ERRNO_TARGET__INVALID_UID; + return TARGET_ERRNO__INVALID_UID; getpwuid_r(uid, &pwd, buf, sizeof(buf), &result); if (result == NULL) - return PERF_ERRNO_TARGET__USER_NOT_FOUND; + return TARGET_ERRNO__USER_NOT_FOUND; } target->uid = result->pw_uid; - return PERF_ERRNO_TARGET__SUCCESS; + return TARGET_ERRNO__SUCCESS; } /* - * This must have a same ordering as the enum perf_target_errno. + * This must have a same ordering as the enum target_errno. */ -static const char *perf_target__error_str[] = { +static const char *target__error_str[] = { "PID/TID switch overriding CPU", "PID/TID switch overriding UID", "UID switch overriding CPU", @@ -104,7 +104,7 @@ static const char *perf_target__error_str[] = { "Problems obtaining information for user %s", }; -int perf_target__strerror(struct perf_target *target, int errnum, +int target__strerror(struct target *target, int errnum, char *buf, size_t buflen) { int idx; @@ -124,21 +124,19 @@ int perf_target__strerror(struct perf_target *target, int errnum, return 0; } - if (errnum < __PERF_ERRNO_TARGET__START || - errnum >= __PERF_ERRNO_TARGET__END) + if (errnum < __TARGET_ERRNO__START || errnum >= __TARGET_ERRNO__END) return -1; - idx = errnum - __PERF_ERRNO_TARGET__START; - msg = perf_target__error_str[idx]; + idx = errnum - __TARGET_ERRNO__START; + msg = target__error_str[idx]; switch (errnum) { - case PERF_ERRNO_TARGET__PID_OVERRIDE_CPU - ... PERF_ERRNO_TARGET__UID_OVERRIDE_SYSTEM: + case TARGET_ERRNO__PID_OVERRIDE_CPU ... TARGET_ERRNO__UID_OVERRIDE_SYSTEM: snprintf(buf, buflen, "%s", msg); break; - case PERF_ERRNO_TARGET__INVALID_UID: - case PERF_ERRNO_TARGET__USER_NOT_FOUND: + case TARGET_ERRNO__INVALID_UID: + case TARGET_ERRNO__USER_NOT_FOUND: snprintf(buf, buflen, msg, target->uid_str); break; diff --git a/tools/perf/util/target.h b/tools/perf/util/target.h index a4be8575fda5..89bab7129de4 100644 --- a/tools/perf/util/target.h +++ b/tools/perf/util/target.h @@ -4,7 +4,7 @@ #include #include -struct perf_target { +struct target { const char *pid; const char *tid; const char *cpu_list; @@ -14,8 +14,8 @@ struct perf_target { bool uses_mmap; }; -enum perf_target_errno { - PERF_ERRNO_TARGET__SUCCESS = 0, +enum target_errno { + TARGET_ERRNO__SUCCESS = 0, /* * Choose an arbitrary negative big number not to clash with standard @@ -24,42 +24,40 @@ enum perf_target_errno { * * http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html */ - __PERF_ERRNO_TARGET__START = -10000, + __TARGET_ERRNO__START = -10000, + /* for target__validate() */ + TARGET_ERRNO__PID_OVERRIDE_CPU = __TARGET_ERRNO__START, + TARGET_ERRNO__PID_OVERRIDE_UID, + TARGET_ERRNO__UID_OVERRIDE_CPU, + TARGET_ERRNO__PID_OVERRIDE_SYSTEM, + TARGET_ERRNO__UID_OVERRIDE_SYSTEM, - /* for perf_target__validate() */ - PERF_ERRNO_TARGET__PID_OVERRIDE_CPU = __PERF_ERRNO_TARGET__START, - PERF_ERRNO_TARGET__PID_OVERRIDE_UID, - PERF_ERRNO_TARGET__UID_OVERRIDE_CPU, - PERF_ERRNO_TARGET__PID_OVERRIDE_SYSTEM, - PERF_ERRNO_TARGET__UID_OVERRIDE_SYSTEM, + /* for target__parse_uid() */ + TARGET_ERRNO__INVALID_UID, + TARGET_ERRNO__USER_NOT_FOUND, - /* for perf_target__parse_uid() */ - PERF_ERRNO_TARGET__INVALID_UID, - PERF_ERRNO_TARGET__USER_NOT_FOUND, - - __PERF_ERRNO_TARGET__END, + __TARGET_ERRNO__END, }; -enum perf_target_errno perf_target__validate(struct perf_target *target); -enum perf_target_errno perf_target__parse_uid(struct perf_target *target); +enum target_errno target__validate(struct target *target); +enum target_errno target__parse_uid(struct target *target); -int perf_target__strerror(struct perf_target *target, int errnum, char *buf, - size_t buflen); +int target__strerror(struct target *target, int errnum, char *buf, size_t buflen); -static inline bool perf_target__has_task(struct perf_target *target) +static inline bool target__has_task(struct target *target) { return target->tid || target->pid || target->uid_str; } -static inline bool perf_target__has_cpu(struct perf_target *target) +static inline bool target__has_cpu(struct target *target) { return target->system_wide || target->cpu_list; } -static inline bool perf_target__none(struct perf_target *target) +static inline bool target__none(struct target *target) { - return !perf_target__has_task(target) && !perf_target__has_cpu(target); + return !target__has_task(target) && !target__has_cpu(target); } #endif /* _PERF_TARGET_H */ diff --git a/tools/perf/util/top.c b/tools/perf/util/top.c index f857b51b6bde..ce793c7dd23c 100644 --- a/tools/perf/util/top.c +++ b/tools/perf/util/top.c @@ -27,7 +27,7 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size) float ksamples_per_sec; float esamples_percent; struct perf_record_opts *opts = &top->record_opts; - struct perf_target *target = &opts->target; + struct target *target = &opts->target; size_t ret = 0; if (top->samples) { -- cgit v1.2.3-58-ga151 From 0497a9ebaf7ae4d573497b3e053ad4c3d5c9921d Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Mon, 11 Nov 2013 16:08:10 -0500 Subject: tools lib traceevent: Add direct access to dynamic arrays Jiri Olsa was writing a plugin for the cfg80211_tx_mlme_mgmt trace event, and was not able to get the implemented function working. The event's print fmt looks like: "netdev:%s(%d), ftype:0x%.2x", REC->name, REC->ifindex, __le16_to_cpup((__le16 *)__get_dynamic_array(frame)) As there's no helper function for __le16_to_cpup(), Jiri was creating one with a plugin. But unfortunately, it would not work even though he set up the plugin correctly. The problem is that the function parameters do not handle the helper function "__get_dynamic_array()", and that passes in a NULL pointer. Adding PRINT_DYNAMIC_ARRAY direct support to eval_num_arg() allows the use of __get_dynamic_array() in function parameters. Reported-by: Jiri Olsa Signed-off-by: Steven Rostedt Tested-by: Jiri Olsa Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Link: http://lkml.kernel.org/r/20131111160810.0ba9df7d@gandalf.local.home Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'tools') diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index 8f450adaa9c2..0362d575de7d 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c @@ -3435,6 +3435,19 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg goto out_warning_op; } break; + case PRINT_DYNAMIC_ARRAY: + /* Without [], we pass the address to the dynamic data */ + offset = pevent_read_number(pevent, + data + arg->dynarray.field->offset, + arg->dynarray.field->size); + /* + * The actual length of the dynamic array is stored + * in the top half of the field, and the offset + * is in the bottom half of the 32 bit field. + */ + offset &= 0xffff; + val = (unsigned long long)(data + offset); + break; default: /* not sure what to do there */ return 0; } -- cgit v1.2.3-58-ga151