[PATCH v2 12/15] perf record: introduce thread local variable for trace streaming

Alexey Budankov
2020-10-21T16:07:07Z

Introduce thread local variable and use it for threaded trace streaming.

Signed-off-by: Alexey Budankov <alexey.budankov@linux.intel.com>
---
tools/perf/builtin-record.c | 71 ++++++++++++++++++++++++++++++++-----
1 file changed, 62 insertions(+), 9 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 89cb8e913fb3..3b7e9026f25b 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -101,6 +101,8 @@ struct thread_data {
u64 bytes_written;
};

+static __thread struct thread_data *thread;
+
struct record {
struct perf_tool tool;
struct record_opts opts;
@@ -587,7 +589,11 @@ static int record__pushfn(struct mmap *map, void *to, void *bf, size_t size)
}
}

- rec->samples++;
+ if (thread)
+ thread->samples++;
+ else
+ rec->samples++;
+
return record__write(rec, map, bf, compressed);
}

@@ -1258,6 +1264,7 @@ static int record__mmap_read_evlist(struct record *rec, struct evlist *evlist,
int i;
int rc = 0;
struct mmap *maps;
+ int nr_mmaps;
int trace_fd = rec->data.file.fd;
off_t off = 0;

@@ -1265,6 +1272,14 @@ static int record__mmap_read_evlist(struct record *rec, struct evlist *evlist,
return 0;

maps = overwrite ? evlist->overwrite_mmap : evlist->mmap;
+ nr_mmaps = evlist->core.nr_mmaps;
+
+ if (thread) {
+ bytes_written = thread->bytes_written;
+ maps = thread->maps;
+ nr_mmaps = thread->nr_mmaps;
+ }
+
if (!maps)
return 0;

@@ -1274,7 +1289,7 @@ static int record__mmap_read_evlist(struct record *rec, struct evlist *evlist,
if (record__aio_enabled(rec))
off = record__aio_get_pos(trace_fd);

- for (i = 0; i < evlist->core.nr_mmaps; i++) {
+ for (i = 0; i < nr_mmaps; i++) {
u64 flush = 0;
struct mmap *map = &maps[i];

@@ -1323,7 +1338,7 @@ static int record__mmap_read_evlist(struct record *rec, struct evlist *evlist,
* because per-cpu maps and files have data
* sorted by kernel.
*/
- if (!record__threads_enabled(rec) && bytes_written != rec->bytes_written)
+ if (!thread && bytes_written != rec->bytes_written)
rc = record__write(rec, NULL, &finished_round_event, sizeof(finished_round_event));

if (overwrite)
@@ -1343,6 +1358,15 @@ static int record__mmap_read_all(struct record *rec, bool synch)
return record__mmap_read_evlist(rec, rec->evlist, true, synch);
}

+static void record__thread_munmap_filtered(struct fdarray *fda, int fd,
+ void *arg __maybe_unused)
+{
+ struct perf_mmap *map = fda->priv[fd].ptr;
+
+ if (map)
+ perf_mmap__put(map);
+}
+
static void record__init_features(struct record *rec)
{
struct perf_session *session = rec->session;
@@ -2020,7 +2044,12 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
trigger_ready(&switch_output_trigger);
perf_hooks__invoke_record_start();
for (;;) {
- unsigned long long hits = rec->samples;
+ unsigned long long hits0, hits1;
+
+ if (thread)
+ hits0 = thread->samples;
+ else
+ hits0 = rec->samples;

/*
* rec->evlist->bkw_mmap_state is possible to be
@@ -2089,20 +2118,44 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
alarm(rec->switch_output.time);
}

- if (hits == rec->samples) {
+ if (thread)
+ hits1 = thread->samples;
+ else
+ hits1 = rec->samples;
+
+ if (hits0 == hits1) {
if (done || draining)
break;
- err = evlist__poll(rec->evlist, -1);
+
+ if (thread)
+ err = fdarray__poll(&thread->pollfd, -1);
+ else
+ err = evlist__poll(rec->evlist, -1);
/*
* Propagate error, only if there's any. Ignore positive
* number of returned events and interrupt error.
*/
if (err > 0 || (err < 0 && errno == EINTR))
err = 0;
- waking++;

- if (evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0)
- draining = true;
+ if (thread) {
+ thread->waking++;
+ if (thread->ctlfd_pos != -1) {
+ evlist__ctlfd_update(rec->evlist,
+ &(thread->pollfd.entries[thread->ctlfd_pos]));
+ }
+ } else {
+ waking++;
+ }
+
+ if (thread) {
+ if (fdarray__filter(&thread->pollfd, POLLERR | POLLHUP,
+ record__thread_munmap_filtered, NULL) == 0)
+ draining = true;
+ } else {
+ if (evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0)
+ draining = true;
+ }
}

if (evlist__ctlfd_process(rec->evlist, &cmd) > 0) {
--
2.24.1