From: Namhyung Kim <namhyung@kernel.org>
To: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Ingo Molnar <mingo@kernel.org>,
Peter Zijlstra <a.p.zijlstra@chello.nl>,
Jiri Olsa <jolsa@redhat.com>, LKML <linux-kernel@vger.kernel.org>,
David Ahern <dsahern@gmail.com>,
Stephane Eranian <eranian@google.com>,
Adrian Hunter <adrian.hunter@intel.com>,
Andi Kleen <andi@firstfloor.org>,
Frederic Weisbecker <fweisbec@gmail.com>
Subject: [PATCH 17/37] perf tools: Maintain map groups list in a leader thread
Date: Wed, 24 Dec 2014 16:15:13 +0900 [thread overview]
Message-ID: <1419405333-27952-18-git-send-email-namhyung@kernel.org> (raw)
In-Reply-To: <1419405333-27952-1-git-send-email-namhyung@kernel.org>
To support multi-threaded perf report, we need to maintain time-sorted
map groups. Add ->mg_list member to struct thread and sort the list
by time. Now leader threads have one more refcnt for map groups in
the list so also update the thread-mg-share test case.
Currently only add a new map groups when an exec (comm) event is
received.
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
tools/perf/tests/thread-mg-share.c | 7 +++-
tools/perf/util/event.c | 2 +
tools/perf/util/machine.c | 2 +-
tools/perf/util/map.c | 1 +
tools/perf/util/map.h | 2 +
tools/perf/util/thread.c | 80 +++++++++++++++++++++++++++++++++++++-
tools/perf/util/thread.h | 3 ++
7 files changed, 93 insertions(+), 4 deletions(-)
diff --git a/tools/perf/tests/thread-mg-share.c b/tools/perf/tests/thread-mg-share.c
index b028499dd3cf..8933e01d0549 100644
--- a/tools/perf/tests/thread-mg-share.c
+++ b/tools/perf/tests/thread-mg-share.c
@@ -23,6 +23,9 @@ int test__thread_mg_share(void)
* with several threads and checks they properly share and
* maintain map groups info (struct map_groups).
*
+ * Note that a leader thread has one more refcnt for its
+ * (current) map groups.
+ *
* thread group (pid: 0, tids: 0, 1, 2, 3)
* other group (pid: 4, tids: 4, 5)
*/
@@ -43,7 +46,7 @@ int test__thread_mg_share(void)
leader && t1 && t2 && t3 && other);
mg = leader->mg;
- TEST_ASSERT_VAL("wrong refcnt", mg->refcnt == 4);
+ TEST_ASSERT_VAL("wrong refcnt", mg->refcnt == 5);
/* test the map groups pointer is shared */
TEST_ASSERT_VAL("map groups don't match", mg == t1->mg);
@@ -59,7 +62,7 @@ int test__thread_mg_share(void)
TEST_ASSERT_VAL("failed to find other leader", other_leader);
other_mg = other->mg;
- TEST_ASSERT_VAL("wrong refcnt", other_mg->refcnt == 2);
+ TEST_ASSERT_VAL("wrong refcnt", other_mg->refcnt == 3);
TEST_ASSERT_VAL("map groups don't match", other_mg == other_leader->mg);
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index ff7594a27c73..2d04949bdc7d 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -750,6 +750,8 @@ void thread__find_addr_map(struct thread *thread, u8 cpumode,
return;
}
+ BUG_ON(mg == NULL);
+
if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) {
al->level = 'k';
mg = &machine->kmaps;
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 2cc088d71922..031bace39fdc 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -330,7 +330,7 @@ static void machine__update_thread_pid(struct machine *machine,
goto out_err;
if (!leader->mg)
- leader->mg = map_groups__new(machine);
+ thread__set_map_groups(leader, map_groups__new(machine), 0);
if (!leader->mg)
goto out_err;
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 62ca9f2607d5..f0c1e2a24fee 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -422,6 +422,7 @@ void map_groups__init(struct map_groups *mg, struct machine *machine)
}
mg->machine = machine;
mg->refcnt = 1;
+ mg->timestamp = 0;
}
static void maps__delete(struct rb_root *maps)
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 6951a9d42339..dd92510b03d1 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -61,7 +61,9 @@ struct map_groups {
struct rb_root maps[MAP__NR_TYPES];
struct list_head removed_maps[MAP__NR_TYPES];
struct machine *machine;
+ u64 timestamp;
int refcnt;
+ struct list_head list;
};
struct map_groups *map_groups__new(struct machine *machine);
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index f2465f17cf16..109ceb5e2a85 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -10,13 +10,64 @@
#include "comm.h"
#include "unwind.h"
+struct map_groups *thread__get_map_groups(struct thread *thread, u64 timestamp)
+{
+ struct map_groups *mg;
+
+ list_for_each_entry(mg, &thread->mg_list, list)
+ if (timestamp >= mg->timestamp)
+ return mg;
+
+ return thread->mg;
+}
+
+int thread__set_map_groups(struct thread *thread, struct map_groups *mg,
+ u64 timestamp)
+{
+ struct list_head *pos;
+ struct map_groups *old;
+
+ if (mg == NULL)
+ return -ENOMEM;
+
+ /*
+ * Only a leader thread can have map groups list - others
+ * reference it through map_groups__get. This means the
+ * leader thread will have one more refcnt than others.
+ */
+ if (thread->tid != thread->pid_)
+ return -EINVAL;
+
+ if (thread->mg) {
+ BUG_ON(thread->mg->refcnt <= 1);
+ map_groups__put(thread->mg);
+ }
+
+ /* sort by time */
+ list_for_each(pos, &thread->mg_list) {
+ old = list_entry(pos, struct map_groups, list);
+ if (timestamp > old->timestamp)
+ break;
+ }
+
+ list_add_tail(&mg->list, pos);
+ mg->timestamp = timestamp;
+
+ /* set current ->mg to most recent one */
+ thread->mg = list_first_entry(&thread->mg_list, struct map_groups, list);
+ /* increase one more refcnt for current */
+ map_groups__get(thread->mg);
+
+ return 0;
+}
+
int thread__init_map_groups(struct thread *thread, struct machine *machine)
{
struct thread *leader;
pid_t pid = thread->pid_;
if (pid == thread->tid || pid == -1) {
- thread->mg = map_groups__new(machine);
+ thread__set_map_groups(thread, map_groups__new(machine), 0);
} else {
leader = machine__findnew_thread(machine, pid, pid);
if (leader)
@@ -39,6 +90,7 @@ struct thread *thread__new(pid_t pid, pid_t tid)
thread->cpu = -1;
INIT_LIST_HEAD(&thread->comm_list);
INIT_LIST_HEAD(&thread->node);
+ INIT_LIST_HEAD(&thread->mg_list);
if (unwind__prepare_access(thread) < 0)
goto err_thread;
@@ -67,6 +119,7 @@ struct thread *thread__new(pid_t pid, pid_t tid)
void thread__delete(struct thread *thread)
{
struct comm *comm, *tmp;
+ struct map_groups *mg, *tmp_mg;
thread_stack__free(thread);
@@ -74,6 +127,11 @@ void thread__delete(struct thread *thread)
map_groups__put(thread->mg);
thread->mg = NULL;
}
+ /* only leader threads have mg list */
+ list_for_each_entry_safe(mg, tmp_mg, &thread->mg_list, list) {
+ list_del(&mg->list);
+ map_groups__put(mg);
+ }
list_for_each_entry_safe(comm, tmp, &thread->comm_list, list) {
list_del(&comm->list);
comm__free(comm);
@@ -150,6 +208,26 @@ int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp,
unwind__flush_access(thread);
}
+ if (exec) {
+ struct machine *machine;
+
+ BUG_ON(thread->mg == NULL || thread->mg->machine == NULL);
+
+ if (thread->tid != thread->pid_) {
+ /* now it'll be a new leader */
+ thread->pid_ = thread->tid;
+
+ /* current mg of leader thread needs one more refcnt */
+ map_groups__get(thread->mg);
+
+ thread__set_map_groups(thread, thread->mg,
+ thread->mg->timestamp);
+ }
+
+ machine = thread->mg->machine;
+ thread__set_map_groups(thread, map_groups__new(machine), timestamp);
+ }
+
thread->comm_set = true;
return 0;
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 5c07cee3b64e..8b9a67764613 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -14,6 +14,7 @@ struct thread {
struct rb_node rb_node;
struct list_head node;
struct map_groups *mg;
+ struct list_head mg_list;
pid_t pid_; /* Not all tools update this */
pid_t tid;
pid_t ppid;
@@ -56,6 +57,8 @@ struct comm *thread__exec_comm(const struct thread *thread);
struct comm *thread__comm_time(const struct thread *thread, u64 timestamp);
const char *thread__comm_str(const struct thread *thread);
const char *thread__comm_time_str(const struct thread *thread, u64 timestamp);
+struct map_groups *thread__get_map_groups(struct thread *thread, u64 timestamp);
+int thread__set_map_groups(struct thread *thread, struct map_groups *mg, u64 timestamp);
void thread__insert_map(struct thread *thread, struct map *map);
int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp);
size_t thread__fprintf(struct thread *thread, FILE *fp);
--
2.1.3
next prev parent reply other threads:[~2014-12-24 7:15 UTC|newest]
Thread overview: 91+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-12-24 7:14 [RFC/PATCHSET 00/37] perf tools: Speed-up perf report by using multi thread (v1) Namhyung Kim
2014-12-24 7:14 ` [PATCH 01/37] perf tools: Set attr.task bit for a tracking event Namhyung Kim
2014-12-31 11:25 ` Jiri Olsa
2014-12-24 7:14 ` [PATCH 02/37] perf record: Use a software dummy event to track task/mmap events Namhyung Kim
2014-12-26 16:27 ` David Ahern
2014-12-27 5:28 ` Namhyung Kim
2014-12-29 12:58 ` Adrian Hunter
2014-12-30 5:51 ` Namhyung Kim
2014-12-30 9:04 ` Adrian Hunter
2014-12-24 7:14 ` [PATCH 03/37] perf tools: Use perf_data_file__fd() consistently Namhyung Kim
2014-12-26 16:30 ` David Ahern
2014-12-27 5:30 ` Namhyung Kim
2014-12-24 7:15 ` [PATCH 04/37] perf tools: Add multi file interface to perf_data_file Namhyung Kim
2014-12-25 22:08 ` Jiri Olsa
2014-12-26 1:19 ` Namhyung Kim
2014-12-31 11:26 ` Jiri Olsa
2014-12-31 14:55 ` Namhyung Kim
2014-12-24 7:15 ` [PATCH 05/37] perf tools: Create separate mmap for dummy tracking event Namhyung Kim
2014-12-25 22:08 ` Jiri Olsa
2014-12-26 1:45 ` Namhyung Kim
2014-12-25 22:09 ` Jiri Olsa
2014-12-26 1:55 ` Namhyung Kim
2014-12-26 16:51 ` David Ahern
2014-12-27 5:32 ` Namhyung Kim
2014-12-29 13:44 ` Adrian Hunter
2014-12-30 5:57 ` Namhyung Kim
2014-12-24 7:15 ` [PATCH 06/37] perf tools: Introduce perf_evlist__mmap_multi() Namhyung Kim
2014-12-24 7:15 ` [PATCH 07/37] perf tools: Do not use __perf_session__process_events() directly Namhyung Kim
2014-12-31 11:33 ` Jiri Olsa
2014-12-24 7:15 ` [PATCH 08/37] perf tools: Handle multi-file session properly Namhyung Kim
2014-12-31 12:01 ` Jiri Olsa
2014-12-31 14:53 ` Namhyung Kim
2014-12-24 7:15 ` [PATCH 09/37] perf record: Add -M/--multi option for multi file recording Namhyung Kim
2014-12-24 7:15 ` [PATCH 10/37] perf report: Skip dummy tracking event Namhyung Kim
2014-12-24 7:15 ` [PATCH 11/37] perf tools: Introduce thread__comm_time() helpers Namhyung Kim
2014-12-26 17:00 ` David Ahern
2014-12-27 5:36 ` Namhyung Kim
2014-12-24 7:15 ` [PATCH 12/37] perf tools: Add a test case for thread comm handling Namhyung Kim
2014-12-24 7:15 ` [PATCH 13/37] perf tools: Use thread__comm_time() when adding hist entries Namhyung Kim
2014-12-25 22:53 ` Jiri Olsa
2014-12-26 2:10 ` Namhyung Kim
2014-12-24 7:15 ` [PATCH 14/37] perf tools: Convert dead thread list into rbtree Namhyung Kim
2014-12-25 23:05 ` Jiri Olsa
2014-12-26 2:26 ` Namhyung Kim
2014-12-26 17:14 ` David Ahern
2014-12-27 5:42 ` Namhyung Kim
2014-12-27 15:31 ` David Ahern
2014-12-28 13:24 ` Namhyung Kim
2014-12-24 7:15 ` [PATCH 15/37] perf tools: Introduce machine__find*_thread_time() Namhyung Kim
2014-12-27 16:33 ` David Ahern
2014-12-28 14:50 ` Namhyung Kim
2014-12-24 7:15 ` [PATCH 16/37] perf tools: Add a test case for timed thread handling Namhyung Kim
2014-12-31 14:17 ` Jiri Olsa
2014-12-31 15:32 ` Namhyung Kim
2014-12-24 7:15 ` Namhyung Kim [this message]
2014-12-24 7:15 ` [PATCH 18/37] perf tools: Remove thread when map groups initialization failed Namhyung Kim
2014-12-28 0:45 ` David Ahern
2014-12-29 7:08 ` Namhyung Kim
2014-12-24 7:15 ` [PATCH 19/37] perf tools: Introduce thread__find_addr_location_time() and friends Namhyung Kim
2014-12-24 7:15 ` [PATCH 20/37] perf tools: Add a test case for timed map groups handling Namhyung Kim
2014-12-24 7:15 ` [PATCH 21/37] perf tools: Protect dso symbol loading using a mutex Namhyung Kim
2014-12-24 7:15 ` [PATCH 22/37] perf tools: Protect dso cache tree using dso->lock Namhyung Kim
2014-12-24 7:15 ` [PATCH 23/37] perf tools: Protect dso cache fd with a mutex Namhyung Kim
2014-12-24 7:15 ` [PATCH 24/37] perf session: Pass struct events stats to event processing functions Namhyung Kim
2014-12-24 7:15 ` [PATCH 25/37] perf hists: Pass hists struct to hist_entry_iter functions Namhyung Kim
2014-12-24 7:15 ` [PATCH 26/37] perf tools: Move BUILD_ID_SIZE definition to perf.h Namhyung Kim
2014-12-24 7:15 ` [PATCH 27/37] perf report: Parallelize perf report using multi-thread Namhyung Kim
2014-12-24 7:15 ` [PATCH 28/37] perf tools: Add missing_threads rb tree Namhyung Kim
2014-12-24 7:15 ` [PATCH 29/37] perf top: Always creates thread in the current task tree Namhyung Kim
2014-12-24 7:15 ` [PATCH 30/37] perf tools: Fix progress ui to support multi thread Namhyung Kim
2014-12-24 7:15 ` [PATCH 31/37] perf record: Show total size of multi file data Namhyung Kim
2014-12-24 7:15 ` [PATCH 32/37] perf report: Add --multi-thread option and config item Namhyung Kim
2014-12-24 7:15 ` [PATCH 33/37] perf tools: Add front cache for dso data access Namhyung Kim
2014-12-24 7:15 ` [PATCH 34/37] perf tools: Convert lseek + read to pread Namhyung Kim
2014-12-24 7:15 ` [PATCH 35/37] perf callchain: Save eh/debug frame offset for dwarf unwind Namhyung Kim
2014-12-24 7:15 ` [PATCH 36/37] perf tools: Add new perf data command Namhyung Kim
2014-12-24 7:15 ` [PATCH 37/37] perf data: Implement 'split' subcommand Namhyung Kim
2014-12-24 13:51 ` Arnaldo Carvalho de Melo
2014-12-24 14:14 ` Namhyung Kim
2014-12-24 14:45 ` Arnaldo Carvalho de Melo
2014-12-26 13:59 ` Jiri Olsa
2014-12-27 5:21 ` Namhyung Kim
2014-12-26 14:02 ` [RFC/PATCHSET 00/37] perf tools: Speed-up perf report by using multi thread (v1) Jiri Olsa
2014-12-27 5:23 ` Namhyung Kim
2015-01-05 18:48 ` Andi Kleen
2015-01-06 15:50 ` Stephane Eranian
2015-01-07 7:13 ` Namhyung Kim
2015-01-07 15:14 ` Stephane Eranian
2015-01-08 5:19 ` Namhyung Kim
2015-01-07 6:58 ` Namhyung Kim
2015-01-08 14:52 ` Andi Kleen
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=1419405333-27952-18-git-send-email-namhyung@kernel.org \
--to=namhyung@kernel.org \
--cc=a.p.zijlstra@chello.nl \
--cc=acme@kernel.org \
--cc=adrian.hunter@intel.com \
--cc=andi@firstfloor.org \
--cc=dsahern@gmail.com \
--cc=eranian@google.com \
--cc=fweisbec@gmail.com \
--cc=jolsa@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@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
all inboxes | Powered by JetHome®