From 1fcb8768636d38cb6fdfeef83a5ee596c4bd9c56 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Mon, 14 Jul 2014 13:02:25 +0300 Subject: perf machine: Fix the value used for unknown pids The value used for unknown pids cannot be zero because that is used by the "idle" task. Use -1 instead. Also handle the unknown pid case when creating map groups. Note that, threads with an unknown pid should not occur because fork (or synthesized) events precede the thread's existence. Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1405332185-4050-2-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/session.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'tools/perf/util/session.c') diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 64a186edc7be..c2f4ca917469 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1083,13 +1083,14 @@ void perf_event_header__bswap(struct perf_event_header *hdr) struct thread *perf_session__findnew(struct perf_session *session, pid_t pid) { - return machine__findnew_thread(&session->machines.host, 0, pid); + return machine__findnew_thread(&session->machines.host, -1, pid); } static struct thread *perf_session__register_idle_thread(struct perf_session *session) { - struct thread *thread = perf_session__findnew(session, 0); + struct thread *thread; + thread = machine__findnew_thread(&session->machines.host, 0, 0); if (thread == NULL || thread__set_comm(thread, "swapper", 0)) { pr_err("problem inserting idle task.\n"); thread = NULL; -- cgit v1.2.3 From 919d86d3a3109d7d4f0d7347f34711ee2f8e6609 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Mon, 14 Jul 2014 13:02:51 +0300 Subject: perf session: Flag if the event stream is entirely in memory Flag if the event stream is a file that has been mmapped in one go. This is useful, for example, if a tool needs to keep an event for later reference. If the new flag is set, a pointer to the event can be retained, otherwise the event must be copied. Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1405332185-4050-28-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/session.c | 9 ++++++++- tools/perf/util/session.h | 3 +++ 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'tools/perf/util/session.c') diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index c2f4ca917469..eac14ce0ae8d 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1297,8 +1297,10 @@ int __perf_session__process_events(struct perf_session *session, ui_progress__init(&prog, file_size, "Processing events..."); mmap_size = MMAP_SIZE; - if (mmap_size > file_size) + if (mmap_size > file_size) { mmap_size = file_size; + session->one_mmap = true; + } memset(mmaps, 0, sizeof(mmaps)); @@ -1320,6 +1322,10 @@ remap: mmaps[map_idx] = buf; map_idx = (map_idx + 1) & (ARRAY_SIZE(mmaps) - 1); file_pos = file_offset + head; + if (session->one_mmap) { + session->one_mmap_addr = buf; + session->one_mmap_offset = file_offset; + } more: event = fetch_mmaped_event(session, head, mmap_size, buf); @@ -1365,6 +1371,7 @@ out_err: ui_progress__finish(); perf_session__warn_about_errors(session, tool); perf_session_free_sample_buffers(session); + session->one_mmap = false; return err; } diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 3140f8ae6148..0321013bd9fd 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -36,6 +36,9 @@ struct perf_session { struct trace_event tevent; struct events_stats stats; bool repipe; + bool one_mmap; + void *one_mmap_addr; + u64 one_mmap_offset; struct ordered_samples ordered_samples; struct perf_data_file *file; }; -- cgit v1.2.3 From 6f917c70998d22bda6d06cb168665068c6066cd4 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Wed, 23 Jul 2014 22:19:57 +0300 Subject: perf session: Add ability to 'skip' a non-piped event stream A piped event stream may contain arbitary sized tracepoint information following a PERF_RECORD_HEADER_TRACING_DATA event. The position in the stream has to be 'skipped' to match the start of the next event. Provide the same ability to a non-piped event stream to allow for Instruction Trace data that may also be in a non-piped event stream. Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1406143198-20732-1-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/session.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'tools/perf/util/session.c') diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index eac14ce0ae8d..f4399b2087c4 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1284,6 +1284,7 @@ int __perf_session__process_events(struct perf_session *session, union perf_event *event; uint32_t size; struct ui_progress prog; + int skip; perf_tool__fill_defaults(tool); @@ -1344,7 +1345,8 @@ more: size = event->header.size; if (size < sizeof(struct perf_event_header) || - perf_session__process_event(session, event, tool, file_pos) < 0) { + (skip = perf_session__process_event(session, event, tool, file_pos)) + < 0) { pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n", file_offset + head, event->header.size, event->header.type); @@ -1352,6 +1354,9 @@ more: goto out_err; } + if (skip) + size += skip; + head += size; file_pos += size; -- cgit v1.2.3 From d5652d865ea734a13a16cf563937291a84d4364d Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Wed, 23 Jul 2014 22:19:58 +0300 Subject: perf session: Add ability to skip 4GiB or more A session can be made to skip portions of the input file. Do not limit that size to 32-bits. Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1406143198-20732-2-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/session.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'tools/perf/util/session.c') diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index f4399b2087c4..d3da1055239f 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -994,8 +994,10 @@ static int perf_session_deliver_event(struct perf_session *session, } } -static int perf_session__process_user_event(struct perf_session *session, union perf_event *event, - struct perf_tool *tool, u64 file_offset) +static s64 perf_session__process_user_event(struct perf_session *session, + union perf_event *event, + struct perf_tool *tool, + u64 file_offset) { int fd = perf_data_file__fd(session->file); int err; @@ -1037,7 +1039,7 @@ static void event_swap(union perf_event *event, bool sample_id_all) swap(event, sample_id_all); } -static int perf_session__process_event(struct perf_session *session, +static s64 perf_session__process_event(struct perf_session *session, union perf_event *event, struct perf_tool *tool, u64 file_offset) @@ -1148,7 +1150,7 @@ static int __perf_session__process_pipe_events(struct perf_session *session, union perf_event *event; uint32_t size, cur_size = 0; void *buf = NULL; - int skip = 0; + s64 skip = 0; u64 head; ssize_t err; void *p; @@ -1277,14 +1279,13 @@ int __perf_session__process_events(struct perf_session *session, u64 file_size, struct perf_tool *tool) { int fd = perf_data_file__fd(session->file); - u64 head, page_offset, file_offset, file_pos; + u64 head, page_offset, file_offset, file_pos, size; int err, mmap_prot, mmap_flags, map_idx = 0; size_t mmap_size; char *buf, *mmaps[NUM_MMAPS]; union perf_event *event; - uint32_t size; struct ui_progress prog; - int skip; + s64 skip; perf_tool__fill_defaults(tool); -- cgit v1.2.3 From d027b64001b21328cc92d35c6444e1a7a926ea76 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Wed, 23 Jul 2014 14:23:00 +0300 Subject: perf machine: Fix the lifetime of the VDSO temporary file The VDSO temporary file is unlinked when a session is deleted. That precludes the possibilities that there is no session or there is more than one session. Correctly the vdso belongs to the machine so put the information on 'struct machine' and get rid of the global variables. Reviewed-by: Jiri Olsa Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/53CF9B14.7040408@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/machine.c | 4 ++++ tools/perf/util/machine.h | 3 +++ tools/perf/util/session.c | 2 -- tools/perf/util/vdso.c | 39 +++++++++++++++++++++++++++++---------- tools/perf/util/vdso.h | 2 +- 5 files changed, 37 insertions(+), 13 deletions(-) (limited to 'tools/perf/util/session.c') diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index a25f3ee1b5b3..65269b8ac186 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -8,6 +8,7 @@ #include "sort.h" #include "strlist.h" #include "thread.h" +#include "vdso.h" #include #include #include "unwind.h" @@ -23,6 +24,8 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid) INIT_LIST_HEAD(&machine->dead_threads); machine->last_match = NULL; + machine->vdso_info = NULL; + machine->kmaps.machine = machine; machine->pid = pid; @@ -105,6 +108,7 @@ void machine__exit(struct machine *machine) map_groups__exit(&machine->kmaps); dsos__delete(&machine->user_dsos); dsos__delete(&machine->kernel_dsos); + vdso__exit(machine); zfree(&machine->root_dir); zfree(&machine->current_tid); } diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h index 8771d0cbe9cb..b972824e6294 100644 --- a/tools/perf/util/machine.h +++ b/tools/perf/util/machine.h @@ -20,6 +20,8 @@ union perf_event; extern const char *ref_reloc_sym_names[]; +struct vdso_info; + struct machine { struct rb_node rb_node; pid_t pid; @@ -28,6 +30,7 @@ struct machine { struct rb_root threads; struct list_head dead_threads; struct thread *last_match; + struct vdso_info *vdso_info; struct list_head user_dsos; struct list_head kernel_dsos; struct map_groups kmaps; diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index d3da1055239f..fab5838c06be 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -14,7 +14,6 @@ #include "util.h" #include "cpumap.h" #include "perf_regs.h" -#include "vdso.h" static int perf_session__open(struct perf_session *session) { @@ -156,7 +155,6 @@ void perf_session__delete(struct perf_session *session) if (session->file) perf_data_file__close(session->file); free(session); - vdso__exit(); } static int process_event_synth_tracing_data_stub(struct perf_tool *tool diff --git a/tools/perf/util/vdso.c b/tools/perf/util/vdso.c index 75245f081b60..fdaccaf67371 100644 --- a/tools/perf/util/vdso.c +++ b/tools/perf/util/vdso.c @@ -28,14 +28,17 @@ struct vdso_info { struct vdso_file vdso; }; -static struct vdso_info vdso_info_ = { - .vdso = { - .temp_file_name = VDSO__TEMP_FILE_NAME, - .dso_name = VDSO__MAP_NAME, - }, -}; - -static struct vdso_info *vdso_info = &vdso_info_; +static struct vdso_info *vdso_info__new(void) +{ + static const struct vdso_info vdso_info_init = { + .vdso = { + .temp_file_name = VDSO__TEMP_FILE_NAME, + .dso_name = VDSO__MAP_NAME, + }, + }; + + return memdup(&vdso_info_init, sizeof(vdso_info_init)); +} static int find_vdso_map(void **start, void **end) { @@ -105,16 +108,32 @@ static char *get_file(struct vdso_file *vdso_file) return vdso; } -void vdso__exit(void) +void vdso__exit(struct machine *machine) { + struct vdso_info *vdso_info = machine->vdso_info; + + if (!vdso_info) + return; + if (vdso_info->vdso.found) unlink(vdso_info->vdso.temp_file_name); + + zfree(&machine->vdso_info); } struct dso *vdso__dso_findnew(struct machine *machine) { - struct dso *dso = dsos__find(&machine->user_dsos, VDSO__MAP_NAME, true); + struct vdso_info *vdso_info; + struct dso *dso; + + if (!machine->vdso_info) + machine->vdso_info = vdso_info__new(); + + vdso_info = machine->vdso_info; + if (!vdso_info) + return NULL; + dso = dsos__find(&machine->user_dsos, VDSO__MAP_NAME, true); if (!dso) { char *file; diff --git a/tools/perf/util/vdso.h b/tools/perf/util/vdso.h index 9ab0738b6752..7cf1576863a4 100644 --- a/tools/perf/util/vdso.h +++ b/tools/perf/util/vdso.h @@ -15,6 +15,6 @@ static inline bool is_vdso_map(const char *filename) struct machine; struct dso *vdso__dso_findnew(struct machine *machine); -void vdso__exit(void); +void vdso__exit(struct machine *machine); #endif /* __PERF_VDSO__ */ -- cgit v1.2.3 From f1dd1460a40894b00bbeacd753025e9251ec11bd Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 20 Jul 2014 23:55:45 +0200 Subject: perf session: Fix accounting of ordered samples queue Properly account flushed samples within the ordered samples queue. Signed-off-by: Jiri Olsa Acked-by: Adrian Hunter Acked-by: David Ahern Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jean Pihet Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1405893363-21967-2-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/session.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'tools/perf/util/session.c') diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index fab5838c06be..88dfef70c13d 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -509,6 +509,7 @@ static int flush_sample_queue(struct perf_session *s, os->last_flush = iter->timestamp; list_del(&iter->list); list_add(&iter->list, &os->sample_cache); + os->nr_samples--; if (show_progress) ui_progress__update(&prog, 1); @@ -521,8 +522,6 @@ static int flush_sample_queue(struct perf_session *s, list_entry(head->prev, struct sample_queue, list); } - os->nr_samples = 0; - return 0; } -- cgit v1.2.3