Messages in this thread Patch in this message | | | From | Jiri Olsa <> | Subject | [PATCH 37/48] perf record: Introduce struct record_thread | Date | Thu, 13 Sep 2018 14:54:39 +0200 |
| |
Adding struct record_thread to carry the single thread's maps.
Link: http://lkml.kernel.org/n/tip-dsyi97xdc7ullvsisqmha0ca@git.kernel.org Signed-off-by: Jiri Olsa <jolsa@kernel.org> --- tools/perf/builtin-record.c | 179 ++++++++++++++++++++++++++++++++++++ 1 file changed, 179 insertions(+)
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 1b01cb4d06b8..5c6b56f164a9 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -65,6 +65,15 @@ struct switch_output { bool set; }; +struct record_thread { + struct perf_mmap **mmap; + int mmap_nr; + struct perf_mmap **ovw_mmap; + int ovw_mmap_nr; + struct fdarray pollfd; + struct record *rec; +}; + struct record { struct perf_tool tool; struct record_opts opts; @@ -83,6 +92,8 @@ struct record { bool timestamp_boundary; struct switch_output switch_output; unsigned long long samples; + struct record_thread *threads; + int threads_cnt; }; static volatile int auxtrace_record__snapshot_started; @@ -967,6 +978,166 @@ static int record__synthesize(struct record *rec, bool tail) return err; } +static void +record_thread__clean(struct record_thread *th) +{ + free(th->mmap); + free(th->ovw_mmap); +} + +static void +record__threads_clean(struct record *rec) +{ + struct record_thread *threads = rec->threads; + int i; + + if (threads) { + for (i = 0; i < rec->threads_cnt; i++) + record_thread__clean(threads + i); + } +} + +static void record_thread__init(struct record_thread *th, struct record *rec) +{ + memset(th, 0, sizeof(*th)); + fdarray__init(&th->pollfd, 64); + th->rec = rec; +} + +static int +record_thread__mmap(struct record_thread *th, int nr, int nr_ovw) +{ + struct perf_mmap **mmap; + + mmap = zalloc(sizeof(*mmap) * nr); + if (!mmap) + return -ENOMEM; + + th->mmap = mmap; + th->mmap_nr = nr; + + if (nr_ovw) { + mmap = zalloc(sizeof(*mmap) * nr_ovw); + if (!mmap) + return -ENOMEM; + + th->ovw_mmap = mmap; + th->ovw_mmap_nr = nr; + } + + return 0; +} + +static int +record__threads_assign(struct record *rec) +{ + struct record_thread *threads = rec->threads; + struct record_thread *thread0 = threads; + struct perf_evlist *evlist = rec->evlist; + int i, j, nr, nr0, nr_ovw, nr_trk; + int ret = -ENOMEM; + + nr = evlist->mmap ? evlist->nr_mmaps : 0; + nr_trk = evlist->track_mmap ? evlist->nr_mmaps : 0; + nr_ovw = evlist->overwrite_mmap ? evlist->nr_mmaps : 0; + + nr0 = nr_trk; + nr0 += nr; + + if (record_thread__mmap(thread0, nr0, nr_ovw)) + goto out_error; + + for (i = 0; i < nr_ovw; i++) + thread0->ovw_mmap[i] = &evlist->overwrite_mmap[i]; + + for (i = 0; i < nr_trk; i++) + thread0->mmap[i] = &evlist->track_mmap[i]; + + for (j = 0; i < nr0 && j < nr; i++, j++) + thread0->mmap[i] = &evlist->mmap[j]; + + ret = 0; + +out_error: + return ret; +} + +static int +record_thread__create_poll(struct record_thread *th, + struct perf_evlist *evlist) +{ + struct fdarray *fda = &evlist->pollfd; + struct perf_mmap *mmap; + int i, j; + + for (i = 0; i < th->mmap_nr; i++) { + mmap = th->mmap[i]; + + for (j = 0; j < fda->nr; j++) { + if (mmap != fda->priv[j].ptr) + continue; + + if (fdarray__add_clone(&th->pollfd, j, fda) < 0) + return -ENOMEM; + + break; + } + } + + return 0; +} + +static int +record__threads_create_poll(struct record *rec) +{ + struct record_thread *threads = rec->threads; + int ret = 0, i; + + for (i = 0; !ret && (i < rec->threads_cnt); i++) + ret = record_thread__create_poll(threads + i, rec->evlist); + + return ret; +} + +static int +record__threads_create(struct record *rec) +{ + struct record_thread *threads; + int i, cnt = rec->threads_cnt; + + threads = zalloc(sizeof(*threads) * cnt); + if (threads) { + for (i = 0; i < cnt; i++) + record_thread__init(threads + i, rec); + + rec->threads = threads; + } + + return threads ? 0 : -ENOMEM; +} + +static int +record__threads_config(struct record *rec) +{ + int ret; + + ret = record__threads_create(rec); + if (ret) + goto out; + + ret = record__threads_assign(rec); + if (ret) + goto out; + + ret = record__threads_create_poll(rec); + +out: + if (ret) + record__threads_clean(rec); + + return ret; +} + static int __cmd_record(struct record *rec, int argc, const char **argv) { int err; @@ -1040,6 +1211,11 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) goto out_child; } + if (record__threads_config(rec)) { + err = -1; + goto out_child; + } + if (opts->index) { err = record__mmap_index(rec); if (err) @@ -1316,6 +1492,8 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) perf_hooks__invoke_record_end(); + record__threads_clean(rec); + if (!err && !quiet) { char samples[128]; const char *postfix = rec->timestamp_filename ? @@ -1657,6 +1835,7 @@ static struct record record = { .mmap2 = perf_event__process_mmap2, .ordered_events = true, }, + .threads_cnt = 1, }; const char record_callchain_help[] = CALLCHAIN_RECORD_HELP -- 2.17.1
| |