summaryrefslogtreecommitdiff
path: root/tools/perf/util/sideband_evlist.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/sideband_evlist.c')
-rw-r--r--tools/perf/util/sideband_evlist.c54
1 files changed, 34 insertions, 20 deletions
diff --git a/tools/perf/util/sideband_evlist.c b/tools/perf/util/sideband_evlist.c
index 388846f17bc1..ba043db6cedc 100644
--- a/tools/perf/util/sideband_evlist.c
+++ b/tools/perf/util/sideband_evlist.c
@@ -8,6 +8,7 @@
#include <perf/mmap.h>
#include <linux/perf_event.h>
#include <limits.h>
+#include <poll.h>
#include <pthread.h>
#include <sched.h>
#include <stdbool.h>
@@ -22,7 +23,7 @@ int evlist__add_sb_event(struct evlist *evlist, struct perf_event_attr *attr,
attr->sample_id_all = 1;
}
- evsel = evsel__new_idx(attr, evlist->core.nr_entries);
+ evsel = evsel__new_idx(attr, evlist__nr_entries(evlist));
if (!evsel)
return -1;
@@ -49,14 +50,27 @@ static void *perf_evlist__poll_thread(void *arg)
while (!done) {
bool got_data = false;
- if (evlist->thread.done)
+ if (evlist__sb_thread_done(evlist))
draining = true;
if (!draining)
evlist__poll(evlist, 1000);
- for (i = 0; i < evlist->core.nr_mmaps; i++) {
- struct mmap *map = &evlist->mmap[i];
+ /*
+ * When a thread of the monitored target exits, its per-cpu
+ * ring-buffer fd is closed and starts returning POLLHUP. Such
+ * dead fds are never requested for POLLIN, but poll() reports
+ * POLLHUP/POLLERR unconditionally, so leaving them in the
+ * pollfd array makes the following evlist__poll() return
+ * immediately forever, spinning this thread at 100% CPU.
+ *
+ * Filter them out here, mirroring what the 'perf record' main
+ * loop does after fdarray__poll().
+ */
+ evlist__filter_pollfd(evlist, POLLERR | POLLHUP);
+
+ for (i = 0; i < evlist__core(evlist)->nr_mmaps; i++) {
+ struct mmap *map = &evlist__mmap(evlist)[i];
union perf_event *event;
if (perf_mmap__read_init(&map->core))
@@ -102,9 +116,9 @@ int evlist__start_sb_thread(struct evlist *evlist, struct target *target)
return 0;
if (evlist__create_maps(evlist, target))
- goto out_delete_evlist;
+ goto out_put_evlist;
- if (evlist->core.nr_entries > 1) {
+ if (evlist__nr_entries(evlist) > 1) {
bool can_sample_identifier = perf_can_sample_identifier();
evlist__for_each_entry(evlist, counter)
@@ -114,27 +128,27 @@ int evlist__start_sb_thread(struct evlist *evlist, struct target *target)
}
evlist__for_each_entry(evlist, counter) {
- if (evsel__open(counter, evlist->core.user_requested_cpus,
- evlist->core.threads) < 0)
- goto out_delete_evlist;
+ if (evsel__open(counter, evlist__core(evlist)->user_requested_cpus,
+ evlist__core(evlist)->threads) < 0)
+ goto out_put_evlist;
}
- if (evlist__mmap(evlist, UINT_MAX))
- goto out_delete_evlist;
+ if (evlist__do_mmap(evlist, UINT_MAX))
+ goto out_put_evlist;
evlist__for_each_entry(evlist, counter) {
if (evsel__enable(counter))
- goto out_delete_evlist;
+ goto out_put_evlist;
}
- evlist->thread.done = 0;
- if (pthread_create(&evlist->thread.th, NULL, perf_evlist__poll_thread, evlist))
- goto out_delete_evlist;
+ evlist__set_sb_thread_done(evlist, 0);
+ if (pthread_create(evlist__sb_thread_th(evlist), NULL, perf_evlist__poll_thread, evlist))
+ goto out_put_evlist;
return 0;
-out_delete_evlist:
- evlist__delete(evlist);
+out_put_evlist:
+ evlist__put(evlist);
evlist = NULL;
return -1;
}
@@ -143,7 +157,7 @@ void evlist__stop_sb_thread(struct evlist *evlist)
{
if (!evlist)
return;
- evlist->thread.done = 1;
- pthread_join(evlist->thread.th, NULL);
- evlist__delete(evlist);
+ evlist__set_sb_thread_done(evlist, 1);
+ pthread_join(*evlist__sb_thread_th(evlist), NULL);
+ evlist__put(evlist);
}