public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Jiri Olsa <jolsa@kernel.org>
To: Peter Zijlstra <a.p.zijlstra@chello.nl>, Ingo Molnar <mingo@kernel.org>
Cc: lkml <linux-kernel@vger.kernel.org>,
	Namhyung Kim <namhyung@kernel.org>,
	David Ahern <dsahern@gmail.com>, Andi Kleen <ak@linux.intel.com>,
	Alexander Shishkin <alexander.shishkin@linux.intel.com>,
	Andy Lutomirski <luto@amacapital.net>,
	Arnaldo Carvalho de Melo <acme@kernel.org>
Subject: [PATCH 15/21] perf report: Add delayed user data event processing
Date: Wed, 24 Jan 2018 12:51:37 +0100	[thread overview]
Message-ID: <20180124115143.14322-16-jolsa@kernel.org> (raw)
In-Reply-To: <20180124115143.14322-1-jolsa@kernel.org>

Adding support to process user data events and attach
their data into samples.

The logic is to copy and store every sample that has
delayed user data (PERF_RECORD_MISC_USER_DATA bit)
under per-thread list.

Then when there's the USER DATA event under this thread,
we go through that list and attach user data to matching
samples (using USER_DATA_ID value).

The processing data at this point are already sorted,
so we don't need to worry about wrongly skipping samples
by unordered USER DATA event. Also we connect only
data that matches same event.

However event loss is still possible, that's why we
match USER_DATA_ID on sample and USER DATA event.
We can remove not matching samples.

Link: http://lkml.kernel.org/n/tip-hacxbv4wzvpt50nf8wj6lk2w@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-report.c | 127 ++++++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/thread.c    |   1 +
 tools/perf/util/thread.h    |   8 +++
 3 files changed, 136 insertions(+)

diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index a08e2c88070a..a1cd5fd793fc 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -293,6 +293,31 @@ perf_sample__process(struct perf_sample *sample, struct addr_location *al,
 	return hist_entry_iter__add(&iter, al, rep->max_stack, rep);
 }
 
+static int
+perf_thread__add_user_data(struct thread *thread,
+			   struct perf_sample *sample,
+			   struct addr_location *al,
+			   struct perf_evsel *evsel)
+{
+	struct user_data *entry;
+
+	entry = zalloc(sizeof(*entry));
+	if (!entry)
+		return -ENOMEM;
+
+	entry->al    = *al;
+	entry->evsel = evsel;
+	INIT_LIST_HEAD(&entry->list);
+
+	if (perf_sample__copy(&entry->sample, sample)) {
+		free(entry);
+		return -ENOMEM;
+	}
+
+	list_add_tail(&entry->list, &thread->user_data_list);
+	return 0;
+}
+
 static int process_sample_event(struct perf_tool *tool,
 				union perf_event *event,
 				struct perf_sample *sample,
@@ -332,6 +357,9 @@ static int process_sample_event(struct perf_tool *tool,
 	if (al.map != NULL)
 		al.map->dso->hit = 1;
 
+	if (event->header.misc & PERF_RECORD_MISC_USER_DATA)
+		return perf_thread__add_user_data(al.thread, sample, &al, evsel);
+
 	ret = perf_sample__process(sample, &al, evsel, rep);
 	if (ret < 0)
 		pr_debug("problem adding hist entry, skipping event\n");
@@ -340,6 +368,104 @@ static int process_sample_event(struct perf_tool *tool,
 	return ret;
 }
 
+static int
+perf_sample__add_user_callchain(struct perf_sample *sample,
+				struct perf_sample *user)
+{
+	struct ip_callchain *sc = sample->callchain;
+	struct ip_callchain *uc = user->callchain;
+	struct ip_callchain *new;
+	u64 nr = 1 + sc->nr + uc->nr;
+
+	new = zalloc(nr * sizeof(u64));
+	if (!new)
+		return -ENOMEM;
+
+	new->nr = nr;
+	memcpy(new->ips,          sc->ips, sc->nr * sizeof(u64));
+	memcpy(new->ips + sc->nr, uc->ips, uc->nr * sizeof(u64));
+
+	free(sample->callchain);
+	sample->callchain = new;
+	return 0;
+}
+
+static int
+perf_sample__add_user_data(struct perf_sample *sample,
+			   struct perf_sample *user,
+			   u64 type)
+{
+	int ret = 0;
+
+	if (type & PERF_SAMPLE_CALLCHAIN)
+		ret = perf_sample__add_user_callchain(sample, user);
+
+	return ret;
+}
+
+static int
+user_data__process(struct user_data *entry, struct perf_sample *sample,
+		   struct user_data_event *event, struct report *rep)
+{
+	int ret;
+
+	ret = perf_sample__add_user_data(&entry->sample, sample, event->type);
+	if (ret)
+		return ret;
+
+	return perf_sample__process(&entry->sample, &entry->al, entry->evsel, rep);
+}
+
+static int
+thread__flush_user_data(struct thread *thread,
+			struct user_data_event *event,
+			struct perf_sample *sample,
+			struct report *rep)
+{
+	struct user_data *entry, *p;
+	int ret = 0;
+
+	list_for_each_entry_safe(entry, p, &thread->user_data_list, list) {
+		/* different event, skip it */
+		if (entry->sample.id != sample->id)
+			continue;
+
+		/*
+		 * We process only matching IDs, if we don't match in here
+		 * it means we've lot master sample, remove user data event
+		 * without any action.
+		 */
+		if (entry->sample.user_data_id == sample->user_data_id) {
+			ret = user_data__process(entry, sample, event, rep);
+			if (ret)
+				pr_debug("problem adding hist entry, skipping event\n");
+		}
+
+		list_del(&entry->list);
+		perf_sample__free(&entry->sample);
+		free(entry);
+	}
+
+	return ret;
+}
+
+static int
+process_user_data_event(struct perf_tool *tool,
+			union perf_event *event,
+			struct perf_sample *sample,
+			struct perf_evsel *evsel __maybe_unused,
+			struct machine *machine)
+{
+	struct report *rep = container_of(tool, struct report, tool);
+	struct thread *thread = machine__findnew_thread(machine, sample->pid,
+							sample->tid);
+
+	if (thread == NULL)
+		return -1;
+
+	return thread__flush_user_data(thread, &event->user_data, sample, rep);
+}
+
 static int process_read_event(struct perf_tool *tool,
 			      union perf_event *event,
 			      struct perf_sample *sample __maybe_unused,
@@ -1025,6 +1151,7 @@ int cmd_report(int argc, const char **argv)
 	struct report report = {
 		.tool = {
 			.sample		 = process_sample_event,
+			.user_data	 = process_user_data_event,
 			.mmap		 = perf_event__process_mmap,
 			.mmap2		 = perf_event__process_mmap2,
 			.comm		 = perf_event__process_comm,
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 68b65b10579b..e9008245a421 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -48,6 +48,7 @@ struct thread *thread__new(pid_t pid, pid_t tid)
 		INIT_LIST_HEAD(&thread->comm_list);
 		init_rwsem(&thread->namespaces_lock);
 		init_rwsem(&thread->comm_lock);
+		INIT_LIST_HEAD(&thread->user_data_list);
 
 		comm_str = malloc(32);
 		if (!comm_str)
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 40cfa36c022a..e78b295bbcdb 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -15,6 +15,13 @@
 struct thread_stack;
 struct unwind_libunwind_ops;
 
+struct user_data {
+	struct perf_sample	 sample;
+	struct addr_location	 al;
+	struct list_head	 list;
+	struct perf_evsel	*evsel;
+};
+
 struct thread {
 	union {
 		struct rb_node	 rb_node;
@@ -34,6 +41,7 @@ struct thread {
 	struct rw_semaphore	namespaces_lock;
 	struct list_head	comm_list;
 	struct rw_semaphore	comm_lock;
+	struct list_head	user_data_list;
 	u64			db_id;
 
 	void			*priv;
-- 
2.13.6

  parent reply	other threads:[~2018-01-24 11:52 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-01-24 11:51 [RFC 00/21] perf tools: Add perf_evsel__is_sample_bit function Jiri Olsa
2018-01-24 11:51 ` [PATCH 01/21] " Jiri Olsa
2018-01-24 11:51 ` [PATCH 02/21] perf tools: Add perf_sample__process function Jiri Olsa
2018-01-24 11:51 ` [PATCH 03/21] perf tools: Add callchain__printf for pure callchain dump Jiri Olsa
2018-01-24 11:51 ` [PATCH 04/21] perf tools: Add perf_sample__copy|free functions Jiri Olsa
2018-01-24 11:51 ` [PATCH 05/21] perf: Add TIF_PERF_USER_DATA bit Jiri Olsa
2018-01-24 11:51 ` [PATCH 06/21] perf: Add PERF_RECORD_USER_DATA event processing Jiri Olsa
2018-01-24 11:51 ` [PATCH 07/21] perf: Add PERF_SAMPLE_USER_DATA_ID sample type Jiri Olsa
2018-01-24 11:51 ` [PATCH 08/21] perf: Add PERF_SAMPLE_CALLCHAIN to user data event Jiri Olsa
2018-01-24 11:51 ` [PATCH 09/21] perf: Export running sample length values through debugfs Jiri Olsa
2018-01-24 11:51 ` [PATCH 10/21] perf tools: Sync perf_event.h uapi header Jiri Olsa
2018-01-24 11:51 ` [PATCH 11/21] perf tools: Add perf_sample__parse function Jiri Olsa
2018-01-24 11:51 ` [PATCH 12/21] perf tools: Add struct parse_args arg to perf_sample__parse Jiri Olsa
2018-01-24 11:51 ` [PATCH 13/21] perf tools: Add support to parse user data event Jiri Olsa
2018-01-24 11:51 ` [PATCH 14/21] perf tools: Add support to dump user data event info Jiri Olsa
2018-01-24 11:51 ` Jiri Olsa [this message]
2018-01-24 11:51 ` [PATCH 16/21] perf record: Enable delayed user data events Jiri Olsa
2018-01-24 11:51 ` [PATCH 17/21] perf script: Add support to display " Jiri Olsa
2018-01-24 11:51 ` [PATCH 18/21] perf script: Add support to display user data ID Jiri Olsa
2018-01-24 11:51 ` [PATCH 19/21] perf script: Display USER_DATA misc char for sample Jiri Olsa
2018-01-24 11:51 ` [PATCH 20/21] perf report: Add user data processing stats Jiri Olsa
2018-01-24 11:51 ` [PATCH 21/21] perf report: Add --stats=ud option to display user data debug info Jiri Olsa
2018-01-24 12:11 ` [RFC 00/21] perf tools: Add user data delayed processing Jiri Olsa

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180124115143.14322-16-jolsa@kernel.org \
    --to=jolsa@kernel.org \
    --cc=a.p.zijlstra@chello.nl \
    --cc=acme@kernel.org \
    --cc=ak@linux.intel.com \
    --cc=alexander.shishkin@linux.intel.com \
    --cc=dsahern@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luto@amacapital.net \
    --cc=mingo@kernel.org \
    --cc=namhyung@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox