aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorWang Nan <wangnan0@huawei.com>2016-05-08 21:47:50 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2016-05-09 16:20:53 -0400
commite24c7520ea9c3e5bb51592c2134aafbf75a3f88a (patch)
treefe6c5e5e1f3ef7676b71a3e3b555a2a6a2647232 /tools/perf
parentaff633406ca2772554bad7b37f2dfbc409b6ea74 (diff)
perf tools: Support reading from backward ring buffer
perf_evlist__mmap_read_backward() is introduced for reading backward ring buffer. Since direction for reading such ring buffer is different from the direction kernel writing to it, and since user need to fetch most recent record from it, a perf_evlist__mmap_read_catchup() is introduced to move the reading pointer to the end of the buffer. Signed-off-by: Wang Nan <wangnan0@huawei.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Zefan Li <lizefan@huawei.com> Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/1462758471-89706-2-git-send-email-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/util/evlist.c50
-rw-r--r--tools/perf/util/evlist.h4
2 files changed, 54 insertions, 0 deletions
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 17cd01421e7f..c4bfe11479a0 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -766,6 +766,56 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
766 return perf_mmap__read(md, evlist->overwrite, old, head, &md->prev); 766 return perf_mmap__read(md, evlist->overwrite, old, head, &md->prev);
767} 767}
768 768
769union perf_event *
770perf_evlist__mmap_read_backward(struct perf_evlist *evlist, int idx)
771{
772 struct perf_mmap *md = &evlist->mmap[idx];
773 u64 head, end;
774 u64 start = md->prev;
775
776 /*
777 * Check if event was unmapped due to a POLLHUP/POLLERR.
778 */
779 if (!atomic_read(&md->refcnt))
780 return NULL;
781
782 head = perf_mmap__read_head(md);
783 if (!head)
784 return NULL;
785
786 /*
787 * 'head' pointer starts from 0. Kernel minus sizeof(record) form
788 * it each time when kernel writes to it, so in fact 'head' is
789 * negative. 'end' pointer is made manually by adding the size of
790 * the ring buffer to 'head' pointer, means the validate data can
791 * read is the whole ring buffer. If 'end' is positive, the ring
792 * buffer has not fully filled, so we must adjust 'end' to 0.
793 *
794 * However, since both 'head' and 'end' is unsigned, we can't
795 * simply compare 'end' against 0. Here we compare '-head' and
796 * the size of the ring buffer, where -head is the number of bytes
797 * kernel write to the ring buffer.
798 */
799 if (-head < (u64)(md->mask + 1))
800 end = 0;
801 else
802 end = head + md->mask + 1;
803
804 return perf_mmap__read(md, false, start, end, &md->prev);
805}
806
807void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx)
808{
809 struct perf_mmap *md = &evlist->mmap[idx];
810 u64 head;
811
812 if (!atomic_read(&md->refcnt))
813 return;
814
815 head = perf_mmap__read_head(md);
816 md->prev = head;
817}
818
769static bool perf_mmap__empty(struct perf_mmap *md) 819static bool perf_mmap__empty(struct perf_mmap *md)
770{ 820{
771 return perf_mmap__read_head(md) == md->prev && !md->auxtrace_mmap.base; 821 return perf_mmap__read_head(md) == md->prev && !md->auxtrace_mmap.base;
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 208897a646ca..85d1b59802e8 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -129,6 +129,10 @@ struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id);
129 129
130union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx); 130union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx);
131 131
132union perf_event *perf_evlist__mmap_read_backward(struct perf_evlist *evlist,
133 int idx);
134void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx);
135
132void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx); 136void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx);
133 137
134int perf_evlist__open(struct perf_evlist *evlist); 138int perf_evlist__open(struct perf_evlist *evlist);