mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: kan.liang@intel.com
To: acme@kernel.org, peterz@infradead.org, mingo@redhat.com,
	linux-kernel@vger.kernel.org
Cc: jolsa@kernel.org, wangnan0@huawei.com, namhyung@kernel.org,
	ak@linux.intel.com, yao.jin@linux.intel.com,
	Kan Liang <kan.liang@intel.com>
Subject: [PATCH V2 2/8] perf tools: rewrite perf mmap read for overwrite
Date: Wed,  6 Dec 2017 15:32:57 -0800	[thread overview]
Message-ID: <1512603183-42754-3-git-send-email-kan.liang@intel.com> (raw)
In-Reply-To: <1512603183-42754-1-git-send-email-kan.liang@intel.com>

From: Kan Liang <kan.liang@intel.com>

perf_mmap__read_catchup and perf_mmap__read_backward are used to read
events one by one from ring buffer under overwrite mode.
It always read the stale buffer which is already processed.
Because the previous location of processed ring buffer is discarded.

Introducing the perf_mmap__read_done, which update the map->prev to
indicate the position of processed buffer.

Refining perf_mmap__read_catchup to calculate the start and the end of
ring buffer. It only need to do the calculation once at the beginning,
because the ring buffer is paused in overwrite mode.
Doesn't need to do the calculation in perf_mmap__read_backward.

For now, the only user is backward-ring-buffer in perf test.

Signed-off-by: Kan Liang <kan.liang@intel.com>
---
 tools/perf/tests/backward-ring-buffer.c |  9 +++-
 tools/perf/util/mmap.c                  | 88 +++++++++++++++++++--------------
 tools/perf/util/mmap.h                  |  7 ++-
 3 files changed, 63 insertions(+), 41 deletions(-)

diff --git a/tools/perf/tests/backward-ring-buffer.c b/tools/perf/tests/backward-ring-buffer.c
index 4035d43..66d9e54 100644
--- a/tools/perf/tests/backward-ring-buffer.c
+++ b/tools/perf/tests/backward-ring-buffer.c
@@ -31,10 +31,14 @@ static int count_samples(struct perf_evlist *evlist, int *sample_count,
 	int i;
 
 	for (i = 0; i < evlist->nr_mmaps; i++) {
+		struct perf_mmap *map = &evlist->overwrite_mmap[i];
 		union perf_event *event;
+		unsigned long size;
+		u64 start, end;
 
-		perf_mmap__read_catchup(&evlist->overwrite_mmap[i]);
-		while ((event = perf_mmap__read_backward(&evlist->overwrite_mmap[i])) != NULL) {
+		perf_mmap__read_catchup(map, true, &start, &end, &size);
+		while ((event = perf_mmap__read_backward(map, &start, end)) !=
+		       NULL) {
 			const u32 type = event->header.type;
 
 			switch (type) {
@@ -49,6 +53,7 @@ static int count_samples(struct perf_evlist *evlist, int *sample_count,
 				return TEST_FAIL;
 			}
 		}
+		perf_mmap__read_done(map);
 	}
 	return TEST_OK;
 }
diff --git a/tools/perf/util/mmap.c b/tools/perf/util/mmap.c
index 05076e6..bf67460 100644
--- a/tools/perf/util/mmap.c
+++ b/tools/perf/util/mmap.c
@@ -85,51 +85,65 @@ union perf_event *perf_mmap__read_forward(struct perf_mmap *map)
 	return perf_mmap__read(map, old, head, &map->prev);
 }
 
-union perf_event *perf_mmap__read_backward(struct perf_mmap *map)
+union perf_event *perf_mmap__read_backward(struct perf_mmap *map,
+					   u64 *start, u64 end)
 {
-	u64 head, end;
-	u64 start = map->prev;
-
-	/*
-	 * Check if event was unmapped due to a POLLHUP/POLLERR.
-	 */
-	if (!refcount_read(&map->refcnt))
-		return NULL;
-
-	head = perf_mmap__read_head(map);
-	if (!head)
-		return NULL;
+	union perf_event *event = NULL;
 
-	/*
-	 * 'head' pointer starts from 0. Kernel minus sizeof(record) form
-	 * it each time when kernel writes to it, so in fact 'head' is
-	 * negative. 'end' pointer is made manually by adding the size of
-	 * the ring buffer to 'head' pointer, means the validate data can
-	 * read is the whole ring buffer. If 'end' is positive, the ring
-	 * buffer has not fully filled, so we must adjust 'end' to 0.
-	 *
-	 * However, since both 'head' and 'end' is unsigned, we can't
-	 * simply compare 'end' against 0. Here we compare '-head' and
-	 * the size of the ring buffer, where -head is the number of bytes
-	 * kernel write to the ring buffer.
-	 */
-	if (-head < (u64)(map->mask + 1))
-		end = 0;
-	else
-		end = head + map->mask + 1;
+	event = perf_mmap__read(map, *start, end, &map->prev);
+	*start = map->prev;
 
-	return perf_mmap__read(map, start, end, &map->prev);
+	return event;
 }
 
-void perf_mmap__read_catchup(struct perf_mmap *map)
+static int overwrite_rb_find_range(void *buf, int mask, u64 head,
+				   u64 *start, u64 *end);
+
+int perf_mmap__read_catchup(struct perf_mmap *map,
+			    bool overwrite,
+			    u64 *start, u64 *end,
+			    unsigned long *size)
 {
-	u64 head;
+	u64 head = perf_mmap__read_head(map);
+	u64 old = map->prev;
+	unsigned char *data = map->base + page_size;
 
-	if (!refcount_read(&map->refcnt))
-		return;
+	*start = overwrite ? head : old;
+	*end = overwrite ? old : head;
 
-	head = perf_mmap__read_head(map);
-	map->prev = head;
+	if (*start == *end)
+		return 0;
+
+	*size = *end - *start;
+	if (*size > (unsigned long)(map->mask) + 1) {
+		if (!overwrite) {
+			WARN_ONCE(1, "failed to keep up with mmap data. (warn only once)\n");
+
+			map->prev = head;
+			perf_mmap__consume(map, overwrite);
+			return 0;
+		}
+
+		/*
+		 * Backward ring buffer is full. We still have a chance to read
+		 * most of data from it.
+		 */
+		if (overwrite_rb_find_range(data, map->mask, head, start, end))
+			return -1;
+	}
+
+	return 1;
+}
+
+/*
+ * Mandatory for overwrite mode
+ * The direction of overwrite mode is backward.
+ * The last mmap__read_event will set tail to map->prev.
+ * Need to correct the map->prev to head which is the end of next read.
+ */
+void perf_mmap__read_done(struct perf_mmap *map)
+{
+	map->prev = perf_mmap__read_head(map);
 }
 
 static bool perf_mmap__empty(struct perf_mmap *map)
diff --git a/tools/perf/util/mmap.h b/tools/perf/util/mmap.h
index d640273..a91222e 100644
--- a/tools/perf/util/mmap.h
+++ b/tools/perf/util/mmap.h
@@ -65,7 +65,9 @@ void perf_mmap__put(struct perf_mmap *map);
 
 void perf_mmap__consume(struct perf_mmap *map, bool overwrite);
 
-void perf_mmap__read_catchup(struct perf_mmap *md);
+int perf_mmap__read_catchup(struct perf_mmap *map, bool overwrite,
+			    u64 *start, u64 *end, unsigned long *size);
+void perf_mmap__read_done(struct perf_mmap *map);
 
 static inline u64 perf_mmap__read_head(struct perf_mmap *mm)
 {
@@ -87,7 +89,8 @@ static inline void perf_mmap__write_tail(struct perf_mmap *md, u64 tail)
 }
 
 union perf_event *perf_mmap__read_forward(struct perf_mmap *map);
-union perf_event *perf_mmap__read_backward(struct perf_mmap *map);
+union perf_event *perf_mmap__read_backward(struct perf_mmap *map,
+					   u64 *start, u64 end);
 
 int perf_mmap__push(struct perf_mmap *md, bool backward,
 		    void *to, int push(void *to, void *buf, size_t size));
-- 
2.5.5

  parent reply	other threads:[~2017-12-06 23:34 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-12-06 23:32 [PATCH V2 0/8] perf top overwrite mode kan.liang
2017-12-06 23:32 ` [PATCH V2 1/8] perf tools: remove stale perf evlist mmap read for backward kan.liang
2017-12-18  6:44   ` Wangnan (F)
2017-12-06 23:32 ` kan.liang [this message]
2017-12-18  8:49   ` [PATCH V2 2/8] perf tools: rewrite perf mmap read for overwrite Wangnan (F)
2017-12-18 19:07     ` Liang, Kan
2017-12-19  3:04       ` Wangnan (F)
2017-12-19 15:23         ` Liang, Kan
2017-12-06 23:32 ` [PATCH V2 3/8] perf tools: reuse perf_mmap__read_catchup in perf_mmap__push kan.liang
2017-12-06 23:32 ` [PATCH V2 4/8] perf tools: introduce perf_mmap__read_event kan.liang
2017-12-06 23:33 ` [PATCH V2 5/8] perf top: check per event overwrite term kan.liang
2017-12-06 23:33 ` [PATCH V2 6/8] perf top: add overwrite fall back kan.liang
2017-12-18  9:23   ` Wangnan (F)
2017-12-18 19:13     ` Liang, Kan
2017-12-06 23:33 ` [PATCH V2 7/8] perf top: switch default mode to overwrite mode kan.liang
2017-12-06 23:33 ` [PATCH V2 8/8] perf top: check the latency of perf_top__mmap_read kan.liang

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=1512603183-42754-3-git-send-email-kan.liang@intel.com \
    --to=kan.liang@intel.com \
    --cc=acme@kernel.org \
    --cc=ak@linux.intel.com \
    --cc=jolsa@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=namhyung@kernel.org \
    --cc=peterz@infradead.org \
    --cc=wangnan0@huawei.com \
    --cc=yao.jin@linux.intel.com \
    /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®