From: Kan Liang <[email protected]> Reading at the start and the end of sampling, and save the counter statistics value to PERF_RECORD_STAT_READ. The absolate value from counter will be stored in prev_raw_counts. The detla value will be caculated and saved in PERF_RECORD_STAT_READ.
Signed-off-by: Kan Liang <[email protected]> --- tools/perf/builtin-record.c | 76 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 5b09318..0e5e4c0 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -29,6 +29,7 @@ #include "util/data.h" #include "util/auxtrace.h" #include "util/parse-branch-options.h" +#include "util/stat.h" #include <unistd.h> #include <sched.h> @@ -266,6 +267,30 @@ int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused) #endif +static void +free_prev_stat_counts(struct perf_evlist *evlist) +{ + struct perf_evsel *evsel; + + evlist__for_each(evlist, evsel) { + if (evsel->prev_raw_counts != NULL) + perf_evsel__free_prev_raw_counts(evsel); + } +} + +static int perf_evlist__alloc_prev_stat(struct perf_evlist *evlist) +{ + struct perf_evsel *evsel; + + evlist__for_each(evlist, evsel) { + if (evsel->stat_read && + (perf_evsel__alloc_prev_raw_counts(evsel, cpu_map__nr(evsel->cpus), 1) < 0)) + return -ENOMEM; + } + + return 0; +} + static int record__open(struct record *rec) { char msg[512]; @@ -352,6 +377,9 @@ try_again: goto out; } + if (perf_evlist__alloc_prev_stat(evlist)) + goto out; + session->evlist = evlist; perf_session__set_id_hdr_size(session); out: @@ -427,6 +455,50 @@ static struct perf_event_header finished_round_event = { .type = PERF_RECORD_FINISHED_ROUND, }; +static void process_stat_read_event(struct record *rec, int id, + struct perf_evsel *pos, + struct perf_counts_values *count, + u32 pos_id) +{ + union perf_event ev; + struct perf_counts_values tmp; + + memset(&ev, 0, sizeof(ev)); + ev.stat_read.header.type = PERF_RECORD_STAT_READ; + ev.stat_read.header.size = sizeof(ev.stat_read); + ev.stat_read.cpu = pos->cpus->map[id]; + ev.stat_read.pos_id = pos_id; + + BUG_ON(pos->prev_raw_counts == NULL); + tmp.val = perf_counts(pos->prev_raw_counts, id, 0)->val; + if (tmp.val) + ev.stat_read.value = count->val - tmp.val; + perf_counts(pos->prev_raw_counts, id, 0)->val = count->val; + + ev.stat_read.time = rdclock(); + + record__write(rec, &ev, sizeof(ev.stat_read)); +} + +static void perf_read_counter(struct record *rec) +{ + struct perf_evlist *evlist = rec->evlist; + struct perf_counts_values count; + struct perf_evsel *pos; + int cpu; + u32 pos_id = 0; + + evlist__for_each(evlist, pos) { + for (cpu = 0; cpu < cpu_map__nr(pos->cpus); cpu++) { + if (pos->stat_read && + !perf_evsel__read(pos, cpu, 0, &count)) { + process_stat_read_event(rec, cpu, pos, &count, pos_id); + } + } + pos_id++; + } +} + static int record__mmap_read_all(struct record *rec) { u64 bytes_written = rec->bytes_written; @@ -664,6 +736,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) perf_evlist__enable(rec->evlist); } + perf_read_counter(rec); auxtrace_snapshot_enabled = 1; for (;;) { int hits = rec->samples; @@ -708,6 +781,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) */ if (done && !disabled && !target__none(&opts->target)) { auxtrace_snapshot_enabled = 0; + perf_read_counter(rec); perf_evlist__disable(rec->evlist); disabled = true; } @@ -776,7 +850,7 @@ out_child: perf_data_file__size(file) / 1024.0 / 1024.0, file->path, samples); } - + free_prev_stat_counts(rec->evlist); out_delete_session: perf_session__delete(session); return status; -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/

