Messages in this thread Patch in this message | | | From | kan.liang@intel ... | Subject | [PATCH 01/10] perf record: new interfaces to read ring buffer to file | Date | Tue, 10 Oct 2017 10:20:14 -0700 |
| |
From: Kan Liang <kan.liang@intel.com>
Factor out the mmap_read related codes into separate functions and move them to evlist.c struct perf_mmap_read is introduced to store the specific range of ring buffer information.
The way to read specific range of ring buffer into file is as below, perf_mmap__read_init perf_mmap__read_to_file perf_mmap__consume
There is no functional change.
Signed-off-by: Kan Liang <kan.liang@intel.com> --- tools/perf/builtin-record.c | 111 ++++++++------------------------------------ tools/perf/util/evlist.c | 111 ++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/evlist.h | 15 ++++++ 3 files changed, 146 insertions(+), 91 deletions(-)
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 234fdf4..df555e9 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -105,6 +105,17 @@ static bool switch_output_time(struct record *rec) trigger_is_ready(&switch_output_trigger); } +static void update_output_size(struct record *rec, size_t size) +{ + if (size == 0) + return; + + rec->bytes_written += size; + + if (switch_output_size(rec)) + trigger_hit(&switch_output_trigger); +} + static int record__write(struct record *rec, void *bf, size_t size) { if (perf_data_file__write(rec->session->file, bf, size) < 0) { @@ -112,10 +123,7 @@ static int record__write(struct record *rec, void *bf, size_t size) return -1; } - rec->bytes_written += size; - - if (switch_output_size(rec)) - trigger_hit(&switch_output_trigger); + update_output_size(rec, size); return 0; } @@ -130,106 +138,27 @@ static int process_synthesized_event(struct perf_tool *tool, } static int -backward_rb_find_range(void *buf, int mask, u64 head, u64 *start, u64 *end) -{ - struct perf_event_header *pheader; - u64 evt_head = head; - int size = mask + 1; - - pr_debug2("backward_rb_find_range: buf=%p, head=%"PRIx64"\n", buf, head); - pheader = (struct perf_event_header *)(buf + (head & mask)); - *start = head; - while (true) { - if (evt_head - head >= (unsigned int)size) { - pr_debug("Finished reading backward ring buffer: rewind\n"); - if (evt_head - head > (unsigned int)size) - evt_head -= pheader->size; - *end = evt_head; - return 0; - } - - pheader = (struct perf_event_header *)(buf + (evt_head & mask)); - - if (pheader->size == 0) { - pr_debug("Finished reading backward ring buffer: get start\n"); - *end = evt_head; - return 0; - } - - evt_head += pheader->size; - pr_debug3("move evt_head: %"PRIx64"\n", evt_head); - } - WARN_ONCE(1, "Shouldn't get here\n"); - return -1; -} - -static int -rb_find_range(void *data, int mask, u64 head, u64 old, - u64 *start, u64 *end, bool backward) -{ - if (!backward) { - *start = old; - *end = head; - return 0; - } - - return backward_rb_find_range(data, mask, head, start, end); -} - -static int record__mmap_read(struct record *rec, struct perf_mmap *md, bool overwrite, bool backward) { - u64 head = perf_mmap__read_head(md); - u64 old = md->prev; - u64 end = head, start = old; - unsigned char *data = md->base + page_size; - unsigned long size; - void *buf; - int rc = 0; + struct perf_mmap_read read; - if (rb_find_range(data, md->mask, head, - old, &start, &end, backward)) + if (perf_mmap__read_init(md, &read, overwrite, backward)) return -1; - if (start == end) + if (read.start == read.end) return 0; rec->samples++; - size = end - start; - if (size > (unsigned long)(md->mask) + 1) { - WARN_ONCE(1, "failed to keep up with mmap data. (warn only once)\n"); - - md->prev = head; - perf_mmap__consume(md, overwrite || backward); - return 0; - } - - if ((start & md->mask) + size != (end & md->mask)) { - buf = &data[start & md->mask]; - size = md->mask + 1 - (start & md->mask); - start += size; - - if (record__write(rec, buf, size) < 0) { - rc = -1; - goto out; - } - } + if (perf_mmap__read_to_file(&read, rec->session->file) < 0) + return -1; - buf = &data[start & md->mask]; - size = end - start; - start += size; + update_output_size(rec, read.size); - if (record__write(rec, buf, size) < 0) { - rc = -1; - goto out; - } - - md->prev = head; perf_mmap__consume(md, overwrite || backward); -out: - return rc; + + return 0; } static volatile int done; diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 6a0d7ff..33b8837 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -704,6 +704,117 @@ static int perf_evlist__resume(struct perf_evlist *evlist) return perf_evlist__set_paused(evlist, false); } +static int +backward_rb_find_range(void *buf, int mask, u64 head, u64 *start, u64 *end) +{ + struct perf_event_header *pheader; + u64 evt_head = head; + int size = mask + 1; + + pr_debug2("backward_rb_find_range: buf=%p, head=%"PRIx64"\n", buf, head); + pheader = (struct perf_event_header *)(buf + (head & mask)); + *start = head; + while (true) { + if (evt_head - head >= (unsigned int)size) { + pr_debug("Finished reading backward ring buffer: rewind\n"); + if (evt_head - head > (unsigned int)size) + evt_head -= pheader->size; + *end = evt_head; + return 0; + } + + pheader = (struct perf_event_header *)(buf + (evt_head & mask)); + + if (pheader->size == 0) { + pr_debug("Finished reading backward ring buffer: get start\n"); + *end = evt_head; + return 0; + } + + evt_head += pheader->size; + pr_debug3("move evt_head: %"PRIx64"\n", evt_head); + } + WARN_ONCE(1, "Shouldn't get here\n"); + return -1; +} + +static int +rb_find_range(void *data, int mask, u64 head, u64 old, + u64 *start, u64 *end, bool backward) +{ + if (!backward) { + *start = old; + *end = head; + return 0; + } + + return backward_rb_find_range(data, mask, head, start, end); +} + +/* + * Initialize struct perf_mmap_read + * Calculate the range of ring buffer to read + */ +int perf_mmap__read_init(struct perf_mmap *md, struct perf_mmap_read *read, + bool overwrite, bool backward) +{ + unsigned char *data = md->base + page_size; + + read->md = md; + read->head = perf_mmap__read_head(md); + read->overwrite = overwrite; + read->backward = backward; + read->size = 0; + return rb_find_range(data, md->mask, read->head, md->prev, + &read->start, &read->end, backward); +} + +/* + * Read the ring buffer in the range which specified in struct perf_mmap_read, + * and write to file. + * Used by perf record. + */ +int perf_mmap__read_to_file(struct perf_mmap_read *read, + struct perf_data_file *file) +{ + struct perf_mmap *md = read->md; + unsigned char *data = md->base + page_size; + unsigned long size; + void *buf; + + size = read->end - read->start; + if (size > (unsigned long)(md->mask) + 1) { + WARN_ONCE(1, "failed to keep up with mmap data. (warn only once)\n"); + read->size = 0; + goto out; + } + + if ((read->start & md->mask) + size != (read->end & md->mask)) { + buf = &data[read->start & md->mask]; + size = md->mask + 1 - (read->start & md->mask); + read->start += size; + read->size += size; + + if (perf_data_file__write(file, buf, size) < 0) { + pr_err("failed to write %s, error: %m\n", file->path); + return -1; + } + } + + buf = &data[read->start & md->mask]; + size = read->end - read->start; + read->start += size; + read->size += size; + + if (perf_data_file__write(file, buf, size) < 0) { + pr_err("failed to write %s, error: %m\n", file->path); + return -1; + } +out: + md->prev = read->head; + return 0; +} + /* When check_messup is true, 'end' must points to a good entry */ static union perf_event * perf_mmap__read(struct perf_mmap *md, bool check_messup, u64 start, diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index b1c14f1..1ce4857 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -39,6 +39,16 @@ struct perf_mmap { char event_copy[PERF_SAMPLE_MAX_SIZE] __aligned(8); }; +struct perf_mmap_read { + struct perf_mmap *md; + u64 head; + u64 start; + u64 end; + bool overwrite; + bool backward; + unsigned long size; +}; + static inline size_t perf_mmap__mmap_len(struct perf_mmap *map) { @@ -193,6 +203,11 @@ void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx); void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx); +int perf_mmap__read_init(struct perf_mmap *md, struct perf_mmap_read *read, + bool overwrite, bool backward); +int perf_mmap__read_to_file(struct perf_mmap_read *read, + struct perf_data_file *file); + int perf_evlist__open(struct perf_evlist *evlist); void perf_evlist__close(struct perf_evlist *evlist); -- 2.5.5
| |