Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1237913 > unrolled thread
| Started by | Namhyung Kim <namhyung@kernel.org> |
|---|---|
| First post | 2015-10-02 07:30 +0200 |
| Last post | 2015-10-02 07:40 +0200 |
| Articles | 13 on this page of 33 — 4 participants |
Back to article view | Back to linux.kernel
[RFC/PATCH 00/38] perf tools: Speed-up perf report by using multi thread (v5) Namhyung Kim <namhyung@kernel.org> - 2015-10-02 07:30 +0200
[RFC/PATCH 04/38] perf tools: pass perf_mmap desc directly Namhyung Kim <namhyung@kernel.org> - 2015-10-02 07:30 +0200
Re: [RFC/PATCH 04/38] perf tools: pass perf_mmap desc directly Arnaldo Carvalho de Melo <acme@kernel.org> - 2015-10-02 20:50 +0200
[RFC/PATCH 27/38] perf hists: Pass hists struct to hist_entry_iter struct Namhyung Kim <namhyung@kernel.org> - 2015-10-02 07:30 +0200
[RFC/PATCH 06/38] perf tools: Extend perf_evlist__mmap_ex() to use track mmap Namhyung Kim <namhyung@kernel.org> - 2015-10-02 07:30 +0200
[RFC/PATCH 18/38] perf tools: Introduce thread__find_addr_location_by_time() and friends Namhyung Kim <namhyung@kernel.org> - 2015-10-02 07:30 +0200
[RFC/PATCH 21/38] perf tools: Save timestamp of a map creation Namhyung Kim <namhyung@kernel.org> - 2015-10-02 07:30 +0200
[RFC/PATCH 15/38] perf tools: Introduce machine__find*_thread_by_time() Namhyung Kim <namhyung@kernel.org> - 2015-10-02 07:30 +0200
[RFC/PATCH 01/38] perf tools: Use a software dummy event to track task/mmap events Namhyung Kim <namhyung@kernel.org> - 2015-10-02 07:30 +0200
Re: [RFC/PATCH 01/38] perf tools: Use a software dummy event to track task/mmap events Jiri Olsa <jolsa@redhat.com> - 2015-10-05 15:00 +0200
[RFC/PATCH 28/38] perf tools: Move BUILD_ID_SIZE definition to perf.h Namhyung Kim <namhyung@kernel.org> - 2015-10-02 07:30 +0200
[RFC/PATCH 13/38] perf tools: Use thread__comm_by_time() when adding hist entries Namhyung Kim <namhyung@kernel.org> - 2015-10-02 07:30 +0200
[RFC/PATCH 14/38] perf tools: Convert dead thread list into rbtree Namhyung Kim <namhyung@kernel.org> - 2015-10-02 07:30 +0200
[RFC/PATCH 22/38] perf tools: Introduce map_groups__{insert,find}_by_time() Namhyung Kim <namhyung@kernel.org> - 2015-10-02 07:30 +0200
[RFC/PATCH 26/38] perf session: Pass struct events stats to event processing functions Namhyung Kim <namhyung@kernel.org> - 2015-10-02 07:30 +0200
[RFC/PATCH 09/38] perf record: Add --index option for building index table Namhyung Kim <namhyung@kernel.org> - 2015-10-02 07:30 +0200
Re: [RFC/PATCH 09/38] perf record: Add --index option for building index table Arnaldo Carvalho de Melo <acme@kernel.org> - 2015-10-02 21:00 +0200
Re: [RFC/PATCH 09/38] perf record: Add --index option for building index table Jiri Olsa <jolsa@redhat.com> - 2015-10-05 15:50 +0200
[RFC/PATCH 23/38] perf tools: Use map_groups__find_addr_by_time() Namhyung Kim <namhyung@kernel.org> - 2015-10-02 07:30 +0200
[RFC/PATCH 28/38] perf tools: Move BUILD_ID_SIZE definition to perf.h Namhyung Kim <namhyung@kernel.org> - 2015-10-02 07:30 +0200
[RFC/PATCH 24/38] perf tools: Add testcase for managing maps with time Namhyung Kim <namhyung@kernel.org> - 2015-10-02 07:30 +0200
[RFC/PATCH 11/38] perf tools: Introduce thread__comm(_str)_by_time() helpers Namhyung Kim <namhyung@kernel.org> - 2015-10-02 07:30 +0200
[RFC/PATCH 17/38] perf tools: Maintain map groups list in a leader thread Namhyung Kim <namhyung@kernel.org> - 2015-10-02 07:30 +0200
[RFC/PATCH 08/38] perf tools: Handle indexed data file properly Namhyung Kim <namhyung@kernel.org> - 2015-10-02 07:40 +0200
[RFC/PATCH 02/38] perf tools: Save mmap_param.len instead of mask Namhyung Kim <namhyung@kernel.org> - 2015-10-02 07:40 +0200
Re: [RFC/PATCH 02/38] perf tools: Save mmap_param.len instead of mask Arnaldo Carvalho de Melo <acme@kernel.org> - 2015-10-02 20:50 +0200
[RFC/PATCH 07/38] perf tools: Add HEADER_DATA_INDEX feature Namhyung Kim <namhyung@kernel.org> - 2015-10-02 07:40 +0200
[RFC/PATCH 10/38] perf report: Skip dummy tracking event Namhyung Kim <namhyung@kernel.org> - 2015-10-02 07:40 +0200
[RFC/PATCH 03/38] perf tools: Move auxtrace_mmap field to struct perf_evlist Namhyung Kim <namhyung@kernel.org> - 2015-10-02 07:40 +0200
Re: [RFC/PATCH 03/38] perf tools: Move auxtrace_mmap field to struct perf_evlist Arnaldo Carvalho de Melo <acme@kernel.org> - 2015-10-02 20:50 +0200
Re: [RFC/PATCH 03/38] perf tools: Move auxtrace_mmap field to struct perf_evlist Adrian Hunter <adrian.hunter@intel.com> - 2015-10-05 13:40 +0200
Re: [RFC/PATCH 03/38] perf tools: Move auxtrace_mmap field to struct perf_evlist Jiri Olsa <jolsa@redhat.com> - 2015-10-05 15:20 +0200
[RFC/PATCH 05/38] perf tools: Create separate mmap for dummy tracking event Namhyung Kim <namhyung@kernel.org> - 2015-10-02 07:40 +0200
Page 2 of 2 — ← Prev page 1 [2]
| From | Namhyung Kim <namhyung@kernel.org> |
|---|---|
| Date | 2015-10-02 07:30 +0200 |
| Subject | [RFC/PATCH 24/38] perf tools: Add testcase for managing maps with time |
| Message-ID | <qf14T-2jW-55@gated-at.bofh.it> |
| In reply to | #1237913 |
This tests new map_groups__{insert,find}_by_time() API working
correctly by using 3 * 100 maps.
Cc: Stephane Eranian <eranian@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
tools/perf/tests/Build | 1 +
tools/perf/tests/builtin-test.c | 4 ++
tools/perf/tests/tests.h | 1 +
tools/perf/tests/thread-map-time.c | 90 ++++++++++++++++++++++++++++++++++++++
4 files changed, 96 insertions(+)
create mode 100644 tools/perf/tests/thread-map-time.c
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index d287b99ff3bb..cc4e3af3e0fd 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -28,6 +28,7 @@ perf-y += thread-comm.o
perf-y += thread-mg-share.o
perf-y += thread-lookup-time.o
perf-y += thread-mg-time.o
+perf-y += thread-map-time.o
perf-y += switch-tracking.o
perf-y += keep-tracking.o
perf-y += code-reading.o
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 62de08a89e0e..d5f9fcef5571 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -203,6 +203,10 @@ static struct test {
.func = test__thread_mg_time,
},
{
+ .desc = "Test thread map lookup with time",
+ .func = test__thread_map_lookup_time,
+ },
+ {
.func = NULL,
},
};
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 03dcaccb570f..e498b23f1580 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -68,6 +68,7 @@ int test_session_topology(void);
int test__thread_comm(void);
int test__thread_lookup_time(void);
int test__thread_mg_time(void);
+int test__thread_map_lookup_time(void);
#if defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__)
#ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/tests/thread-map-time.c b/tools/perf/tests/thread-map-time.c
new file mode 100644
index 000000000000..6f28975faeb5
--- /dev/null
+++ b/tools/perf/tests/thread-map-time.c
@@ -0,0 +1,90 @@
+#include "debug.h"
+#include "tests.h"
+#include "machine.h"
+#include "thread.h"
+#include "map.h"
+
+#define PERF_MAP_START 0x40000
+#define LIBC_MAP_START 0x80000
+#define VDSO_MAP_START 0x7F000
+
+#define NR_MAPS 100
+
+static int lookup_maps(struct map_groups *mg)
+{
+ struct map *map;
+ int i, ret = -1;
+ size_t n;
+ struct {
+ const char *path;
+ u64 start;
+ } maps[] = {
+ { "/usr/bin/perf", PERF_MAP_START },
+ { "/usr/lib/libc.so", LIBC_MAP_START },
+ { "[vdso]", VDSO_MAP_START },
+ };
+
+ /* this is needed to insert/find map by time */
+ perf_has_index = true;
+
+ for (n = 0; n < ARRAY_SIZE(maps); n++) {
+ for (i = 0; i < NR_MAPS; i++) {
+ map = map__new2(maps[n].start, dso__new(maps[n].path),
+ MAP__FUNCTION, i * 10000);
+ if (map == NULL) {
+ pr_debug("memory allocation failed\n");
+ goto out;
+ }
+
+ map->end = map->start + 0x1000;
+ map_groups__insert_by_time(mg, map);
+ }
+ }
+
+ if (verbose > 1)
+ map_groups__fprintf(mg, stderr);
+
+ for (n = 0; n < ARRAY_SIZE(maps); n++) {
+ for (i = 0; i < NR_MAPS; i++) {
+ u64 timestamp = i * 10000;
+
+ map = map_groups__find_by_time(mg, MAP__FUNCTION,
+ maps[n].start,
+ timestamp);
+
+ TEST_ASSERT_VAL("cannot find map", map);
+ TEST_ASSERT_VAL("addr not matched",
+ map->start == maps[n].start);
+ TEST_ASSERT_VAL("pathname not matched",
+ !strcmp(map->dso->name, maps[n].path));
+ TEST_ASSERT_VAL("timestamp not matched",
+ map->timestamp == timestamp);
+ }
+ }
+
+ ret = 0;
+out:
+ return ret;
+}
+
+/*
+ * This test creates large number of overlapping maps for increasing
+ * time and find a map based on timestamp.
+ */
+int test__thread_map_lookup_time(void)
+{
+ struct machines machines;
+ struct machine *machine;
+ struct thread *t;
+ int ret;
+
+ machines__init(&machines);
+ machine = &machines.host;
+
+ t = machine__findnew_thread(machine, 0, 0);
+
+ ret = lookup_maps(t->mg);
+
+ machine__delete_threads(machine);
+ return ret;
+}
--
2.6.0
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Namhyung Kim <namhyung@kernel.org> |
|---|---|
| Date | 2015-10-02 07:30 +0200 |
| Subject | [RFC/PATCH 11/38] perf tools: Introduce thread__comm(_str)_by_time() helpers |
| Message-ID | <qf14T-2jW-57@gated-at.bofh.it> |
| In reply to | #1237913 |
When data file indexing is enabled, it processes all task, comm and mmap
events first and then goes to the sample events. So all it sees is the
last comm of a thread although it has information at the time of sample.
Sort thread's comm by time so that it can find appropriate comm at the
sample time. The thread__comm_by_time() will mostly work even if
PERF_SAMPLE_TIME bit is off since in that case, sample->time will be
-1 so it'll take the last comm anyway.
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
tools/perf/util/thread.c | 33 ++++++++++++++++++++++++++++++++-
tools/perf/util/thread.h | 2 ++
2 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 0a9ae8014729..8244397753fd 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -121,6 +121,21 @@ struct comm *thread__exec_comm(const struct thread *thread)
return last;
}
+struct comm *thread__comm_by_time(const struct thread *thread, u64 timestamp)
+{
+ struct comm *comm;
+
+ list_for_each_entry(comm, &thread->comm_list, list) {
+ if (timestamp >= comm->start)
+ return comm;
+ }
+
+ if (list_empty(&thread->comm_list))
+ return NULL;
+
+ return list_last_entry(&thread->comm_list, struct comm, list);
+}
+
int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp,
bool exec)
{
@@ -136,7 +151,13 @@ int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp,
new = comm__new(str, timestamp, exec);
if (!new)
return -ENOMEM;
- list_add(&new->list, &thread->comm_list);
+
+ /* sort by time */
+ list_for_each_entry(curr, &thread->comm_list, list) {
+ if (timestamp >= curr->start)
+ break;
+ }
+ list_add_tail(&new->list, &curr->list);
if (exec)
unwind__flush_access(thread);
@@ -157,6 +178,16 @@ const char *thread__comm_str(const struct thread *thread)
return comm__str(comm);
}
+const char *thread__comm_str_by_time(const struct thread *thread, u64 timestamp)
+{
+ const struct comm *comm = thread__comm_by_time(thread, timestamp);
+
+ if (!comm)
+ return NULL;
+
+ return comm__str(comm);
+}
+
/* CHECKME: it should probably better return the max comm len from its comm list */
int thread__comm_len(struct thread *thread)
{
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index a0ac0317affb..33418e6dc64a 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -68,7 +68,9 @@ static inline int thread__set_comm(struct thread *thread, const char *comm,
int thread__comm_len(struct thread *thread);
struct comm *thread__comm(const struct thread *thread);
struct comm *thread__exec_comm(const struct thread *thread);
+struct comm *thread__comm_by_time(const struct thread *thread, u64 timestamp);
const char *thread__comm_str(const struct thread *thread);
+const char *thread__comm_str_by_time(const struct thread *thread, 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.6.0
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Namhyung Kim <namhyung@kernel.org> |
|---|---|
| Date | 2015-10-02 07:30 +0200 |
| Subject | [RFC/PATCH 17/38] perf tools: Maintain map groups list in a leader thread |
| Message-ID | <qf14T-2jW-59@gated-at.bofh.it> |
| In reply to | #1237913 |
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 | 15 ++++-
tools/perf/util/map.c | 3 +
tools/perf/util/map.h | 2 +
tools/perf/util/thread.c | 111 ++++++++++++++++++++++++++++++++++++-
tools/perf/util/thread.h | 3 +
7 files changed, 138 insertions(+), 5 deletions(-)
diff --git a/tools/perf/tests/thread-mg-share.c b/tools/perf/tests/thread-mg-share.c
index 01fabb19d746..b258d5298b9b 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_EQUAL("wrong refcnt", atomic_read(&mg->refcnt), 4);
+ TEST_ASSERT_EQUAL("wrong refcnt", atomic_read(&mg->refcnt), 5);
/* test the map groups pointer is shared */
TEST_ASSERT_VAL("map groups don't match", mg == t1->mg);
@@ -71,7 +74,7 @@ int test__thread_mg_share(void)
machine__remove_thread(machine, other_leader);
other_mg = other->mg;
- TEST_ASSERT_EQUAL("wrong refcnt", atomic_read(&other_mg->refcnt), 2);
+ TEST_ASSERT_EQUAL("wrong refcnt", atomic_read(&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 3dff1b5cd4cc..887f18266ab5 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -914,6 +914,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 7cfaa2c3f131..3373e8455945 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -349,8 +349,19 @@ static void machine__update_thread_pid(struct machine *machine,
if (!leader)
goto out_err;
- if (!leader->mg)
- leader->mg = map_groups__new(machine);
+ if (!leader->mg) {
+ struct map_groups *mg = map_groups__new(machine);
+
+ if (mg == NULL) {
+ pr_err("Not enough memory for map groups\n");
+ return;
+ }
+
+ if (thread__set_map_groups(leader, mg, 0) < 0) {
+ map_groups__put(mg);
+ goto out_err;
+ }
+ }
if (!leader->mg)
goto out_err;
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 4e38c396a897..addd4b323027 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -471,6 +471,8 @@ void map_groups__init(struct map_groups *mg, struct machine *machine)
}
mg->machine = machine;
atomic_set(&mg->refcnt, 1);
+ mg->timestamp = 0;
+ INIT_LIST_HEAD(&mg->list);
}
static void __maps__purge(struct maps *maps)
@@ -527,6 +529,7 @@ struct map_groups *map_groups__new(struct machine *machine)
void map_groups__delete(struct map_groups *mg)
{
map_groups__exit(mg);
+ list_del(&mg->list);
free(mg);
}
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 7309d64ce39e..1e3313a22d3a 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -68,6 +68,8 @@ struct map_groups {
struct maps maps[MAP__NR_TYPES];
struct machine *machine;
atomic_t refcnt;
+ u64 timestamp;
+ 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 ad7c2a00bff8..33de8b010282 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -11,13 +11,79 @@
#include "unwind.h"
#include "machine.h"
+struct map_groups *thread__get_map_groups(struct thread *thread, u64 timestamp)
+{
+ struct map_groups *mg;
+ struct thread *leader = thread;
+
+ BUG_ON(thread->mg == NULL);
+
+ if (thread->tid != thread->pid_) {
+ leader = machine__find_thread_by_time(thread->mg->machine,
+ thread->pid_, thread->pid_,
+ timestamp);
+ if (leader == NULL)
+ goto out;
+ }
+
+ list_for_each_entry(mg, &leader->mg_list, list)
+ if (timestamp >= mg->timestamp)
+ return mg;
+
+out:
+ 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(atomic_read(&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);
+ struct map_groups *mg = map_groups__new(machine);
+
+ if (thread__set_map_groups(thread, mg, 0) < 0)
+ map_groups__put(mg);
} else {
leader = __machine__findnew_thread(machine, pid, pid);
if (leader)
@@ -39,6 +105,7 @@ struct thread *thread__new(pid_t pid, pid_t tid)
thread->ppid = -1;
thread->cpu = -1;
INIT_LIST_HEAD(&thread->comm_list);
+ INIT_LIST_HEAD(&thread->mg_list);
if (unwind__prepare_access(thread) < 0)
goto err_thread;
@@ -69,6 +136,7 @@ err_thread:
void thread__delete(struct thread *thread)
{
struct comm *comm, *tmp;
+ struct map_groups *mg, *tmp_mg;
BUG_ON(!RB_EMPTY_NODE(&thread->rb_node));
BUG_ON(!list_empty(&thread->tid_list));
@@ -79,6 +147,10 @@ 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)
+ map_groups__put(mg);
+
list_for_each_entry_safe(comm, tmp, &thread->comm_list, list) {
list_del(&comm->list);
comm__free(comm);
@@ -152,6 +224,9 @@ struct comm *thread__comm_by_time(const struct thread *thread, u64 timestamp)
return list_last_entry(&thread->comm_list, struct comm, list);
}
+static int thread__clone_map_groups(struct thread *thread,
+ struct thread *parent);
+
int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp,
bool exec)
{
@@ -182,6 +257,40 @@ 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);
+
+ machine = thread->mg->machine;
+
+ if (thread->tid != thread->pid_) {
+ struct map_groups *old = thread->mg;
+ struct thread *leader;
+
+ leader = machine__findnew_thread(machine, thread->pid_,
+ thread->pid_);
+
+ /* now it'll be a new leader */
+ thread->pid_ = thread->tid;
+
+ thread->mg = map_groups__new(old->machine);
+ if (thread->mg == NULL)
+ return -ENOMEM;
+
+ /* save current mg in the new leader */
+ thread__clone_map_groups(thread, leader);
+
+ /* current mg of leader thread needs one more refcnt */
+ map_groups__get(thread->mg);
+
+ thread__set_map_groups(thread, thread->mg, old->timestamp);
+ }
+
+ /* create a new mg for newly executed binary */
+ 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 97026a9660ec..c8463d08a6dd 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -16,6 +16,7 @@ struct thread {
struct rb_node rb_node;
struct list_head tid_list;
struct map_groups *mg;
+ struct list_head mg_list;
pid_t pid_; /* Not all tools update this */
pid_t tid;
pid_t ppid;
@@ -71,6 +72,8 @@ struct comm *thread__exec_comm(const struct thread *thread);
struct comm *thread__comm_by_time(const struct thread *thread, u64 timestamp);
const char *thread__comm_str(const struct thread *thread);
const char *thread__comm_str_by_time(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.6.0
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Namhyung Kim <namhyung@kernel.org> |
|---|---|
| Date | 2015-10-02 07:40 +0200 |
| Subject | [RFC/PATCH 08/38] perf tools: Handle indexed data file properly |
| Message-ID | <qf1ex-2v1-1@gated-at.bofh.it> |
| In reply to | #1237913 |
When perf detects data file has index table, process header part first
and then rest data files in a row. Note that the indexed sample data is
recorded for each cpu/thread separately, it's already ordered with
respect to themselves so no need to use the ordered event queue
interface.
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
tools/perf/perf.c | 1 +
tools/perf/perf.h | 2 ++
tools/perf/util/session.c | 55 +++++++++++++++++++++++++++++++++++++++--------
3 files changed, 49 insertions(+), 9 deletions(-)
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 1fded922bcc8..9664d84a9f8c 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -28,6 +28,7 @@ const char perf_more_info_string[] =
int use_browser = -1;
static int use_pager = -1;
const char *input_name;
+bool perf_has_index;
struct cmd_struct {
const char *cmd;
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 90129accffbe..f4b4d7d8752c 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -39,6 +39,8 @@ void pthread__unblock_sigwinch(void);
#include "util/target.h"
+extern bool perf_has_index;
+
struct record_opts {
struct target target;
bool group;
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 428149bc64d2..91fa9647f565 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1586,7 +1586,9 @@ static int __perf_session__process_events(struct perf_session *session,
mmap_size = MMAP_SIZE;
if (mmap_size > file_size) {
mmap_size = file_size;
- session->one_mmap = true;
+
+ if (!perf_has_index)
+ session->one_mmap = true;
}
memset(mmaps, 0, sizeof(mmaps));
@@ -1664,28 +1666,63 @@ out:
err = perf_session__flush_thread_stacks(session);
out_err:
ui_progress__finish();
- perf_session__warn_about_errors(session);
ordered_events__free(&session->ordered_events);
auxtrace__free_events(session);
session->one_mmap = false;
return err;
}
+static int __perf_session__process_indexed_events(struct perf_session *session)
+{
+ struct perf_data_file *file = session->file;
+ struct perf_tool *tool = session->tool;
+ u64 size = perf_data_file__size(file);
+ int err = 0, i;
+
+ for (i = 0; i < (int)session->header.nr_index; i++) {
+ struct perf_file_section *idx = &session->header.index[i];
+
+ if (!idx->size)
+ continue;
+
+ /*
+ * For indexed data file, samples are processed for
+ * each cpu/thread so it's already ordered. However
+ * meta-events at index 0 should be processed in order.
+ */
+ if (i > 0)
+ tool->ordered_events = false;
+
+ err = __perf_session__process_events(session, idx->offset,
+ idx->size, size);
+ if (err < 0)
+ break;
+ }
+
+ perf_session__warn_about_errors(session);
+ return err;
+}
+
int perf_session__process_events(struct perf_session *session)
{
- u64 size = perf_data_file__size(session->file);
+ struct perf_data_file *file = session->file;
+ u64 size = perf_data_file__size(file);
int err;
if (perf_session__register_idle_thread(session) == NULL)
return -ENOMEM;
- if (!perf_data_file__is_pipe(session->file))
- err = __perf_session__process_events(session,
- session->header.data_offset,
- session->header.data_size, size);
- else
- err = __perf_session__process_pipe_events(session);
+ if (perf_data_file__is_pipe(file))
+ return __perf_session__process_pipe_events(session);
+ if (perf_has_index)
+ return __perf_session__process_indexed_events(session);
+
+ err = __perf_session__process_events(session,
+ session->header.data_offset,
+ session->header.data_size,
+ size);
+ perf_session__warn_about_errors(session);
return err;
}
--
2.6.0
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Namhyung Kim <namhyung@kernel.org> |
|---|---|
| Date | 2015-10-02 07:40 +0200 |
| Subject | [RFC/PATCH 02/38] perf tools: Save mmap_param.len instead of mask |
| Message-ID | <qf1ex-2v1-3@gated-at.bofh.it> |
| In reply to | #1237913 |
It is more convenient saving mmap length rather than (bit) mask. With
this patch, we can eliminate dependency to perf_evlist other than
getting mmap_desc for dealing with mmaps. The mask and length can be
converted using perf_evlist__mmap_mask/len().
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
tools/perf/util/evlist.c | 31 +++++++++++++++++++++++++------
1 file changed, 25 insertions(+), 6 deletions(-)
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index c5180a29db1b..e46adcd5b408 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -29,6 +29,8 @@
static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx);
static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx);
+static size_t perf_evlist__mmap_mask(size_t len);
+static size_t perf_evlist__mmap_len(size_t mask);
#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
#define SID(e, x, y) xyarray__entry(e->sample_id, x, y)
@@ -871,7 +873,9 @@ void __weak auxtrace_mmap_params__set_idx(
static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx)
{
if (evlist->mmap[idx].base != NULL) {
- munmap(evlist->mmap[idx].base, evlist->mmap_len);
+ size_t mmap_len = perf_evlist__mmap_len(evlist->mmap[idx].mask);
+
+ munmap(evlist->mmap[idx].base, mmap_len);
evlist->mmap[idx].base = NULL;
atomic_set(&evlist->mmap[idx].refcnt, 0);
}
@@ -901,8 +905,8 @@ static int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
}
struct mmap_params {
- int prot;
- int mask;
+ int prot;
+ size_t len;
struct auxtrace_mmap_params auxtrace_mp;
};
@@ -924,8 +928,8 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx,
*/
atomic_set(&evlist->mmap[idx].refcnt, 2);
evlist->mmap[idx].prev = 0;
- evlist->mmap[idx].mask = mp->mask;
- evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, mp->prot,
+ evlist->mmap[idx].mask = perf_evlist__mmap_mask(mp->len);
+ evlist->mmap[idx].base = mmap(NULL, mp->len, mp->prot,
MAP_SHARED, fd, 0);
if (evlist->mmap[idx].base == MAP_FAILED) {
pr_debug2("failed to mmap perf event ring buffer, error %d\n",
@@ -1071,6 +1075,21 @@ static size_t perf_evlist__mmap_size(unsigned long pages)
return (pages + 1) * page_size;
}
+static size_t perf_evlist__mmap_mask(size_t len)
+{
+ BUG_ON(len <= page_size);
+ BUG_ON((len % page_size) != 0);
+
+ return len - page_size - 1;
+}
+
+static size_t perf_evlist__mmap_len(size_t mask)
+{
+ BUG_ON(((mask + 1) % page_size) != 0);
+
+ return mask + 1 + page_size;
+}
+
static long parse_pages_arg(const char *str, unsigned long min,
unsigned long max)
{
@@ -1176,7 +1195,7 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,
evlist->overwrite = overwrite;
evlist->mmap_len = perf_evlist__mmap_size(pages);
pr_debug("mmap size %zuB\n", evlist->mmap_len);
- mp.mask = evlist->mmap_len - page_size - 1;
+ mp.len = evlist->mmap_len;
auxtrace_mmap_params__init(&mp.auxtrace_mp, evlist->mmap_len,
auxtrace_pages, auxtrace_overwrite);
--
2.6.0
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Arnaldo Carvalho de Melo <acme@kernel.org> |
|---|---|
| Date | 2015-10-02 20:50 +0200 |
| Subject | Re: [RFC/PATCH 02/38] perf tools: Save mmap_param.len instead of mask |
| Message-ID | <qfdz3-3iS-11@gated-at.bofh.it> |
| In reply to | #1237936 |
Em Fri, Oct 02, 2015 at 02:18:43PM +0900, Namhyung Kim escreveu:
> It is more convenient saving mmap length rather than (bit) mask. With
> this patch, we can eliminate dependency to perf_evlist other than
> getting mmap_desc for dealing with mmaps. The mask and length can be
> converted using perf_evlist__mmap_mask/len().
>
> Cc: Jiri Olsa <jolsa@redhat.com>
> Cc: Adrian Hunter <adrian.hunter@intel.com>
> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
> ---
> tools/perf/util/evlist.c | 31 +++++++++++++++++++++++++------
> 1 file changed, 25 insertions(+), 6 deletions(-)
>
> diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
> index c5180a29db1b..e46adcd5b408 100644
> --- a/tools/perf/util/evlist.c
> +++ b/tools/perf/util/evlist.c
> @@ -29,6 +29,8 @@
>
> static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx);
> static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx);
> +static size_t perf_evlist__mmap_mask(size_t len);
> +static size_t perf_evlist__mmap_len(size_t mask);
Are these "perf_evlist" methods? I don't think so, those are related to
"perf_mmap".
> #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
> #define SID(e, x, y) xyarray__entry(e->sample_id, x, y)
> @@ -871,7 +873,9 @@ void __weak auxtrace_mmap_params__set_idx(
> static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx)
> {
> if (evlist->mmap[idx].base != NULL) {
> - munmap(evlist->mmap[idx].base, evlist->mmap_len);
> + size_t mmap_len = perf_evlist__mmap_len(evlist->mmap[idx].mask);
I.e. here you could have it as:
size_t mmap_len = perf_mmap__len(evlist->mmap[idx]);
> +
> + munmap(evlist->mmap[idx].base, mmap_len);
> evlist->mmap[idx].base = NULL;
> atomic_set(&evlist->mmap[idx].refcnt, 0);
> }
> @@ -901,8 +905,8 @@ static int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
> }
>
> struct mmap_params {
> - int prot;
> - int mask;
> + int prot;
> + size_t len;
> struct auxtrace_mmap_params auxtrace_mp;
> };
>
> @@ -924,8 +928,8 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx,
> */
> atomic_set(&evlist->mmap[idx].refcnt, 2);
> evlist->mmap[idx].prev = 0;
> - evlist->mmap[idx].mask = mp->mask;
> - evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, mp->prot,
> + evlist->mmap[idx].mask = perf_evlist__mmap_mask(mp->len);
Here, since you're not using a perf_mmap instance, but the calculation
is relative to a perf_mmap property, we would use:
evlist->mmap[idx].mask = __perf_mmap__mask(mp->len);
> + evlist->mmap[idx].base = mmap(NULL, mp->len, mp->prot,
> MAP_SHARED, fd, 0);
> if (evlist->mmap[idx].base == MAP_FAILED) {
> pr_debug2("failed to mmap perf event ring buffer, error %d\n",
> @@ -1071,6 +1075,21 @@ static size_t perf_evlist__mmap_size(unsigned long pages)
> return (pages + 1) * page_size;
> }
>
> +static size_t perf_evlist__mmap_mask(size_t len)
> +{
> + BUG_ON(len <= page_size);
> + BUG_ON((len % page_size) != 0);
> +
> + return len - page_size - 1;
> +}
> +
> +static size_t perf_evlist__mmap_len(size_t mask)
> +{
> + BUG_ON(((mask + 1) % page_size) != 0);
> +
> + return mask + 1 + page_size;
> +}
> +
> static long parse_pages_arg(const char *str, unsigned long min,
> unsigned long max)
> {
> @@ -1176,7 +1195,7 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,
> evlist->overwrite = overwrite;
> evlist->mmap_len = perf_evlist__mmap_size(pages);
> pr_debug("mmap size %zuB\n", evlist->mmap_len);
> - mp.mask = evlist->mmap_len - page_size - 1;
> + mp.len = evlist->mmap_len;
>
> auxtrace_mmap_params__init(&mp.auxtrace_mp, evlist->mmap_len,
> auxtrace_pages, auxtrace_overwrite);
> --
> 2.6.0
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Namhyung Kim <namhyung@kernel.org> |
|---|---|
| Date | 2015-10-02 07:40 +0200 |
| Subject | [RFC/PATCH 07/38] perf tools: Add HEADER_DATA_INDEX feature |
| Message-ID | <qf1ex-2v1-5@gated-at.bofh.it> |
| In reply to | #1237913 |
The HEADER_DATA_INDEX feature is to record index table for sample data
so that they can be processed by multiple thread concurrently. Each
item is a struct perf_file_section which consists of an offset and size.
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
tools/perf/builtin-record.c | 2 ++
tools/perf/util/header.c | 64 +++++++++++++++++++++++++++++++++++++++++++++
tools/perf/util/header.h | 3 +++
3 files changed, 69 insertions(+)
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 90b1237d2525..623984c81478 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -451,6 +451,8 @@ static void record__init_features(struct record *rec)
if (!rec->opts.full_auxtrace)
perf_header__clear_feat(&session->header, HEADER_AUXTRACE);
+
+ perf_header__clear_feat(&session->header, HEADER_DATA_INDEX);
}
static volatile int workload_exec_errno;
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 43838003c1a1..c357f7f47d32 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -868,6 +868,24 @@ static int write_auxtrace(int fd, struct perf_header *h,
return err;
}
+static int write_data_index(int fd, struct perf_header *h,
+ struct perf_evlist *evlist __maybe_unused)
+{
+ int ret;
+ unsigned i;
+
+ ret = do_write(fd, &h->nr_index, sizeof(h->nr_index));
+ if (ret < 0)
+ return ret;
+
+ for (i = 0; i < h->nr_index; i++) {
+ ret = do_write(fd, &h->index[i], sizeof(*h->index));
+ if (ret < 0)
+ return ret;
+ }
+ return 0;
+}
+
static void print_hostname(struct perf_header *ph, int fd __maybe_unused,
FILE *fp)
{
@@ -1221,6 +1239,12 @@ static void print_group_desc(struct perf_header *ph, int fd __maybe_unused,
}
}
+static void print_data_index(struct perf_header *ph __maybe_unused,
+ int fd __maybe_unused, FILE *fp)
+{
+ fprintf(fp, "# contains data index for parallel processing\n");
+}
+
static int __event_process_build_id(struct build_id_event *bev,
char *filename,
struct perf_session *session)
@@ -1891,6 +1915,7 @@ out_free:
return ret;
}
+
static int process_auxtrace(struct perf_file_section *section,
struct perf_header *ph, int fd,
void *data __maybe_unused)
@@ -1907,6 +1932,44 @@ static int process_auxtrace(struct perf_file_section *section,
return err;
}
+static int process_data_index(struct perf_file_section *section __maybe_unused,
+ struct perf_header *ph, int fd,
+ void *data __maybe_unused)
+{
+ ssize_t ret;
+ u64 nr_idx;
+ unsigned i;
+ struct perf_file_section *idx;
+
+ ret = readn(fd, &nr_idx, sizeof(nr_idx));
+ if (ret != sizeof(nr_idx))
+ return -1;
+
+ if (ph->needs_swap)
+ nr_idx = bswap_64(nr_idx);
+
+ idx = calloc(nr_idx, sizeof(*idx));
+ if (idx == NULL)
+ return -1;
+
+ for (i = 0; i < nr_idx; i++) {
+ ret = readn(fd, &idx[i], sizeof(*idx));
+ if (ret != sizeof(*idx)) {
+ free(idx);
+ return -1;
+ }
+
+ if (ph->needs_swap) {
+ idx[i].offset = bswap_64(idx[i].offset);
+ idx[i].size = bswap_64(idx[i].size);
+ }
+ }
+
+ ph->index = idx;
+ ph->nr_index = nr_idx;
+ return 0;
+}
+
struct feature_ops {
int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist);
void (*print)(struct perf_header *h, int fd, FILE *fp);
@@ -1948,6 +2011,7 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
FEAT_OPP(HEADER_PMU_MAPPINGS, pmu_mappings),
FEAT_OPP(HEADER_GROUP_DESC, group_desc),
FEAT_OPP(HEADER_AUXTRACE, auxtrace),
+ FEAT_OPP(HEADER_DATA_INDEX, data_index),
};
struct header_print_data {
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 05f27cb6b7e3..add455a7abff 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -31,6 +31,7 @@ enum {
HEADER_PMU_MAPPINGS,
HEADER_GROUP_DESC,
HEADER_AUXTRACE,
+ HEADER_DATA_INDEX,
HEADER_LAST_FEATURE,
HEADER_FEAT_BITS = 256,
};
@@ -71,6 +72,8 @@ struct perf_header {
bool needs_swap;
u64 data_offset;
u64 data_size;
+ struct perf_file_section *index;
+ u64 nr_index;
u64 feat_offset;
DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS);
struct perf_env env;
--
2.6.0
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Namhyung Kim <namhyung@kernel.org> |
|---|---|
| Date | 2015-10-02 07:40 +0200 |
| Subject | [RFC/PATCH 10/38] perf report: Skip dummy tracking event |
| Message-ID | <qf1ey-2v1-15@gated-at.bofh.it> |
| In reply to | #1237913 |
The dummy tracking event is only for tracking task/comom/mmap events
and has no sample data for itself. So no need to report, just skip it.
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
tools/perf/builtin-report.c | 3 +++
tools/perf/ui/browsers/hists.c | 30 ++++++++++++++++++++++++------
tools/perf/ui/gtk/hists.c | 3 +++
3 files changed, 30 insertions(+), 6 deletions(-)
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index b5623639f67d..aeced4fa27e8 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -362,6 +362,9 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
struct hists *hists = evsel__hists(pos);
const char *evname = perf_evsel__name(pos);
+ if (perf_evsel__is_dummy_tracking(pos))
+ continue;
+
if (symbol_conf.event_group &&
!perf_evsel__is_group_leader(pos))
continue;
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index a4e9b370c037..c8227dbb0fcc 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -2219,14 +2219,17 @@ out:
return key;
}
-static bool filter_group_entries(struct ui_browser *browser __maybe_unused,
- void *entry)
+static bool filter_entries(struct ui_browser *browser __maybe_unused,
+ void *entry)
{
struct perf_evsel *evsel = list_entry(entry, struct perf_evsel, node);
if (symbol_conf.event_group && !perf_evsel__is_group_leader(evsel))
return true;
+ if (perf_evsel__is_dummy_tracking(evsel))
+ return true;
+
return false;
}
@@ -2243,7 +2246,7 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist,
.refresh = ui_browser__list_head_refresh,
.seek = ui_browser__list_head_seek,
.write = perf_evsel_menu__write,
- .filter = filter_group_entries,
+ .filter = filter_entries,
.nr_entries = nr_entries,
.priv = evlist,
},
@@ -2270,21 +2273,22 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
struct perf_env *env)
{
int nr_entries = evlist->nr_entries;
+ struct perf_evsel *first = perf_evlist__first(evlist);
+ struct perf_evsel *pos;
single_entry:
if (nr_entries == 1) {
- struct perf_evsel *first = perf_evlist__first(evlist);
-
return perf_evsel__hists_browse(first, nr_entries, help,
false, hbt, min_pcnt,
env);
}
if (symbol_conf.event_group) {
- struct perf_evsel *pos;
nr_entries = 0;
evlist__for_each(evlist, pos) {
+ if (perf_evsel__is_dummy_tracking(pos))
+ continue;
if (perf_evsel__is_group_leader(pos))
nr_entries++;
}
@@ -2293,6 +2297,20 @@ single_entry:
goto single_entry;
}
+ evlist__for_each(evlist, pos) {
+ if (perf_evsel__is_dummy_tracking(pos))
+ nr_entries--;
+ }
+
+ if (nr_entries == 1) {
+ evlist__for_each(evlist, pos) {
+ if (!perf_evsel__is_dummy_tracking(pos)) {
+ first = pos;
+ goto single_entry;
+ }
+ }
+ }
+
return __perf_evlist__tui_browse_hists(evlist, nr_entries, help,
hbt, min_pcnt, env);
}
diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
index 4b3585eed1e8..83a7ecd5cda8 100644
--- a/tools/perf/ui/gtk/hists.c
+++ b/tools/perf/ui/gtk/hists.c
@@ -317,6 +317,9 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
char buf[512];
size_t size = sizeof(buf);
+ if (perf_evsel__is_dummy_tracking(pos))
+ continue;
+
if (symbol_conf.event_group) {
if (!perf_evsel__is_group_leader(pos))
continue;
--
2.6.0
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Namhyung Kim <namhyung@kernel.org> |
|---|---|
| Date | 2015-10-02 07:40 +0200 |
| Subject | [RFC/PATCH 03/38] perf tools: Move auxtrace_mmap field to struct perf_evlist |
| Message-ID | <qf1ey-2v1-17@gated-at.bofh.it> |
| In reply to | #1237913 |
Since it's gonna share struct mmap with dummy tracking evsel to track
meta events only, let's move auxtrace out of struct perf_mmap.
Cc: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
tools/perf/builtin-record.c | 4 ++--
tools/perf/util/evlist.c | 30 +++++++++++++++++++++---------
tools/perf/util/evlist.h | 2 +-
3 files changed, 24 insertions(+), 12 deletions(-)
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 5e01c070dbf2..0accac6e0812 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -220,7 +220,7 @@ static int record__auxtrace_read_snapshot_all(struct record *rec)
for (i = 0; i < rec->evlist->nr_mmaps; i++) {
struct auxtrace_mmap *mm =
- &rec->evlist->mmap[i].auxtrace_mmap;
+ &rec->evlist->auxtrace_mmap[i];
if (!mm->base)
continue;
@@ -405,7 +405,7 @@ static int record__mmap_read_all(struct record *rec)
int rc = 0;
for (i = 0; i < rec->evlist->nr_mmaps; i++) {
- struct auxtrace_mmap *mm = &rec->evlist->mmap[i].auxtrace_mmap;
+ struct auxtrace_mmap *mm = &rec->evlist->auxtrace_mmap[i];
if (rec->evlist->mmap[i].base) {
if (record__mmap_read(rec, i) != 0) {
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index e46adcd5b408..042dffc67986 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -810,9 +810,12 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
return event;
}
-static bool perf_mmap__empty(struct perf_mmap *md)
+static bool perf_evlist__mmap_empty(struct perf_evlist *evlist, int idx)
{
- return perf_mmap__read_head(md) == md->prev && !md->auxtrace_mmap.base;
+ struct perf_mmap *md = &evlist->mmap[idx];
+
+ return perf_mmap__read_head(md) == md->prev &&
+ evlist->auxtrace_mmap[idx].base == NULL;
}
static void perf_evlist__mmap_get(struct perf_evlist *evlist, int idx)
@@ -838,7 +841,7 @@ void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx)
perf_mmap__write_tail(md, old);
}
- if (atomic_read(&md->refcnt) == 1 && perf_mmap__empty(md))
+ if (atomic_read(&md->refcnt) == 1 && perf_evlist__mmap_empty(evlist, idx))
perf_evlist__mmap_put(evlist, idx);
}
@@ -879,7 +882,7 @@ static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx)
evlist->mmap[idx].base = NULL;
atomic_set(&evlist->mmap[idx].refcnt, 0);
}
- auxtrace_mmap__munmap(&evlist->mmap[idx].auxtrace_mmap);
+ auxtrace_mmap__munmap(&evlist->auxtrace_mmap[idx]);
}
void perf_evlist__munmap(struct perf_evlist *evlist)
@@ -901,7 +904,15 @@ static int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
if (cpu_map__empty(evlist->cpus))
evlist->nr_mmaps = thread_map__nr(evlist->threads);
evlist->mmap = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap));
- return evlist->mmap != NULL ? 0 : -ENOMEM;
+ if (evlist->mmap == NULL)
+ return -ENOMEM;
+ evlist->auxtrace_mmap = calloc(evlist->nr_mmaps,
+ sizeof(struct auxtrace_mmap));
+ if (evlist->auxtrace_mmap == NULL) {
+ zfree(&evlist->mmap);
+ return -ENOMEM;
+ }
+ return 0;
}
struct mmap_params {
@@ -938,10 +949,6 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx,
return -1;
}
- if (auxtrace_mmap__mmap(&evlist->mmap[idx].auxtrace_mmap,
- &mp->auxtrace_mp, evlist->mmap[idx].base, fd))
- return -1;
-
return 0;
}
@@ -963,6 +970,11 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
*output = fd;
if (__perf_evlist__mmap(evlist, idx, mp, *output) < 0)
return -1;
+
+ if (auxtrace_mmap__mmap(&evlist->auxtrace_mmap[idx],
+ &mp->auxtrace_mp,
+ evlist->mmap[idx].base, fd))
+ return -1;
} else {
if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0)
return -1;
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 414e383885f5..51574ce8ac69 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -30,7 +30,6 @@ struct perf_mmap {
int mask;
atomic_t refcnt;
u64 prev;
- struct auxtrace_mmap auxtrace_mmap;
char event_copy[PERF_SAMPLE_MAX_SIZE] __attribute__((aligned(8)));
};
@@ -53,6 +52,7 @@ struct perf_evlist {
} workload;
struct fdarray pollfd;
struct perf_mmap *mmap;
+ struct auxtrace_mmap *auxtrace_mmap;
struct thread_map *threads;
struct cpu_map *cpus;
struct perf_evsel *selected;
--
2.6.0
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Arnaldo Carvalho de Melo <acme@kernel.org> |
|---|---|
| Date | 2015-10-02 20:50 +0200 |
| Subject | Re: [RFC/PATCH 03/38] perf tools: Move auxtrace_mmap field to struct perf_evlist |
| Message-ID | <qfdz4-3iS-17@gated-at.bofh.it> |
| In reply to | #1237940 |
Em Fri, Oct 02, 2015 at 02:18:44PM +0900, Namhyung Kim escreveu:
> Since it's gonna share struct mmap with dummy tracking evsel to track
> meta events only, let's move auxtrace out of struct perf_mmap.
Is this moving around _strictly_ needed?
- Arnaldo
> Cc: Adrian Hunter <adrian.hunter@intel.com>
> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
> ---
> tools/perf/builtin-record.c | 4 ++--
> tools/perf/util/evlist.c | 30 +++++++++++++++++++++---------
> tools/perf/util/evlist.h | 2 +-
> 3 files changed, 24 insertions(+), 12 deletions(-)
>
> diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
> index 5e01c070dbf2..0accac6e0812 100644
> --- a/tools/perf/builtin-record.c
> +++ b/tools/perf/builtin-record.c
> @@ -220,7 +220,7 @@ static int record__auxtrace_read_snapshot_all(struct record *rec)
>
> for (i = 0; i < rec->evlist->nr_mmaps; i++) {
> struct auxtrace_mmap *mm =
> - &rec->evlist->mmap[i].auxtrace_mmap;
> + &rec->evlist->auxtrace_mmap[i];
>
> if (!mm->base)
> continue;
> @@ -405,7 +405,7 @@ static int record__mmap_read_all(struct record *rec)
> int rc = 0;
>
> for (i = 0; i < rec->evlist->nr_mmaps; i++) {
> - struct auxtrace_mmap *mm = &rec->evlist->mmap[i].auxtrace_mmap;
> + struct auxtrace_mmap *mm = &rec->evlist->auxtrace_mmap[i];
>
> if (rec->evlist->mmap[i].base) {
> if (record__mmap_read(rec, i) != 0) {
> diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
> index e46adcd5b408..042dffc67986 100644
> --- a/tools/perf/util/evlist.c
> +++ b/tools/perf/util/evlist.c
> @@ -810,9 +810,12 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
> return event;
> }
>
> -static bool perf_mmap__empty(struct perf_mmap *md)
> +static bool perf_evlist__mmap_empty(struct perf_evlist *evlist, int idx)
> {
> - return perf_mmap__read_head(md) == md->prev && !md->auxtrace_mmap.base;
> + struct perf_mmap *md = &evlist->mmap[idx];
> +
> + return perf_mmap__read_head(md) == md->prev &&
> + evlist->auxtrace_mmap[idx].base == NULL;
> }
>
> static void perf_evlist__mmap_get(struct perf_evlist *evlist, int idx)
> @@ -838,7 +841,7 @@ void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx)
> perf_mmap__write_tail(md, old);
> }
>
> - if (atomic_read(&md->refcnt) == 1 && perf_mmap__empty(md))
> + if (atomic_read(&md->refcnt) == 1 && perf_evlist__mmap_empty(evlist, idx))
> perf_evlist__mmap_put(evlist, idx);
> }
>
> @@ -879,7 +882,7 @@ static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx)
> evlist->mmap[idx].base = NULL;
> atomic_set(&evlist->mmap[idx].refcnt, 0);
> }
> - auxtrace_mmap__munmap(&evlist->mmap[idx].auxtrace_mmap);
> + auxtrace_mmap__munmap(&evlist->auxtrace_mmap[idx]);
> }
>
> void perf_evlist__munmap(struct perf_evlist *evlist)
> @@ -901,7 +904,15 @@ static int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
> if (cpu_map__empty(evlist->cpus))
> evlist->nr_mmaps = thread_map__nr(evlist->threads);
> evlist->mmap = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap));
> - return evlist->mmap != NULL ? 0 : -ENOMEM;
> + if (evlist->mmap == NULL)
> + return -ENOMEM;
> + evlist->auxtrace_mmap = calloc(evlist->nr_mmaps,
> + sizeof(struct auxtrace_mmap));
> + if (evlist->auxtrace_mmap == NULL) {
> + zfree(&evlist->mmap);
> + return -ENOMEM;
> + }
> + return 0;
> }
>
> struct mmap_params {
> @@ -938,10 +949,6 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx,
> return -1;
> }
>
> - if (auxtrace_mmap__mmap(&evlist->mmap[idx].auxtrace_mmap,
> - &mp->auxtrace_mp, evlist->mmap[idx].base, fd))
> - return -1;
> -
> return 0;
> }
>
> @@ -963,6 +970,11 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
> *output = fd;
> if (__perf_evlist__mmap(evlist, idx, mp, *output) < 0)
> return -1;
> +
> + if (auxtrace_mmap__mmap(&evlist->auxtrace_mmap[idx],
> + &mp->auxtrace_mp,
> + evlist->mmap[idx].base, fd))
> + return -1;
> } else {
> if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0)
> return -1;
> diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
> index 414e383885f5..51574ce8ac69 100644
> --- a/tools/perf/util/evlist.h
> +++ b/tools/perf/util/evlist.h
> @@ -30,7 +30,6 @@ struct perf_mmap {
> int mask;
> atomic_t refcnt;
> u64 prev;
> - struct auxtrace_mmap auxtrace_mmap;
> char event_copy[PERF_SAMPLE_MAX_SIZE] __attribute__((aligned(8)));
> };
>
> @@ -53,6 +52,7 @@ struct perf_evlist {
> } workload;
> struct fdarray pollfd;
> struct perf_mmap *mmap;
> + struct auxtrace_mmap *auxtrace_mmap;
> struct thread_map *threads;
> struct cpu_map *cpus;
> struct perf_evsel *selected;
> --
> 2.6.0
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Adrian Hunter <adrian.hunter@intel.com> |
|---|---|
| Date | 2015-10-05 13:40 +0200 |
| Subject | Re: [RFC/PATCH 03/38] perf tools: Move auxtrace_mmap field to struct perf_evlist |
| Message-ID | <qgchz-64T-1@gated-at.bofh.it> |
| In reply to | #1238523 |
On 02/10/15 21:45, Arnaldo Carvalho de Melo wrote:
> Em Fri, Oct 02, 2015 at 02:18:44PM +0900, Namhyung Kim escreveu:
>> Since it's gonna share struct mmap with dummy tracking evsel to track
>> meta events only, let's move auxtrace out of struct perf_mmap.
> Is this moving around _strictly_ needed?
Also, what if you wanted to capture AUX data and tracking together.
In addition, currently Intel PT can have either 1 dummy event for tracking
plus sched_switch
or 2 dummy events to allow for system-wide tracking of context switches.
i.e. there
are multiple tracking events.
>
> - Arnaldo
>
>> Cc: Adrian Hunter <adrian.hunter@intel.com>
>> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
>> ---
>> tools/perf/builtin-record.c | 4 ++--
>> tools/perf/util/evlist.c | 30 +++++++++++++++++++++---------
>> tools/perf/util/evlist.h | 2 +-
>> 3 files changed, 24 insertions(+), 12 deletions(-)
>>
>> diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
>> index 5e01c070dbf2..0accac6e0812 100644
>> --- a/tools/perf/builtin-record.c
>> +++ b/tools/perf/builtin-record.c
>> @@ -220,7 +220,7 @@ static int record__auxtrace_read_snapshot_all(struct record *rec)
>>
>> for (i = 0; i < rec->evlist->nr_mmaps; i++) {
>> struct auxtrace_mmap *mm =
>> - &rec->evlist->mmap[i].auxtrace_mmap;
>> + &rec->evlist->auxtrace_mmap[i];
>>
>> if (!mm->base)
>> continue;
>> @@ -405,7 +405,7 @@ static int record__mmap_read_all(struct record *rec)
>> int rc = 0;
>>
>> for (i = 0; i < rec->evlist->nr_mmaps; i++) {
>> - struct auxtrace_mmap *mm = &rec->evlist->mmap[i].auxtrace_mmap;
>> + struct auxtrace_mmap *mm = &rec->evlist->auxtrace_mmap[i];
>>
>> if (rec->evlist->mmap[i].base) {
>> if (record__mmap_read(rec, i) != 0) {
>> diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
>> index e46adcd5b408..042dffc67986 100644
>> --- a/tools/perf/util/evlist.c
>> +++ b/tools/perf/util/evlist.c
>> @@ -810,9 +810,12 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
>> return event;
>> }
>>
>> -static bool perf_mmap__empty(struct perf_mmap *md)
>> +static bool perf_evlist__mmap_empty(struct perf_evlist *evlist, int idx)
>> {
>> - return perf_mmap__read_head(md) == md->prev && !md->auxtrace_mmap.base;
>> + struct perf_mmap *md = &evlist->mmap[idx];
>> +
>> + return perf_mmap__read_head(md) == md->prev &&
>> + evlist->auxtrace_mmap[idx].base == NULL;
>> }
>>
>> static void perf_evlist__mmap_get(struct perf_evlist *evlist, int idx)
>> @@ -838,7 +841,7 @@ void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx)
>> perf_mmap__write_tail(md, old);
>> }
>>
>> - if (atomic_read(&md->refcnt) == 1 && perf_mmap__empty(md))
>> + if (atomic_read(&md->refcnt) == 1 && perf_evlist__mmap_empty(evlist, idx))
>> perf_evlist__mmap_put(evlist, idx);
>> }
>>
>> @@ -879,7 +882,7 @@ static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx)
>> evlist->mmap[idx].base = NULL;
>> atomic_set(&evlist->mmap[idx].refcnt, 0);
>> }
>> - auxtrace_mmap__munmap(&evlist->mmap[idx].auxtrace_mmap);
>> + auxtrace_mmap__munmap(&evlist->auxtrace_mmap[idx]);
>> }
>>
>> void perf_evlist__munmap(struct perf_evlist *evlist)
>> @@ -901,7 +904,15 @@ static int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
>> if (cpu_map__empty(evlist->cpus))
>> evlist->nr_mmaps = thread_map__nr(evlist->threads);
>> evlist->mmap = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap));
>> - return evlist->mmap != NULL ? 0 : -ENOMEM;
>> + if (evlist->mmap == NULL)
>> + return -ENOMEM;
>> + evlist->auxtrace_mmap = calloc(evlist->nr_mmaps,
>> + sizeof(struct auxtrace_mmap));
>> + if (evlist->auxtrace_mmap == NULL) {
>> + zfree(&evlist->mmap);
>> + return -ENOMEM;
>> + }
>> + return 0;
>> }
>>
>> struct mmap_params {
>> @@ -938,10 +949,6 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx,
>> return -1;
>> }
>>
>> - if (auxtrace_mmap__mmap(&evlist->mmap[idx].auxtrace_mmap,
>> - &mp->auxtrace_mp, evlist->mmap[idx].base, fd))
>> - return -1;
>> -
>> return 0;
>> }
>>
>> @@ -963,6 +970,11 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
>> *output = fd;
>> if (__perf_evlist__mmap(evlist, idx, mp, *output) < 0)
>> return -1;
>> +
>> + if (auxtrace_mmap__mmap(&evlist->auxtrace_mmap[idx],
>> + &mp->auxtrace_mp,
>> + evlist->mmap[idx].base, fd))
>> + return -1;
>> } else {
>> if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0)
>> return -1;
>> diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
>> index 414e383885f5..51574ce8ac69 100644
>> --- a/tools/perf/util/evlist.h
>> +++ b/tools/perf/util/evlist.h
>> @@ -30,7 +30,6 @@ struct perf_mmap {
>> int mask;
>> atomic_t refcnt;
>> u64 prev;
>> - struct auxtrace_mmap auxtrace_mmap;
>> char event_copy[PERF_SAMPLE_MAX_SIZE] __attribute__((aligned(8)));
>> };
>>
>> @@ -53,6 +52,7 @@ struct perf_evlist {
>> } workload;
>> struct fdarray pollfd;
>> struct perf_mmap *mmap;
>> + struct auxtrace_mmap *auxtrace_mmap;
>> struct thread_map *threads;
>> struct cpu_map *cpus;
>> struct perf_evsel *selected;
>> --
>> 2.6.0
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Jiri Olsa <jolsa@redhat.com> |
|---|---|
| Date | 2015-10-05 15:20 +0200 |
| Subject | Re: [RFC/PATCH 03/38] perf tools: Move auxtrace_mmap field to struct perf_evlist |
| Message-ID | <qgdQm-8oB-9@gated-at.bofh.it> |
| In reply to | #1237940 |
On Fri, Oct 02, 2015 at 02:18:44PM +0900, Namhyung Kim wrote:
SNIP
> @@ -838,7 +841,7 @@ void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx)
> perf_mmap__write_tail(md, old);
> }
>
> - if (atomic_read(&md->refcnt) == 1 && perf_mmap__empty(md))
> + if (atomic_read(&md->refcnt) == 1 && perf_evlist__mmap_empty(evlist, idx))
> perf_evlist__mmap_put(evlist, idx);
> }
>
> @@ -879,7 +882,7 @@ static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx)
> evlist->mmap[idx].base = NULL;
> atomic_set(&evlist->mmap[idx].refcnt, 0);
> }
> - auxtrace_mmap__munmap(&evlist->mmap[idx].auxtrace_mmap);
> + auxtrace_mmap__munmap(&evlist->auxtrace_mmap[idx]);
> }
>
> void perf_evlist__munmap(struct perf_evlist *evlist)
> @@ -901,7 +904,15 @@ static int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
> if (cpu_map__empty(evlist->cpus))
> evlist->nr_mmaps = thread_map__nr(evlist->threads);
> evlist->mmap = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap));
> - return evlist->mmap != NULL ? 0 : -ENOMEM;
> + if (evlist->mmap == NULL)
> + return -ENOMEM;
> + evlist->auxtrace_mmap = calloc(evlist->nr_mmaps,
> + sizeof(struct auxtrace_mmap));
> + if (evlist->auxtrace_mmap == NULL) {
> + zfree(&evlist->mmap);
> + return -ENOMEM;
> + }
can't see evlist->auxtrace_mmap being freed
jirka
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Namhyung Kim <namhyung@kernel.org> |
|---|---|
| Date | 2015-10-02 07:40 +0200 |
| Subject | [RFC/PATCH 05/38] perf tools: Create separate mmap for dummy tracking event |
| Message-ID | <qf1ey-2v1-19@gated-at.bofh.it> |
| In reply to | #1237913 |
When indexed data file support is enabled, a dummy tracking event will
be used to track metadata (like task, comm and mmap events) for a
session and actual samples will be recorded in separate (intermediate)
files and then merged (with index table).
Provide separate mmap to the dummy tracking event. The size is fixed
to 128KiB (+ 1 page) as the event rate will be lower than samples. I
originally wanted to use a single mmap for this but cross-cpu sharing
is prohibited so it's per-cpu (or per-task) like normal mmaps.
Cc: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
tools/perf/builtin-record.c | 2 +-
tools/perf/util/evlist.c | 106 ++++++++++++++++++++++++++++++++++----------
tools/perf/util/evlist.h | 9 ++++
3 files changed, 93 insertions(+), 24 deletions(-)
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 0accac6e0812..33dc2eafe2b5 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -74,7 +74,7 @@ static int process_synthesized_event(struct perf_tool *tool,
static int record__mmap_read(struct record *rec, int idx)
{
- struct perf_mmap *md = &rec->evlist->mmap[idx];
+ struct perf_mmap *md = perf_evlist__mmap_desc(rec->evlist, idx);
u64 head = perf_mmap__read_head(md);
u64 old = md->prev;
unsigned char *data = md->base + page_size;
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 8d31883cbeb8..25a9c3b5f473 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -743,7 +743,7 @@ static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist,
union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
{
- struct perf_mmap *md = &evlist->mmap[idx];
+ struct perf_mmap *md = perf_evlist__mmap_desc(evlist, idx);
u64 head;
u64 old = md->prev;
unsigned char *data = md->base + page_size;
@@ -812,28 +812,38 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
static bool perf_evlist__mmap_empty(struct perf_evlist *evlist, int idx)
{
- struct perf_mmap *md = &evlist->mmap[idx];
+ struct perf_mmap *md = perf_evlist__mmap_desc(evlist, idx);
- return perf_mmap__read_head(md) == md->prev &&
- evlist->auxtrace_mmap[idx].base == NULL;
+ if (perf_mmap__read_head(md) != md->prev)
+ return false;
+
+ if (idx >= 0)
+ return !evlist->auxtrace_mmap[idx].base;
+ return true;
}
static void perf_evlist__mmap_get(struct perf_evlist *evlist, int idx)
{
- atomic_inc(&evlist->mmap[idx].refcnt);
+ struct perf_mmap *md = perf_evlist__mmap_desc(evlist, idx);
+
+ atomic_inc(&md->refcnt);
}
static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx)
{
- BUG_ON(atomic_read(&evlist->mmap[idx].refcnt) == 0);
+ struct perf_mmap *md = perf_evlist__mmap_desc(evlist, idx);
+
+ BUG_ON(atomic_read(&md->refcnt) == 0);
- if (atomic_dec_and_test(&evlist->mmap[idx].refcnt))
- __perf_evlist__munmap(evlist, idx);
+ if (!atomic_dec_and_test(&md->refcnt))
+ return;
+
+ __perf_evlist__munmap(evlist, idx);
}
void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx)
{
- struct perf_mmap *md = &evlist->mmap[idx];
+ struct perf_mmap *md = perf_evlist__mmap_desc(evlist, idx);
if (!evlist->overwrite) {
u64 old = md->prev;
@@ -875,14 +885,15 @@ void __weak auxtrace_mmap_params__set_idx(
static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx)
{
- if (evlist->mmap[idx].base != NULL) {
- size_t mmap_len = perf_evlist__mmap_len(evlist->mmap[idx].mask);
+ struct perf_mmap *md = perf_evlist__mmap_desc(evlist, idx);
+
+ if (md->base != NULL) {
+ size_t mmap_len = perf_evlist__mmap_len(md->mask);
- munmap(evlist->mmap[idx].base, mmap_len);
- evlist->mmap[idx].base = NULL;
- atomic_set(&evlist->mmap[idx].refcnt, 0);
+ munmap(md->base, mmap_len);
+ md->base = NULL;
+ atomic_set(&md->refcnt, 0);
}
- auxtrace_mmap__munmap(&evlist->auxtrace_mmap[idx]);
}
void perf_evlist__munmap(struct perf_evlist *evlist)
@@ -892,13 +903,17 @@ void perf_evlist__munmap(struct perf_evlist *evlist)
if (evlist->mmap == NULL)
return;
- for (i = 0; i < evlist->nr_mmaps; i++)
+ for (i = 0; i < evlist->nr_mmaps; i++) {
__perf_evlist__munmap(evlist, i);
+ auxtrace_mmap__munmap(&evlist->auxtrace_mmap[i]);
+ if (evlist->track_mmap)
+ __perf_evlist__munmap(evlist, track_mmap_idx(i));
+ }
zfree(&evlist->mmap);
}
-static int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
+static int perf_evlist__alloc_mmap(struct perf_evlist *evlist, bool track_mmap)
{
evlist->nr_mmaps = cpu_map__nr(evlist->cpus);
if (cpu_map__empty(evlist->cpus))
@@ -912,12 +927,22 @@ static int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
zfree(&evlist->mmap);
return -ENOMEM;
}
+ if (track_mmap) {
+ evlist->track_mmap = calloc(evlist->nr_mmaps,
+ sizeof(struct perf_mmap));
+ if (evlist->track_mmap == NULL) {
+ zfree(&evlist->mmap);
+ zfree(&evlist->auxtrace_mmap);
+ return -ENOMEM;
+ }
+ }
return 0;
}
struct mmap_params {
int prot;
size_t len;
+ bool track_mmap;
struct auxtrace_mmap_params auxtrace_mp;
};
@@ -954,12 +979,16 @@ static int perf_mmap__mmap(struct perf_mmap *desc,
struct perf_mmap *perf_evlist__mmap_desc(struct perf_evlist *evlist, int idx)
{
- return &evlist->mmap[idx];
+ if (idx >= 0)
+ return &evlist->mmap[idx];
+ else
+ return &evlist->track_mmap[track_mmap_idx(idx)];
}
static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
struct mmap_params *mp, int cpu,
- int thread, int *output)
+ int thread, int *output,
+ int *track_output)
{
struct perf_evsel *evsel;
@@ -972,7 +1001,30 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
fd = FD(evsel, cpu, thread);
- if (*output == -1) {
+ if (mp->track_mmap && perf_evsel__is_dummy_tracking(evsel)) {
+ size_t old_len = mp->len;
+
+ /* mark idx as track mmap idx (negative) */
+ idx = track_mmap_idx(idx);
+
+ desc = perf_evlist__mmap_desc(evlist, idx);
+ mp->len = TRACK_MMAP_SIZE;
+
+ if (*track_output == -1) {
+ *track_output = fd;
+ if (perf_mmap__mmap(desc, mp, fd) < 0)
+ return -1;
+ } else {
+ if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT,
+ *track_output) != 0)
+ return -1;
+
+ perf_evlist__mmap_get(evlist, idx);
+ }
+
+ mp->len = old_len;
+
+ } else if (*output == -1) {
*output = fd;
if (perf_mmap__mmap(desc, mp, *output) < 0)
return -1;
@@ -1008,6 +1060,11 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
perf_evlist__set_sid_idx(evlist, evsel, idx, cpu,
thread);
}
+
+ if (mp->track_mmap && perf_evsel__is_dummy_tracking(evsel)) {
+ /* restore idx as normal mmap idx (positive) */
+ idx = track_mmap_idx(idx);
+ }
}
return 0;
@@ -1023,13 +1080,15 @@ static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist,
pr_debug2("perf event ring buffer mmapped per cpu\n");
for (cpu = 0; cpu < nr_cpus; cpu++) {
int output = -1;
+ int track_output = -1;
auxtrace_mmap_params__set_idx(&mp->auxtrace_mp, evlist, cpu,
true);
for (thread = 0; thread < nr_threads; thread++) {
if (perf_evlist__mmap_per_evsel(evlist, cpu, mp, cpu,
- thread, &output))
+ thread, &output,
+ &track_output))
goto out_unmap;
}
}
@@ -1051,12 +1110,13 @@ static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist,
pr_debug2("perf event ring buffer mmapped per thread\n");
for (thread = 0; thread < nr_threads; thread++) {
int output = -1;
+ int track_output = -1;
auxtrace_mmap_params__set_idx(&mp->auxtrace_mp, evlist, thread,
false);
if (perf_evlist__mmap_per_evsel(evlist, thread, mp, 0, thread,
- &output))
+ &output, &track_output))
goto out_unmap;
}
@@ -1204,7 +1264,7 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,
.prot = PROT_READ | (overwrite ? 0 : PROT_WRITE),
};
- if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0)
+ if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist, mp.track_mmap) < 0)
return -ENOMEM;
if (evlist->pollfd.entries == NULL && perf_evlist__alloc_pollfd(evlist) < 0)
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 79f8245300ad..fc53eb817c51 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -33,6 +33,8 @@ struct perf_mmap {
char event_copy[PERF_SAMPLE_MAX_SIZE] __attribute__((aligned(8)));
};
+#define TRACK_MMAP_SIZE (((128 * 1024 / page_size) + 1) * page_size)
+
struct perf_evlist {
struct list_head entries;
struct hlist_head heads[PERF_EVLIST__HLIST_SIZE];
@@ -52,6 +54,7 @@ struct perf_evlist {
} workload;
struct fdarray pollfd;
struct perf_mmap *mmap;
+ struct perf_mmap *track_mmap;
struct auxtrace_mmap *auxtrace_mmap;
struct thread_map *threads;
struct cpu_map *cpus;
@@ -224,6 +227,12 @@ bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str);
void perf_evlist__to_front(struct perf_evlist *evlist,
struct perf_evsel *move_evsel);
+/* convert from/to negative idx for track mmap */
+static inline int track_mmap_idx(int idx)
+{
+ return -idx - 1;
+}
+
/**
* __evlist__for_each - iterate thru all the evsels
* @list: list_head instance to iterate
--
2.6.0
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [standalone]
Page 2 of 2 — ← Prev page 1 [2]
Back to top | Article view | linux.kernel
csiph-web